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
, struct command_invocation
*cmd
)
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 command_print_sameline(cmd
, "Unable to find bank information.");
445 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
446 cut_number
= bluenrgx_info
->die_id
& 0xF;
448 command_print_sameline(cmd
, "%s - Rev: %d.%d",
449 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
,