comparison packages/hal/arm/pid/current/src/flash.c @ 76:435cced73e2f ecos-v1_3_1-release

eCos v1.3.1 merged from eCos master repository on 2000-03-27-23:22:51-BST
author jlarmour
date Tue, 28 Mar 2000 14:10:45 +0000
parents
children e0c0827131d1
comparison
equal deleted inserted replaced
75:41bf073c0c32 76:435cced73e2f
1 //==========================================================================
2 //
3 // flash.c
4 //
5 // ARM PID7 eval board FLASH program tool
6 //
7 //==========================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Red Hat eCos Public License
12 // Version 1.1 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://www.redhat.com/
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Configurable Operating System,
22 // released September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Red Hat.
25 // Portions created by Red Hat are
26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
27 // All Rights Reserved.
28 // -------------------------------------------
29 //
30 //####COPYRIGHTEND####
31 //==========================================================================
32 //#####DESCRIPTIONBEGIN####
33 //
34 // Author(s): gthomas
35 // Contributors: gthomas
36 // Date: 1998-11-18
37 // Description: Tool used to program onboard FLASH image
38 //####DESCRIPTIONEND####
39
40 //
41 // This program will program the FLASH on the PID board
42 //
43
44 #include <pkgconf/libc.h> // Configuration header
45
46 #include <cyg/kernel/kapi.h>
47 #include <stdlib.h>
48 #include <ctype.h>
49 #include <cyg/infra/testcase.h>
50 #include <sys/cstartup.h>
51
52 #ifndef FALSE
53 #define FALSE 0
54 #define TRUE 1
55 #endif
56
57 #define SYNC_COUNT 63
58
59 extern void diag_printf(const char *, ...);
60 int identify_FLASH(void);
61 void write_sector(int, char *);
62 bool load_srecords(char (*readc)(), CYG_ADDRESS *start, int *size);
63
64 char dbuf[256];
65 char *raw = (char *)0x10000;
66 char *flash_buffer = (char *)0x30000;
67 int pos, len;
68
69 // FUNCTIONS
70
71 externC void
72 cyg_package_start( void )
73 {
74 #ifdef CYGPKG_LIBC
75 cyg_iso_c_start();
76 #else
77 (void)main(0, NULL);
78 #endif
79 } // cyg_package_start()
80
81 char nextch(void)
82 {
83 return (raw[pos++]);
84 }
85
86 int
87 main( int argc, char *argv[] )
88 {
89 int i, j, size;
90 CYG_ADDRESS entry;
91 char c;
92 diag_printf("FLASH here!\n");
93 while (identify_FLASH() == 0) {
94 diag_printf("... Please change FLASH jumper - hit C/R to continue:");
95 do {
96 hal_diag_read_char(&c);
97 } while ((c != '\r') && (c != '\n'));
98 diag_printf("\n");
99 }
100 restart:
101 diag_printf("Ready file - hit C/R to continue:");
102 while (TRUE) {
103 hal_diag_read_char(&c);
104 if (c == '>') break;
105 }
106 i = 0; j = 0;
107 while (1) {
108 hal_diag_read_char(&c);
109 if (c == '!') {
110 diag_printf("... Reset\n");
111 goto restart;
112 }
113 raw[i++] = c;
114 if (++j == SYNC_COUNT) {
115 hal_diag_write_char(c);
116 j = 0;
117 }
118 if (c == ':') break;
119 }
120 diag_printf("\n");
121 pos = 0; len = i;
122 if (load_srecords(nextch, &entry, &size)) {
123 diag_printf("Read %x bytes, entry: %x\n", size, entry);
124 dump_buf(flash_buffer, 128);
125 diag_printf("\nData loaded - hit '!' to continue:");
126 while (TRUE) {
127 hal_diag_read_char(&c);
128 if (c == '!') break;
129 }
130 diag_printf("\n");
131 diag_printf("...Programming FLASH\n");
132 pos = 0; i = 0;
133 while (pos < size) {
134 write_sector(i++, flash_buffer+pos);
135 pos += 256;
136 }
137 } else {
138 // Display buffer around failure
139 dump_buf(&raw[pos-32], 64);
140 }
141 diag_printf("All done!\n");
142 while (1) ;
143 }
144
145 // Adapted from ARM sample code
146 #define SEQ_ADD1 0x5555
147 #define SEQ_ADD2 0xAAAA
148 #define START_CMD1 0xAA
149 #define START_CMD2 0x55
150 #define ID_CMD 0x90
151 #define PROG_CMD 0xA0
152 #define STOP_CMD 0xF0
153
154 #define MAN_ATMEL 0x1F
155 #define ATMEL_AT29C040_ID 0X5B
156 #define ATMEL_AT29C040A_ID 0XA4
157 #define ATMEL_AT29C1024_ID 0X25
158 #define ATMEL_SECTOR_SIZE 256
159 #define ATMEL_MAX_SECTORS 2048
160
161 int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode;
162 volatile char *FLASH = (volatile char *)0x04000000;
163
164 int
165 identify_FLASH(void )
166 {
167 // Enter Software Product Identification Mode
168 FLASH[SEQ_ADD1] = START_CMD1;
169 FLASH[SEQ_ADD2] = START_CMD2;
170 FLASH[SEQ_ADD1] = ID_CMD;
171
172 // Wait at least 10ms
173 cyg_thread_delay(2);
174
175 // Read Manufacturer and device code from the device
176 manuf_code = FLASH[0];
177 device_code = FLASH[1];
178
179 diag_printf("manuf: %x, device: %x\n", manuf_code, device_code);
180
181 // Exit Software Product Identification Mode
182 FLASH[SEQ_ADD1] = START_CMD1;
183 FLASH[SEQ_ADD2] = START_CMD2;
184 FLASH[SEQ_ADD1] = STOP_CMD;
185
186 // Wait at least 10ms
187 cyg_thread_delay(5);
188
189 if (manuf_code != MAN_ATMEL) {
190 diag_printf ( "Error: Wrong Manufaturer: %02x\n",manuf_code );
191 return (0);
192 }
193
194 switch (device_code) {
195 case ATMEL_AT29C040A_ID:
196 diag_printf ("AT29C040A recognised\n");
197 sector_size = ATMEL_SECTOR_SIZE;
198 max_no_of_sectors = ATMEL_MAX_SECTORS;
199 word_mode = FALSE;
200 break;
201 case ATMEL_AT29C1024_ID:
202 diag_printf ("AT29C1024 recognised\n");
203 sector_size = ATMEL_SECTOR_SIZE;
204 max_no_of_sectors = ATMEL_MAX_SECTORS;
205 word_mode = TRUE;
206 break;
207 default :
208 diag_printf ( "Error: Unsupported device: %02x\n", device_code);
209 return (0);
210 }
211 return (1);
212 }
213
214 void
215 write_sector(int num, char *buf)
216 {
217 int i, cnt;
218 volatile char *wrt = (volatile int *)&FLASH[num*sector_size];
219
220 // diag_printf("Writing to %08x\n", wrt);
221 // Enter Program Mode
222 FLASH[SEQ_ADD1] = START_CMD1;
223 FLASH[SEQ_ADD2] = START_CMD2;
224 FLASH[SEQ_ADD1] = PROG_CMD;
225
226 // Note: write bytes as longs regardless of bus width
227 for (i = 0; i < sector_size; i++) {
228 wrt[i] = buf[i];
229 }
230
231 // Wait for sector to program
232 cnt = 0;
233 i = sector_size - 1;
234 while (wrt[i] != buf[i]) {
235 if (cnt++ > 0x01000000) break;
236 }
237 // diag_printf("Out - i: %d, wrt[i] = %08X.%08X, buf[i] = %08X, count = %x\n", i, &wrt[i], wrt[i], buf[i], cnt);
238
239 // Verify
240 for (i = 0; i < sector_size; i++) {
241 for (cnt = 0; cnt < 10; cnt++) {
242 if (*wrt == *buf) break;
243 cyg_thread_delay(1);
244 }
245 if (cnt == 10) {
246 diag_printf("Can't program at 0x%08X: %02X not %02X\n", wrt, *wrt, *buf);
247 }
248 wrt++; buf++;
249 }
250 }
251
252 // S-record download code - viciously 'adapted' from "kernel/src/sload/sload.c"
253
254 /*---------------------------------------------------------------------------*/
255 /*
256 //
257 // An srecord looks like this:
258 //
259 // byte count-+ address
260 // start ---+ | | data +- checksum
261 // | | | |
262 // S01000006F6B692D746573742E73726563E4
263 // S315000448600000000000000000FC00005900000000E9
264 // S31A0004000023C1400037DE00F023604000377B009020825000348D
265 // S30B0004485A0000000000004E
266 // S70500040000F6
267 //
268 // S<type><length><address><data><checksum>
269 //
270 // Where
271 // - length (2 characters)
272 // is the number of bytes following upto the checksum. Note that
273 // this is not the number of chars following, since it takes two
274 // chars to represent a byte.
275 // - type (2 characters)
276 // is one of:
277 // 0) header record
278 // 1) two byte address data record
279 // 2) three byte address data record
280 // 3) four byte address data record
281 // 5) record containing the number of S1, S2, or S3 records
282 // 7) four byte address termination record
283 // 8) three byte address termination record
284 // 9) two byte address termination record
285 //
286 // - address (4, 6, or 8 characters)
287 // is the start address of the data following, or in the case of
288 // a termination record, the start address of the image
289 // - data (0-2n characters)
290 // is the data.
291 // - checksum (2 characters)
292 // is the sum of all the raw byte data in the record, from the length
293 // upwards, modulo 256 and subtracted from 255.
294 //
295 // Useful S-records for testing purposes:
296 // Start record:
297 // S00B0000737461303030447563
298 // This sets the default address to be 0x02005000:
299 // S31A020050002700801481C4E0B0A15000000100000091D02000018F
300 // S31A0200501500000001000000010000002700801881C4E2E4A150C1
301 // S311020080A42407070A090B0A0781050000E1
302 // Termination record:
303 // S70502005000A8
304 //
305 */
306
307 #define S0 0
308 #define S1 1
309 #define S2 2
310 #define S3 3
311 #define S5 5
312 #define S7 7
313 #define S8 8
314 #define S9 9
315
316 /*---------------------------------------------------------------------------*/
317
318 int hex2digit(char c)
319 {
320 if( c & 0x40 ) c += 9;;
321 return c &0x0f;
322
323 // return ( c <= '9' ? c - '0' :
324 // c <= 'Z' ? c - 'A' + 10 :
325 // c - 'a' + 10);
326 }
327
328 /*---------------------------------------------------------------------------*/
329
330 bool load_srecords(char (*readc)(),
331 CYG_ADDRESS *start,
332 int *size)
333 {
334 CYG_ADDRESS addr, load_addr;
335 int addrsize;
336 int length;
337 int i;
338 cyg_uint8 chksum, ochksum;
339 cyg_uint8 val;
340 cyg_uint8 *tdata;
341 char s;
342 char type;
343 char len0;
344 char len1;
345 bool first = true;
346
347
348 do {
349 // Skip whitespace characters until we find something that
350 // might be an 'S'.
351 do {
352 s = readc();
353 } while( s == '\r' || s == '\n' || s == ' ');
354
355 // Check that this is an S record
356 if( s != 'S' ) {
357 diag_printf("Invalid 'S' record\n");
358 return false;
359 }
360
361 // First 4 bytes are standard S + type + len
362 type = readc();
363 len0 = readc();
364 len1 = readc();
365
366 // decode the type
367 type = hex2digit(type);
368
369 // determine address size
370 switch (type) {
371 case S0: // start records have no address
372 addrsize = 0;
373 break;
374 case S1: // two byte address
375 case S9:
376 addrsize = 4;
377 break;
378 case S2: // 3 byte address
379 case S8:
380 addrsize = 6;
381 break;
382 case S3: // 4 byte address
383 case S7:
384 addrsize = 8;
385 break;
386 }
387
388 length = hex2digit (len0) << 4;
389 length |= hex2digit (len1);
390 chksum = length;
391
392 // read the address
393 addr = 0;
394 for (i = 0; i < addrsize; i++) {
395 val = hex2digit(readc());
396 addr = (addr << 4) | val;
397 }
398
399 // calculate the checksum, which is done by the byte, not the digit
400 for (i = 0; i < addrsize*4; i += 8) {
401 chksum += ((addr >> i) & 0xff);
402 }
403
404 // decide where to load this data
405 if (first && (type != S0)) {
406 load_addr = addr;
407 first = false;
408 }
409
410 // read the data and put it directly into memory where it belongs
411 tdata = (cyg_uint8 *)((addr - load_addr) + flash_buffer);
412 if (type < S7) {
413 *size = (addr - load_addr);
414 }
415 val = 0;
416 for (i = 0; i < ((length - 1) * 2) - addrsize; i += 2 ) {
417 val = hex2digit (readc()) << 4;
418 val |= hex2digit (readc());
419 chksum += val;
420 if( type != S0 ) *tdata++ = val;
421 if (type < S7) *size = *size + 1;
422 }
423
424 // now get the old checksum
425 ochksum = hex2digit(readc()) << 4;
426 ochksum |= hex2digit(readc());
427 chksum = ~chksum;
428 if (chksum != ochksum) {
429 diag_printf("Bad checksum - addr: %x\n", addr);
430 return false;
431 }
432
433 } while( type < S7 );
434
435 *start = addr;
436 return true;
437 }