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>
27 #include "bluenrg-x.h"
29 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
30 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
32 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
33 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
34 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
36 struct flash_ctrl_priv_data
{
38 uint32_t jtag_idcode_reg
;
40 uint32_t flash_regs_base
;
41 uint32_t flash_page_size
;
46 static const struct flash_ctrl_priv_data flash_priv_data_1
= {
47 .die_id_reg
= 0x4090001C,
48 .jtag_idcode_reg
= 0x40900028,
49 .flash_base
= 0x10040000,
50 .flash_regs_base
= 0x40100000,
51 .flash_page_size
= 2048,
52 .jtag_idcode
= 0x00000000,
53 .part_name
= "BLUENRG-1",
56 static const struct flash_ctrl_priv_data flash_priv_data_2
= {
57 .die_id_reg
= 0x4090001C,
58 .jtag_idcode_reg
= 0x40900028,
59 .flash_base
= 0x10040000,
60 .flash_regs_base
= 0x40100000,
61 .flash_page_size
= 2048,
62 .jtag_idcode
= 0x0200A041,
63 .part_name
= "BLUENRG-2",
66 static const struct flash_ctrl_priv_data flash_priv_data_lp
= {
67 .die_id_reg
= 0x40000000,
68 .jtag_idcode_reg
= 0x40000004,
69 .flash_base
= 0x10040000,
70 .flash_regs_base
= 0x40001000,
71 .flash_page_size
= 2048,
72 .jtag_idcode
= 0x0201E041,
73 .part_name
= "BLUENRG-LP",
76 struct bluenrgx_flash_bank
{
79 const struct flash_ctrl_priv_data
*flash_ptr
;
82 static const struct flash_ctrl_priv_data
*flash_ctrl
[] = {
88 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
89 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
91 struct bluenrgx_flash_bank
*bluenrgx_info
;
92 /* Create the bank structure */
93 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
95 /* Check allocation */
96 if (bluenrgx_info
== NULL
) {
97 LOG_ERROR("failed to allocate bank structure");
101 bank
->write_start_alignment
= 16;
102 bank
->write_end_alignment
= 16;
104 bank
->driver_priv
= bluenrgx_info
;
106 bluenrgx_info
->probed
= false;
109 return ERROR_COMMAND_SYNTAX_ERROR
;
114 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
)
116 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
117 return bluenrgx_info
->flash_ptr
->flash_regs_base
+ reg_offset
;
120 static inline int bluenrgx_read_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t *value
)
122 return target_read_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
125 static inline int bluenrgx_write_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t value
)
127 return target_write_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
130 static int bluenrgx_erase(struct flash_bank
*bank
, unsigned int first
,
133 int retval
= ERROR_OK
;
134 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
135 unsigned int num_sectors
= (last
- first
+ 1);
136 const bool mass_erase
= (num_sectors
== bank
->num_sectors
);
137 struct target
*target
= bank
->target
;
138 uint32_t address
, command
;
140 /* check preconditions */
141 if (!bluenrgx_info
->probed
)
142 return ERROR_FLASH_BANK_NOT_PROBED
;
144 if (bank
->target
->state
!= TARGET_HALTED
) {
145 LOG_ERROR("Target not halted");
146 return ERROR_TARGET_NOT_HALTED
;
148 /* Disable blue module */
149 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
150 LOG_ERROR("Blue disable failed");
155 command
= FLASH_CMD_MASSERASE
;
156 address
= bank
->base
;
157 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
158 LOG_ERROR("Register write failed");
162 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
163 (address
- bank
->base
) >> 2) != ERROR_OK
) {
164 LOG_ERROR("Register write failed");
168 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
169 LOG_ERROR("Register write failed");
173 for (unsigned int i
= 0; i
< 100; i
++) {
175 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
176 LOG_ERROR("Register write failed");
179 if (value
& FLASH_INT_CMDDONE
)
182 LOG_ERROR("Mass erase command failed (timeout)");
188 command
= FLASH_CMD_ERASE_PAGE
;
189 for (unsigned int i
= first
; i
<= last
; i
++) {
190 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
191 LOG_DEBUG("address = %08" PRIx32
", index = %u", address
, i
);
193 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
194 LOG_ERROR("Register write failed");
198 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
199 (address
- bank
->base
) >> 2) != ERROR_OK
) {
200 LOG_ERROR("Register write failed");
204 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
209 for (unsigned int j
= 0; j
< 100; j
++) {
211 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
212 LOG_ERROR("Register write failed");
215 if (value
& FLASH_INT_CMDDONE
)
218 LOG_ERROR("Erase command failed (timeout)");
229 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
230 uint32_t offset
, uint32_t count
)
232 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
233 struct target
*target
= bank
->target
;
234 uint32_t buffer_size
= 16384 + 8;
235 struct working_area
*write_algorithm
;
236 struct working_area
*write_algorithm_sp
;
237 struct working_area
*source
;
238 uint32_t address
= bank
->base
+ offset
;
239 struct reg_param reg_params
[5];
240 struct mem_param mem_params
[1];
241 struct armv7m_algorithm armv7m_info
;
242 int retval
= ERROR_OK
;
244 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
245 * hints how to generate the data!
247 static const uint8_t bluenrgx_flash_write_code
[] = {
248 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
251 /* check preconditions */
252 if (!bluenrgx_info
->probed
)
253 return ERROR_FLASH_BANK_NOT_PROBED
;
255 if ((offset
+ count
) > bank
->size
) {
256 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32
", size=%" PRIu32
,
259 return ERROR_FLASH_DST_OUT_OF_BANK
;
262 if (bank
->target
->state
!= TARGET_HALTED
) {
263 LOG_ERROR("Target not halted");
264 return ERROR_TARGET_NOT_HALTED
;
267 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
268 &write_algorithm
) != ERROR_OK
) {
269 LOG_WARNING("no working area available, can't do block memory writes");
270 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
273 retval
= target_write_buffer(target
, write_algorithm
->address
,
274 sizeof(bluenrgx_flash_write_code
),
275 bluenrgx_flash_write_code
);
276 if (retval
!= ERROR_OK
)
280 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
281 LOG_WARNING("no large enough working area available");
282 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
285 /* Stack pointer area */
286 if (target_alloc_working_area(target
, 128,
287 &write_algorithm_sp
) != ERROR_OK
) {
288 LOG_DEBUG("no working area for write code stack pointer");
289 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
292 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
293 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
295 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
296 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
297 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
298 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
299 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
300 /* Put the parameter at the first available stack location */
301 init_mem_param(&mem_params
[0], write_algorithm_sp
->address
+ 80, 32, PARAM_OUT
);
303 /* FIFO start address (first two words used for write and read pointers) */
304 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
305 /* FIFO end address (first two words used for write and read pointers) */
306 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
307 /* Flash memory address */
308 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
309 /* Number of bytes */
310 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
311 /* Stack pointer for program working area */
312 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
313 /* Flash register base address */
314 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
316 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
317 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
318 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT
, write_algorithm_sp
->address
);
319 LOG_DEBUG("address = %08" PRIx32
, address
);
320 LOG_DEBUG("count = %08" PRIx32
, count
);
322 retval
= target_run_flash_async_algorithm(target
,
325 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
332 write_algorithm
->address
,
336 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
337 LOG_ERROR("error executing bluenrg-x flash write algorithm");
339 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
342 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
344 if (retval
== ERROR_OK
) {
346 /* Read back rp and check that is valid */
347 retval
= target_read_u32(target
, source
->address
+4, &rp
);
348 if (retval
== ERROR_OK
) {
349 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
350 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
351 retval
= ERROR_FLASH_OPERATION_FAILED
;
355 target_free_working_area(target
, source
);
356 target_free_working_area(target
, write_algorithm
);
357 target_free_working_area(target
, write_algorithm_sp
);
359 destroy_reg_param(®_params
[0]);
360 destroy_reg_param(®_params
[1]);
361 destroy_reg_param(®_params
[2]);
362 destroy_reg_param(®_params
[3]);
363 destroy_reg_param(®_params
[4]);
364 destroy_mem_param(&mem_params
[0]);
369 static int bluenrgx_probe(struct flash_bank
*bank
)
371 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
372 uint32_t idcode
, size_info
, die_id
;
373 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
375 if (retval
!= ERROR_OK
)
378 if (idcode
!= flash_priv_data_lp
.jtag_idcode
) {
379 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
380 if (retval
!= ERROR_OK
)
384 /* Default device is BlueNRG-1 */
385 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
386 bank
->base
= flash_priv_data_1
.flash_base
;
388 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
389 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
390 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
391 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
395 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
396 if (retval
!= ERROR_OK
)
399 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
400 if (retval
!= ERROR_OK
)
403 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
404 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
405 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
407 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
408 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
409 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
410 bank
->sectors
[i
].is_erased
= -1;
411 bank
->sectors
[i
].is_protected
= 0;
414 bluenrgx_info
->probed
= true;
415 bluenrgx_info
->die_id
= die_id
;
420 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
422 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
424 if (bluenrgx_info
->probed
)
427 return bluenrgx_probe(bank
);
430 /* This method must return a string displaying information about the bank */
431 static int bluenrgx_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
433 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
434 int mask_number
, cut_number
;
436 if (!bluenrgx_info
->probed
) {
437 int retval
= bluenrgx_probe(bank
);
438 if (retval
!= ERROR_OK
) {
439 snprintf(buf
, buf_size
,
440 "Unable to find bank information.");
445 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
446 cut_number
= bluenrgx_info
->die_id
& 0xF;
448 snprintf(buf
, buf_size
,
449 "%s - Rev: %d.%d", bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
453 const struct flash_driver bluenrgx_flash
= {
455 .flash_bank_command
= bluenrgx_flash_bank_command
,
456 .erase
= bluenrgx_erase
,
458 .write
= bluenrgx_write
,
459 .read
= default_flash_read
,
460 .probe
= bluenrgx_probe
,
461 .erase_check
= default_flash_blank_check
,
462 .protect_check
= NULL
,
463 .auto_probe
= bluenrgx_auto_probe
,
464 .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)