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");
284 if (target_read_u32(target
, post_address
, &post_word
)) {
285 LOG_ERROR("Memory read failed");
292 memcpy(new_buffer
, &pre_word
, pre_bytes
);
293 memcpy((new_buffer
+((pre_bytes
+old_count
) & ~3)), &post_word
, 4);
294 memcpy(new_buffer
+pre_bytes
, buffer
, old_count
);
298 retval
= bluenrgx_write_word(target
, address_base
- pre_bytes
, buffer
, count
/4);
306 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
307 uint32_t offset
, uint32_t count
)
309 struct target
*target
= bank
->target
;
310 uint32_t buffer_size
= 16384 + 8;
311 struct working_area
*write_algorithm
;
312 struct working_area
*write_algorithm_sp
;
313 struct working_area
*source
;
314 uint32_t address
= bank
->base
+ offset
;
315 struct reg_param reg_params
[5];
316 struct armv7m_algorithm armv7m_info
;
317 int retval
= ERROR_OK
;
318 uint32_t pre_size
= 0, fast_size
= 0, post_size
= 0;
319 uint32_t pre_offset
= 0, fast_offset
= 0, post_offset
= 0;
321 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
322 * hints how to generate the data!
324 static const uint8_t bluenrgx_flash_write_code
[] = {
325 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
328 if ((offset
+ count
) > bank
->size
) {
329 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
332 return ERROR_FLASH_DST_OUT_OF_BANK
;
335 if (bank
->target
->state
!= TARGET_HALTED
) {
336 LOG_ERROR("Target not halted");
337 return ERROR_TARGET_NOT_HALTED
;
340 /* We are good here and we need to compute pre_size, fast_size, post_size */
341 pre_size
= MIN(count
, ((offset
+0xF) & ~0xF) - offset
);
343 fast_size
= 16*((count
- pre_size
) / 16);
344 fast_offset
= offset
+ pre_size
;
345 post_size
= (count
-pre_size
-fast_size
) % 16;
346 post_offset
= fast_offset
+ fast_size
;
348 LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size
, pre_offset
);
349 LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size
, fast_offset
);
350 LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size
, post_offset
);
352 /* Program initial chunk not 16 bytes aligned */
353 retval
= bluenrgx_write_bytes(target
, bank
->base
+pre_offset
, (uint8_t *) buffer
, pre_size
);
355 LOG_ERROR("bluenrgx_write_bytes failed %d", retval
);
359 /* Program chunk 16 bytes aligned in fast mode */
362 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
363 &write_algorithm
) != ERROR_OK
) {
364 LOG_WARNING("no working area available, can't do block memory writes");
365 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
368 retval
= target_write_buffer(target
, write_algorithm
->address
,
369 sizeof(bluenrgx_flash_write_code
),
370 bluenrgx_flash_write_code
);
371 if (retval
!= ERROR_OK
)
375 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
376 LOG_WARNING("no large enough working area available");
377 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
380 /* Stack pointer area */
381 if (target_alloc_working_area(target
, 64,
382 &write_algorithm_sp
) != ERROR_OK
) {
383 LOG_DEBUG("no working area for write code stack pointer");
384 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
387 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
388 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
390 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
391 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
392 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
393 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
394 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
396 /* FIFO start address (first two words used for write and read pointers) */
397 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
398 /* FIFO end address (first two words used for write and read pointers) */
399 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
400 /* Flash memory address */
401 buf_set_u32(reg_params
[2].value
, 0, 32, address
+pre_size
);
402 /* Number of bytes */
403 buf_set_u32(reg_params
[3].value
, 0, 32, fast_size
);
404 /* Stack pointer for program working area */
405 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
407 LOG_DEBUG("source->address = %08" TARGET_PRIxADDR
, source
->address
);
408 LOG_DEBUG("source->address+ source->size = %08" TARGET_PRIxADDR
, source
->address
+source
->size
);
409 LOG_DEBUG("write_algorithm_sp->address = %08" TARGET_PRIxADDR
, write_algorithm_sp
->address
);
410 LOG_DEBUG("address = %08x", address
+pre_size
);
411 LOG_DEBUG("count = %08x", count
);
413 retval
= target_run_flash_async_algorithm(target
,
416 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
423 write_algorithm
->address
,
427 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
428 LOG_ERROR("error executing bluenrg-x flash write algorithm");
430 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
433 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
435 if (retval
== ERROR_OK
) {
437 /* Read back rp and check that is valid */
438 retval
= target_read_u32(target
, source
->address
+4, &rp
);
439 if (retval
== ERROR_OK
) {
440 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
441 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
442 retval
= ERROR_FLASH_OPERATION_FAILED
;
446 target_free_working_area(target
, source
);
447 target_free_working_area(target
, write_algorithm
);
448 target_free_working_area(target
, write_algorithm_sp
);
450 destroy_reg_param(®_params
[0]);
451 destroy_reg_param(®_params
[1]);
452 destroy_reg_param(®_params
[2]);
453 destroy_reg_param(®_params
[3]);
454 destroy_reg_param(®_params
[4]);
455 if (retval
!= ERROR_OK
)
460 /* Program chunk at end, not addressable by fast burst write algorithm */
461 retval
= bluenrgx_write_bytes(target
, bank
->base
+post_offset
, (uint8_t *) (buffer
+pre_size
+fast_size
), post_size
);
463 LOG_ERROR("bluenrgx_write_bytes failed %d", retval
);
469 static int bluenrgx_probe(struct flash_bank
*bank
)
471 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
472 uint32_t idcode
, size_info
, die_id
;
474 int retval
= target_read_u32(bank
->target
, JTAG_IDCODE_REG
, &idcode
);
475 if (retval
!= ERROR_OK
)
477 retval
= target_read_u32(bank
->target
, FLASH_SIZE_REG
, &size_info
);
478 if (retval
!= ERROR_OK
)
481 retval
= target_read_u32(bank
->target
, DIE_ID_REG
, &die_id
);
482 if (retval
!= ERROR_OK
)
485 bank
->size
= (size_info
+ 1) * 4;
486 bank
->base
= FLASH_BASE
;
487 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE
;
488 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
490 for (i
= 0; i
< bank
->num_sectors
; i
++) {
491 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE
;
492 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE
;
493 bank
->sectors
[i
].is_erased
= -1;
494 bank
->sectors
[i
].is_protected
= 0;
497 bluenrgx_info
->probed
= 1;
498 bluenrgx_info
->die_id
= die_id
;
499 bluenrgx_info
->idcode
= idcode
;
503 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
505 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
507 if (bluenrgx_info
->probed
)
510 return bluenrgx_probe(bank
);
513 /* This method must return a string displaying information about the bank */
514 static int bluenrgx_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
516 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
517 int mask_number
, cut_number
;
520 if (!bluenrgx_info
->probed
) {
521 int retval
= bluenrgx_probe(bank
);
522 if (retval
!= ERROR_OK
) {
523 snprintf(buf
, buf_size
,
524 "Unable to find bank information.");
529 if (bluenrgx_info
->idcode
== BLUENRG2_IDCODE
)
530 part_name
= "BLUENRG-2";
532 part_name
= "BLUENRG-1";
534 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
535 cut_number
= bluenrgx_info
->die_id
& 0xF;
537 snprintf(buf
, buf_size
,
538 "%s - Rev: %d.%d", part_name
, mask_number
, cut_number
);
542 struct flash_driver bluenrgx_flash
= {
544 .flash_bank_command
= bluenrgx_flash_bank_command
,
545 .erase
= bluenrgx_erase
,
546 .protect
= bluenrgx_protect
,
547 .write
= bluenrgx_write
,
548 .read
= default_flash_read
,
549 .probe
= bluenrgx_probe
,
550 .erase_check
= default_flash_blank_check
,
551 .protect_check
= bluenrgx_protect_check
,
552 .auto_probe
= bluenrgx_auto_probe
,
553 .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)