change #include "binarybuffer.h" to <helper/binarybuffer.h>
[openocd.git] / src / flash / nor / lpc288x.c
1 /***************************************************************************
2 * Copyright (C) 2008 by *
3 * Karl RobinSod <karl.robinsod@gmail.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21 /***************************************************************************
22 * There are some things to notice
23 *
24 * You need to unprotect flash sectors each time you connect the OpenOCD
25 * Dumping 1MB takes about 60 Seconds
26 * Full erase (sectors 0-22 inclusive) takes 2-4 seconds
27 * Writing 1MB takes 88 seconds
28 *
29 ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "lpc288x.h"
35 #include <helper/binarybuffer.h>
36
37
38 #define LOAD_TIMER_ERASE 0
39 #define LOAD_TIMER_WRITE 1
40
41 #define FLASH_PAGE_SIZE 512
42
43 /* LPC288X control registers */
44 #define DBGU_CIDR 0x8000507C
45 /* LPC288X flash registers */
46 #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
47 #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
48 #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
49 #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
50 #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0 */
51 #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
52 #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
53 #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
54 #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
55 #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
56 #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
57 #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power savings. R/W 1*/
58 #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from Power Down mode. R/W -*/
59
60 /* F_CTRL bits */
61 #define FC_CS 0x0001
62 #define FC_FUNC 0x0002
63 #define FC_WEN 0x0004
64 #define FC_RD_LATCH 0x0020
65 #define FC_PROTECT 0x0080
66 #define FC_SET_DATA 0x0400
67 #define FC_RSSL 0x0800
68 #define FC_PROG_REQ 0x1000
69 #define FC_CLR_BUF 0x4000
70 #define FC_LOAD_REQ 0x8000
71 /* F_STAT bits */
72 #define FS_DONE 0x0001
73 #define FS_PROGGNT 0x0002
74 #define FS_RDY 0x0004
75 #define FS_ERR 0x0020
76 /* F_PROG_TIME */
77 #define FPT_TIME_MASK 0x7FFF
78
79 #define FPT_ENABLE 0x8000
80 /* F_WAIT */
81 #define FW_WAIT_STATES_MASK 0x00FF
82 #define FW_SET_MASK 0xC000
83
84 /* F_CLK_TIME */
85 #define FCT_CLK_DIV_MASK 0x0FFF
86
87 static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout);
88 static void lpc288x_load_timer(int erase, struct target *target);
89 static void lpc288x_set_flash_clk(struct flash_bank *bank);
90 static uint32_t lpc288x_system_ready(struct flash_bank *bank);
91
92 static uint32_t lpc288x_wait_status_busy(struct flash_bank *bank, int timeout)
93 {
94 uint32_t status;
95 struct target *target = bank->target;
96 do
97 {
98 alive_sleep(1);
99 timeout--;
100 target_read_u32(target, F_STAT, &status);
101 } while (((status & FS_DONE) == 0) && timeout);
102
103 if (timeout == 0)
104 {
105 LOG_DEBUG("Timedout!");
106 return ERROR_FLASH_OPERATION_FAILED;
107 }
108 return ERROR_OK;
109 }
110
111 /* Read device id register and fill in driver info structure */
112 static int lpc288x_read_part_info(struct flash_bank *bank)
113 {
114 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
115 struct target *target = bank->target;
116 uint32_t cidr;
117
118 int i = 0;
119 uint32_t offset;
120
121 if (lpc288x_info->cidr == 0x0102100A)
122 return ERROR_OK; /* already probed, multiple probes may cause memory leak, not allowed */
123
124 /* Read and parse chip identification register */
125 target_read_u32(target, DBGU_CIDR, &cidr);
126
127 if (cidr != 0x0102100A)
128 {
129 LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32 ")",cidr);
130 return ERROR_FLASH_OPERATION_FAILED;
131 }
132
133 lpc288x_info->cidr = cidr;
134 lpc288x_info->sector_size_break = 0x000F0000;
135 lpc288x_info->target_name = "LPC288x";
136
137 /* setup the sector info... */
138 offset = bank->base;
139 bank->num_sectors = 23;
140 bank->sectors = malloc(sizeof(struct flash_sector) * 23);
141
142 for (i = 0; i < 15; i++)
143 {
144 bank->sectors[i].offset = offset;
145 bank->sectors[i].size = 64 * 1024;
146 offset += bank->sectors[i].size;
147 bank->sectors[i].is_erased = -1;
148 bank->sectors[i].is_protected = 1;
149 }
150 for (i = 15; i < 23; i++)
151 {
152 bank->sectors[i].offset = offset;
153 bank->sectors[i].size = 8 * 1024;
154 offset += bank->sectors[i].size;
155 bank->sectors[i].is_erased = -1;
156 bank->sectors[i].is_protected = 1;
157 }
158
159 return ERROR_OK;
160 }
161
162 static int lpc288x_protect_check(struct flash_bank *bank)
163 {
164 return ERROR_OK;
165 }
166
167 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
168 FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command)
169 {
170 struct lpc288x_flash_bank *lpc288x_info;
171
172 if (CMD_ARGC < 6)
173 {
174 LOG_WARNING("incomplete flash_bank LPC288x configuration");
175 return ERROR_FLASH_BANK_INVALID;
176 }
177
178 lpc288x_info = malloc(sizeof(struct lpc288x_flash_bank));
179 bank->driver_priv = lpc288x_info;
180
181 /* part wasn't probed for info yet */
182 lpc288x_info->cidr = 0;
183 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[6], lpc288x_info->cclk);
184
185 return ERROR_OK;
186 }
187
188 /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
189 * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
190 * AHB = 12 MHz ?
191 * 12000000/66000 = 182
192 * CLK_DIV = 60 ? */
193 static void lpc288x_set_flash_clk(struct flash_bank *bank)
194 {
195 uint32_t clk_time;
196 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
197 clk_time = (lpc288x_info->cclk / 66000) / 3;
198 target_write_u32(bank->target, F_CTRL, FC_CS | FC_WEN);
199 target_write_u32(bank->target, F_CLK_TIME, clk_time);
200 }
201
202 /* AHB tcyc (in ns) 83 ns
203 * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
204 * = 9412 (9500) (AN10548 9375)
205 * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
206 * = 23 (75) (AN10548 72 - is this wrong?)
207 * TODO: Sort out timing calcs ;) */
208 static void lpc288x_load_timer(int erase, struct target *target)
209 {
210 if (erase == LOAD_TIMER_ERASE)
211 {
212 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 9500);
213 }
214 else
215 {
216 target_write_u32(target, F_PROG_TIME, FPT_ENABLE | 75);
217 }
218 }
219
220 static uint32_t lpc288x_system_ready(struct flash_bank *bank)
221 {
222 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
223 if (lpc288x_info->cidr == 0)
224 {
225 return ERROR_FLASH_BANK_NOT_PROBED;
226 }
227
228 if (bank->target->state != TARGET_HALTED)
229 {
230 LOG_ERROR("Target not halted");
231 return ERROR_TARGET_NOT_HALTED;
232 }
233 return ERROR_OK;
234 }
235
236 static int lpc288x_erase_check(struct flash_bank *bank)
237 {
238 uint32_t status = lpc288x_system_ready(bank); /* probed? halted? */
239 if (status != ERROR_OK)
240 {
241 LOG_INFO("Processor not halted/not probed");
242 return status;
243 }
244
245 return ERROR_OK;
246 }
247
248 static int lpc288x_erase(struct flash_bank *bank, int first, int last)
249 {
250 uint32_t status;
251 int sector;
252 struct target *target = bank->target;
253
254 status = lpc288x_system_ready(bank); /* probed? halted? */
255 if (status != ERROR_OK)
256 {
257 return status;
258 }
259
260 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
261 {
262 LOG_INFO("Bad sector range");
263 return ERROR_FLASH_SECTOR_INVALID;
264 }
265
266 /* Configure the flash controller timing */
267 lpc288x_set_flash_clk(bank);
268
269 for (sector = first; sector <= last; sector++)
270 {
271 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
272 {
273 return ERROR_FLASH_OPERATION_FAILED;
274 }
275
276 lpc288x_load_timer(LOAD_TIMER_ERASE,target);
277
278 target_write_u32(target, bank->sectors[sector].offset, 0x00);
279
280 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_CS);
281 }
282 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
283 {
284 return ERROR_FLASH_OPERATION_FAILED;
285 }
286 return ERROR_OK;
287 }
288
289 static int lpc288x_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
290 {
291 uint8_t page_buffer[FLASH_PAGE_SIZE];
292 uint32_t status, source_offset,dest_offset;
293 struct target *target = bank->target;
294 uint32_t bytes_remaining = count;
295 uint32_t first_sector, last_sector, sector, page;
296 int i;
297
298 /* probed? halted? */
299 status = lpc288x_system_ready(bank);
300 if (status != ERROR_OK)
301 {
302 return status;
303 }
304
305 /* Initialise search indices */
306 first_sector = last_sector = 0xffffffff;
307
308 /* validate the write range... */
309 for (i = 0; i < bank->num_sectors; i++)
310 {
311 if ((offset >= bank->sectors[i].offset) &&
312 (offset < (bank->sectors[i].offset + bank->sectors[i].size)) &&
313 (first_sector == 0xffffffff))
314 {
315 first_sector = i;
316 /* all writes must start on a sector boundary... */
317 if (offset % bank->sectors[i].size)
318 {
319 LOG_INFO("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32 "", offset, bank->sectors[i].size);
320 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
321 }
322 }
323 if (((offset + count) > bank->sectors[i].offset) &&
324 ((offset + count) <= (bank->sectors[i].offset + bank->sectors[i].size)) &&
325 (last_sector == 0xffffffff))
326 {
327 last_sector = i;
328 }
329 }
330
331 /* Range check... */
332 if (first_sector == 0xffffffff || last_sector == 0xffffffff)
333 {
334 LOG_INFO("Range check failed %" PRIx32 " %" PRIx32 "", offset, count);
335 return ERROR_FLASH_DST_OUT_OF_BANK;
336 }
337
338 /* Configure the flash controller timing */
339 lpc288x_set_flash_clk(bank);
340
341 /* initialise the offsets */
342 source_offset = 0;
343 dest_offset = 0;
344
345 for (sector = first_sector; sector <= last_sector; sector++)
346 {
347 for (page = 0; page < bank->sectors[sector].size / FLASH_PAGE_SIZE; page++)
348 {
349 if (bytes_remaining == 0)
350 {
351 count = 0;
352 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
353 }
354 else if (bytes_remaining < FLASH_PAGE_SIZE)
355 {
356 count = bytes_remaining;
357 memset(page_buffer, 0xFF, FLASH_PAGE_SIZE);
358 memcpy(page_buffer, &buffer[source_offset], count);
359 }
360 else
361 {
362 count = FLASH_PAGE_SIZE;
363 memcpy(page_buffer, &buffer[source_offset], count);
364 }
365
366 /* Wait for flash to become ready */
367 if (lpc288x_wait_status_busy(bank, 1000) != ERROR_OK)
368 {
369 return ERROR_FLASH_OPERATION_FAILED;
370 }
371
372 /* fill flash data latches with 1's */
373 target_write_u32(target, F_CTRL, FC_CS | FC_SET_DATA | FC_WEN | FC_FUNC);
374
375 target_write_u32(target, F_CTRL, FC_CS | FC_WEN | FC_FUNC);
376 /*would be better to use the clean target_write_buffer() interface but
377 * it seems not to be a LOT slower....
378 * bulk_write_memory() is no quicker :(*/
379 #if 1
380 if (target_write_memory(target, offset + dest_offset, 4, 128, page_buffer) != ERROR_OK)
381 {
382 LOG_ERROR("Write failed s %" PRIx32 " p %" PRIx32 "", sector, page);
383 return ERROR_FLASH_OPERATION_FAILED;
384 }
385 #else
386 if (target_write_buffer(target, offset + dest_offset, FLASH_PAGE_SIZE, page_buffer) != ERROR_OK)
387 {
388 LOG_INFO("Write to flash buffer failed");
389 return ERROR_FLASH_OPERATION_FAILED;
390 }
391 #endif
392 dest_offset += FLASH_PAGE_SIZE;
393 source_offset += count;
394 bytes_remaining -= count;
395
396 lpc288x_load_timer(LOAD_TIMER_WRITE, target);
397
398 target_write_u32(target, F_CTRL, FC_PROG_REQ | FC_PROTECT | FC_FUNC | FC_CS);
399 }
400 }
401
402 return ERROR_OK;
403 }
404
405 static int lpc288x_probe(struct flash_bank *bank)
406 {
407 /* we only deal with LPC2888 so flash config is fixed */
408 struct lpc288x_flash_bank *lpc288x_info = bank->driver_priv;
409 int retval;
410
411 if (lpc288x_info->cidr != 0)
412 {
413 return ERROR_OK; /* already probed */
414 }
415
416 if (bank->target->state != TARGET_HALTED)
417 {
418 LOG_ERROR("Target not halted");
419 return ERROR_TARGET_NOT_HALTED;
420 }
421
422 retval = lpc288x_read_part_info(bank);
423 if (retval != ERROR_OK)
424 return retval;
425 return ERROR_OK;
426 }
427
428 static int lpc288x_info(struct flash_bank *bank, char *buf, int buf_size)
429 {
430 snprintf(buf, buf_size, "lpc288x flash driver");
431 return ERROR_OK;
432 }
433
434 static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last)
435 {
436 int lockregion, status;
437 uint32_t value;
438 struct target *target = bank->target;
439
440 /* probed? halted? */
441 status = lpc288x_system_ready(bank);
442 if (status != ERROR_OK)
443 {
444 return status;
445 }
446
447 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
448 {
449 return ERROR_FLASH_SECTOR_INVALID;
450 }
451
452 /* Configure the flash controller timing */
453 lpc288x_set_flash_clk(bank);
454
455 for (lockregion = first; lockregion <= last; lockregion++)
456 {
457 if (set)
458 {
459 /* write an odd value to base addy to protect... */
460 value = 0x01;
461 }
462 else
463 {
464 /* write an even value to base addy to unprotect... */
465 value = 0x00;
466 }
467 target_write_u32(target, bank->sectors[lockregion].offset, value);
468 target_write_u32(target, F_CTRL, FC_LOAD_REQ | FC_PROTECT | FC_WEN | FC_FUNC | FC_CS);
469 }
470
471 return ERROR_OK;
472 }
473
474 struct flash_driver lpc288x_flash = {
475 .name = "lpc288x",
476 .flash_bank_command = &lpc288x_flash_bank_command,
477 .erase = &lpc288x_erase,
478 .protect = &lpc288x_protect,
479 .write = &lpc288x_write,
480 .probe = &lpc288x_probe,
481 .auto_probe = &lpc288x_probe,
482 .erase_check = &lpc288x_erase_check,
483 .protect_check = &lpc288x_protect_check,
484 .info = &lpc288x_info,
485 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)