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

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)