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 struct flash_ctrl_priv_data
{
40 uint32_t jtag_idcode_reg
;
42 uint32_t flash_regs_base
;
43 uint32_t flash_page_size
;
48 static const struct flash_ctrl_priv_data flash_priv_data_1
= {
49 .die_id_reg
= 0x4090001C,
50 .jtag_idcode_reg
= 0x40900028,
51 .flash_base
= 0x10040000,
52 .flash_regs_base
= 0x40100000,
53 .flash_page_size
= 2048,
54 .jtag_idcode
= 0x00000000,
55 .part_name
= "BLUENRG-1",
58 static const struct flash_ctrl_priv_data flash_priv_data_2
= {
59 .die_id_reg
= 0x4090001C,
60 .jtag_idcode_reg
= 0x40900028,
61 .flash_base
= 0x10040000,
62 .flash_regs_base
= 0x40100000,
63 .flash_page_size
= 2048,
64 .jtag_idcode
= 0x0200A041,
65 .part_name
= "BLUENRG-2",
68 static const struct flash_ctrl_priv_data flash_priv_data_lp
= {
69 .die_id_reg
= 0x40000000,
70 .jtag_idcode_reg
= 0x40000004,
71 .flash_base
= 0x10040000,
72 .flash_regs_base
= 0x40001000,
73 .flash_page_size
= 2048,
74 .jtag_idcode
= 0x0201E041,
75 .part_name
= "BLUENRG-LP",
78 struct bluenrgx_flash_bank
{
81 const struct flash_ctrl_priv_data
*flash_ptr
;
84 static const struct flash_ctrl_priv_data
*flash_ctrl
[] = {
90 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
91 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
93 struct bluenrgx_flash_bank
*bluenrgx_info
;
94 /* Create the bank structure */
95 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
97 /* Check allocation */
99 LOG_ERROR("failed to allocate bank structure");
103 bank
->write_start_alignment
= 16;
104 bank
->write_end_alignment
= 16;
106 bank
->driver_priv
= bluenrgx_info
;
108 bluenrgx_info
->probed
= false;
111 return ERROR_COMMAND_SYNTAX_ERROR
;
116 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
)
118 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
119 return bluenrgx_info
->flash_ptr
->flash_regs_base
+ reg_offset
;
122 static inline int bluenrgx_read_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t *value
)
124 return target_read_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
127 static inline int bluenrgx_write_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t value
)
129 return target_write_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
132 static int bluenrgx_erase(struct flash_bank
*bank
, unsigned int first
,
135 int retval
= ERROR_OK
;
136 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
137 unsigned int num_sectors
= (last
- first
+ 1);
138 const bool mass_erase
= (num_sectors
== bank
->num_sectors
);
139 struct target
*target
= bank
->target
;
140 uint32_t address
, command
;
142 /* check preconditions */
143 if (!bluenrgx_info
->probed
)
144 return ERROR_FLASH_BANK_NOT_PROBED
;
146 if (bank
->target
->state
!= TARGET_HALTED
) {
147 LOG_ERROR("Target not halted");
148 return ERROR_TARGET_NOT_HALTED
;
150 /* Disable blue module */
151 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
152 LOG_ERROR("Blue disable failed");
157 command
= FLASH_CMD_MASSERASE
;
158 address
= bank
->base
;
159 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
160 LOG_ERROR("Register write failed");
164 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
165 (address
- bank
->base
) >> 2) != ERROR_OK
) {
166 LOG_ERROR("Register write failed");
170 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
171 LOG_ERROR("Register write failed");
175 for (unsigned int i
= 0; i
< 100; i
++) {
177 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
178 LOG_ERROR("Register write failed");
181 if (value
& FLASH_INT_CMDDONE
)
184 LOG_ERROR("Mass erase command failed (timeout)");
190 command
= FLASH_CMD_ERASE_PAGE
;
191 for (unsigned int i
= first
; i
<= last
; i
++) {
192 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
193 LOG_DEBUG("address = %08" PRIx32
", index = %u", address
, i
);
195 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
196 LOG_ERROR("Register write failed");
200 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
201 (address
- bank
->base
) >> 2) != ERROR_OK
) {
202 LOG_ERROR("Register write failed");
206 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
211 for (unsigned int j
= 0; j
< 100; j
++) {
213 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
214 LOG_ERROR("Register write failed");
217 if (value
& FLASH_INT_CMDDONE
)
220 LOG_ERROR("Erase command failed (timeout)");
231 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
232 uint32_t offset
, uint32_t count
)
234 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
235 struct target
*target
= bank
->target
;
236 uint32_t buffer_size
= 16384 + 8;
237 struct working_area
*write_algorithm
;
238 struct working_area
*write_algorithm_sp
;
239 struct working_area
*source
;
240 uint32_t address
= bank
->base
+ offset
;
241 struct reg_param reg_params
[5];
242 struct mem_param mem_params
[1];
243 struct armv7m_algorithm armv7m_info
;
244 int retval
= ERROR_OK
;
246 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
247 * hints how to generate the data!
249 static const uint8_t bluenrgx_flash_write_code
[] = {
250 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
253 /* check preconditions */
254 if (!bluenrgx_info
->probed
)
255 return ERROR_FLASH_BANK_NOT_PROBED
;
257 if ((offset
+ count
) > bank
->size
) {
258 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32
", size=%" PRIu32
,
261 return ERROR_FLASH_DST_OUT_OF_BANK
;
264 if (bank
->target
->state
!= TARGET_HALTED
) {
265 LOG_ERROR("Target not halted");
266 return ERROR_TARGET_NOT_HALTED
;
269 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
270 &write_algorithm
) != ERROR_OK
) {
271 LOG_WARNING("no working area available, can't do block memory writes");
272 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
275 retval
= target_write_buffer(target
, write_algorithm
->address
,
276 sizeof(bluenrgx_flash_write_code
),
277 bluenrgx_flash_write_code
);
278 if (retval
!= ERROR_OK
)
282 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
283 LOG_WARNING("no large enough working area available");
284 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
287 /* Stack pointer area */
288 if (target_alloc_working_area(target
, 128,
289 &write_algorithm_sp
) != ERROR_OK
) {
290 LOG_DEBUG("no working area for write code stack pointer");
291 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
294 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
295 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
297 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
298 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
299 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
300 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
301 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
302 /* Put the parameter at the first available stack location */
303 init_mem_param(&mem_params
[0], write_algorithm_sp
->address
+ 80, 32, PARAM_OUT
);
305 /* FIFO start address (first two words used for write and read pointers) */
306 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
307 /* FIFO end address (first two words used for write and read pointers) */
308 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
309 /* Flash memory address */
310 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
311 /* Number of bytes */
312 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
313 /* Stack pointer for program working area */
314 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
315 /* Flash register base address */
316 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
318 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
319 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
320 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT
, write_algorithm_sp
->address
);
321 LOG_DEBUG("address = %08" PRIx32
, address
);
322 LOG_DEBUG("count = %08" PRIx32
, count
);
324 retval
= target_run_flash_async_algorithm(target
,
327 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
334 write_algorithm
->address
,
338 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
339 LOG_ERROR("error executing bluenrg-x flash write algorithm");
341 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
344 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
346 if (retval
== ERROR_OK
) {
348 /* Read back rp and check that is valid */
349 retval
= target_read_u32(target
, source
->address
+4, &rp
);
350 if (retval
== ERROR_OK
) {
351 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
352 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
353 retval
= ERROR_FLASH_OPERATION_FAILED
;
357 target_free_working_area(target
, source
);
358 target_free_working_area(target
, write_algorithm
);
359 target_free_working_area(target
, write_algorithm_sp
);
361 destroy_reg_param(®_params
[0]);
362 destroy_reg_param(®_params
[1]);
363 destroy_reg_param(®_params
[2]);
364 destroy_reg_param(®_params
[3]);
365 destroy_reg_param(®_params
[4]);
366 destroy_mem_param(&mem_params
[0]);
371 static int bluenrgx_probe(struct flash_bank
*bank
)
373 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
374 uint32_t idcode
, size_info
, die_id
;
375 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
377 if (retval
!= ERROR_OK
)
380 if (idcode
!= flash_priv_data_lp
.jtag_idcode
) {
381 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
382 if (retval
!= ERROR_OK
)
386 /* Default device is BlueNRG-1 */
387 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
388 bank
->base
= flash_priv_data_1
.flash_base
;
390 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
391 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
392 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
393 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
397 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
398 if (retval
!= ERROR_OK
)
401 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
402 if (retval
!= ERROR_OK
)
405 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
406 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
407 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
409 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
410 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
411 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
412 bank
->sectors
[i
].is_erased
= -1;
413 bank
->sectors
[i
].is_protected
= 0;
416 bluenrgx_info
->probed
= true;
417 bluenrgx_info
->die_id
= die_id
;
422 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
424 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
426 if (bluenrgx_info
->probed
)
429 return bluenrgx_probe(bank
);
432 /* This method must return a string displaying information about the bank */
433 static int bluenrgx_get_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
435 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
436 int mask_number
, cut_number
;
438 if (!bluenrgx_info
->probed
) {
439 int retval
= bluenrgx_probe(bank
);
440 if (retval
!= ERROR_OK
) {
441 command_print_sameline(cmd
, "Unable to find bank information.");
446 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
447 cut_number
= bluenrgx_info
->die_id
& 0xF;
449 command_print_sameline(cmd
, "%s - Rev: %d.%d",
450 bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
454 const struct flash_driver bluenrgx_flash
= {
456 .flash_bank_command
= bluenrgx_flash_bank_command
,
457 .erase
= bluenrgx_erase
,
459 .write
= bluenrgx_write
,
460 .read
= default_flash_read
,
461 .probe
= bluenrgx_probe
,
462 .erase_check
= default_flash_blank_check
,
463 .protect_check
= NULL
,
464 .auto_probe
= bluenrgx_auto_probe
,
465 .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)