nuclear@0: #include nuclear@1: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include nuclear@0: #include "serial.h" nuclear@0: nuclear@1: /* pin assignments: nuclear@1: * A[0,7] data nuclear@1: * B[0,7] A0 - A7 nuclear@1: * C[0,3] A8 - A11 nuclear@1: * D7 CAS3 nuclear@1: * D6 RAS2 nuclear@1: * D5 RAS3 nuclear@1: */ nuclear@1: nuclear@1: #define CAS3_BIT 0x80 nuclear@1: #define RAS2_BIT 0x40 nuclear@1: #define RAS3_BIT 0x20 nuclear@1: #define WE_BIT 0x04 nuclear@1: nuclear@1: void proc_cmd(char *cmd); nuclear@1: void cmd_read(char *buf); nuclear@1: void cmd_write(char *buf); nuclear@1: void cmd_setcfg(char *buf); nuclear@1: nuclear@1: void dram_init(void); nuclear@1: void dram_detect(void); nuclear@1: int memtest(unsigned long addr); nuclear@1: void dram_refresh(void); nuclear@1: void dram_write(unsigned long addr, unsigned char val); nuclear@1: unsigned char dram_read(unsigned long addr); nuclear@0: nuclear@0: #define MAX_INPUT_SIZE 128 nuclear@0: static char input[MAX_INPUT_SIZE]; nuclear@0: static unsigned char inp_cidx; nuclear@0: nuclear@1: /* SIMM access config */ nuclear@1: static int addr_bits; nuclear@1: static unsigned long addr_mask; nuclear@1: static int ras_lines = 1; nuclear@1: static long memsize_kb; /* derived from the above */ nuclear@1: nuclear@1: nuclear@0: int main(void) nuclear@0: { nuclear@1: dram_init(); nuclear@0: init_serial(38400); nuclear@0: sei(); nuclear@0: nuclear@1: printf("Detecting memory ...\n"); nuclear@1: dram_detect(); nuclear@1: nuclear@1: memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines; nuclear@1: nuclear@1: printf("Address lines: %d\n", addr_bits); nuclear@1: printf("RAS lines: %d\n", ras_lines); nuclear@1: printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb); nuclear@1: fputs("> ", stdout); nuclear@0: nuclear@0: for(;;) { nuclear@0: while(have_input()) { nuclear@0: int c = getchar(); nuclear@0: putchar(c); nuclear@0: nuclear@0: if(c == '\r' || c == '\n') { nuclear@0: input[inp_cidx] = 0; nuclear@1: proc_cmd(input); nuclear@0: inp_cidx = 0; nuclear@1: nuclear@1: fputs("> ", stdout); nuclear@0: } else if(inp_cidx < sizeof input - 1) { nuclear@0: input[inp_cidx++] = c; nuclear@0: } nuclear@0: } nuclear@1: nuclear@1: dram_refresh(); nuclear@1: } nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: void proc_cmd(char *cmd) nuclear@1: { nuclear@1: switch(cmd[0]) { nuclear@1: case 'w': nuclear@1: cmd_write(cmd + 1); nuclear@1: break; nuclear@1: nuclear@1: case 'r': nuclear@1: cmd_read(cmd + 1); nuclear@1: break; nuclear@1: nuclear@1: case 's': nuclear@1: cmd_setcfg(cmd + 1); nuclear@1: break; nuclear@1: nuclear@1: case 'h': nuclear@1: printf("commands:\n"); nuclear@1: printf(" w - write byte to address\n"); nuclear@1: printf(" r - read byte from address\n"); nuclear@1: printf(" s \n"); nuclear@1: printf(" h - help\n"); nuclear@1: break; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void cmd_read(char *buf) nuclear@1: { nuclear@1: char *endp; nuclear@1: unsigned long addr; nuclear@1: unsigned char data; nuclear@1: nuclear@1: addr = strtol(buf, &endp, 0); nuclear@1: if(endp == buf) { nuclear@1: fprintf(stderr, "invalid argument to write command: %s\n", buf); nuclear@1: return; nuclear@1: } nuclear@1: buf = endp; nuclear@1: nuclear@1: data = dram_read(addr); nuclear@1: printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); nuclear@1: } nuclear@1: nuclear@1: void cmd_write(char *buf) nuclear@1: { nuclear@1: char *endp; nuclear@1: unsigned long addr; nuclear@1: unsigned char data; nuclear@1: nuclear@1: addr = strtol(buf, &endp, 0); nuclear@1: if(endp == buf) { nuclear@1: fprintf(stderr, "invalid address argument to read command: %s\n", buf); nuclear@1: return; nuclear@1: } nuclear@1: buf = endp; nuclear@1: nuclear@1: data = strtol(buf, &endp, 0); nuclear@1: if(endp == buf) { nuclear@1: fprintf(stderr, "invalid data argument to read command: %s\n", buf); nuclear@1: return; nuclear@1: } nuclear@1: buf = endp; nuclear@1: nuclear@1: dram_write(addr, data); nuclear@1: printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data); nuclear@1: } nuclear@1: nuclear@1: void cmd_setcfg(char *buf) nuclear@1: { nuclear@1: char *endp; nuclear@1: char *name, *valstr; nuclear@1: long value; nuclear@1: nuclear@1: name = buf; nuclear@1: while(*name && isspace(*name)) ++name; nuclear@1: if(!*name) { nuclear@1: fprintf(stderr, "invalid or missing variable name\n"); nuclear@1: return; nuclear@1: } nuclear@1: endp = name; nuclear@1: while(*endp && !isspace(*endp)) ++endp; nuclear@1: *endp = 0; nuclear@1: nuclear@1: valstr = endp + 1; nuclear@1: value = strtol(valstr, &endp, 0); nuclear@1: if(endp == valstr) { nuclear@1: fprintf(stderr, "invalid or missing variable value: %s\n", valstr); nuclear@1: return; nuclear@1: } nuclear@1: nuclear@1: if(strcmp(name, "addr_bits") == 0) { nuclear@1: if(value > 0 && value <= 12) { nuclear@1: addr_bits = value; nuclear@1: printf("Address bits: %ld\n", value); nuclear@1: } else { nuclear@1: fprintf(stderr, "invalid address bits value: %ld\n", value); nuclear@1: } nuclear@1: } else if(strcmp(name, "ras_lines") == 0) { nuclear@1: if(value > 0 && value <= 2) { nuclear@1: ras_lines = value; nuclear@1: printf("RAS lines: %d\n", ras_lines); nuclear@1: } else { nuclear@1: fprintf(stderr, "invalid RAS lines value: %ld\n", value); nuclear@1: } nuclear@1: } else { nuclear@1: fprintf(stderr, "unknown variable: %s\n", name); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void dram_set_data(unsigned char val) nuclear@1: { nuclear@1: DDRA = 0xff; nuclear@1: PORTA = val; nuclear@1: } nuclear@1: nuclear@1: void dram_release_data(void) nuclear@1: { nuclear@1: DDRA = 0; nuclear@1: PORTA = 0; nuclear@1: } nuclear@1: nuclear@1: void dram_set_addr(unsigned long addr) nuclear@1: { nuclear@1: PORTB = addr & 0xff; nuclear@1: PORTC = (addr >> 8) & 3; nuclear@1: } nuclear@1: nuclear@1: void dram_assert_cas(void) nuclear@1: { nuclear@1: PORTD &= ~CAS3_BIT; nuclear@1: } nuclear@1: nuclear@1: void dram_release_cas(void) nuclear@1: { nuclear@1: PORTD |= CAS3_BIT; nuclear@1: } nuclear@1: nuclear@1: void dram_assert_ras(unsigned char bits) nuclear@1: { nuclear@1: PORTD &= ~bits; nuclear@1: } nuclear@1: nuclear@1: void dram_release_ras(unsigned char bits) nuclear@1: { nuclear@1: PORTD |= bits; nuclear@1: } nuclear@1: nuclear@1: void dram_set_we(void) nuclear@1: { nuclear@1: PORTD &= ~WE_BIT; nuclear@1: } nuclear@1: nuclear@1: void dram_clear_we(void) nuclear@1: { nuclear@1: PORTD |= WE_BIT; nuclear@1: } nuclear@1: nuclear@1: void dram_init(void) nuclear@1: { nuclear@1: DDRA = 0; /* port A is the data bus */ nuclear@1: PORTA = 0; /* no pullups when A is input */ nuclear@1: DDRB = 0xff; /* port B is A0-A7 */ nuclear@1: DDRC = 0xff; /* port C (low nibble) is A8-A11 */ nuclear@1: DDRD = 0xff; /* port D are the control lines CAS/RAS/WR */ nuclear@1: nuclear@1: PORTD = 0xff; /* deassert all control signals */ nuclear@1: } nuclear@1: nuclear@1: void dram_detect(void) nuclear@1: { nuclear@1: /* detect how many address bits we've got */ nuclear@1: addr_bits = 12; nuclear@1: while(addr_bits > 8) { nuclear@1: printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1)); nuclear@1: addr_mask = (1 << (unsigned long)addr_bits) - 1; nuclear@1: if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) { nuclear@1: break; nuclear@1: } nuclear@1: --addr_bits; nuclear@1: } nuclear@1: if(addr_bits < 1) { nuclear@1: fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n"); nuclear@1: return; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: int memtest(unsigned long addr) nuclear@1: { nuclear@1: int i; nuclear@1: unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 }; nuclear@1: unsigned char val; nuclear@1: nuclear@1: printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines); nuclear@1: nuclear@1: for(i=0; i> addr_bits) & addr_mask); nuclear@1: dram_assert_ras(RAS2_BIT); nuclear@1: /* set column address */ nuclear@1: dram_set_addr(addr & addr_mask); nuclear@1: dram_assert_cas(); nuclear@1: dram_release_ras(RAS2_BIT); nuclear@1: dram_release_cas(); nuclear@1: dram_release_data(); nuclear@1: dram_clear_we(); nuclear@1: } nuclear@1: nuclear@1: unsigned char dram_read(unsigned long addr) nuclear@1: { nuclear@1: unsigned char val; nuclear@1: nuclear@1: dram_clear_we(); nuclear@1: dram_release_data(); nuclear@1: nuclear@1: /* set row address */ nuclear@1: dram_set_addr((addr >> addr_bits) & addr_mask); nuclear@1: dram_assert_ras(RAS2_BIT); nuclear@1: /* set column address */ nuclear@1: dram_set_addr(addr & addr_mask); nuclear@1: dram_assert_cas(); nuclear@1: nuclear@1: val = PINA; nuclear@1: nuclear@1: dram_release_ras(RAS2_BIT); nuclear@1: dram_release_cas(); nuclear@1: nuclear@1: return val; nuclear@1: }