| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dfuutil_programming_spiflash_algorithm.c
Go to the documentation of this file.
1 /*
2 * @brief DFU Utility program for IRAM/peripheral addresses
3 * This programming algortihm allows reading or writing
4 * any address in the device.
5 *
6 * @note
7 * Copyright(C) NXP Semiconductors, 2012
8 * All rights reserved.
9 *
10 * @par
11 * Software that is described herein is for illustrative purposes only
12 * which provides customers with programming information regarding the
13 * LPC products. This software is supplied "AS IS" without any warranties of
14 * any kind, and NXP Semiconductors and its licensor disclaim any and
15 * all warranties, express or implied, including all implied warranties of
16 * merchantability, fitness for a particular purpose and non-infringement of
17 * intellectual property rights. NXP Semiconductors assumes no responsibility
18 * or liability for the use of the software, conveys no license or rights under any
19 * patent, copyright, mask work right, or any other intellectual property rights in
20 * or to any products. NXP Semiconductors reserves the right to make changes
21 * in the software without notification. NXP Semiconductors also makes no
22 * representation or warranty that such application will be suitable for the
23 * specified use without further testing or modification.
24 *
25 * @par
26 * Permission to use, copy, modify, and distribute this software and its
27 * documentation is hereby granted, under NXP Semiconductors' and its
28 * licensor's relevant copyrights in the software, without fee, provided that it
29 * is used in conjunction with NXP Semiconductors microcontrollers. This
30 * copyright, permission, and disclaimer notice must appear in all copies of
31 * this code.
32 */
33
34 #include "board.h"
35 #include "dfuutil_programming_api.h"
36 #include "stdio.h"
37 #include "string.h"
38
39 /* Use the SPIFI library instead of ROM PTR table */
40 #define USE_SPIFI_LIB
41 #include "spifi_rom_api.h"
42
69 /*****************************************************************************
70 * Private types/enumerations/variables
71 ****************************************************************************/
72
73 /* Number of program regions */
74 #define PROGRAM_REGIONS 2
75
76 /* Size of DFU USB buffer in bytes, do not exceed 4K */
77 #define DFU_BUFF_PROG_SIZE 2048
78
79 /* Forward references */
80 int32_t progalgo_spiflash_erase(uint32_t start, uint32_t size);
81
82 int32_t progalgo_spiflash_erase_all(void);
83
84 int32_t progalgo_spiflash_write(void *buff, uint32_t start, uint32_t size);
85
86 int32_t progalgo_spiflash_read(void *buff, uint32_t start, uint32_t size);
87
88 /* Function table for exposed API functions */
89 static const PROGALGOS_T palgos = {
90 progalgo_spiflash_erase,
91 progalgo_spiflash_erase_all,
92 progalgo_spiflash_write,
93 progalgo_spiflash_read
94 };
95
96 /* Regions and sizes for this device. The regions will be filled in after
97 IAP init. */
98 static DFUPROG_REGZONE_T pregions[PROGRAM_REGIONS] = {
99 {0x00000000, 0x00000000},
100 {0x00000000, 0x00000000}
101 };
102
103 /* DFU programming region/API structure
104 This structure puts them all together and is used by the DFU streamer */
105 static DFUPROG_REGION_T dfuregion = {
106 PROGRAM_REGIONS, /* Regions per device */
107 DFU_BUFF_PROG_SIZE, /* Size of buffer provided to DFU streamer */
108 &palgos, /* Pointer to programming algorithm function table */
109 pregions, /* Array of region addresses and sizes */
110 DFUPROG_VALIDVAL,
111 "SPIFLASH"
112 };
113
114 /* Needed SPIFI library supoprt objects */
115 static SPIFIobj spiobj;
116 static SPIFIopers spiopers;
117
118 /* SPIFI FLASH good initialization flag */
119 static int SpiGood;
120
121 /* Temporary work string for formatting */
122 static char tempSTR[128];
123
124 /*****************************************************************************
125 * Public types/enumerations/variables
126 ****************************************************************************/
127
128 /*****************************************************************************
129 * Private functions
130 ****************************************************************************/
131
132 /* Alternate region */
133 static uint32_t progalgo_spiflash_chk_alt(uint32_t addr)
134 {
135 if ((addr & 0xFF000000) == pregions[1].region_addr) {
136 addr &= ~0xFF000000;
137 addr |= pregions[0].region_addr;
138 }
139
140 return addr;
141 }
142
143 /* Verify a program address range is valid */
144 static int progalgo_spiflash_progaddrvalid(uint32_t addr, uint32_t size)
145 {
146 if (!SpiGood) {
147 return 0;
148 }
149
150 /* Make sure operation is 32-bit algined */
151 if (addr & 0x3) {
152 return 0;
153 }
154
155 addr = progalgo_spiflash_chk_alt(addr);
156 if ((addr >= dfuregion.pregions[0].region_addr) &&
157 ((addr + size) <= (dfuregion.pregions[0].region_addr + dfuregion.pregions[0].region_size))) {
158 return size;
159 }
160
161 return 0;
162 }
163
164 /* Region erase not supported on SPI FLASH */
165 static int32_t progalgo_spiflash_erase(uint32_t start, uint32_t size)
166 {
167 if (progalgo_spiflash_progaddrvalid(start, size) == 0) {
168 return 0;
169 }
170
171 sprintf(tempSTR, "ERASE region: Start %p, size %p\n", (void *) start, (void *) size);
172 usbDebug(tempSTR);
173
174 start = progalgo_spiflash_chk_alt(start);
175
176 /* Erase just selected region */
177 spiopers.dest = (char *) start;
178 spiopers.length = size;
179 spiopers.scratch = NULL;
180 spiopers.options = S_VERIFY_ERASE;
181
182 if (spifi_erase(&spiobj, &spiopers)) {
183 return 0;
184 }
185
186 return size;
187 }
188
189 /* Erse entire FPI FLASh device */
190 static int32_t progalgo_spiflash_erase_all(void)
191 {
192 if (!SpiGood) {
193 return 0;
194 }
195
196 usbDebug("ERASE: entire device\r\n");
197
198 spiopers.dest = (char *) (spiobj.base);
199 spiopers.length = spiobj.memSize;
200 spiopers.scratch = NULL;
201 spiopers.options = S_VERIFY_ERASE;
202
203 if (spifi_erase(&spiobj, &spiopers)) {
204 return 0;
205 }
206
207 return spiobj.memSize;
208 }
209
210 /* Write the buffer to the device. Returns 0 if the region cannot
211 be written (programming failure or region overlap) or the write
212 size>0 if it passed. */
213 static int32_t progalgo_spiflash_write(void *buff, uint32_t start, uint32_t size)
214 {
215
216 uint8_t *p8s = (uint8_t *) start, *p8d = (uint8_t *) buff;
217 uint32_t vsz = size;
218 int tmp;
219
220 /* Check address range and alternate range */
221 start = progalgo_spiflash_chk_alt(start);
222 if (progalgo_spiflash_progaddrvalid(start, size) == 0) {
223 return 0;
224 }
225
226 /* Setup SPI FLASH operation via the SPI FLASH driver */
227 spiopers.dest = (char *) start;
228 spiopers.length = size;
229 spiopers.scratch = (void *) NULL;
230 spiopers.protect = 0;
231 spiopers.options = S_CALLER_ERASE;
232
233 /* Setup SPI FLASH operation via the SPI FLASH driver */
234 sprintf(tempSTR, "PROG @ 0x%p, %p bytes\n", (void *) start, (void *) size);
235 usbDebug(tempSTR);
236
237 tmp = spifi_program(&spiobj, (char *) p8d, &spiopers);
238 if (tmp != 0) {
239 sprintf(tempSTR, "PROG fail: status %x at %p, size %p\n", tmp, (void *) start, (void *) size);
240 usbDebug(tempSTR);
241 return 0;
242 }
243
244 /* Verify */
245 while (vsz > 0) {
246 if (*p8s != *p8d) {
247 sprintf(tempSTR, "PROG verify fail: address %p, is: %x, should be: %x\n", p8s, *p8s, *p8d);
248 usbDebug(tempSTR);
249 return 0;
250 }
251 p8d++;
252 p8s++;
253 vsz--;
254 }
255
256 return size;
257 }
258
259 /* Read data from the device. Returns 0 if the region cannot
260 be read. */
261 static int32_t progalgo_spiflash_read(void *buff, uint32_t start, uint32_t size)
262 {
263 sprintf(tempSTR, "READ @ 0x%p, %p bytes\n", (void *) start, (void *) size);
264 usbDebug(tempSTR);
265
266 /* SPI FLASH is memory mapped, so just copy the data to the buffer */
267 memmove(buff, (void *) start, size);
268
269 return size;
270 }
271
272 /*****************************************************************************
273 * Public functions
274 ****************************************************************************/
275
283 DFUPROG_REGION_T *algo_flash_init(void)
284 {
285 SpiGood = 0;
286
287 /* Initialize SPI FLASH */
288 if (spifi_init(&spiobj, 3, S_RCVCLK | S_FULLCLK, 12)) {
289 usbDebug("SPIFLASH check: initialization failed\r\n");
290 return &dfuregion; /* Failed */
291 }
292
293 SpiGood = 1;
294
295 /* Set first region */
296 pregions[0].region_addr = (uint32_t) spiobj.base;
297 pregions[0].region_size = pregions[1].region_size = (uint32_t) spiobj.memSize;
298
299 /* Allow alternate address for SPI FLASH programming */
300 if (pregions[0].region_addr == 0x80000000) {
301 pregions[1].region_addr = 0x14000000;
302 }
303 else {
304 pregions[1].region_addr = 0x80000000;
305 }
306
307 sprintf(tempSTR, "SPIFLASH: device base %p with size %p bytes\r\n",
308 (void *) spiobj.base, (void *) spiobj.memSize);
309 usbDebug(tempSTR);
310 sprintf(tempSTR, "SPIFLASH: Alternate device base %p with size %p bytes\r\n",
311 (void *) pregions[1].region_addr, (void *) pregions[1].region_size);
312 usbDebug(tempSTR);
313
314 return &dfuregion;
315 }
316