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 +}