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