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 <helper/binarybuffer.h>
24 #include "helper/types.h"
25 #include <target/algorithm.h>
26 #include <target/armv7m.h>
27 #include <target/cortex_m.h>
29 #include "bluenrg-x.h"
31 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
32 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
34 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
35 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
36 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
38 #define FLASH_SIZE_REG_MASK (0xFFFF)
40 struct flash_ctrl_priv_data
{
42 uint32_t jtag_idcode_reg
;
44 uint32_t flash_regs_base
;
45 uint32_t flash_page_size
;
50 static const struct flash_ctrl_priv_data flash_priv_data_1
= {
51 .die_id_reg
= 0x4090001C,
52 .jtag_idcode_reg
= 0x40900028,
53 .flash_base
= 0x10040000,
54 .flash_regs_base
= 0x40100000,
55 .flash_page_size
= 2048,
56 .jtag_idcode
= 0x00000000,
57 .part_name
= "BLUENRG-1",
60 static const struct flash_ctrl_priv_data flash_priv_data_2
= {
61 .die_id_reg
= 0x4090001C,
62 .jtag_idcode_reg
= 0x40900028,
63 .flash_base
= 0x10040000,
64 .flash_regs_base
= 0x40100000,
65 .flash_page_size
= 2048,
66 .jtag_idcode
= 0x0200A041,
67 .part_name
= "BLUENRG-2",
70 static const struct flash_ctrl_priv_data flash_priv_data_lp
= {
71 .die_id_reg
= 0x40000000,
72 .jtag_idcode_reg
= 0x40000004,
73 .flash_base
= 0x10040000,
74 .flash_regs_base
= 0x40001000,
75 .flash_page_size
= 2048,
76 .jtag_idcode
= 0x0201E041,
77 .part_name
= "BLUENRG-LP",
80 static const struct flash_ctrl_priv_data flash_priv_data_lps
= {
81 .die_id_reg
= 0x40000000,
82 .jtag_idcode_reg
= 0x40000004,
83 .flash_base
= 0x10040000,
84 .flash_regs_base
= 0x40001000,
85 .flash_page_size
= 2048,
86 .jtag_idcode
= 0x02028041,
87 .part_name
= "BLUENRG-LPS",
90 struct bluenrgx_flash_bank
{
93 const struct flash_ctrl_priv_data
*flash_ptr
;
96 static const struct flash_ctrl_priv_data
*flash_ctrl
[] = {
100 &flash_priv_data_lps
};
102 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
103 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
105 struct bluenrgx_flash_bank
*bluenrgx_info
;
106 /* Create the bank structure */
107 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
109 /* Check allocation */
110 if (!bluenrgx_info
) {
111 LOG_ERROR("failed to allocate bank structure");
115 bank
->write_start_alignment
= 16;
116 bank
->write_end_alignment
= 16;
118 bank
->driver_priv
= bluenrgx_info
;
120 bluenrgx_info
->probed
= false;
123 return ERROR_COMMAND_SYNTAX_ERROR
;
128 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
)
130 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
131 return bluenrgx_info
->flash_ptr
->flash_regs_base
+ reg_offset
;
134 static inline int bluenrgx_read_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t *value
)
136 return target_read_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
139 static inline int bluenrgx_write_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t value
)
141 return target_write_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
144 static int bluenrgx_erase(struct flash_bank
*bank
, unsigned int first
,
147 int retval
= ERROR_OK
;
148 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
149 unsigned int num_sectors
= (last
- first
+ 1);
150 const bool mass_erase
= (num_sectors
== bank
->num_sectors
);
151 struct target
*target
= bank
->target
;
152 uint32_t address
, command
;
154 /* check preconditions */
155 if (!bluenrgx_info
->probed
)
156 return ERROR_FLASH_BANK_NOT_PROBED
;
158 if (bank
->target
->state
!= TARGET_HALTED
) {
159 LOG_ERROR("Target not halted");
160 return ERROR_TARGET_NOT_HALTED
;
162 /* Disable blue module */
163 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
164 LOG_ERROR("Blue disable failed");
169 command
= FLASH_CMD_MASSERASE
;
170 address
= bank
->base
;
171 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
172 LOG_ERROR("Register write failed");
176 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
177 (address
- bank
->base
) >> 2) != ERROR_OK
) {
178 LOG_ERROR("Register write failed");
182 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
183 LOG_ERROR("Register write failed");
187 for (unsigned int i
= 0; i
< 100; i
++) {
189 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
190 LOG_ERROR("Register write failed");
193 if (value
& FLASH_INT_CMDDONE
)
196 LOG_ERROR("Mass erase command failed (timeout)");
202 command
= FLASH_CMD_ERASE_PAGE
;
203 for (unsigned int i
= first
; i
<= last
; i
++) {
204 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
205 LOG_DEBUG("address = %08" PRIx32
", index = %u", address
, i
);
207 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
208 LOG_ERROR("Register write failed");
212 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
213 (address
- bank
->base
) >> 2) != ERROR_OK
) {
214 LOG_ERROR("Register write failed");
218 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
223 for (unsigned int j
= 0; j
< 100; j
++) {
225 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
226 LOG_ERROR("Register write failed");
229 if (value
& FLASH_INT_CMDDONE
)
232 LOG_ERROR("Erase command failed (timeout)");
243 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
244 uint32_t offset
, uint32_t count
)
246 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
247 struct target
*target
= bank
->target
;
248 uint32_t buffer_size
= 16384 + 8;
249 struct working_area
*write_algorithm
;
250 struct working_area
*write_algorithm_sp
;
251 struct working_area
*source
;
252 uint32_t address
= bank
->base
+ offset
;
253 struct reg_param reg_params
[5];
254 struct mem_param mem_params
[1];
255 struct armv7m_algorithm armv7m_info
;
256 int retval
= ERROR_OK
;
258 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
259 * hints how to generate the data!
261 static const uint8_t bluenrgx_flash_write_code
[] = {
262 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
265 /* check preconditions */
266 if (!bluenrgx_info
->probed
)
267 return ERROR_FLASH_BANK_NOT_PROBED
;
269 if ((offset
+ count
) > bank
->size
) {
270 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32
", size=%" PRIu32
,
273 return ERROR_FLASH_DST_OUT_OF_BANK
;
276 if (bank
->target
->state
!= TARGET_HALTED
) {
277 LOG_ERROR("Target not halted");
278 return ERROR_TARGET_NOT_HALTED
;
281 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
282 &write_algorithm
) != ERROR_OK
) {
283 LOG_WARNING("no working area available, can't do block memory writes");
284 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
287 retval
= target_write_buffer(target
, write_algorithm
->address
,
288 sizeof(bluenrgx_flash_write_code
),
289 bluenrgx_flash_write_code
);
290 if (retval
!= ERROR_OK
)
294 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
295 LOG_WARNING("no large enough working area available");
296 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
299 /* Stack pointer area */
300 if (target_alloc_working_area(target
, 128,
301 &write_algorithm_sp
) != ERROR_OK
) {
302 LOG_DEBUG("no working area for write code stack pointer");
303 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
306 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
307 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
309 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
310 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
311 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
312 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
313 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
314 /* Put the parameter at the first available stack location */
315 init_mem_param(&mem_params
[0], write_algorithm_sp
->address
+ 80, 32, PARAM_OUT
);
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 /* Stack pointer for program working area */
326 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
327 /* Flash register base address */
328 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
330 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
331 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
332 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT
, write_algorithm_sp
->address
);
333 LOG_DEBUG("address = %08" PRIx32
, address
);
334 LOG_DEBUG("count = %08" PRIx32
, count
);
336 retval
= target_run_flash_async_algorithm(target
,
339 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
346 write_algorithm
->address
,
350 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
351 LOG_ERROR("error executing bluenrg-x flash write algorithm");
353 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
356 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
358 if (retval
== ERROR_OK
) {
360 /* Read back rp and check that is valid */
361 retval
= target_read_u32(target
, source
->address
+4, &rp
);
362 if (retval
== ERROR_OK
) {
363 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
364 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
365 retval
= ERROR_FLASH_OPERATION_FAILED
;
369 target_free_working_area(target
, source
);
370 target_free_working_area(target
, write_algorithm
);
371 target_free_working_area(target
, write_algorithm_sp
);
373 destroy_reg_param(®_params
[0]);
374 destroy_reg_param(®_params
[1]);
375 destroy_reg_param(®_params
[2]);
376 destroy_reg_param(®_params
[3]);
377 destroy_reg_param(®_params
[4]);
378 destroy_mem_param(&mem_params
[0]);
383 static int bluenrgx_probe(struct flash_bank
*bank
)
385 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
386 uint32_t idcode
, size_info
, die_id
;
387 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
389 if (retval
!= ERROR_OK
)
392 if ((idcode
!= flash_priv_data_lp
.jtag_idcode
) && (idcode
!= flash_priv_data_lps
.jtag_idcode
)) {
393 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
394 if (retval
!= ERROR_OK
)
398 /* Default device is BlueNRG-1 */
399 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
400 bank
->base
= flash_priv_data_1
.flash_base
;
402 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
403 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
404 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
405 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
409 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
410 size_info
= size_info
& FLASH_SIZE_REG_MASK
;
411 if (retval
!= ERROR_OK
)
414 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
415 if (retval
!= ERROR_OK
)
418 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
419 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
420 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
422 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
423 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
424 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
425 bank
->sectors
[i
].is_erased
= -1;
426 bank
->sectors
[i
].is_protected
= 0;
429 bluenrgx_info
->probed
= true;
430 bluenrgx_info
->die_id
= die_id
;
435 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
437 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
439 if (bluenrgx_info
->probed
)
442 return bluenrgx_probe(bank
);
445 /* This method must return a string displaying information about the bank */
446 static int bluenrgx_get_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
448 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
449 int mask_number
, cut_number
;
451 if (!bluenrgx_info
->probed
) {
452 int retval
= bluenrgx_probe(bank
);
453 if (retval
!= ERROR_OK
) {
454 command_print_sameline(cmd
, "Unable to find bank information.");
459 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
460 cut_number
= bluenrgx_info
->die_id
& 0xF;
462 command_print_sameline(cmd
, "%s - Rev: %d.%d",
463 bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
467 const struct flash_driver bluenrgx_flash
= {
469 .flash_bank_command
= bluenrgx_flash_bank_command
,
470 .erase
= bluenrgx_erase
,
472 .write
= bluenrgx_write
,
473 .read
= default_flash_read
,
474 .probe
= bluenrgx_probe
,
475 .erase_check
= default_flash_blank_check
,
476 .protect_check
= NULL
,
477 .auto_probe
= bluenrgx_auto_probe
,
478 .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)