avr_test_simm72_dram

changeset 1:318a758ede82

ops
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 08 Mar 2017 09:05:19 +0200
parents c47d05df0667
children 42d26388b709
files Makefile test.c
diffstat 2 files changed, 295 insertions(+), 10 deletions(-) [+]
line diff
     1.1 --- a/Makefile	Tue Mar 07 23:50:45 2017 +0200
     1.2 +++ b/Makefile	Wed Mar 08 09:05:19 2017 +0200
     1.3 @@ -1,6 +1,6 @@
     1.4  src = $(wildcard *.c)
     1.5  obj = $(src:.c=.o)
     1.6 -bin = test_ftdi
     1.7 +bin = test_simm72_dram
     1.8  hex = $(bin).hex
     1.9  eep = $(bin).eep
    1.10  
     2.1 --- a/test.c	Tue Mar 07 23:50:45 2017 +0200
     2.2 +++ b/test.c	Wed Mar 08 09:05:19 2017 +0200
     2.3 @@ -1,22 +1,63 @@
     2.4  #include <stdio.h>
     2.5 +#include <stdlib.h>
     2.6  #include <string.h>
     2.7  #include <ctype.h>
     2.8  #include <avr/io.h>
     2.9  #include <avr/interrupt.h>
    2.10  #include "serial.h"
    2.11  
    2.12 -void procmd(const char *cmd);
    2.13 +/* pin assignments:
    2.14 + * A[0,7]	data
    2.15 + * B[0,7]	A0 - A7
    2.16 + * C[0,3]	A8 - A11
    2.17 + * D7		CAS3
    2.18 + * D6		RAS2
    2.19 + * D5		RAS3
    2.20 + */
    2.21 +
    2.22 +#define CAS3_BIT	0x80
    2.23 +#define RAS2_BIT	0x40
    2.24 +#define RAS3_BIT	0x20
    2.25 +#define WE_BIT		0x04
    2.26 +
    2.27 +void proc_cmd(char *cmd);
    2.28 +void cmd_read(char *buf);
    2.29 +void cmd_write(char *buf);
    2.30 +void cmd_setcfg(char *buf);
    2.31 +
    2.32 +void dram_init(void);
    2.33 +void dram_detect(void);
    2.34 +int memtest(unsigned long addr);
    2.35 +void dram_refresh(void);
    2.36 +void dram_write(unsigned long addr, unsigned char val);
    2.37 +unsigned char dram_read(unsigned long addr);
    2.38  
    2.39  #define MAX_INPUT_SIZE	128
    2.40  static char input[MAX_INPUT_SIZE];
    2.41  static unsigned char inp_cidx;
    2.42  
    2.43 +/* SIMM access config */
    2.44 +static int addr_bits;
    2.45 +static unsigned long addr_mask;
    2.46 +static int ras_lines = 1;
    2.47 +static long memsize_kb;	/* derived from the above */
    2.48 +
    2.49 +
    2.50  int main(void)
    2.51  {
    2.52 +	dram_init();
    2.53  	init_serial(38400);
    2.54  	sei();
    2.55  
    2.56 -	printf("welcome!\n");
    2.57 +	printf("Detecting memory ...\n");
    2.58 +	dram_detect();
    2.59 +
    2.60 +	memsize_kb = (1 << (addr_bits * 2)) * 4 * ras_lines;
    2.61 +
    2.62 +	printf("Address lines: %d\n", addr_bits);
    2.63 +	printf("RAS lines: %d\n", ras_lines);
    2.64 +	printf("Memory size: %ldmb (%ldkb)\n", memsize_kb >> 10, memsize_kb);
    2.65 +	fputs("> ", stdout);
    2.66  
    2.67  	for(;;) {
    2.68  		while(have_input()) {
    2.69 @@ -25,21 +66,265 @@
    2.70  
    2.71  			if(c == '\r' || c == '\n') {
    2.72  				input[inp_cidx] = 0;
    2.73 -				procmd(input);
    2.74 +				proc_cmd(input);
    2.75  				inp_cidx = 0;
    2.76 +
    2.77 +				fputs("> ", stdout);
    2.78  			} else if(inp_cidx < sizeof input - 1) {
    2.79  				input[inp_cidx++] = c;
    2.80  			}
    2.81  		}
    2.82 +
    2.83 +		dram_refresh();
    2.84 +	}
    2.85 +	return 0;
    2.86 +}
    2.87 +
    2.88 +void proc_cmd(char *cmd)
    2.89 +{
    2.90 +	switch(cmd[0]) {
    2.91 +	case 'w':
    2.92 +		cmd_write(cmd + 1);
    2.93 +		break;
    2.94 +
    2.95 +	case 'r':
    2.96 +		cmd_read(cmd + 1);
    2.97 +		break;
    2.98 +
    2.99 +	case 's':
   2.100 +		cmd_setcfg(cmd + 1);
   2.101 +		break;
   2.102 +
   2.103 +	case 'h':
   2.104 +		printf("commands:\n");
   2.105 +		printf(" w <addr> <value> - write byte to address\n");
   2.106 +		printf(" r <addr> - read byte from address\n");
   2.107 +		printf(" s <addr_bits|ras_lines> <value>\n");
   2.108 +		printf(" h - help\n");
   2.109 +		break;
   2.110 +	}
   2.111 +}
   2.112 +
   2.113 +void cmd_read(char *buf)
   2.114 +{
   2.115 +	char *endp;
   2.116 +	unsigned long addr;
   2.117 +	unsigned char data;
   2.118 +
   2.119 +	addr = strtol(buf, &endp, 0);
   2.120 +	if(endp == buf) {
   2.121 +		fprintf(stderr, "invalid argument to write command: %s\n", buf);
   2.122 +		return;
   2.123 +	}
   2.124 +	buf = endp;
   2.125 +
   2.126 +	data = dram_read(addr);
   2.127 +	printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data);
   2.128 +}
   2.129 +
   2.130 +void cmd_write(char *buf)
   2.131 +{
   2.132 +	char *endp;
   2.133 +	unsigned long addr;
   2.134 +	unsigned char data;
   2.135 +
   2.136 +	addr = strtol(buf, &endp, 0);
   2.137 +	if(endp == buf) {
   2.138 +		fprintf(stderr, "invalid address argument to read command: %s\n", buf);
   2.139 +		return;
   2.140 +	}
   2.141 +	buf = endp;
   2.142 +
   2.143 +	data = strtol(buf, &endp, 0);
   2.144 +	if(endp == buf) {
   2.145 +		fprintf(stderr, "invalid data argument to read command: %s\n", buf);
   2.146 +		return;
   2.147 +	}
   2.148 +	buf = endp;
   2.149 +
   2.150 +	dram_write(addr, data);
   2.151 +	printf("%04lx: %02x (%u)\n", addr, (unsigned int)data, (unsigned int)data);
   2.152 +}
   2.153 +
   2.154 +void cmd_setcfg(char *buf)
   2.155 +{
   2.156 +	char *endp;
   2.157 +	char *name, *valstr;
   2.158 +	long value;
   2.159 +
   2.160 +	name = buf;
   2.161 +	while(*name && isspace(*name)) ++name;
   2.162 +	if(!*name) {
   2.163 +		fprintf(stderr, "invalid or missing variable name\n");
   2.164 +		return;
   2.165 +	}
   2.166 +	endp = name;
   2.167 +	while(*endp && !isspace(*endp)) ++endp;
   2.168 +	*endp = 0;
   2.169 +
   2.170 +	valstr = endp + 1;
   2.171 +	value = strtol(valstr, &endp, 0);
   2.172 +	if(endp == valstr) {
   2.173 +		fprintf(stderr, "invalid or missing variable value: %s\n", valstr);
   2.174 +		return;
   2.175 +	}
   2.176 +
   2.177 +	if(strcmp(name, "addr_bits") == 0) {
   2.178 +		if(value > 0 && value <= 12) {
   2.179 +			addr_bits = value;
   2.180 +			printf("Address bits: %ld\n", value);
   2.181 +		} else {
   2.182 +			fprintf(stderr, "invalid address bits value: %ld\n", value);
   2.183 +		}
   2.184 +	} else if(strcmp(name, "ras_lines") == 0) {
   2.185 +		if(value > 0 && value <= 2) {
   2.186 +			ras_lines = value;
   2.187 +			printf("RAS lines: %d\n", ras_lines);
   2.188 +		} else {
   2.189 +			fprintf(stderr, "invalid RAS lines value: %ld\n", value);
   2.190 +		}
   2.191 +	} else {
   2.192 +		fprintf(stderr, "unknown variable: %s\n", name);
   2.193 +	}
   2.194 +}
   2.195 +
   2.196 +void dram_set_data(unsigned char val)
   2.197 +{
   2.198 +	DDRA = 0xff;
   2.199 +	PORTA = val;
   2.200 +}
   2.201 +
   2.202 +void dram_release_data(void)
   2.203 +{
   2.204 +	DDRA = 0;
   2.205 +	PORTA = 0;
   2.206 +}
   2.207 +
   2.208 +void dram_set_addr(unsigned long addr)
   2.209 +{
   2.210 +	PORTB = addr & 0xff;
   2.211 +	PORTC = (addr >> 8) & 3;
   2.212 +}
   2.213 +
   2.214 +void dram_assert_cas(void)
   2.215 +{
   2.216 +	PORTD &= ~CAS3_BIT;
   2.217 +}
   2.218 +
   2.219 +void dram_release_cas(void)
   2.220 +{
   2.221 +	PORTD |= CAS3_BIT;
   2.222 +}
   2.223 +
   2.224 +void dram_assert_ras(unsigned char bits)
   2.225 +{
   2.226 +	PORTD &= ~bits;
   2.227 +}
   2.228 +
   2.229 +void dram_release_ras(unsigned char bits)
   2.230 +{
   2.231 +	PORTD |= bits;
   2.232 +}
   2.233 +
   2.234 +void dram_set_we(void)
   2.235 +{
   2.236 +	PORTD &= ~WE_BIT;
   2.237 +}
   2.238 +
   2.239 +void dram_clear_we(void)
   2.240 +{
   2.241 +	PORTD |= WE_BIT;
   2.242 +}
   2.243 +
   2.244 +void dram_init(void)
   2.245 +{
   2.246 +	DDRA = 0;	/* port A is the data bus */
   2.247 +	PORTA = 0;	/* no pullups when A is input */
   2.248 +	DDRB = 0xff;	/* port B is A0-A7 */
   2.249 +	DDRC = 0xff;	/* port C (low nibble) is A8-A11 */
   2.250 +	DDRD = 0xff;	/* port D are the control lines CAS/RAS/WR */
   2.251 +
   2.252 +	PORTD = 0xff;	/* deassert all control signals */
   2.253 +}
   2.254 +
   2.255 +void dram_detect(void)
   2.256 +{
   2.257 +	/* detect how many address bits we've got */
   2.258 +	addr_bits = 12;
   2.259 +	while(addr_bits > 8) {
   2.260 +		printf("addr mask: %lu\n", (unsigned long)((1 << (unsigned long)addr_bits) - 1));
   2.261 +		addr_mask = (1 << (unsigned long)addr_bits) - 1;
   2.262 +		if(memtest((1 << ((unsigned long)addr_bits * 2)) - 1) == 0) {
   2.263 +			break;
   2.264 +		}
   2.265 +		--addr_bits;
   2.266 +	}
   2.267 +	if(addr_bits < 1) {
   2.268 +		fprintf(stderr, "Failed to detect DRAM configuration (address lines)...\n");
   2.269 +		return;
   2.270 +	}
   2.271 +}
   2.272 +
   2.273 +int memtest(unsigned long addr)
   2.274 +{
   2.275 +	int i;
   2.276 +	unsigned char pat[] = { 0xf0, 0x0f, 0xaa, 0x55, 0xc0, 0x30, 0x0c, 0x03 };
   2.277 +	unsigned char val;
   2.278 +
   2.279 +	printf("testing address: %lx (a:%d,r:%d)\n", addr, addr_bits, ras_lines);
   2.280 +
   2.281 +	for(i=0; i<sizeof pat / sizeof *pat; i++) {
   2.282 +		dram_write(addr, pat[i]);
   2.283 +		if((val = dram_read(addr)) != pat[i]) {
   2.284 +			printf("pattern %x failed, got: %x\n", (int)pat[i], val);
   2.285 +			return -1;
   2.286 +		}
   2.287  	}
   2.288  	return 0;
   2.289  }
   2.290  
   2.291 -void procmd(const char *cmd)
   2.292 +void dram_refresh(void)
   2.293  {
   2.294 -	if(strcmp(cmd, "info") == 0) {
   2.295 -		printf("test firmware v0\n");
   2.296 -	} else {
   2.297 -		printf("unknown command: %s\n", cmd);
   2.298 -	}
   2.299 +	dram_assert_cas();
   2.300 +	dram_assert_ras(RAS2_BIT | RAS3_BIT);
   2.301 +	dram_release_cas();
   2.302 +	dram_release_ras(RAS2_BIT | RAS3_BIT);
   2.303  }
   2.304 +
   2.305 +void dram_write(unsigned long addr, unsigned char val)
   2.306 +{
   2.307 +	dram_set_data(val);
   2.308 +	dram_set_we();
   2.309 +	/* set row address */
   2.310 +	dram_set_addr((addr >> addr_bits) & addr_mask);
   2.311 +	dram_assert_ras(RAS2_BIT);
   2.312 +	/* set column address */
   2.313 +	dram_set_addr(addr & addr_mask);
   2.314 +	dram_assert_cas();
   2.315 +	dram_release_ras(RAS2_BIT);
   2.316 +	dram_release_cas();
   2.317 +	dram_release_data();
   2.318 +	dram_clear_we();
   2.319 +}
   2.320 +
   2.321 +unsigned char dram_read(unsigned long addr)
   2.322 +{
   2.323 +	unsigned char val;
   2.324 +
   2.325 +	dram_clear_we();
   2.326 +	dram_release_data();
   2.327 +
   2.328 +	/* set row address */
   2.329 +	dram_set_addr((addr >> addr_bits) & addr_mask);
   2.330 +	dram_assert_ras(RAS2_BIT);
   2.331 +	/* set column address */
   2.332 +	dram_set_addr(addr & addr_mask);
   2.333 +	dram_assert_cas();
   2.334 +
   2.335 +	val = PINA;
   2.336 +
   2.337 +	dram_release_ras(RAS2_BIT);
   2.338 +	dram_release_cas();
   2.339 +
   2.340 +	return val;
   2.341 +}