# HG changeset patch # User John Tsiombikas # Date 1489016431 -7200 # Node ID 42d26388b709439be1ef3c37d3c309e77e73442a # Parent 318a758ede823de15afe508708976a7abe095819 memory detection works diff -r 318a758ede82 -r 42d26388b709 test.c --- a/test.c Wed Mar 08 09:05:19 2017 +0200 +++ b/test.c Thu Mar 09 01:40:31 2017 +0200 @@ -1,9 +1,13 @@ +#define F_CPU XTAL + #include #include #include #include +#include #include #include +#include #include "serial.h" /* pin assignments: @@ -24,13 +28,15 @@ void cmd_read(char *buf); void cmd_write(char *buf); void cmd_setcfg(char *buf); +void cmd_test(char *buf); +void cmd_detect(void); void dram_init(void); void dram_detect(void); -int memtest(unsigned long addr); +int memtest(uint32_t addr); void dram_refresh(void); -void dram_write(unsigned long addr, unsigned char val); -unsigned char dram_read(unsigned long addr); +void dram_write(uint32_t addr, unsigned char val); +unsigned char dram_read(uint32_t addr); #define MAX_INPUT_SIZE 128 static char input[MAX_INPUT_SIZE]; @@ -38,29 +44,24 @@ /* SIMM access config */ static int addr_bits; -static unsigned long addr_mask; +static uint32_t addr_mask; static int ras_lines = 1; static long memsize_kb; /* derived from the above */ - int main(void) { dram_init(); init_serial(38400); sei(); - printf("Detecting memory ...\n"); - dram_detect(); + printf("\n72pin SIMM DRAM tester by John Tsiombikas \n"); - memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines; + cmd_detect(); - printf("Address lines: %d\n", addr_bits); - printf("RAS lines: %d\n", ras_lines); - printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb); fputs("> ", stdout); for(;;) { - while(have_input()) { + if(have_input()) { int c = getchar(); putchar(c); @@ -95,11 +96,21 @@ cmd_setcfg(cmd + 1); break; + case 't': + cmd_test(cmd + 1); + break; + + case 'd': + cmd_detect(); + break; + case 'h': printf("commands:\n"); printf(" w - write byte to address\n"); printf(" r - read byte from address\n"); printf(" s \n"); + printf(" t - test address\n"); + printf(" d - detect DRAM\n"); printf(" h - help\n"); break; } @@ -108,7 +119,7 @@ void cmd_read(char *buf) { char *endp; - unsigned long addr; + uint32_t addr; unsigned char data; addr = strtol(buf, &endp, 0); @@ -119,13 +130,13 @@ buf = endp; data = dram_read(addr); - printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); + printf("%04lx: %02x (%u)\n", (unsigned long)addr, (unsigned int)data, (unsigned int)data); } void cmd_write(char *buf) { char *endp; - unsigned long addr; + uint32_t addr; unsigned char data; addr = strtol(buf, &endp, 0); @@ -143,7 +154,7 @@ buf = endp; dram_write(addr, data); - printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); + printf("%04lx: %02x (%u)\n", (unsigned long)addr, (unsigned int)data, (unsigned int)data); } void cmd_setcfg(char *buf) @@ -172,7 +183,8 @@ if(strcmp(name, "addr_bits") == 0) { if(value > 0 && value <= 12) { addr_bits = value; - printf("Address bits: %ld\n", value); + addr_mask = ((uint32_t)1 << addr_bits) - 1; + printf("Address bits: %ld (mask: %lx)\n", value, (unsigned long)addr_mask); } else { fprintf(stderr, "invalid address bits value: %ld\n", value); } @@ -188,6 +200,36 @@ } } +void cmd_test(char *buf) +{ + char *endp; + uint32_t addr; + + addr = strtol(buf, &endp, 0); + if(endp == buf) { + fprintf(stderr, "invalid argument to test command: %s\n", buf); + return; + } + + if(memtest(addr) == 0) { + printf("success!\n"); + } +} + + +void cmd_detect(void) +{ + printf("Detecting memory ...\n"); + dram_detect(); + + memsize_kb = ((uint32_t)1 << (addr_bits * 2)) * 4 * ras_lines; + + printf("Address lines: %d\n", addr_bits); + printf("RAS lines: %d\n", ras_lines); + printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 20, memsize_kb >> 10); +} + + void dram_set_data(unsigned char val) { DDRA = 0xff; @@ -245,16 +287,21 @@ DDRD = 0xff; /* port D are the control lines CAS/RAS/WR */ PORTD = 0xff; /* deassert all control signals */ + + /* it seems like nothing works until we do one refresh cycle... */ + dram_refresh(); } void dram_detect(void) { + uint32_t addr = 0; + /* detect how many address bits we've got */ addr_bits = 12; while(addr_bits > 8) { - printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1)); - addr_mask = (1 << (unsigned long)addr_bits) - 1; - if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) { + addr_mask = ((uint32_t)1 << (uint32_t)addr_bits) - 1; + addr = ((uint32_t)1 << ((uint32_t)addr_bits * 2)) - 1; + if(memtest(addr) == 0) { break; } --addr_bits; @@ -263,20 +310,27 @@ fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n"); return; } + + /* now detect if there's a second ras pair */ + ++addr; /* addr was already the highest of the first bank, see if there's a second */ + ras_lines = 2; + if(memtest(addr) != 0) { + ras_lines = 1; + } } -int memtest(unsigned long addr) +int memtest(uint32_t addr) { int i; unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 }; unsigned char val; - printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines); + printf("testing address: %lx (a:%d,r:%d)\n", (unsigned long)addr, addr_bits, ras_lines); for(i=0; i> addr_bits) & addr_mask; + uint32_t col_addr = addr & addr_mask; + unsigned char ras = (addr >> (addr_bits * 2)) ? RAS3_BIT : RAS2_BIT; + dram_set_data(val); dram_set_we(); /* set row address */ - dram_set_addr((addr >> addr_bits) & addr_mask); - dram_assert_ras(RAS2_BIT); + dram_set_addr(row_addr); + dram_assert_ras(ras); /* set column address */ - dram_set_addr(addr & addr_mask); + dram_set_addr(col_addr); dram_assert_cas(); - dram_release_ras(RAS2_BIT); + dram_release_ras(ras); dram_release_cas(); dram_release_data(); dram_clear_we(); } -unsigned char dram_read(unsigned long addr) +unsigned char dram_read(uint32_t addr) { unsigned char val; + uint32_t row_addr = (addr >> addr_bits) & addr_mask; + uint32_t col_addr = addr & addr_mask; + unsigned char ras = (addr >> (addr_bits * 2)) ? RAS3_BIT : RAS2_BIT; dram_clear_we(); + /* this is necessary to remove previous data from the lines when no-one is driving them + * in case we're trying to detect the presence of a RAS line which doesn't exist + */ + dram_set_data(0); dram_release_data(); /* set row address */ - dram_set_addr((addr >> addr_bits) & addr_mask); - dram_assert_ras(RAS2_BIT); + dram_set_addr(row_addr); + dram_assert_ras(ras); /* set column address */ - dram_set_addr(addr & addr_mask); + dram_set_addr(col_addr); dram_assert_cas(); val = PINA; - dram_release_ras(RAS2_BIT); + dram_release_ras(ras); dram_release_cas(); return val;