1 /***************************************************************************
2 * Copyright (C) 2017 by Michele Sardo *
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 ***************************************************************************/
23 #include <target/algorithm.h>
24 #include <target/armv7m.h>
25 #include <target/cortex_m.h>
28 #define FLASH_SIZE_REG (0x40100014)
29 #define DIE_ID_REG (0x4090001C)
30 #define JTAG_IDCODE_REG (0x40900028)
31 #define BLUENRG2_IDCODE (0x0200A041)
32 #define FLASH_BASE (0x10040000)
33 #define FLASH_PAGE_SIZE (2048)
34 #define FLASH_REG_COMMAND (0x40100000)
35 #define FLASH_REG_IRQRAW (0x40100010)
36 #define FLASH_REG_ADDRESS (0x40100018)
37 #define FLASH_REG_DATA (0x40100040)
38 #define FLASH_CMD_ERASE_PAGE 0x11
39 #define FLASH_CMD_MASSERASE 0x22
40 #define FLASH_CMD_WRITE 0x33
41 #define FLASH_CMD_BURSTWRITE 0xCC
42 #define FLASH_INT_CMDDONE 0x01
43 #define FLASH_WORD_LEN 4
45 struct bluenrgx_flash_bank
{
51 static int bluenrgx_protect_check(struct flash_bank
*bank
)
53 /* Nothing to do. Protection is only handled in SW. */
57 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
58 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
60 struct bluenrgx_flash_bank
*bluenrgx_info
;
61 /* Create the bank structure */
62 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
64 /* Check allocation */
65 if (bluenrgx_info
== NULL
) {
66 LOG_ERROR("failed to allocate bank structure");
70 bank
->driver_priv
= bluenrgx_info
;
72 bluenrgx_info
->probed
= 0;
75 return ERROR_COMMAND_SYNTAX_ERROR
;
80 static int bluenrgx_erase(struct flash_bank
*bank
, int first
, int last
)
82 int retval
= ERROR_OK
;
83 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
84 int num_sectors
= (last
- first
+ 1);
85 int mass_erase
= (num_sectors
== bank
->num_sectors
);
86 struct target
*target
= bank
->target
;
87 uint32_t address
, command
;
89 /* check preconditions */
90 if (bluenrgx_info
->probed
== 0)
91 return ERROR_FLASH_BANK_NOT_PROBED
;
93 if (bank
->target
->state
!= TARGET_HALTED
) {
94 LOG_ERROR("Target not halted");
95 return ERROR_TARGET_NOT_HALTED
;
97 /* Disable blue module */
98 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
99 LOG_ERROR("Blue disable failed");
104 command
= FLASH_CMD_MASSERASE
;
105 address
= bank
->base
;
106 if (target_write_u32(target
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
107 LOG_ERROR("Register write failed");
111 if (target_write_u32(target
, FLASH_REG_ADDRESS
, address
>> 2) != ERROR_OK
) {
112 LOG_ERROR("Register write failed");
116 if (target_write_u32(target
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
117 LOG_ERROR("Register write failed");
121 for (int i
= 0; i
< 100; i
++) {
123 if (target_read_u32(target
, FLASH_REG_IRQRAW
, &value
)) {
124 LOG_ERROR("Register write failed");
127 if (value
& FLASH_INT_CMDDONE
)
130 LOG_ERROR("Mass erase command failed (timeout)");
136 command
= FLASH_CMD_ERASE_PAGE
;
137 for (int i
= first
; i
<= last
; i
++) {
138 address
= bank
->base
+i
*FLASH_PAGE_SIZE
;
140 if (target_write_u32(target
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
141 LOG_ERROR("Register write failed");
145 if (target_write_u32(target
, FLASH_REG_ADDRESS
, address
>> 2) != ERROR_OK
) {
146 LOG_ERROR("Register write failed");
150 if (target_write_u32(target
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
155 for (int j
= 0; j
< 100; j
++) {
157 if (target_read_u32(target
, FLASH_REG_IRQRAW
, &value
)) {
158 LOG_ERROR("Register write failed");
161 if (value
& FLASH_INT_CMDDONE
)
164 LOG_ERROR("Erase command failed (timeout)");
175 static int bluenrgx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
177 /* Protection is only handled in software: no hardware write protection
178 available in BlueNRG-x devices */
181 for (sector
= first
; sector
<= last
; sector
++)
182 bank
->sectors
[sector
].is_protected
= set
;
185 static int bluenrgx_write_word(struct target
*target
, uint32_t address_base
, uint8_t *values
, uint32_t count
)
187 int retval
= ERROR_OK
;
189 retval
= target_write_u32(target
, FLASH_REG_IRQRAW
, 0x3f);
190 if (retval
!= ERROR_OK
) {
191 LOG_ERROR("Register write failed, error code: %d", retval
);
195 for (uint32_t i
= 0; i
< count
; i
++) {
196 uint32_t address
= address_base
+ i
* FLASH_WORD_LEN
;
198 retval
= target_write_u32(target
, FLASH_REG_ADDRESS
, address
>> 2);
199 if (retval
!= ERROR_OK
) {
200 LOG_ERROR("Register write failed, error code: %d", retval
);
204 retval
= target_write_buffer(target
, FLASH_REG_DATA
, FLASH_WORD_LEN
, values
+ i
* FLASH_WORD_LEN
);
205 if (retval
!= ERROR_OK
) {
206 LOG_ERROR("Register write failed, error code: %d", retval
);
210 retval
= target_write_u32(target
, FLASH_REG_COMMAND
, FLASH_CMD_WRITE
);
211 if (retval
!= ERROR_OK
) {
212 LOG_ERROR("Register write failed, error code: %d", retval
);
216 for (int j
= 0; j
< 100; j
++) {
218 retval
= target_read_u32(target
, FLASH_REG_IRQRAW
, ®_value
);
220 if (retval
!= ERROR_OK
) {
221 LOG_ERROR("Register read failed, error code: %d", retval
);
225 if (reg_value
& FLASH_INT_CMDDONE
)
229 LOG_ERROR("Write command failed (timeout)");
237 static int bluenrgx_write_bytes(struct target
*target
, uint32_t address_base
, uint8_t *buffer
, uint32_t count
)
239 int retval
= ERROR_OK
;
240 uint8_t *new_buffer
= NULL
;
241 uint32_t pre_bytes
= 0, post_bytes
= 0, pre_word
, post_word
, pre_address
, post_address
;
244 /* Just return if there are no bytes to write */
248 if (address_base
& 3) {
249 pre_bytes
= address_base
& 3;
250 pre_address
= address_base
- pre_bytes
;
253 if ((count
+ pre_bytes
) & 3) {
254 post_bytes
= ((count
+ pre_bytes
+ 3) & ~3) - (count
+ pre_bytes
);
255 post_address
= (address_base
+ count
) & ~3;
258 if (pre_bytes
|| post_bytes
) {
259 uint32_t old_count
= count
;
261 count
= old_count
+ pre_bytes
+ post_bytes
;
263 new_buffer
= malloc(count
);
265 if (new_buffer
== NULL
) {
266 LOG_ERROR("odd number of bytes to write and no memory "
267 "for padding buffer");
271 LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32
"), extending to %"
272 PRIu32
" ", old_count
, count
);
275 if (target_read_u32(target
, pre_address
, &pre_word
)) {
276 LOG_ERROR("Memory read failed");
283 if (target_read_u32(target
, post_address
, &post_word
)) {
284 LOG_ERROR("Memory read failed");
290 memcpy(new_buffer
, &pre_word
, pre_bytes
);
291 memcpy((new_buffer
+((pre_bytes
+old_count
) & ~3)), &post_word
, 4);
292 memcpy(new_buffer
+pre_bytes
, buffer
, old_count
);
296 retval
= bluenrgx_write_word(target
, address_base
- pre_bytes
, buffer
, count
/4);
304 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
305 uint32_t offset
, uint32_t count
)
307 struct target
*target
= bank
->target
;
308 uint32_t buffer_size
= 16384 + 8;
309 struct working_area
*write_algorithm
;
310 struct working_area
*write_algorithm_sp
;
311 struct working_area
*source
;
312 uint32_t address
= bank
->base
+ offset
;
313 struct reg_param reg_params
[5];
314 struct armv7m_algorithm armv7m_info
;
315 int retval
= ERROR_OK
;
316 uint32_t pre_size
= 0, fast_size
= 0, post_size
= 0;
317 uint32_t pre_offset
= 0, fast_offset
= 0, post_offset
= 0;
319 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
320 * hints how to generate the data!
322 static const uint8_t bluenrgx_flash_write_code
[] = {
323 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
326 if ((offset
+ count
) > bank
->size
) {
327 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
330 return ERROR_FLASH_DST_OUT_OF_BANK
;
333 if (bank
->target
->state
!= TARGET_HALTED
) {
334 LOG_ERROR("Target not halted");
335 return ERROR_TARGET_NOT_HALTED
;
338 /* We are good here and we need to compute pre_size, fast_size, post_size */
339 pre_size
= MIN(count
, ((offset
+0xF) & ~0xF) - offset
);
341 fast_size
= 16*((count
- pre_size
) / 16);
342 fast_offset
= offset
+ pre_size
;
343 post_size
= (count
-pre_size
-fast_size
) % 16;
344 post_offset
= fast_offset
+ fast_size
;
346 LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size
, pre_offset
);
347 LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size
, fast_offset
);
348 LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size
, post_offset
);
350 /* Program initial chunk not 16 bytes aligned */
351 retval
= bluenrgx_write_bytes(target
, bank
->base
+pre_offset
, (uint8_t *) buffer
, pre_size
);
353 LOG_ERROR("bluenrgx_write_bytes failed %d", retval
);
357 /* Program chunk 16 bytes aligned in fast mode */
360 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
361 &write_algorithm
) != ERROR_OK
) {
362 LOG_WARNING("no working area available, can't do block memory writes");
363 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
366 retval
= target_write_buffer(target
, write_algorithm
->address
,
367 sizeof(bluenrgx_flash_write_code
),
368 bluenrgx_flash_write_code
);
369 if (retval
!= ERROR_OK
)
373 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
374 LOG_WARNING("no large enough working area available");
375 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
378 /* Stack pointer area */
379 if (target_alloc_working_area(target
, 64,
380 &write_algorithm_sp
) != ERROR_OK
) {
381 LOG_DEBUG("no working area for write code stack pointer");
382 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
385 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
386 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
388 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
389 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
390 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
391 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
392 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
394 /* FIFO start address (first two words used for write and read pointers) */
395 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
396 /* FIFO end address (first two words used for write and read pointers) */
397 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
398 /* Flash memory address */
399 buf_set_u32(reg_params
[2].value
, 0, 32, address
+pre_size
);
400 /* Number of bytes */
401 buf_set_u32(reg_params
[3].value
, 0, 32, fast_size
);
402 /* Stack pointer for program working area */
403 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
405 LOG_DEBUG("source->address = %08" TARGET_PRIxADDR
, source
->address
);
406 LOG_DEBUG("source->address+ source->size = %08" TARGET_PRIxADDR
, source
->address
+source
->size
);
407 LOG_DEBUG("write_algorithm_sp->address = %08" TARGET_PRIxADDR
, write_algorithm_sp
->address
);
408 LOG_DEBUG("address = %08x", address
+pre_size
);
409 LOG_DEBUG("count = %08x", count
);
411 retval
= target_run_flash_async_algorithm(target
,
414 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
421 write_algorithm
->address
,
425 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
426 LOG_ERROR("error executing bluenrg-x flash write algorithm");
428 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
431 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
433 if (retval
== ERROR_OK
) {
435 /* Read back rp and check that is valid */
436 retval
= target_read_u32(target
, source
->address
+4, &rp
);
437 if (retval
== ERROR_OK
) {
438 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
439 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
440 retval
= ERROR_FLASH_OPERATION_FAILED
;
444 target_free_working_area(target
, source
);
445 target_free_working_area(target
, write_algorithm
);
446 target_free_working_area(target
, write_algorithm_sp
);
448 destroy_reg_param(®_params
[0]);
449 destroy_reg_param(®_params
[1]);
450 destroy_reg_param(®_params
[2]);
451 destroy_reg_param(®_params
[3]);
452 destroy_reg_param(®_params
[4]);
455 /* Program chunk at end, not addressable by fast burst write algorithm */
456 retval
= bluenrgx_write_bytes(target
, bank
->base
+post_offset
, (uint8_t *) (buffer
+pre_size
+fast_size
), post_size
);
458 LOG_ERROR("bluenrgx_write_bytes failed %d", retval
);
464 static int bluenrgx_probe(struct flash_bank
*bank
)
466 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
467 uint32_t idcode
, size_info
, die_id
;
469 int retval
= target_read_u32(bank
->target
, JTAG_IDCODE_REG
, &idcode
);
470 if (retval
!= ERROR_OK
)
472 retval
= target_read_u32(bank
->target
, FLASH_SIZE_REG
, &size_info
);
473 if (retval
!= ERROR_OK
)
476 retval
= target_read_u32(bank
->target
, DIE_ID_REG
, &die_id
);
477 if (retval
!= ERROR_OK
)
480 bank
->size
= (size_info
+ 1) * 4;
481 bank
->base
= FLASH_BASE
;
482 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE
;
483 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
485 for (i
= 0; i
< bank
->num_sectors
; i
++) {
486 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE
;
487 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE
;
488 bank
->sectors
[i
].is_erased
= -1;
489 bank
->sectors
[i
].is_protected
= 0;
492 bluenrgx_info
->probed
= 1;
493 bluenrgx_info
->die_id
= die_id
;
494 bluenrgx_info
->idcode
= idcode
;
498 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
500 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
502 if (bluenrgx_info
->probed
)
505 return bluenrgx_probe(bank
);
508 /* This method must return a string displaying information about the bank */
509 static int bluenrgx_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
511 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
512 int mask_number
, cut_number
;
515 if (!bluenrgx_info
->probed
) {
516 int retval
= bluenrgx_probe(bank
);
517 if (retval
!= ERROR_OK
) {
518 snprintf(buf
, buf_size
,
519 "Unable to find bank information.");
524 if (bluenrgx_info
->idcode
== BLUENRG2_IDCODE
)
525 part_name
= "BLUENRG-2";
527 part_name
= "BLUENRG-1";
529 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
530 cut_number
= bluenrgx_info
->die_id
& 0xF;
532 snprintf(buf
, buf_size
,
533 "%s - Rev: %d.%d", part_name
, mask_number
, cut_number
);
537 struct flash_driver bluenrgx_flash
= {
539 .flash_bank_command
= bluenrgx_flash_bank_command
,
540 .erase
= bluenrgx_erase
,
541 .protect
= bluenrgx_protect
,
542 .write
= bluenrgx_write
,
543 .read
= default_flash_read
,
544 .probe
= bluenrgx_probe
,
545 .erase_check
= default_flash_blank_check
,
546 .protect_check
= bluenrgx_protect_check
,
547 .auto_probe
= bluenrgx_auto_probe
,
548 .info
= bluenrgx_get_info
,
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)