test_simm30_dram

annotate 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
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@1 2 #include <stdlib.h>
nuclear@0 3 #include <string.h>
nuclear@0 4 #include <ctype.h>
nuclear@0 5 #include <avr/io.h>
nuclear@0 6 #include <avr/interrupt.h>
nuclear@0 7 #include "serial.h"
nuclear@0 8
nuclear@1 9 /* pin assignments:
nuclear@1 10 * A[0,7] data
nuclear@1 11 * B[0,7] A0 - A7
nuclear@1 12 * C[0,3] A8 - A11
nuclear@1 13 * D7 CAS3
nuclear@1 14 * D6 RAS2
nuclear@1 15 * D5 RAS3
nuclear@1 16 */
nuclear@1 17
nuclear@1 18 #define CAS3_BIT 0x80
nuclear@1 19 #define RAS2_BIT 0x40
nuclear@1 20 #define RAS3_BIT 0x20
nuclear@1 21 #define WE_BIT 0x04
nuclear@1 22
nuclear@1 23 void proc_cmd(char *cmd);
nuclear@1 24 void cmd_read(char *buf);
nuclear@1 25 void cmd_write(char *buf);
nuclear@1 26 void cmd_setcfg(char *buf);
nuclear@1 27
nuclear@1 28 void dram_init(void);
nuclear@1 29 void dram_detect(void);
nuclear@1 30 int memtest(unsigned long addr);
nuclear@1 31 void dram_refresh(void);
nuclear@1 32 void dram_write(unsigned long addr, unsigned char val);
nuclear@1 33 unsigned char dram_read(unsigned long addr);
nuclear@0 34
nuclear@0 35 #define MAX_INPUT_SIZE 128
nuclear@0 36 static char input[MAX_INPUT_SIZE];
nuclear@0 37 static unsigned char inp_cidx;
nuclear@0 38
nuclear@1 39 /* SIMM access config */
nuclear@1 40 static int addr_bits;
nuclear@1 41 static unsigned long addr_mask;
nuclear@1 42 static int ras_lines = 1;
nuclear@1 43 static long memsize_kb; /* derived from the above */
nuclear@1 44
nuclear@1 45
nuclear@0 46 int main(void)
nuclear@0 47 {
nuclear@1 48 dram_init();
nuclear@0 49 init_serial(38400);
nuclear@0 50 sei();
nuclear@0 51
nuclear@1 52 printf("Detecting memory ...\n");
nuclear@1 53 dram_detect();
nuclear@1 54
nuclear@1 55 memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines;
nuclear@1 56
nuclear@1 57 printf("Address lines: %d\n", addr_bits);
nuclear@1 58 printf("RAS lines: %d\n", ras_lines);
nuclear@1 59 printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb);
nuclear@1 60 fputs("> ", stdout);
nuclear@0 61
nuclear@0 62 for(;;) {
nuclear@0 63 while(have_input()) {
nuclear@0 64 int c = getchar();
nuclear@0 65 putchar(c);
nuclear@0 66
nuclear@0 67 if(c == '\r' || c == '\n') {
nuclear@0 68 input[inp_cidx] = 0;
nuclear@1 69 proc_cmd(input);
nuclear@0 70 inp_cidx = 0;
nuclear@1 71
nuclear@1 72 fputs("> ", stdout);
nuclear@0 73 } else if(inp_cidx < sizeof input - 1) {
nuclear@0 74 input[inp_cidx++] = c;
nuclear@0 75 }
nuclear@0 76 }
nuclear@1 77
nuclear@1 78 dram_refresh();
nuclear@1 79 }
nuclear@1 80 return 0;
nuclear@1 81 }
nuclear@1 82
nuclear@1 83 void proc_cmd(char *cmd)
nuclear@1 84 {
nuclear@1 85 switch(cmd[0]) {
nuclear@1 86 case 'w':
nuclear@1 87 cmd_write(cmd + 1);
nuclear@1 88 break;
nuclear@1 89
nuclear@1 90 case 'r':
nuclear@1 91 cmd_read(cmd + 1);
nuclear@1 92 break;
nuclear@1 93
nuclear@1 94 case 's':
nuclear@1 95 cmd_setcfg(cmd + 1);
nuclear@1 96 break;
nuclear@1 97
nuclear@1 98 case 'h':
nuclear@1 99 printf("commands:\n");
nuclear@1 100 printf(" w <addr> <value> - write byte to address\n");
nuclear@1 101 printf(" r <addr> - read byte from address\n");
nuclear@1 102 printf(" s <addr_bits|ras_lines> <value>\n");
nuclear@1 103 printf(" h - help\n");
nuclear@1 104 break;
nuclear@1 105 }
nuclear@1 106 }
nuclear@1 107
nuclear@1 108 void cmd_read(char *buf)
nuclear@1 109 {
nuclear@1 110 char *endp;
nuclear@1 111 unsigned long addr;
nuclear@1 112 unsigned char data;
nuclear@1 113
nuclear@1 114 addr = strtol(buf, &endp, 0);
nuclear@1 115 if(endp == buf) {
nuclear@1 116 fprintf(stderr, "invalid argument to write command: %s\n", buf);
nuclear@1 117 return;
nuclear@1 118 }
nuclear@1 119 buf = endp;
nuclear@1 120
nuclear@1 121 data = dram_read(addr);
nuclear@1 122 printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data);
nuclear@1 123 }
nuclear@1 124
nuclear@1 125 void cmd_write(char *buf)
nuclear@1 126 {
nuclear@1 127 char *endp;
nuclear@1 128 unsigned long addr;
nuclear@1 129 unsigned char data;
nuclear@1 130
nuclear@1 131 addr = strtol(buf, &endp, 0);
nuclear@1 132 if(endp == buf) {
nuclear@1 133 fprintf(stderr, "invalid address argument to read command: %s\n", buf);
nuclear@1 134 return;
nuclear@1 135 }
nuclear@1 136 buf = endp;
nuclear@1 137
nuclear@1 138 data = strtol(buf, &endp, 0);
nuclear@1 139 if(endp == buf) {
nuclear@1 140 fprintf(stderr, "invalid data argument to read command: %s\n", buf);
nuclear@1 141 return;
nuclear@1 142 }
nuclear@1 143 buf = endp;
nuclear@1 144
nuclear@1 145 dram_write(addr, data);
nuclear@1 146 printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data);
nuclear@1 147 }
nuclear@1 148
nuclear@1 149 void cmd_setcfg(char *buf)
nuclear@1 150 {
nuclear@1 151 char *endp;
nuclear@1 152 char *name, *valstr;
nuclear@1 153 long value;
nuclear@1 154
nuclear@1 155 name = buf;
nuclear@1 156 while(*name && isspace(*name)) ++name;
nuclear@1 157 if(!*name) {
nuclear@1 158 fprintf(stderr, "invalid or missing variable name\n");
nuclear@1 159 return;
nuclear@1 160 }
nuclear@1 161 endp = name;
nuclear@1 162 while(*endp && !isspace(*endp)) ++endp;
nuclear@1 163 *endp = 0;
nuclear@1 164
nuclear@1 165 valstr = endp + 1;
nuclear@1 166 value = strtol(valstr, &endp, 0);
nuclear@1 167 if(endp == valstr) {
nuclear@1 168 fprintf(stderr, "invalid or missing variable value: %s\n", valstr);
nuclear@1 169 return;
nuclear@1 170 }
nuclear@1 171
nuclear@1 172 if(strcmp(name, "addr_bits") == 0) {
nuclear@1 173 if(value > 0 && value <= 12) {
nuclear@1 174 addr_bits = value;
nuclear@1 175 printf("Address bits: %ld\n", value);
nuclear@1 176 } else {
nuclear@1 177 fprintf(stderr, "invalid address bits value: %ld\n", value);
nuclear@1 178 }
nuclear@1 179 } else if(strcmp(name, "ras_lines") == 0) {
nuclear@1 180 if(value > 0 && value <= 2) {
nuclear@1 181 ras_lines = value;
nuclear@1 182 printf("RAS lines: %d\n", ras_lines);
nuclear@1 183 } else {
nuclear@1 184 fprintf(stderr, "invalid RAS lines value: %ld\n", value);
nuclear@1 185 }
nuclear@1 186 } else {
nuclear@1 187 fprintf(stderr, "unknown variable: %s\n", name);
nuclear@1 188 }
nuclear@1 189 }
nuclear@1 190
nuclear@1 191 void dram_set_data(unsigned char val)
nuclear@1 192 {
nuclear@1 193 DDRA = 0xff;
nuclear@1 194 PORTA = val;
nuclear@1 195 }
nuclear@1 196
nuclear@1 197 void dram_release_data(void)
nuclear@1 198 {
nuclear@1 199 DDRA = 0;
nuclear@1 200 PORTA = 0;
nuclear@1 201 }
nuclear@1 202
nuclear@1 203 void dram_set_addr(unsigned long addr)
nuclear@1 204 {
nuclear@1 205 PORTB = addr & 0xff;
nuclear@1 206 PORTC = (addr >> 8) & 3;
nuclear@1 207 }
nuclear@1 208
nuclear@1 209 void dram_assert_cas(void)
nuclear@1 210 {
nuclear@1 211 PORTD &= ~CAS3_BIT;
nuclear@1 212 }
nuclear@1 213
nuclear@1 214 void dram_release_cas(void)
nuclear@1 215 {
nuclear@1 216 PORTD |= CAS3_BIT;
nuclear@1 217 }
nuclear@1 218
nuclear@1 219 void dram_assert_ras(unsigned char bits)
nuclear@1 220 {
nuclear@1 221 PORTD &= ~bits;
nuclear@1 222 }
nuclear@1 223
nuclear@1 224 void dram_release_ras(unsigned char bits)
nuclear@1 225 {
nuclear@1 226 PORTD |= bits;
nuclear@1 227 }
nuclear@1 228
nuclear@1 229 void dram_set_we(void)
nuclear@1 230 {
nuclear@1 231 PORTD &= ~WE_BIT;
nuclear@1 232 }
nuclear@1 233
nuclear@1 234 void dram_clear_we(void)
nuclear@1 235 {
nuclear@1 236 PORTD |= WE_BIT;
nuclear@1 237 }
nuclear@1 238
nuclear@1 239 void dram_init(void)
nuclear@1 240 {
nuclear@1 241 DDRA = 0; /* port A is the data bus */
nuclear@1 242 PORTA = 0; /* no pullups when A is input */
nuclear@1 243 DDRB = 0xff; /* port B is A0-A7 */
nuclear@1 244 DDRC = 0xff; /* port C (low nibble) is A8-A11 */
nuclear@1 245 DDRD = 0xff; /* port D are the control lines CAS/RAS/WR */
nuclear@1 246
nuclear@1 247 PORTD = 0xff; /* deassert all control signals */
nuclear@1 248 }
nuclear@1 249
nuclear@1 250 void dram_detect(void)
nuclear@1 251 {
nuclear@1 252 /* detect how many address bits we've got */
nuclear@1 253 addr_bits = 12;
nuclear@1 254 while(addr_bits > 8) {
nuclear@1 255 printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1));
nuclear@1 256 addr_mask = (1 << (unsigned long)addr_bits) - 1;
nuclear@1 257 if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) {
nuclear@1 258 break;
nuclear@1 259 }
nuclear@1 260 --addr_bits;
nuclear@1 261 }
nuclear@1 262 if(addr_bits < 1) {
nuclear@1 263 fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n");
nuclear@1 264 return;
nuclear@1 265 }
nuclear@1 266 }
nuclear@1 267
nuclear@1 268 int memtest(unsigned long addr)
nuclear@1 269 {
nuclear@1 270 int i;
nuclear@1 271 unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 };
nuclear@1 272 unsigned char val;
nuclear@1 273
nuclear@1 274 printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines);
nuclear@1 275
nuclear@1 276 for(i=0; i<sizeof pat / sizeof *pat; i++) {
nuclear@1 277 dram_write(addr, pat[i]);
nuclear@1 278 if((val = dram_read(addr)) != pat[i]) {
nuclear@1 279 printf("pattern %x failed, got: %x\n", (int)pat[i], val);
nuclear@1 280 return -1;
nuclear@1 281 }
nuclear@0 282 }
nuclear@0 283 return 0;
nuclear@0 284 }
nuclear@0 285
nuclear@1 286 void dram_refresh(void)
nuclear@0 287 {
nuclear@1 288 dram_assert_cas();
nuclear@1 289 dram_assert_ras(RAS2_BIT | RAS3_BIT);
nuclear@1 290 dram_release_cas();
nuclear@1 291 dram_release_ras(RAS2_BIT | RAS3_BIT);
nuclear@0 292 }
nuclear@1 293
nuclear@1 294 void dram_write(unsigned long addr, unsigned char val)
nuclear@1 295 {
nuclear@1 296 dram_set_data(val);
nuclear@1 297 dram_set_we();
nuclear@1 298 /* set row address */
nuclear@1 299 dram_set_addr((addr >> addr_bits) & addr_mask);
nuclear@1 300 dram_assert_ras(RAS2_BIT);
nuclear@1 301 /* set column address */
nuclear@1 302 dram_set_addr(addr & addr_mask);
nuclear@1 303 dram_assert_cas();
nuclear@1 304 dram_release_ras(RAS2_BIT);
nuclear@1 305 dram_release_cas();
nuclear@1 306 dram_release_data();
nuclear@1 307 dram_clear_we();
nuclear@1 308 }
nuclear@1 309
nuclear@1 310 unsigned char dram_read(unsigned long addr)
nuclear@1 311 {
nuclear@1 312 unsigned char val;
nuclear@1 313
nuclear@1 314 dram_clear_we();
nuclear@1 315 dram_release_data();
nuclear@1 316
nuclear@1 317 /* set row address */
nuclear@1 318 dram_set_addr((addr >> addr_bits) & addr_mask);
nuclear@1 319 dram_assert_ras(RAS2_BIT);
nuclear@1 320 /* set column address */
nuclear@1 321 dram_set_addr(addr & addr_mask);
nuclear@1 322 dram_assert_cas();
nuclear@1 323
nuclear@1 324 val = PINA;
nuclear@1 325
nuclear@1 326 dram_release_ras(RAS2_BIT);
nuclear@1 327 dram_release_cas();
nuclear@1 328
nuclear@1 329 return val;
nuclear@1 330 }