test_simm30_dram
diff test.c @ 2:42d26388b709
memory detection works
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 09 Mar 2017 01:40:31 +0200 |
parents | 318a758ede82 |
children | bd6ad00cb1bc |
line diff
1.1 --- a/test.c Wed Mar 08 09:05:19 2017 +0200 1.2 +++ b/test.c Thu Mar 09 01:40:31 2017 +0200 1.3 @@ -1,9 +1,13 @@ 1.4 +#define F_CPU XTAL 1.5 + 1.6 #include <stdio.h> 1.7 #include <stdlib.h> 1.8 #include <string.h> 1.9 #include <ctype.h> 1.10 +#include <stdint.h> 1.11 #include <avr/io.h> 1.12 #include <avr/interrupt.h> 1.13 +#include <util/delay.h> 1.14 #include "serial.h" 1.15 1.16 /* pin assignments: 1.17 @@ -24,13 +28,15 @@ 1.18 void cmd_read(char *buf); 1.19 void cmd_write(char *buf); 1.20 void cmd_setcfg(char *buf); 1.21 +void cmd_test(char *buf); 1.22 +void cmd_detect(void); 1.23 1.24 void dram_init(void); 1.25 void dram_detect(void); 1.26 -int memtest(unsigned long addr); 1.27 +int memtest(uint32_t addr); 1.28 void dram_refresh(void); 1.29 -void dram_write(unsigned long addr, unsigned char val); 1.30 -unsigned char dram_read(unsigned long addr); 1.31 +void dram_write(uint32_t addr, unsigned char val); 1.32 +unsigned char dram_read(uint32_t addr); 1.33 1.34 #define MAX_INPUT_SIZE 128 1.35 static char input[MAX_INPUT_SIZE]; 1.36 @@ -38,29 +44,24 @@ 1.37 1.38 /* SIMM access config */ 1.39 static int addr_bits; 1.40 -static unsigned long addr_mask; 1.41 +static uint32_t addr_mask; 1.42 static int ras_lines = 1; 1.43 static long memsize_kb; /* derived from the above */ 1.44 1.45 - 1.46 int main(void) 1.47 { 1.48 dram_init(); 1.49 init_serial(38400); 1.50 sei(); 1.51 1.52 - printf("Detecting memory ...\n"); 1.53 - dram_detect(); 1.54 + printf("\n72pin SIMM DRAM tester by John Tsiombikas <nuclear@member.fsf.org>\n"); 1.55 1.56 - memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines; 1.57 + cmd_detect(); 1.58 1.59 - printf("Address lines: %d\n", addr_bits); 1.60 - printf("RAS lines: %d\n", ras_lines); 1.61 - printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb); 1.62 fputs("> ", stdout); 1.63 1.64 for(;;) { 1.65 - while(have_input()) { 1.66 + if(have_input()) { 1.67 int c = getchar(); 1.68 putchar(c); 1.69 1.70 @@ -95,11 +96,21 @@ 1.71 cmd_setcfg(cmd + 1); 1.72 break; 1.73 1.74 + case 't': 1.75 + cmd_test(cmd + 1); 1.76 + break; 1.77 + 1.78 + case 'd': 1.79 + cmd_detect(); 1.80 + break; 1.81 + 1.82 case 'h': 1.83 printf("commands:\n"); 1.84 printf(" w <addr> <value> - write byte to address\n"); 1.85 printf(" r <addr> - read byte from address\n"); 1.86 printf(" s <addr_bits|ras_lines> <value>\n"); 1.87 + printf(" t <addr> - test address\n"); 1.88 + printf(" d - detect DRAM\n"); 1.89 printf(" h - help\n"); 1.90 break; 1.91 } 1.92 @@ -108,7 +119,7 @@ 1.93 void cmd_read(char *buf) 1.94 { 1.95 char *endp; 1.96 - unsigned long addr; 1.97 + uint32_t addr; 1.98 unsigned char data; 1.99 1.100 addr = strtol(buf, &endp, 0); 1.101 @@ -119,13 +130,13 @@ 1.102 buf = endp; 1.103 1.104 data = dram_read(addr); 1.105 - printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); 1.106 + printf("%04lx: %02x (%u)\n", (unsigned long)addr, (unsigned int)data, (unsigned int)data); 1.107 } 1.108 1.109 void cmd_write(char *buf) 1.110 { 1.111 char *endp; 1.112 - unsigned long addr; 1.113 + uint32_t addr; 1.114 unsigned char data; 1.115 1.116 addr = strtol(buf, &endp, 0); 1.117 @@ -143,7 +154,7 @@ 1.118 buf = endp; 1.119 1.120 dram_write(addr, data); 1.121 - printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); 1.122 + printf("%04lx: %02x (%u)\n", (unsigned long)addr, (unsigned int)data, (unsigned int)data); 1.123 } 1.124 1.125 void cmd_setcfg(char *buf) 1.126 @@ -172,7 +183,8 @@ 1.127 if(strcmp(name, "addr_bits") == 0) { 1.128 if(value > 0 && value <= 12) { 1.129 addr_bits = value; 1.130 - printf("Address bits: %ld\n", value); 1.131 + addr_mask = ((uint32_t)1 << addr_bits) - 1; 1.132 + printf("Address bits: %ld (mask: %lx)\n", value, (unsigned long)addr_mask); 1.133 } else { 1.134 fprintf(stderr, "invalid address bits value: %ld\n", value); 1.135 } 1.136 @@ -188,6 +200,36 @@ 1.137 } 1.138 } 1.139 1.140 +void cmd_test(char *buf) 1.141 +{ 1.142 + char *endp; 1.143 + uint32_t addr; 1.144 + 1.145 + addr = strtol(buf, &endp, 0); 1.146 + if(endp == buf) { 1.147 + fprintf(stderr, "invalid argument to test command: %s\n", buf); 1.148 + return; 1.149 + } 1.150 + 1.151 + if(memtest(addr) == 0) { 1.152 + printf("success!\n"); 1.153 + } 1.154 +} 1.155 + 1.156 + 1.157 +void cmd_detect(void) 1.158 +{ 1.159 + printf("Detecting memory ...\n"); 1.160 + dram_detect(); 1.161 + 1.162 + memsize_kb = ((uint32_t)1 << (addr_bits * 2)) * 4 * ras_lines; 1.163 + 1.164 + printf("Address lines: %d\n", addr_bits); 1.165 + printf("RAS lines: %d\n", ras_lines); 1.166 + printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 20, memsize_kb >> 10); 1.167 +} 1.168 + 1.169 + 1.170 void dram_set_data(unsigned char val) 1.171 { 1.172 DDRA = 0xff; 1.173 @@ -245,16 +287,21 @@ 1.174 DDRD = 0xff; /* port D are the control lines CAS/RAS/WR */ 1.175 1.176 PORTD = 0xff; /* deassert all control signals */ 1.177 + 1.178 + /* it seems like nothing works until we do one refresh cycle... */ 1.179 + dram_refresh(); 1.180 } 1.181 1.182 void dram_detect(void) 1.183 { 1.184 + uint32_t addr = 0; 1.185 + 1.186 /* detect how many address bits we've got */ 1.187 addr_bits = 12; 1.188 while(addr_bits > 8) { 1.189 - printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1)); 1.190 - addr_mask = (1 << (unsigned long)addr_bits) - 1; 1.191 - if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) { 1.192 + addr_mask = ((uint32_t)1 << (uint32_t)addr_bits) - 1; 1.193 + addr = ((uint32_t)1 << ((uint32_t)addr_bits * 2)) - 1; 1.194 + if(memtest(addr) == 0) { 1.195 break; 1.196 } 1.197 --addr_bits; 1.198 @@ -263,20 +310,27 @@ 1.199 fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n"); 1.200 return; 1.201 } 1.202 + 1.203 + /* now detect if there's a second ras pair */ 1.204 + ++addr; /* addr was already the highest of the first bank, see if there's a second */ 1.205 + ras_lines = 2; 1.206 + if(memtest(addr) != 0) { 1.207 + ras_lines = 1; 1.208 + } 1.209 } 1.210 1.211 -int memtest(unsigned long addr) 1.212 +int memtest(uint32_t addr) 1.213 { 1.214 int i; 1.215 unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 }; 1.216 unsigned char val; 1.217 1.218 - printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines); 1.219 + printf("testing address: %lx (a:%d,r:%d)\n", (unsigned long)addr, addr_bits, ras_lines); 1.220 1.221 for(i=0; i<sizeof pat / sizeof *pat; i++) { 1.222 dram_write(addr, pat[i]); 1.223 if((val = dram_read(addr)) != pat[i]) { 1.224 - printf("pattern %x failed, got: %x\n", (int)pat[i], val); 1.225 + printf("pattern %x failed, got: %x\n", (unsigned int)pat[i], (unsigned int)val); 1.226 return -1; 1.227 } 1.228 } 1.229 @@ -291,39 +345,50 @@ 1.230 dram_release_ras(RAS2_BIT | RAS3_BIT); 1.231 } 1.232 1.233 -void dram_write(unsigned long addr, unsigned char val) 1.234 +void dram_write(uint32_t addr, unsigned char val) 1.235 { 1.236 + uint32_t row_addr = (addr >> addr_bits) & addr_mask; 1.237 + uint32_t col_addr = addr & addr_mask; 1.238 + unsigned char ras = (addr >> (addr_bits * 2)) ? RAS3_BIT : RAS2_BIT; 1.239 + 1.240 dram_set_data(val); 1.241 dram_set_we(); 1.242 /* set row address */ 1.243 - dram_set_addr((addr >> addr_bits) & addr_mask); 1.244 - dram_assert_ras(RAS2_BIT); 1.245 + dram_set_addr(row_addr); 1.246 + dram_assert_ras(ras); 1.247 /* set column address */ 1.248 - dram_set_addr(addr & addr_mask); 1.249 + dram_set_addr(col_addr); 1.250 dram_assert_cas(); 1.251 - dram_release_ras(RAS2_BIT); 1.252 + dram_release_ras(ras); 1.253 dram_release_cas(); 1.254 dram_release_data(); 1.255 dram_clear_we(); 1.256 } 1.257 1.258 -unsigned char dram_read(unsigned long addr) 1.259 +unsigned char dram_read(uint32_t addr) 1.260 { 1.261 unsigned char val; 1.262 + uint32_t row_addr = (addr >> addr_bits) & addr_mask; 1.263 + uint32_t col_addr = addr & addr_mask; 1.264 + unsigned char ras = (addr >> (addr_bits * 2)) ? RAS3_BIT : RAS2_BIT; 1.265 1.266 dram_clear_we(); 1.267 + /* this is necessary to remove previous data from the lines when no-one is driving them 1.268 + * in case we're trying to detect the presence of a RAS line which doesn't exist 1.269 + */ 1.270 + dram_set_data(0); 1.271 dram_release_data(); 1.272 1.273 /* set row address */ 1.274 - dram_set_addr((addr >> addr_bits) & addr_mask); 1.275 - dram_assert_ras(RAS2_BIT); 1.276 + dram_set_addr(row_addr); 1.277 + dram_assert_ras(ras); 1.278 /* set column address */ 1.279 - dram_set_addr(addr & addr_mask); 1.280 + dram_set_addr(col_addr); 1.281 dram_assert_cas(); 1.282 1.283 val = PINA; 1.284 1.285 - dram_release_ras(RAS2_BIT); 1.286 + dram_release_ras(ras); 1.287 dram_release_cas(); 1.288 1.289 return val;