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 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 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 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 const struct flash_ctrl_priv_data
*flash_ctrl
[] = {&flash_priv_data_1
, &flash_priv_data_2
, &flash_priv_data_lp
};
84 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
85 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
87 struct bluenrgx_flash_bank
*bluenrgx_info
;
88 /* Create the bank structure */
89 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
91 /* Check allocation */
92 if (bluenrgx_info
== NULL
) {
93 LOG_ERROR("failed to allocate bank structure");
97 bank
->write_start_alignment
= 16;
98 bank
->write_end_alignment
= 16;
100 bank
->driver_priv
= bluenrgx_info
;
102 bluenrgx_info
->probed
= false;
105 return ERROR_COMMAND_SYNTAX_ERROR
;
110 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
)
112 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
113 return bluenrgx_info
->flash_ptr
->flash_regs_base
+ reg_offset
;
116 static inline int bluenrgx_read_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t *value
)
118 return target_read_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
121 static inline int bluenrgx_write_flash_reg(struct flash_bank
*bank
, uint32_t reg_offset
, uint32_t value
)
123 return target_write_u32(bank
->target
, bluenrgx_get_flash_reg(bank
, reg_offset
), value
);
126 static int bluenrgx_erase(struct flash_bank
*bank
, unsigned int first
,
129 int retval
= ERROR_OK
;
130 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
131 unsigned int num_sectors
= (last
- first
+ 1);
132 const bool mass_erase
= (num_sectors
== bank
->num_sectors
);
133 struct target
*target
= bank
->target
;
134 uint32_t address
, command
;
136 /* check preconditions */
137 if (!bluenrgx_info
->probed
)
138 return ERROR_FLASH_BANK_NOT_PROBED
;
140 if (bank
->target
->state
!= TARGET_HALTED
) {
141 LOG_ERROR("Target not halted");
142 return ERROR_TARGET_NOT_HALTED
;
144 /* Disable blue module */
145 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
146 LOG_ERROR("Blue disable failed");
151 command
= FLASH_CMD_MASSERASE
;
152 address
= bank
->base
;
153 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
154 LOG_ERROR("Register write failed");
158 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
159 (address
- bank
->base
) >> 2) != ERROR_OK
) {
160 LOG_ERROR("Register write failed");
164 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
165 LOG_ERROR("Register write failed");
169 for (unsigned int i
= 0; i
< 100; i
++) {
171 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
172 LOG_ERROR("Register write failed");
175 if (value
& FLASH_INT_CMDDONE
)
178 LOG_ERROR("Mass erase command failed (timeout)");
184 command
= FLASH_CMD_ERASE_PAGE
;
185 for (unsigned int i
= first
; i
<= last
; i
++) {
186 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
187 LOG_DEBUG("address = %08x, index = %u", address
, i
);
189 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
190 LOG_ERROR("Register write failed");
194 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
195 (address
- bank
->base
) >> 2) != ERROR_OK
) {
196 LOG_ERROR("Register write failed");
200 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
205 for (unsigned int j
= 0; j
< 100; j
++) {
207 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
208 LOG_ERROR("Register write failed");
211 if (value
& FLASH_INT_CMDDONE
)
214 LOG_ERROR("Erase command failed (timeout)");
225 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
226 uint32_t offset
, uint32_t count
)
228 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
229 struct target
*target
= bank
->target
;
230 uint32_t buffer_size
= 16384 + 8;
231 struct working_area
*write_algorithm
;
232 struct working_area
*write_algorithm_sp
;
233 struct working_area
*source
;
234 uint32_t address
= bank
->base
+ offset
;
235 struct reg_param reg_params
[5];
236 struct mem_param mem_params
[1];
237 struct armv7m_algorithm armv7m_info
;
238 int retval
= ERROR_OK
;
240 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
241 * hints how to generate the data!
243 static const uint8_t bluenrgx_flash_write_code
[] = {
244 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
247 /* check preconditions */
248 if (!bluenrgx_info
->probed
)
249 return ERROR_FLASH_BANK_NOT_PROBED
;
251 if ((offset
+ count
) > bank
->size
) {
252 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
255 return ERROR_FLASH_DST_OUT_OF_BANK
;
258 if (bank
->target
->state
!= TARGET_HALTED
) {
259 LOG_ERROR("Target not halted");
260 return ERROR_TARGET_NOT_HALTED
;
263 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
264 &write_algorithm
) != ERROR_OK
) {
265 LOG_WARNING("no working area available, can't do block memory writes");
266 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
269 retval
= target_write_buffer(target
, write_algorithm
->address
,
270 sizeof(bluenrgx_flash_write_code
),
271 bluenrgx_flash_write_code
);
272 if (retval
!= ERROR_OK
)
276 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
277 LOG_WARNING("no large enough working area available");
278 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
281 /* Stack pointer area */
282 if (target_alloc_working_area(target
, 128,
283 &write_algorithm_sp
) != ERROR_OK
) {
284 LOG_DEBUG("no working area for write code stack pointer");
285 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
288 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
289 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
291 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
292 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
293 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
294 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
295 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
296 /* Put the parameter at the first available stack location */
297 init_mem_param(&mem_params
[0], write_algorithm_sp
->address
+ 80, 32, PARAM_OUT
);
299 /* FIFO start address (first two words used for write and read pointers) */
300 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
301 /* FIFO end address (first two words used for write and read pointers) */
302 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
303 /* Flash memory address */
304 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
305 /* Number of bytes */
306 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
307 /* Stack pointer for program working area */
308 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
309 /* Flash register base address */
310 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
312 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
313 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
314 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT
, write_algorithm_sp
->address
);
315 LOG_DEBUG("address = %08x", address
);
316 LOG_DEBUG("count = %08x", count
);
318 retval
= target_run_flash_async_algorithm(target
,
321 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
328 write_algorithm
->address
,
332 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
333 LOG_ERROR("error executing bluenrg-x flash write algorithm");
335 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
338 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
340 if (retval
== ERROR_OK
) {
342 /* Read back rp and check that is valid */
343 retval
= target_read_u32(target
, source
->address
+4, &rp
);
344 if (retval
== ERROR_OK
) {
345 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
346 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
347 retval
= ERROR_FLASH_OPERATION_FAILED
;
351 target_free_working_area(target
, source
);
352 target_free_working_area(target
, write_algorithm
);
353 target_free_working_area(target
, write_algorithm_sp
);
355 destroy_reg_param(®_params
[0]);
356 destroy_reg_param(®_params
[1]);
357 destroy_reg_param(®_params
[2]);
358 destroy_reg_param(®_params
[3]);
359 destroy_reg_param(®_params
[4]);
360 destroy_mem_param(&mem_params
[0]);
365 static int bluenrgx_probe(struct flash_bank
*bank
)
367 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
368 uint32_t idcode
, size_info
, die_id
;
369 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
371 if (retval
!= ERROR_OK
)
374 if (idcode
!= flash_priv_data_lp
.jtag_idcode
) {
375 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
376 if (retval
!= ERROR_OK
)
380 /* Default device is BlueNRG-1 */
381 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
382 bank
->base
= flash_priv_data_1
.flash_base
;
384 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
385 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
386 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
387 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
391 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
392 if (retval
!= ERROR_OK
)
395 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
396 if (retval
!= ERROR_OK
)
399 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
400 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
401 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
403 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
404 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
405 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
406 bank
->sectors
[i
].is_erased
= -1;
407 bank
->sectors
[i
].is_protected
= 0;
410 bluenrgx_info
->probed
= true;
411 bluenrgx_info
->die_id
= die_id
;
416 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
418 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
420 if (bluenrgx_info
->probed
)
423 return bluenrgx_probe(bank
);
426 /* This method must return a string displaying information about the bank */
427 static int bluenrgx_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
429 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
430 int mask_number
, cut_number
;
432 if (!bluenrgx_info
->probed
) {
433 int retval
= bluenrgx_probe(bank
);
434 if (retval
!= ERROR_OK
) {
435 snprintf(buf
, buf_size
,
436 "Unable to find bank information.");
441 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
442 cut_number
= bluenrgx_info
->die_id
& 0xF;
444 snprintf(buf
, buf_size
,
445 "%s - Rev: %d.%d", bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
449 const struct flash_driver bluenrgx_flash
= {
451 .flash_bank_command
= bluenrgx_flash_bank_command
,
452 .erase
= bluenrgx_erase
,
454 .write
= bluenrgx_write
,
455 .read
= default_flash_read
,
456 .probe
= bluenrgx_probe
,
457 .erase_check
= default_flash_blank_check
,
458 .protect_check
= NULL
,
459 .auto_probe
= bluenrgx_auto_probe
,
460 .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)