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

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)