1 //==========================================================================
5 // Cirrus CL7211 eval board FLASH program tool
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
41 //#####DESCRIPTIONBEGIN####
44 // Contributors: gthomas
46 // Description: Tool used to program onboard FLASH image
47 //####DESCRIPTIONEND####
50 // This program will program the FLASH on the CL7211 board from a fixed buffer
53 #include <pkgconf/kernel.h> // Configuration header
54 #include <cyg/kernel/kapi.h>
55 #include <cyg/infra/diag.h>
56 #include <cyg/hal/hal_cache.h>
63 #define STACK_SIZE 4096
64 static char stack[STACK_SIZE];
65 static cyg_thread thread_data;
66 static cyg_handle_t thread_handle;
68 void identify_FLASH(void);
69 int write_flash(long *data, volatile long *mem);
70 int erase_sector(volatile long *mem);
72 // Note: these are mapped addresses
73 // 0xE0000000 = ROM Bank 0
74 // 0xF0000000 = ROM Bank 1
75 volatile unsigned long *FLASH = (volatile unsigned long *)0xE0000000;
77 long *flash_buffer = (long *)0x60000;
78 long *flash_buffer_end = (long *)0x64000;
79 long *ROM_address = (long *)0xE07E0000;
81 // Adapted from Cirrus sample code
82 #define ATMEL_SEQ_ADD1 0x00015554>>2
83 #define ATMEL_SEQ_ADD2 0x0000AAA8>>2
84 #define ATMEL_START_CMD1 0xAAAAAAAA
85 #define ATMEL_START_CMD2 0x55555555
86 #define ATMEL_ID_CMD 0x90909090
87 #define ATMEL_PROG_CMD 0xA0A0A0A0
88 #define ATMEL_ERASE_CMD 0x80808080
89 #define ATMEL_SECTOR_ERASE_CMD 0x30303030
90 #define ATMEL_STOP_CMD 0xF0F0F0F0
91 #define ATMEL_BUSY_TOGGLE 0x00400040
92 #define ATMEL_ERASE_TOGGLE 0x00440044
94 #define ATMEL_MANUF 0x1F
95 #define ATMEL_AT29C040_ID 0X5B
96 #define ATMEL_AT29C040A_ID 0XA4
97 #define ATMEL_AT29C1024_ID 0X25
98 #define ATMEL_SECTOR_SIZE 256
99 #define ATMEL_MAX_SECTORS 2048
101 #define INTEL_MANUF 0x0089
102 #define INTEL_STOP_CMD 0x00FF00FF
103 #define INTEL_PROG_CMD 0x00400040
104 #define INTEL_ERASE_CMD 0x00200020
105 #define INTEL_ERASE_CONFIRM 0x00D000D0
106 #define INTEL_READ_STATUS 0x00700070
107 #define INTEL_CLEAR_STATUS 0x00500050
108 #define INTEL_SB_WSMS 0x00800080 // Write state machine = ready
109 #define INTEL_SB_ERASE_ERROR 0x00200020 // Erase failure
110 #define INTEL_SB_PROG_ERROR 0x00100010 // Programming failure
112 #define ERASE_TIMEOUT 10 // seconds
114 int manuf_code, device_code, sector_size, max_no_of_sectors, word_mode;
125 program_flash(cyg_addrword_t arg)
127 diag_printf("PROGRAM FLASH here!\n");
128 HAL_UCACHE_SYNC(); // ROM space is marked cacheable which causes problems!
129 HAL_UCACHE_DISABLE(); // So, just disable caches.
131 diag_printf("About to program FLASH using data at %x..%x\n", flash_buffer, flash_buffer_end);
132 diag_printf("*** Press RESET now to abort!\n");
133 cyg_thread_delay(5*100);
135 diag_printf("... Erase sector\n");
136 if (erase_sector(ROM_address)) {
137 diag_printf("... Programming FLASH\n");
138 while (flash_buffer < flash_buffer_end) {
139 if (!write_flash(flash_buffer++, ROM_address++)) break;
144 switch (manuf_code) {
146 FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
147 FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
148 FLASH[ATMEL_SEQ_ADD1] = ATMEL_STOP_CMD;
151 FLASH[0] = INTEL_STOP_CMD;
154 diag_printf("All done!\n");
159 identify_FLASH(void )
161 // Enter Software Product Identification Mode
162 FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
163 FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
164 FLASH[ATMEL_SEQ_ADD1] = ATMEL_ID_CMD;
166 // Wait at least 10ms
169 // Read Manufacturer and device code from the device
170 manuf_code = FLASH[0] >> 16;
171 device_code = FLASH[1] >> 16;
173 diag_printf("manufacturer: 0x%04x, device: 0x%04x\n", manuf_code, device_code);
175 // Exit Software Product Identification Mode
176 switch (manuf_code) {
178 FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
179 FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
180 FLASH[ATMEL_SEQ_ADD1] = ATMEL_STOP_CMD;
183 FLASH[0] = INTEL_STOP_CMD;
186 diag_printf("Unrecognized FLASH manufacturer - I give up!\n");
195 for (i = 0; i < 100; i++) ;
199 write_flash(long *data, volatile long *mem)
204 switch (manuf_code) {
206 // Enter Program Mode
207 FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
208 FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
209 FLASH[ATMEL_SEQ_ADD1] = ATMEL_PROG_CMD;
210 // Send data to selected address
213 data1 = *mem; // Read cell back twice
215 // Bit 6 toggles between reads while programming in progress
216 if ((data1 & ATMEL_BUSY_TOGGLE) == (data2 & ATMEL_BUSY_TOGGLE)) break;
220 // Clear current errors
221 FLASH[0] = INTEL_CLEAR_STATUS;
222 // Issue program command
223 FLASH[0] = INTEL_PROG_CMD;
224 // Send data to selected address
227 // Read the status register to wait for programming complete
231 } while (((status & INTEL_SB_WSMS) != INTEL_SB_WSMS) &&
235 diag_printf("Programming at 0x%08x timed out - status: 0x%08x\n", mem, status);
237 if ((status & INTEL_SB_PROG_ERROR) != 0) {
238 diag_printf("Device reports programming error at 0x%08x - status: 0x%08x\n", mem, status);
241 FLASH[0] = INTEL_STOP_CMD;
245 diag_printf("Programming failed at 0x%08x - write: 0x%08x, read: 0x%08x\n",
253 erase_sector(volatile long *mem)
258 switch (manuf_code) {
260 // Erase sector command
261 FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
262 FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
263 FLASH[ATMEL_SEQ_ADD1] = ATMEL_ERASE_CMD;
264 FLASH[ATMEL_SEQ_ADD1] = ATMEL_START_CMD1;
265 FLASH[ATMEL_SEQ_ADD2] = ATMEL_START_CMD2;
266 *mem = ATMEL_SECTOR_ERASE_CMD;
268 data1 = *mem; // Read cell back twice
270 // Bits 6+2 toggle between reads while programming in progress
271 if ((data1 & ATMEL_ERASE_TOGGLE) == (data2 & ATMEL_ERASE_TOGGLE)) break;
275 // Clear current errors
276 FLASH[0] = INTEL_CLEAR_STATUS;
277 // Issue erase block command
278 FLASH[0] = INTEL_ERASE_CMD;
279 *mem = INTEL_ERASE_CONFIRM;
280 timer = ERASE_TIMEOUT*50;
281 // Read the status register while erase in progress
285 } while (((status & INTEL_SB_WSMS) != INTEL_SB_WSMS) &&
289 diag_printf("Erase not complete after %d seconds - status: 0x%08x\n",
290 ERASE_TIMEOUT, status);
292 if ((status & INTEL_SB_ERASE_ERROR) != 0) {
293 diag_printf("Device reports erase error - status: 0x%08x\n", status);
296 FLASH[0] = INTEL_STOP_CMD;
299 if (*mem != 0xFFFFFFFF) {
300 diag_printf("Erase failed at 0x%08x - read: 0x%08x\n",
310 // Create a main thread, so we can run the scheduler and have time 'pass'
311 cyg_thread_create(10, // Priority - just a number
312 program_flash, // entry
314 "program_thread", // Name
317 &thread_handle, // Handle
318 &thread_data // Thread data structure
320 cyg_thread_resume(thread_handle); // Start it
321 cyg_scheduler_start();
322 } // cyg_package_start()