1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Michele Sardo *
6 ***************************************************************************/
12 #include <helper/binarybuffer.h>
13 #include "helper/types.h"
14 #include <target/algorithm.h>
15 #include <target/armv7m.h>
16 #include <target/cortex_m.h>
18 #include "bluenrg-x.h"
20 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
21 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
23 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
24 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
25 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
27 #define FLASH_SIZE_REG_MASK (0xFFFF)
29 struct flash_ctrl_priv_data
{
31 uint32_t jtag_idcode_reg
;
33 uint32_t flash_regs_base
;
34 uint32_t flash_page_size
;
39 static const struct flash_ctrl_priv_data flash_priv_data_1
= {
40 .die_id_reg
= 0x4090001C,
41 .jtag_idcode_reg
= 0x40900028,
42 .flash_base
= 0x10040000,
43 .flash_regs_base
= 0x40100000,
44 .flash_page_size
= 2048,
45 .jtag_idcode
= 0x00000000,
46 .part_name
= "BLUENRG-1",
49 static const struct flash_ctrl_priv_data flash_priv_data_2
= {
50 .die_id_reg
= 0x4090001C,
51 .jtag_idcode_reg
= 0x40900028,
52 .flash_base
= 0x10040000,
53 .flash_regs_base
= 0x40100000,
54 .flash_page_size
= 2048,
55 .jtag_idcode
= 0x0200A041,
56 .part_name
= "BLUENRG-2",
59 static const struct flash_ctrl_priv_data flash_priv_data_lp
= {
60 .die_id_reg
= 0x40000000,
61 .jtag_idcode_reg
= 0x40000004,
62 .flash_base
= 0x10040000,
63 .flash_regs_base
= 0x40001000,
64 .flash_page_size
= 2048,
65 .jtag_idcode
= 0x0201E041,
66 .part_name
= "BLUENRG-LP",
69 static const struct flash_ctrl_priv_data flash_priv_data_lps
= {
70 .die_id_reg
= 0x40000000,
71 .jtag_idcode_reg
= 0x40000004,
72 .flash_base
= 0x10040000,
73 .flash_regs_base
= 0x40001000,
74 .flash_page_size
= 2048,
75 .jtag_idcode
= 0x02028041,
76 .part_name
= "BLUENRG-LPS",
79 struct bluenrgx_flash_bank
{
82 const struct flash_ctrl_priv_data
*flash_ptr
;
85 static const struct flash_ctrl_priv_data
*flash_ctrl
[] = {
89 &flash_priv_data_lps
};
91 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
92 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
94 struct bluenrgx_flash_bank
*bluenrgx_info
;
95 /* Create the bank structure */
96 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
98 /* Check allocation */
100 LOG_ERROR("failed to allocate bank structure");
104 bank
->write_start_alignment
= 16;
105 bank
->write_end_alignment
= 16;
107 bank
->driver_priv
= bluenrgx_info
;
109 bluenrgx_info
->probed
= false;
112 return ERROR_COMMAND_SYNTAX_ERROR
;
117 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
)
119 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
120 return bluenrgx_info
->flash_ptr
->flash_regs_base
+ reg_offset
;
123 static inline int bluenrgx_read_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t *value
)
125 return target_read_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
128 static inline int bluenrgx_write_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t value
)
130 return target_write_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
133 static int bluenrgx_erase(struct flash_bank
*bank
, unsigned int first
,
136 int retval
= ERROR_OK
;
137 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
138 unsigned int num_sectors
= (last
- first
+ 1);
139 const bool mass_erase
= (num_sectors
== bank
->num_sectors
);
140 struct target
*target
= bank
->target
;
141 uint32_t address
, command
;
143 /* check preconditions */
144 if (!bluenrgx_info
->probed
)
145 return ERROR_FLASH_BANK_NOT_PROBED
;
147 if (bank
->target
->state
!= TARGET_HALTED
) {
148 LOG_ERROR("Target not halted");
149 return ERROR_TARGET_NOT_HALTED
;
151 /* Disable blue module */
152 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
153 LOG_ERROR("Blue disable failed");
158 command
= FLASH_CMD_MASSERASE
;
159 address
= bank
->base
;
160 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
161 LOG_ERROR("Register write failed");
165 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
166 (address
- bank
->base
) >> 2) != ERROR_OK
) {
167 LOG_ERROR("Register write failed");
171 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
172 LOG_ERROR("Register write failed");
176 for (unsigned int i
= 0; i
< 100; i
++) {
178 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
179 LOG_ERROR("Register write failed");
182 if (value
& FLASH_INT_CMDDONE
)
185 LOG_ERROR("Mass erase command failed (timeout)");
191 command
= FLASH_CMD_ERASE_PAGE
;
192 for (unsigned int i
= first
; i
<= last
; i
++) {
193 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
194 LOG_DEBUG("address = %08" PRIx32
", index = %u", address
, i
);
196 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
197 LOG_ERROR("Register write failed");
201 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
202 (address
- bank
->base
) >> 2) != ERROR_OK
) {
203 LOG_ERROR("Register write failed");
207 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
212 for (unsigned int j
= 0; j
< 100; j
++) {
214 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
215 LOG_ERROR("Register write failed");
218 if (value
& FLASH_INT_CMDDONE
)
221 LOG_ERROR("Erase command failed (timeout)");
232 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
233 uint32_t offset
, uint32_t count
)
235 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
236 struct target
*target
= bank
->target
;
237 uint32_t buffer_size
= 16384 + 8;
238 struct working_area
*write_algorithm
;
239 struct working_area
*write_algorithm_stack
;
240 struct working_area
*source
;
241 uint32_t address
= bank
->base
+ offset
;
242 struct reg_param reg_params
[5];
243 struct mem_param mem_params
[1];
244 struct armv7m_algorithm armv7m_info
;
245 int retval
= ERROR_OK
;
247 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
248 * hints how to generate the data!
250 static const uint8_t bluenrgx_flash_write_code
[] = {
251 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
254 /* check preconditions */
255 if (!bluenrgx_info
->probed
)
256 return ERROR_FLASH_BANK_NOT_PROBED
;
258 if ((offset
+ count
) > bank
->size
) {
259 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32
", size=%" PRIu32
,
262 return ERROR_FLASH_DST_OUT_OF_BANK
;
265 if (bank
->target
->state
!= TARGET_HALTED
) {
266 LOG_ERROR("Target not halted");
267 return ERROR_TARGET_NOT_HALTED
;
270 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
271 &write_algorithm
) != ERROR_OK
) {
272 LOG_WARNING("no working area available, can't do block memory writes");
273 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
276 retval
= target_write_buffer(target
, write_algorithm
->address
,
277 sizeof(bluenrgx_flash_write_code
),
278 bluenrgx_flash_write_code
);
279 if (retval
!= ERROR_OK
)
283 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
284 LOG_WARNING("no large enough working area available");
285 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
289 if (target_alloc_working_area(target
, 128,
290 &write_algorithm_stack
) != ERROR_OK
) {
291 LOG_DEBUG("no working area for target algorithm stack");
292 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
295 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
296 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
298 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
299 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
300 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
301 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
302 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
303 /* Put the 4th parameter at the location in the stack frame of target write() function.
304 * See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.lst
305 * 34 ldr r6, [sp, #80]
308 init_mem_param(&mem_params
[0], write_algorithm_stack
->address
+ 80, 32, PARAM_OUT
);
309 /* Stack for target write algorithm - target write() function has
310 * __attribute__((naked)) so it does not setup the new stack frame.
311 * Therefore the stack frame uses the area from SP upwards!
312 * Interrupts are disabled and no subroutines are called from write()
313 * so no need to allocate stack below SP.
314 * TODO: remove __attribute__((naked)) and use similar parameter passing as stm32l4x */
315 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_stack
->address
);
317 /* FIFO start address (first two words used for write and read pointers) */
318 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
319 /* FIFO end address (first two words used for write and read pointers) */
320 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
321 /* Flash memory address */
322 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
323 /* Number of bytes */
324 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
325 /* Flash register base address */
326 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
328 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
329 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
330 LOG_DEBUG("write_algorithm_stack->address = " TARGET_ADDR_FMT
, write_algorithm_stack
->address
);
331 LOG_DEBUG("address = %08" PRIx32
, address
);
332 LOG_DEBUG("count = %08" PRIx32
, count
);
334 retval
= target_run_flash_async_algorithm(target
,
337 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
344 write_algorithm
->address
,
348 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
349 LOG_ERROR("error executing bluenrg-x flash write algorithm");
351 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
354 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
356 if (retval
== ERROR_OK
) {
358 /* Read back rp and check that is valid */
359 retval
= target_read_u32(target
, source
->address
+4, &rp
);
360 if (retval
== ERROR_OK
) {
361 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
362 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
363 retval
= ERROR_FLASH_OPERATION_FAILED
;
367 target_free_working_area(target
, source
);
368 target_free_working_area(target
, write_algorithm
);
369 target_free_working_area(target
, write_algorithm_stack
);
371 destroy_reg_param(®_params
[0]);
372 destroy_reg_param(®_params
[1]);
373 destroy_reg_param(®_params
[2]);
374 destroy_reg_param(®_params
[3]);
375 destroy_reg_param(®_params
[4]);
376 destroy_mem_param(&mem_params
[0]);
381 static int bluenrgx_probe(struct flash_bank
*bank
)
383 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
384 uint32_t idcode
, size_info
, die_id
;
385 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
387 if (retval
!= ERROR_OK
)
390 if ((idcode
!= flash_priv_data_lp
.jtag_idcode
) && (idcode
!= flash_priv_data_lps
.jtag_idcode
)) {
391 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
392 if (retval
!= ERROR_OK
)
396 /* Default device is BlueNRG-1 */
397 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
398 bank
->base
= flash_priv_data_1
.flash_base
;
400 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
401 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
402 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
403 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
407 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
408 size_info
= size_info
& FLASH_SIZE_REG_MASK
;
409 if (retval
!= ERROR_OK
)
412 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
413 if (retval
!= ERROR_OK
)
416 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
417 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
418 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
420 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
421 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
422 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
423 bank
->sectors
[i
].is_erased
= -1;
424 bank
->sectors
[i
].is_protected
= 0;
427 bluenrgx_info
->probed
= true;
428 bluenrgx_info
->die_id
= die_id
;
433 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
435 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
437 if (bluenrgx_info
->probed
)
440 return bluenrgx_probe(bank
);
443 /* This method must return a string displaying information about the bank */
444 static int bluenrgx_get_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
446 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
447 int mask_number
, cut_number
;
449 if (!bluenrgx_info
->probed
) {
450 int retval
= bluenrgx_probe(bank
);
451 if (retval
!= ERROR_OK
) {
452 command_print_sameline(cmd
, "Unable to find bank information.");
457 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
458 cut_number
= bluenrgx_info
->die_id
& 0xF;
460 command_print_sameline(cmd
, "%s - Rev: %d.%d",
461 bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
465 const struct flash_driver bluenrgx_flash
= {
467 .flash_bank_command
= bluenrgx_flash_bank_command
,
468 .erase
= bluenrgx_erase
,
470 .write
= bluenrgx_write
,
471 .read
= default_flash_read
,
472 .probe
= bluenrgx_probe
,
473 .erase_check
= default_flash_blank_check
,
474 .protect_check
= NULL
,
475 .auto_probe
= bluenrgx_auto_probe
,
476 .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)