test_simm30_dram
diff test.c @ 1:318a758ede82
ops
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 08 Mar 2017 09:05:19 +0200 |
parents | c47d05df0667 |
children | 42d26388b709 |
line diff
1.1 --- a/test.c Tue Mar 07 23:50:45 2017 +0200 1.2 +++ b/test.c Wed Mar 08 09:05:19 2017 +0200 1.3 @@ -1,22 +1,63 @@ 1.4 #include <stdio.h> 1.5 +#include <stdlib.h> 1.6 #include <string.h> 1.7 #include <ctype.h> 1.8 #include <avr/io.h> 1.9 #include <avr/interrupt.h> 1.10 #include "serial.h" 1.11 1.12 -void procmd(const char *cmd); 1.13 +/* pin assignments: 1.14 + * A[0,7] data 1.15 + * B[0,7] A0 - A7 1.16 + * C[0,3] A8 - A11 1.17 + * D7 CAS3 1.18 + * D6 RAS2 1.19 + * D5 RAS3 1.20 + */ 1.21 + 1.22 +#define CAS3_BIT 0x80 1.23 +#define RAS2_BIT 0x40 1.24 +#define RAS3_BIT 0x20 1.25 +#define WE_BIT 0x04 1.26 + 1.27 +void proc_cmd(char *cmd); 1.28 +void cmd_read(char *buf); 1.29 +void cmd_write(char *buf); 1.30 +void cmd_setcfg(char *buf); 1.31 + 1.32 +void dram_init(void); 1.33 +void dram_detect(void); 1.34 +int memtest(unsigned long addr); 1.35 +void dram_refresh(void); 1.36 +void dram_write(unsigned long addr, unsigned char val); 1.37 +unsigned char dram_read(unsigned long addr); 1.38 1.39 #define MAX_INPUT_SIZE 128 1.40 static char input[MAX_INPUT_SIZE]; 1.41 static unsigned char inp_cidx; 1.42 1.43 +/* SIMM access config */ 1.44 +static int addr_bits; 1.45 +static unsigned long addr_mask; 1.46 +static int ras_lines = 1; 1.47 +static long memsize_kb; /* derived from the above */ 1.48 + 1.49 + 1.50 int main(void) 1.51 { 1.52 + dram_init(); 1.53 init_serial(38400); 1.54 sei(); 1.55 1.56 - printf("welcome!\n"); 1.57 + printf("Detecting memory ...\n"); 1.58 + dram_detect(); 1.59 + 1.60 + memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines; 1.61 + 1.62 + printf("Address lines: %d\n", addr_bits); 1.63 + printf("RAS lines: %d\n", ras_lines); 1.64 + printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb); 1.65 + fputs("> ", stdout); 1.66 1.67 for(;;) { 1.68 while(have_input()) { 1.69 @@ -25,21 +66,265 @@ 1.70 1.71 if(c == '\r' || c == '\n') { 1.72 input[inp_cidx] = 0; 1.73 - procmd(input); 1.74 + proc_cmd(input); 1.75 inp_cidx = 0; 1.76 + 1.77 + fputs("> ", stdout); 1.78 } else if(inp_cidx < sizeof input - 1) { 1.79 input[inp_cidx++] = c; 1.80 } 1.81 } 1.82 + 1.83 + dram_refresh(); 1.84 + } 1.85 + return 0; 1.86 +} 1.87 + 1.88 +void proc_cmd(char *cmd) 1.89 +{ 1.90 + switch(cmd[0]) { 1.91 + case 'w': 1.92 + cmd_write(cmd + 1); 1.93 + break; 1.94 + 1.95 + case 'r': 1.96 + cmd_read(cmd + 1); 1.97 + break; 1.98 + 1.99 + case 's': 1.100 + cmd_setcfg(cmd + 1); 1.101 + break; 1.102 + 1.103 + case 'h': 1.104 + printf("commands:\n"); 1.105 + printf(" w <addr> <value> - write byte to address\n"); 1.106 + printf(" r <addr> - read byte from address\n"); 1.107 + printf(" s <addr_bits|ras_lines> <value>\n"); 1.108 + printf(" h - help\n"); 1.109 + break; 1.110 + } 1.111 +} 1.112 + 1.113 +void cmd_read(char *buf) 1.114 +{ 1.115 + char *endp; 1.116 + unsigned long addr; 1.117 + unsigned char data; 1.118 + 1.119 + addr = strtol(buf, &endp, 0); 1.120 + if(endp == buf) { 1.121 + fprintf(stderr, "invalid argument to write command: %s\n", buf); 1.122 + return; 1.123 + } 1.124 + buf = endp; 1.125 + 1.126 + data = dram_read(addr); 1.127 + printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); 1.128 +} 1.129 + 1.130 +void cmd_write(char *buf) 1.131 +{ 1.132 + char *endp; 1.133 + unsigned long addr; 1.134 + unsigned char data; 1.135 + 1.136 + addr = strtol(buf, &endp, 0); 1.137 + if(endp == buf) { 1.138 + fprintf(stderr, "invalid address argument to read command: %s\n", buf); 1.139 + return; 1.140 + } 1.141 + buf = endp; 1.142 + 1.143 + data = strtol(buf, &endp, 0); 1.144 + if(endp == buf) { 1.145 + fprintf(stderr, "invalid data argument to read command: %s\n", buf); 1.146 + return; 1.147 + } 1.148 + buf = endp; 1.149 + 1.150 + dram_write(addr, data); 1.151 + printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); 1.152 +} 1.153 + 1.154 +void cmd_setcfg(char *buf) 1.155 +{ 1.156 + char *endp; 1.157 + char *name, *valstr; 1.158 + long value; 1.159 + 1.160 + name = buf; 1.161 + while(*name && isspace(*name)) ++name; 1.162 + if(!*name) { 1.163 + fprintf(stderr, "invalid or missing variable name\n"); 1.164 + return; 1.165 + } 1.166 + endp = name; 1.167 + while(*endp && !isspace(*endp)) ++endp; 1.168 + *endp = 0; 1.169 + 1.170 + valstr = endp + 1; 1.171 + value = strtol(valstr, &endp, 0); 1.172 + if(endp == valstr) { 1.173 + fprintf(stderr, "invalid or missing variable value: %s\n", valstr); 1.174 + return; 1.175 + } 1.176 + 1.177 + if(strcmp(name, "addr_bits") == 0) { 1.178 + if(value > 0 && value <= 12) { 1.179 + addr_bits = value; 1.180 + printf("Address bits: %ld\n", value); 1.181 + } else { 1.182 + fprintf(stderr, "invalid address bits value: %ld\n", value); 1.183 + } 1.184 + } else if(strcmp(name, "ras_lines") == 0) { 1.185 + if(value > 0 && value <= 2) { 1.186 + ras_lines = value; 1.187 + printf("RAS lines: %d\n", ras_lines); 1.188 + } else { 1.189 + fprintf(stderr, "invalid RAS lines value: %ld\n", value); 1.190 + } 1.191 + } else { 1.192 + fprintf(stderr, "unknown variable: %s\n", name); 1.193 + } 1.194 +} 1.195 + 1.196 +void dram_set_data(unsigned char val) 1.197 +{ 1.198 + DDRA = 0xff; 1.199 + PORTA = val; 1.200 +} 1.201 + 1.202 +void dram_release_data(void) 1.203 +{ 1.204 + DDRA = 0; 1.205 + PORTA = 0; 1.206 +} 1.207 + 1.208 +void dram_set_addr(unsigned long addr) 1.209 +{ 1.210 + PORTB = addr & 0xff; 1.211 + PORTC = (addr >> 8) & 3; 1.212 +} 1.213 + 1.214 +void dram_assert_cas(void) 1.215 +{ 1.216 + PORTD &= ~CAS3_BIT; 1.217 +} 1.218 + 1.219 +void dram_release_cas(void) 1.220 +{ 1.221 + PORTD |= CAS3_BIT; 1.222 +} 1.223 + 1.224 +void dram_assert_ras(unsigned char bits) 1.225 +{ 1.226 + PORTD &= ~bits; 1.227 +} 1.228 + 1.229 +void dram_release_ras(unsigned char bits) 1.230 +{ 1.231 + PORTD |= bits; 1.232 +} 1.233 + 1.234 +void dram_set_we(void) 1.235 +{ 1.236 + PORTD &= ~WE_BIT; 1.237 +} 1.238 + 1.239 +void dram_clear_we(void) 1.240 +{ 1.241 + PORTD |= WE_BIT; 1.242 +} 1.243 + 1.244 +void dram_init(void) 1.245 +{ 1.246 + DDRA = 0; /* port A is the data bus */ 1.247 + PORTA = 0; /* no pullups when A is input */ 1.248 + DDRB = 0xff; /* port B is A0-A7 */ 1.249 + DDRC = 0xff; /* port C (low nibble) is A8-A11 */ 1.250 + DDRD = 0xff; /* port D are the control lines CAS/RAS/WR */ 1.251 + 1.252 + PORTD = 0xff; /* deassert all control signals */ 1.253 +} 1.254 + 1.255 +void dram_detect(void) 1.256 +{ 1.257 + /* detect how many address bits we've got */ 1.258 + addr_bits = 12; 1.259 + while(addr_bits > 8) { 1.260 + printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1)); 1.261 + addr_mask = (1 << (unsigned long)addr_bits) - 1; 1.262 + if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) { 1.263 + break; 1.264 + } 1.265 + --addr_bits; 1.266 + } 1.267 + if(addr_bits < 1) { 1.268 + fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n"); 1.269 + return; 1.270 + } 1.271 +} 1.272 + 1.273 +int memtest(unsigned long addr) 1.274 +{ 1.275 + int i; 1.276 + unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 }; 1.277 + unsigned char val; 1.278 + 1.279 + printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines); 1.280 + 1.281 + for(i=0; i<sizeof pat / sizeof *pat; i++) { 1.282 + dram_write(addr, pat[i]); 1.283 + if((val = dram_read(addr)) != pat[i]) { 1.284 + printf("pattern %x failed, got: %x\n", (int)pat[i], val); 1.285 + return -1; 1.286 + } 1.287 } 1.288 return 0; 1.289 } 1.290 1.291 -void procmd(const char *cmd) 1.292 +void dram_refresh(void) 1.293 { 1.294 - if(strcmp(cmd, "info") == 0) { 1.295 - printf("test firmware v0\n"); 1.296 - } else { 1.297 - printf("unknown command: %s\n", cmd); 1.298 - } 1.299 + dram_assert_cas(); 1.300 + dram_assert_ras(RAS2_BIT | RAS3_BIT); 1.301 + dram_release_cas(); 1.302 + dram_release_ras(RAS2_BIT | RAS3_BIT); 1.303 } 1.304 + 1.305 +void dram_write(unsigned long addr, unsigned char val) 1.306 +{ 1.307 + dram_set_data(val); 1.308 + dram_set_we(); 1.309 + /* set row address */ 1.310 + dram_set_addr((addr >> addr_bits) & addr_mask); 1.311 + dram_assert_ras(RAS2_BIT); 1.312 + /* set column address */ 1.313 + dram_set_addr(addr & addr_mask); 1.314 + dram_assert_cas(); 1.315 + dram_release_ras(RAS2_BIT); 1.316 + dram_release_cas(); 1.317 + dram_release_data(); 1.318 + dram_clear_we(); 1.319 +} 1.320 + 1.321 +unsigned char dram_read(unsigned long addr) 1.322 +{ 1.323 + unsigned char val; 1.324 + 1.325 + dram_clear_we(); 1.326 + dram_release_data(); 1.327 + 1.328 + /* set row address */ 1.329 + dram_set_addr((addr >> addr_bits) & addr_mask); 1.330 + dram_assert_ras(RAS2_BIT); 1.331 + /* set column address */ 1.332 + dram_set_addr(addr & addr_mask); 1.333 + dram_assert_cas(); 1.334 + 1.335 + val = PINA; 1.336 + 1.337 + dram_release_ras(RAS2_BIT); 1.338 + dram_release_cas(); 1.339 + 1.340 + return val; 1.341 +}