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/types.h"
24 #include <target/algorithm.h>
25 #include <target/armv7m.h>
26 #include <target/cortex_m.h>
28 #include "bluenrg-x.h"
30 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
31 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
33 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
34 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
35 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
37 struct flash_ctrl_priv_data
{
39 uint32_t jtag_idcode_reg
;
41 uint32_t flash_regs_base
;
42 uint32_t flash_page_size
;
47 static const struct flash_ctrl_priv_data flash_priv_data_1
= {
48 .die_id_reg
= 0x4090001C,
49 .jtag_idcode_reg
= 0x40900028,
50 .flash_base
= 0x10040000,
51 .flash_regs_base
= 0x40100000,
52 .flash_page_size
= 2048,
53 .jtag_idcode
= 0x00000000,
54 .part_name
= "BLUENRG-1",
57 static const struct flash_ctrl_priv_data flash_priv_data_2
= {
58 .die_id_reg
= 0x4090001C,
59 .jtag_idcode_reg
= 0x40900028,
60 .flash_base
= 0x10040000,
61 .flash_regs_base
= 0x40100000,
62 .flash_page_size
= 2048,
63 .jtag_idcode
= 0x0200A041,
64 .part_name
= "BLUENRG-2",
67 static const struct flash_ctrl_priv_data flash_priv_data_lp
= {
68 .die_id_reg
= 0x40000000,
69 .jtag_idcode_reg
= 0x40000004,
70 .flash_base
= 0x10040000,
71 .flash_regs_base
= 0x40001000,
72 .flash_page_size
= 2048,
73 .jtag_idcode
= 0x0201E041,
74 .part_name
= "BLUENRG-LP",
77 struct bluenrgx_flash_bank
{
80 const struct flash_ctrl_priv_data
*flash_ptr
;
83 static const struct flash_ctrl_priv_data
*flash_ctrl
[] = {
89 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
90 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
92 struct bluenrgx_flash_bank
*bluenrgx_info
;
93 /* Create the bank structure */
94 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
96 /* Check allocation */
97 if (bluenrgx_info
== NULL
) {
98 LOG_ERROR("failed to allocate bank structure");
102 bank
->write_start_alignment
= 16;
103 bank
->write_end_alignment
= 16;
105 bank
->driver_priv
= bluenrgx_info
;
107 bluenrgx_info
->probed
= false;
110 return ERROR_COMMAND_SYNTAX_ERROR
;
115 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
)
117 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
118 return bluenrgx_info
->flash_ptr
->flash_regs_base
+ reg_offset
;
121 static inline int bluenrgx_read_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t *value
)
123 return target_read_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
126 static inline int bluenrgx_write_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t value
)
128 return target_write_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
131 static int bluenrgx_erase(struct flash_bank
*bank
, unsigned int first
,
134 int retval
= ERROR_OK
;
135 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
136 unsigned int num_sectors
= (last
- first
+ 1);
137 const bool mass_erase
= (num_sectors
== bank
->num_sectors
);
138 struct target
*target
= bank
->target
;
139 uint32_t address
, command
;
141 /* check preconditions */
142 if (!bluenrgx_info
->probed
)
143 return ERROR_FLASH_BANK_NOT_PROBED
;
145 if (bank
->target
->state
!= TARGET_HALTED
) {
146 LOG_ERROR("Target not halted");
147 return ERROR_TARGET_NOT_HALTED
;
149 /* Disable blue module */
150 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
151 LOG_ERROR("Blue disable failed");
156 command
= FLASH_CMD_MASSERASE
;
157 address
= bank
->base
;
158 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
159 LOG_ERROR("Register write failed");
163 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
164 (address
- bank
->base
) >> 2) != ERROR_OK
) {
165 LOG_ERROR("Register write failed");
169 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
170 LOG_ERROR("Register write failed");
174 for (unsigned int i
= 0; i
< 100; i
++) {
176 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
177 LOG_ERROR("Register write failed");
180 if (value
& FLASH_INT_CMDDONE
)
183 LOG_ERROR("Mass erase command failed (timeout)");
189 command
= FLASH_CMD_ERASE_PAGE
;
190 for (unsigned int i
= first
; i
<= last
; i
++) {
191 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
192 LOG_DEBUG("address = %08" PRIx32
", index = %u", address
, i
);
194 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
195 LOG_ERROR("Register write failed");
199 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
200 (address
- bank
->base
) >> 2) != ERROR_OK
) {
201 LOG_ERROR("Register write failed");
205 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
210 for (unsigned int j
= 0; j
< 100; j
++) {
212 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
213 LOG_ERROR("Register write failed");
216 if (value
& FLASH_INT_CMDDONE
)
219 LOG_ERROR("Erase command failed (timeout)");
230 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
231 uint32_t offset
, uint32_t count
)
233 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
234 struct target
*target
= bank
->target
;
235 uint32_t buffer_size
= 16384 + 8;
236 struct working_area
*write_algorithm
;
237 struct working_area
*write_algorithm_sp
;
238 struct working_area
*source
;
239 uint32_t address
= bank
->base
+ offset
;
240 struct reg_param reg_params
[5];
241 struct mem_param mem_params
[1];
242 struct armv7m_algorithm armv7m_info
;
243 int retval
= ERROR_OK
;
245 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
246 * hints how to generate the data!
248 static const uint8_t bluenrgx_flash_write_code
[] = {
249 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
252 /* check preconditions */
253 if (!bluenrgx_info
->probed
)
254 return ERROR_FLASH_BANK_NOT_PROBED
;
256 if ((offset
+ count
) > bank
->size
) {
257 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32
", size=%" PRIu32
,
260 return ERROR_FLASH_DST_OUT_OF_BANK
;
263 if (bank
->target
->state
!= TARGET_HALTED
) {
264 LOG_ERROR("Target not halted");
265 return ERROR_TARGET_NOT_HALTED
;
268 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
269 &write_algorithm
) != ERROR_OK
) {
270 LOG_WARNING("no working area available, can't do block memory writes");
271 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
274 retval
= target_write_buffer(target
, write_algorithm
->address
,
275 sizeof(bluenrgx_flash_write_code
),
276 bluenrgx_flash_write_code
);
277 if (retval
!= ERROR_OK
)
281 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
282 LOG_WARNING("no large enough working area available");
283 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
286 /* Stack pointer area */
287 if (target_alloc_working_area(target
, 128,
288 &write_algorithm_sp
) != ERROR_OK
) {
289 LOG_DEBUG("no working area for write code stack pointer");
290 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
293 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
294 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
296 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
297 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
298 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
299 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
300 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
301 /* Put the parameter at the first available stack location */
302 init_mem_param(&mem_params
[0], write_algorithm_sp
->address
+ 80, 32, PARAM_OUT
);
304 /* FIFO start address (first two words used for write and read pointers) */
305 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
306 /* FIFO end address (first two words used for write and read pointers) */
307 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
308 /* Flash memory address */
309 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
310 /* Number of bytes */
311 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
312 /* Stack pointer for program working area */
313 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
314 /* Flash register base address */
315 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
317 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
318 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
319 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT
, write_algorithm_sp
->address
);
320 LOG_DEBUG("address = %08" PRIx32
, address
);
321 LOG_DEBUG("count = %08" PRIx32
, count
);
323 retval
= target_run_flash_async_algorithm(target
,
326 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
333 write_algorithm
->address
,
337 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
338 LOG_ERROR("error executing bluenrg-x flash write algorithm");
340 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
343 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
345 if (retval
== ERROR_OK
) {
347 /* Read back rp and check that is valid */
348 retval
= target_read_u32(target
, source
->address
+4, &rp
);
349 if (retval
== ERROR_OK
) {
350 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
351 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
352 retval
= ERROR_FLASH_OPERATION_FAILED
;
356 target_free_working_area(target
, source
);
357 target_free_working_area(target
, write_algorithm
);
358 target_free_working_area(target
, write_algorithm_sp
);
360 destroy_reg_param(®_params
[0]);
361 destroy_reg_param(®_params
[1]);
362 destroy_reg_param(®_params
[2]);
363 destroy_reg_param(®_params
[3]);
364 destroy_reg_param(®_params
[4]);
365 destroy_mem_param(&mem_params
[0]);
370 static int bluenrgx_probe(struct flash_bank
*bank
)
372 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
373 uint32_t idcode
, size_info
, die_id
;
374 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
376 if (retval
!= ERROR_OK
)
379 if (idcode
!= flash_priv_data_lp
.jtag_idcode
) {
380 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
381 if (retval
!= ERROR_OK
)
385 /* Default device is BlueNRG-1 */
386 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
387 bank
->base
= flash_priv_data_1
.flash_base
;
389 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
390 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
391 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
392 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
396 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
397 if (retval
!= ERROR_OK
)
400 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
401 if (retval
!= ERROR_OK
)
404 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
405 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
406 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
408 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
409 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
410 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
411 bank
->sectors
[i
].is_erased
= -1;
412 bank
->sectors
[i
].is_protected
= 0;
415 bluenrgx_info
->probed
= true;
416 bluenrgx_info
->die_id
= die_id
;
421 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
423 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
425 if (bluenrgx_info
->probed
)
428 return bluenrgx_probe(bank
);
431 /* This method must return a string displaying information about the bank */
432 static int bluenrgx_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
434 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
435 int mask_number
, cut_number
;
437 if (!bluenrgx_info
->probed
) {
438 int retval
= bluenrgx_probe(bank
);
439 if (retval
!= ERROR_OK
) {
440 snprintf(buf
, buf_size
,
441 "Unable to find bank information.");
446 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
447 cut_number
= bluenrgx_info
->die_id
& 0xF;
449 snprintf(buf
, buf_size
,
450 "%s - Rev: %d.%d", 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)