test_simm30_dram
changeset 1:318a758ede82
ops
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 08 Mar 2017 09:05:19 +0200 |
parents | c47d05df0667 |
children | 42d26388b709 |
files | Makefile test.c |
diffstat | 2 files changed, 295 insertions(+), 10 deletions(-) [+] |
line diff
1.1 --- a/Makefile Tue Mar 07 23:50:45 2017 +0200 1.2 +++ b/Makefile Wed Mar 08 09:05:19 2017 +0200 1.3 @@ -1,6 +1,6 @@ 1.4 src = $(wildcard *.c) 1.5 obj = $(src:.c=.o) 1.6 -bin = test_ftdi 1.7 +bin = test_simm72_dram 1.8 hex = $(bin).hex 1.9 eep = $(bin).eep 1.10
2.1 --- a/test.c Tue Mar 07 23:50:45 2017 +0200 2.2 +++ b/test.c Wed Mar 08 09:05:19 2017 +0200 2.3 @@ -1,22 +1,63 @@ 2.4 #include <stdio.h> 2.5 +#include <stdlib.h> 2.6 #include <string.h> 2.7 #include <ctype.h> 2.8 #include <avr/io.h> 2.9 #include <avr/interrupt.h> 2.10 #include "serial.h" 2.11 2.12 -void procmd(const char *cmd); 2.13 +/* pin assignments: 2.14 + * A[0,7] data 2.15 + * B[0,7] A0 - A7 2.16 + * C[0,3] A8 - A11 2.17 + * D7 CAS3 2.18 + * D6 RAS2 2.19 + * D5 RAS3 2.20 + */ 2.21 + 2.22 +#define CAS3_BIT 0x80 2.23 +#define RAS2_BIT 0x40 2.24 +#define RAS3_BIT 0x20 2.25 +#define WE_BIT 0x04 2.26 + 2.27 +void proc_cmd(char *cmd); 2.28 +void cmd_read(char *buf); 2.29 +void cmd_write(char *buf); 2.30 +void cmd_setcfg(char *buf); 2.31 + 2.32 +void dram_init(void); 2.33 +void dram_detect(void); 2.34 +int memtest(unsigned long addr); 2.35 +void dram_refresh(void); 2.36 +void dram_write(unsigned long addr, unsigned char val); 2.37 +unsigned char dram_read(unsigned long addr); 2.38 2.39 #define MAX_INPUT_SIZE 128 2.40 static char input[MAX_INPUT_SIZE]; 2.41 static unsigned char inp_cidx; 2.42 2.43 +/* SIMM access config */ 2.44 +static int addr_bits; 2.45 +static unsigned long addr_mask; 2.46 +static int ras_lines = 1; 2.47 +static long memsize_kb; /* derived from the above */ 2.48 + 2.49 + 2.50 int main(void) 2.51 { 2.52 + dram_init(); 2.53 init_serial(38400); 2.54 sei(); 2.55 2.56 - printf("welcome!\n"); 2.57 + printf("Detecting memory ...\n"); 2.58 + dram_detect(); 2.59 + 2.60 + memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines; 2.61 + 2.62 + printf("Address lines: %d\n", addr_bits); 2.63 + printf("RAS lines: %d\n", ras_lines); 2.64 + printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb); 2.65 + fputs("> ", stdout); 2.66 2.67 for(;;) { 2.68 while(have_input()) { 2.69 @@ -25,21 +66,265 @@ 2.70 2.71 if(c == '\r' || c == '\n') { 2.72 input[inp_cidx] = 0; 2.73 - procmd(input); 2.74 + proc_cmd(input); 2.75 inp_cidx = 0; 2.76 + 2.77 + fputs("> ", stdout); 2.78 } else if(inp_cidx < sizeof input - 1) { 2.79 input[inp_cidx++] = c; 2.80 } 2.81 } 2.82 + 2.83 + dram_refresh(); 2.84 + } 2.85 + return 0; 2.86 +} 2.87 + 2.88 +void proc_cmd(char *cmd) 2.89 +{ 2.90 + switch(cmd[0]) { 2.91 + case 'w': 2.92 + cmd_write(cmd + 1); 2.93 + break; 2.94 + 2.95 + case 'r': 2.96 + cmd_read(cmd + 1); 2.97 + break; 2.98 + 2.99 + case 's': 2.100 + cmd_setcfg(cmd + 1); 2.101 + break; 2.102 + 2.103 + case 'h': 2.104 + printf("commands:\n"); 2.105 + printf(" w <addr> <value> - write byte to address\n"); 2.106 + printf(" r <addr> - read byte from address\n"); 2.107 + printf(" s <addr_bits|ras_lines> <value>\n"); 2.108 + printf(" h - help\n"); 2.109 + break; 2.110 + } 2.111 +} 2.112 + 2.113 +void cmd_read(char *buf) 2.114 +{ 2.115 + char *endp; 2.116 + unsigned long addr; 2.117 + unsigned char data; 2.118 + 2.119 + addr = strtol(buf, &endp, 0); 2.120 + if(endp == buf) { 2.121 + fprintf(stderr, "invalid argument to write command: %s\n", buf); 2.122 + return; 2.123 + } 2.124 + buf = endp; 2.125 + 2.126 + data = dram_read(addr); 2.127 + printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); 2.128 +} 2.129 + 2.130 +void cmd_write(char *buf) 2.131 +{ 2.132 + char *endp; 2.133 + unsigned long addr; 2.134 + unsigned char data; 2.135 + 2.136 + addr = strtol(buf, &endp, 0); 2.137 + if(endp == buf) { 2.138 + fprintf(stderr, "invalid address argument to read command: %s\n", buf); 2.139 + return; 2.140 + } 2.141 + buf = endp; 2.142 + 2.143 + data = strtol(buf, &endp, 0); 2.144 + if(endp == buf) { 2.145 + fprintf(stderr, "invalid data argument to read command: %s\n", buf); 2.146 + return; 2.147 + } 2.148 + buf = endp; 2.149 + 2.150 + dram_write(addr, data); 2.151 + printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); 2.152 +} 2.153 + 2.154 +void cmd_setcfg(char *buf) 2.155 +{ 2.156 + char *endp; 2.157 + char *name, *valstr; 2.158 + long value; 2.159 + 2.160 + name = buf; 2.161 + while(*name && isspace(*name)) ++name; 2.162 + if(!*name) { 2.163 + fprintf(stderr, "invalid or missing variable name\n"); 2.164 + return; 2.165 + } 2.166 + endp = name; 2.167 + while(*endp && !isspace(*endp)) ++endp; 2.168 + *endp = 0; 2.169 + 2.170 + valstr = endp + 1; 2.171 + value = strtol(valstr, &endp, 0); 2.172 + if(endp == valstr) { 2.173 + fprintf(stderr, "invalid or missing variable value: %s\n", valstr); 2.174 + return; 2.175 + } 2.176 + 2.177 + if(strcmp(name, "addr_bits") == 0) { 2.178 + if(value > 0 && value <= 12) { 2.179 + addr_bits = value; 2.180 + printf("Address bits: %ld\n", value); 2.181 + } else { 2.182 + fprintf(stderr, "invalid address bits value: %ld\n", value); 2.183 + } 2.184 + } else if(strcmp(name, "ras_lines") == 0) { 2.185 + if(value > 0 && value <= 2) { 2.186 + ras_lines = value; 2.187 + printf("RAS lines: %d\n", ras_lines); 2.188 + } else { 2.189 + fprintf(stderr, "invalid RAS lines value: %ld\n", value); 2.190 + } 2.191 + } else { 2.192 + fprintf(stderr, "unknown variable: %s\n", name); 2.193 + } 2.194 +} 2.195 + 2.196 +void dram_set_data(unsigned char val) 2.197 +{ 2.198 + DDRA = 0xff; 2.199 + PORTA = val; 2.200 +} 2.201 + 2.202 +void dram_release_data(void) 2.203 +{ 2.204 + DDRA = 0; 2.205 + PORTA = 0; 2.206 +} 2.207 + 2.208 +void dram_set_addr(unsigned long addr) 2.209 +{ 2.210 + PORTB = addr & 0xff; 2.211 + PORTC = (addr >> 8) & 3; 2.212 +} 2.213 + 2.214 +void dram_assert_cas(void) 2.215 +{ 2.216 + PORTD &= ~CAS3_BIT; 2.217 +} 2.218 + 2.219 +void dram_release_cas(void) 2.220 +{ 2.221 + PORTD |= CAS3_BIT; 2.222 +} 2.223 + 2.224 +void dram_assert_ras(unsigned char bits) 2.225 +{ 2.226 + PORTD &= ~bits; 2.227 +} 2.228 + 2.229 +void dram_release_ras(unsigned char bits) 2.230 +{ 2.231 + PORTD |= bits; 2.232 +} 2.233 + 2.234 +void dram_set_we(void) 2.235 +{ 2.236 + PORTD &= ~WE_BIT; 2.237 +} 2.238 + 2.239 +void dram_clear_we(void) 2.240 +{ 2.241 + PORTD |= WE_BIT; 2.242 +} 2.243 + 2.244 +void dram_init(void) 2.245 +{ 2.246 + DDRA = 0; /* port A is the data bus */ 2.247 + PORTA = 0; /* no pullups when A is input */ 2.248 + DDRB = 0xff; /* port B is A0-A7 */ 2.249 + DDRC = 0xff; /* port C (low nibble) is A8-A11 */ 2.250 + DDRD = 0xff; /* port D are the control lines CAS/RAS/WR */ 2.251 + 2.252 + PORTD = 0xff; /* deassert all control signals */ 2.253 +} 2.254 + 2.255 +void dram_detect(void) 2.256 +{ 2.257 + /* detect how many address bits we've got */ 2.258 + addr_bits = 12; 2.259 + while(addr_bits > 8) { 2.260 + printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1)); 2.261 + addr_mask = (1 << (unsigned long)addr_bits) - 1; 2.262 + if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) { 2.263 + break; 2.264 + } 2.265 + --addr_bits; 2.266 + } 2.267 + if(addr_bits < 1) { 2.268 + fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n"); 2.269 + return; 2.270 + } 2.271 +} 2.272 + 2.273 +int memtest(unsigned long addr) 2.274 +{ 2.275 + int i; 2.276 + unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 }; 2.277 + unsigned char val; 2.278 + 2.279 + printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines); 2.280 + 2.281 + for(i=0; i<sizeof pat / sizeof *pat; i++) { 2.282 + dram_write(addr, pat[i]); 2.283 + if((val = dram_read(addr)) != pat[i]) { 2.284 + printf("pattern %x failed, got: %x\n", (int)pat[i], val); 2.285 + return -1; 2.286 + } 2.287 } 2.288 return 0; 2.289 } 2.290 2.291 -void procmd(const char *cmd) 2.292 +void dram_refresh(void) 2.293 { 2.294 - if(strcmp(cmd, "info") == 0) { 2.295 - printf("test firmware v0\n"); 2.296 - } else { 2.297 - printf("unknown command: %s\n", cmd); 2.298 - } 2.299 + dram_assert_cas(); 2.300 + dram_assert_ras(RAS2_BIT | RAS3_BIT); 2.301 + dram_release_cas(); 2.302 + dram_release_ras(RAS2_BIT | RAS3_BIT); 2.303 } 2.304 + 2.305 +void dram_write(unsigned long addr, unsigned char val) 2.306 +{ 2.307 + dram_set_data(val); 2.308 + dram_set_we(); 2.309 + /* set row address */ 2.310 + dram_set_addr((addr >> addr_bits) & addr_mask); 2.311 + dram_assert_ras(RAS2_BIT); 2.312 + /* set column address */ 2.313 + dram_set_addr(addr & addr_mask); 2.314 + dram_assert_cas(); 2.315 + dram_release_ras(RAS2_BIT); 2.316 + dram_release_cas(); 2.317 + dram_release_data(); 2.318 + dram_clear_we(); 2.319 +} 2.320 + 2.321 +unsigned char dram_read(unsigned long addr) 2.322 +{ 2.323 + unsigned char val; 2.324 + 2.325 + dram_clear_we(); 2.326 + dram_release_data(); 2.327 + 2.328 + /* set row address */ 2.329 + dram_set_addr((addr >> addr_bits) & addr_mask); 2.330 + dram_assert_ras(RAS2_BIT); 2.331 + /* set column address */ 2.332 + dram_set_addr(addr & addr_mask); 2.333 + dram_assert_cas(); 2.334 + 2.335 + val = PINA; 2.336 + 2.337 + dram_release_ras(RAS2_BIT); 2.338 + dram_release_cas(); 2.339 + 2.340 + return val; 2.341 +}