1 /***************************************************************************
2 * Copyright (C) 2008 by *
3 * Karl RobinSod <karl.robinsod@gmail.com> *
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. *
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. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
19 /***************************************************************************
20 * There are some things to notice
22 * You need to unprotect flash sectors each time you connect the OpenOCD
23 * Dumping 1MB takes about 60 Seconds
24 * Full erase (sectors 0-22 inclusive) takes 2-4 seconds
25 * Writing 1MB takes 88 seconds
27 ***************************************************************************/
33 #include <helper/binarybuffer.h>
35 #define LOAD_TIMER_ERASE 0
36 #define LOAD_TIMER_WRITE 1
38 #define FLASH_PAGE_SIZE 512
40 /* LPC288X control registers */
41 #define DBGU_CIDR 0x8000507C
42 /* LPC288X flash registers */
43 #define F_CTRL 0x80102000 /* Flash control register R/W 0x5 */
44 #define F_STAT 0x80102004 /* Flash status register RO 0x45 */
45 #define F_PROG_TIME 0x80102008 /* Flash program time register R/W 0 */
46 #define F_WAIT 0x80102010 /* Flash read wait state register R/W 0xC004 */
47 #define F_CLK_TIME 0x8010201C /* Flash clock divider for 66 kHz generation R/W 0
49 #define F_INTEN_CLR 0x80102FD8 /* Clear interrupt enable bits WO - */
50 #define F_INTEN_SET 0x80102FDC /* Set interrupt enable bits WO - */
51 #define F_INT_STAT 0x80102FE0 /* Interrupt status bits RO 0 */
52 #define F_INTEN 0x80102FE4 /* Interrupt enable bits RO 0 */
53 #define F_INT_CLR 0x80102FE8 /* Clear interrupt status bits WO */
54 #define F_INT_SET 0x80102FEC /* Set interrupt status bits WO - */
55 #define FLASH_PD 0x80005030 /* Allows turning off the Flash memory for power
57 #define FLASH_INIT 0x80005034 /* Monitors Flash readiness, such as recovery from
58 *Power Down mode. R/W -*/
62 #define FC_FUNC 0x0002
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
72 #define FS_DONE 0x0001
73 #define FS_PROGGNT 0x0002
77 #define FPT_TIME_MASK 0x7FFF
79 #define FPT_ENABLE 0x8000
81 #define FW_WAIT_STATES_MASK 0x00FF
82 #define FW_SET_MASK 0xC000
85 #define FCT_CLK_DIV_MASK 0x0FFF
87 struct lpc288x_flash_bank
{
88 uint32_t working_area
;
89 uint32_t working_area_size
;
91 /* chip id register */
93 const char *target_name
;
96 uint32_t sector_size_break
;
99 static uint32_t lpc288x_wait_status_busy(struct flash_bank
*bank
, int timeout
);
100 static void lpc288x_load_timer(int erase
, struct target
*target
);
101 static void lpc288x_set_flash_clk(struct flash_bank
*bank
);
102 static uint32_t lpc288x_system_ready(struct flash_bank
*bank
);
104 static uint32_t lpc288x_wait_status_busy(struct flash_bank
*bank
, int timeout
)
107 struct target
*target
= bank
->target
;
111 target_read_u32(target
, F_STAT
, &status
);
112 } while (((status
& FS_DONE
) == 0) && timeout
);
115 LOG_DEBUG("Timedout!");
116 return ERROR_FLASH_OPERATION_FAILED
;
121 /* Read device id register and fill in driver info structure */
122 static int lpc288x_read_part_info(struct flash_bank
*bank
)
124 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
125 struct target
*target
= bank
->target
;
131 if (lpc288x_info
->cidr
== 0x0102100A)
132 return ERROR_OK
;/* already probed, multiple probes may cause memory leak, not
135 /* Read and parse chip identification register */
136 target_read_u32(target
, DBGU_CIDR
, &cidr
);
138 if (cidr
!= 0x0102100A) {
139 LOG_WARNING("Cannot identify target as an LPC288X (%08" PRIx32
")", cidr
);
140 return ERROR_FLASH_OPERATION_FAILED
;
143 lpc288x_info
->cidr
= cidr
;
144 lpc288x_info
->sector_size_break
= 0x000F0000;
145 lpc288x_info
->target_name
= "LPC288x";
147 /* setup the sector info... */
149 bank
->num_sectors
= 23;
150 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 23);
152 for (i
= 0; i
< 15; i
++) {
153 bank
->sectors
[i
].offset
= offset
;
154 bank
->sectors
[i
].size
= 64 * 1024;
155 offset
+= bank
->sectors
[i
].size
;
156 bank
->sectors
[i
].is_erased
= -1;
157 bank
->sectors
[i
].is_protected
= 1;
159 for (i
= 15; i
< 23; i
++) {
160 bank
->sectors
[i
].offset
= offset
;
161 bank
->sectors
[i
].size
= 8 * 1024;
162 offset
+= bank
->sectors
[i
].size
;
163 bank
->sectors
[i
].is_erased
= -1;
164 bank
->sectors
[i
].is_protected
= 1;
170 /* TODO: Revisit! Is it impossible to read protection status? */
171 static int lpc288x_protect_check(struct flash_bank
*bank
)
176 /* flash_bank LPC288x 0 0 0 0 <target#> <cclk> */
177 FLASH_BANK_COMMAND_HANDLER(lpc288x_flash_bank_command
)
179 struct lpc288x_flash_bank
*lpc288x_info
;
182 return ERROR_COMMAND_SYNTAX_ERROR
;
184 lpc288x_info
= malloc(sizeof(struct lpc288x_flash_bank
));
185 bank
->driver_priv
= lpc288x_info
;
187 /* part wasn't probed for info yet */
188 lpc288x_info
->cidr
= 0;
189 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[6], lpc288x_info
->cclk
);
194 /* The frequency is the AHB clock frequency divided by (CLK_DIV ×3) + 1.
195 * This must be programmed such that the Flash Programming clock frequency is 66 kHz ± 20%.
197 * 12000000/66000 = 182
199 static void lpc288x_set_flash_clk(struct flash_bank
*bank
)
202 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
203 clk_time
= (lpc288x_info
->cclk
/ 66000) / 3;
204 target_write_u32(bank
->target
, F_CTRL
, FC_CS
| FC_WEN
);
205 target_write_u32(bank
->target
, F_CLK_TIME
, clk_time
);
208 /* AHB tcyc (in ns) 83 ns
209 * LOAD_TIMER_ERASE FPT_TIME = ((400,000,000 / AHB tcyc (in ns)) - 2) / 512
210 * = 9412 (9500) (AN10548 9375)
211 * LOAD_TIMER_WRITE FPT_TIME = ((1,000,000 / AHB tcyc (in ns)) - 2) / 512
212 * = 23 (75) (AN10548 72 - is this wrong?)
213 * TODO: Sort out timing calcs ;) */
214 static void lpc288x_load_timer(int erase
, struct target
*target
)
216 if (erase
== LOAD_TIMER_ERASE
)
217 target_write_u32(target
, F_PROG_TIME
, FPT_ENABLE
| 9500);
219 target_write_u32(target
, F_PROG_TIME
, FPT_ENABLE
| 75);
222 static uint32_t lpc288x_system_ready(struct flash_bank
*bank
)
224 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
225 if (lpc288x_info
->cidr
== 0)
226 return ERROR_FLASH_BANK_NOT_PROBED
;
228 if (bank
->target
->state
!= TARGET_HALTED
) {
229 LOG_ERROR("Target not halted");
230 return ERROR_TARGET_NOT_HALTED
;
235 static int lpc288x_erase(struct flash_bank
*bank
, unsigned int first
,
239 struct target
*target
= bank
->target
;
241 status
= lpc288x_system_ready(bank
); /* probed? halted? */
242 if (status
!= ERROR_OK
)
245 if ((last
< first
) || (last
>= bank
->num_sectors
)) {
246 LOG_INFO("Bad sector range");
247 return ERROR_FLASH_SECTOR_INVALID
;
250 /* Configure the flash controller timing */
251 lpc288x_set_flash_clk(bank
);
253 for (unsigned int sector
= first
; sector
<= last
; sector
++) {
254 if (lpc288x_wait_status_busy(bank
, 1000) != ERROR_OK
)
255 return ERROR_FLASH_OPERATION_FAILED
;
257 lpc288x_load_timer(LOAD_TIMER_ERASE
, target
);
259 target_write_u32(target
, bank
->sectors
[sector
].offset
, 0x00);
261 target_write_u32(target
, F_CTRL
, FC_PROG_REQ
| FC_PROTECT
| FC_CS
);
263 if (lpc288x_wait_status_busy(bank
, 1000) != ERROR_OK
)
264 return ERROR_FLASH_OPERATION_FAILED
;
268 static int lpc288x_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
270 uint8_t page_buffer
[FLASH_PAGE_SIZE
];
271 uint32_t status
, source_offset
, dest_offset
;
272 struct target
*target
= bank
->target
;
273 uint32_t bytes_remaining
= count
;
274 uint32_t first_sector
, last_sector
, sector
, page
;
276 /* probed? halted? */
277 status
= lpc288x_system_ready(bank
);
278 if (status
!= ERROR_OK
)
281 /* Initialise search indices */
282 first_sector
= last_sector
= 0xffffffff;
284 /* validate the write range... */
285 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
286 if ((offset
>= bank
->sectors
[i
].offset
) &&
287 (offset
< (bank
->sectors
[i
].offset
+ bank
->sectors
[i
].size
)) &&
288 (first_sector
== 0xffffffff)) {
290 /* all writes must start on a sector boundary... */
291 if (offset
% bank
->sectors
[i
].size
) {
293 "offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
"",
295 bank
->sectors
[i
].size
);
296 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
299 if (((offset
+ count
) > bank
->sectors
[i
].offset
) &&
300 ((offset
+ count
) <= (bank
->sectors
[i
].offset
+ bank
->sectors
[i
].size
)) &&
301 (last_sector
== 0xffffffff))
306 if (first_sector
== 0xffffffff || last_sector
== 0xffffffff) {
307 LOG_INFO("Range check failed %" PRIx32
" %" PRIx32
"", offset
, count
);
308 return ERROR_FLASH_DST_OUT_OF_BANK
;
311 /* Configure the flash controller timing */
312 lpc288x_set_flash_clk(bank
);
314 /* initialise the offsets */
318 for (sector
= first_sector
; sector
<= last_sector
; sector
++) {
319 for (page
= 0; page
< bank
->sectors
[sector
].size
/ FLASH_PAGE_SIZE
; page
++) {
320 if (bytes_remaining
== 0) {
322 memset(page_buffer
, 0xFF, FLASH_PAGE_SIZE
);
323 } else if (bytes_remaining
< FLASH_PAGE_SIZE
) {
324 count
= bytes_remaining
;
325 memset(page_buffer
, 0xFF, FLASH_PAGE_SIZE
);
326 memcpy(page_buffer
, &buffer
[source_offset
], count
);
328 count
= FLASH_PAGE_SIZE
;
329 memcpy(page_buffer
, &buffer
[source_offset
], count
);
332 /* Wait for flash to become ready */
333 if (lpc288x_wait_status_busy(bank
, 1000) != ERROR_OK
)
334 return ERROR_FLASH_OPERATION_FAILED
;
336 /* fill flash data latches with 1's */
337 target_write_u32(target
, F_CTRL
, FC_CS
| FC_SET_DATA
| FC_WEN
| FC_FUNC
);
339 target_write_u32(target
, F_CTRL
, FC_CS
| FC_WEN
| FC_FUNC
);
341 if (target_write_buffer(target
, offset
+ dest_offset
, FLASH_PAGE_SIZE
,
342 page_buffer
) != ERROR_OK
) {
343 LOG_INFO("Write to flash buffer failed");
344 return ERROR_FLASH_OPERATION_FAILED
;
347 dest_offset
+= FLASH_PAGE_SIZE
;
348 source_offset
+= count
;
349 bytes_remaining
-= count
;
351 lpc288x_load_timer(LOAD_TIMER_WRITE
, target
);
353 target_write_u32(target
, F_CTRL
, FC_PROG_REQ
| FC_PROTECT
| FC_FUNC
|
361 static int lpc288x_probe(struct flash_bank
*bank
)
363 /* we only deal with LPC2888 so flash config is fixed */
364 struct lpc288x_flash_bank
*lpc288x_info
= bank
->driver_priv
;
367 if (lpc288x_info
->cidr
!= 0)
368 return ERROR_OK
;/* already probed */
370 if (bank
->target
->state
!= TARGET_HALTED
) {
371 LOG_ERROR("Target not halted");
372 return ERROR_TARGET_NOT_HALTED
;
375 retval
= lpc288x_read_part_info(bank
);
376 if (retval
!= ERROR_OK
)
381 static int lpc288x_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
386 struct target
*target
= bank
->target
;
388 /* probed? halted? */
389 status
= lpc288x_system_ready(bank
);
390 if (status
!= ERROR_OK
)
393 if ((last
< first
) || (last
>= bank
->num_sectors
))
394 return ERROR_FLASH_SECTOR_INVALID
;
396 /* Configure the flash controller timing */
397 lpc288x_set_flash_clk(bank
);
399 for (unsigned int lockregion
= first
; lockregion
<= last
; lockregion
++) {
401 /* write an odd value to base address to protect... */
404 /* write an even value to base address to unprotect... */
407 target_write_u32(target
, bank
->sectors
[lockregion
].offset
, value
);
408 target_write_u32(target
, F_CTRL
, FC_LOAD_REQ
| FC_PROTECT
| FC_WEN
| FC_FUNC
|
415 const struct flash_driver lpc288x_flash
= {
417 .flash_bank_command
= lpc288x_flash_bank_command
,
418 .erase
= lpc288x_erase
,
419 .protect
= lpc288x_protect
,
420 .write
= lpc288x_write
,
421 .read
= default_flash_read
,
422 .probe
= lpc288x_probe
,
423 .auto_probe
= lpc288x_probe
,
424 .erase_check
= default_flash_blank_check
,
425 .protect_check
= lpc288x_protect_check
,
426 .free_driver_priv
= default_flash_free_driver_priv
,
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)