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

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)