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
, int first
, int last
)
128 int retval
= ERROR_OK
;
129 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
130 int num_sectors
= (last
- first
+ 1);
131 int mass_erase
= (num_sectors
== bank
->num_sectors
);
132 struct target
*target
= bank
->target
;
133 uint32_t address
, command
;
135 /* check preconditions */
136 if (!bluenrgx_info
->probed
)
137 return ERROR_FLASH_BANK_NOT_PROBED
;
139 if (bank
->target
->state
!= TARGET_HALTED
) {
140 LOG_ERROR("Target not halted");
141 return ERROR_TARGET_NOT_HALTED
;
143 /* Disable blue module */
144 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
145 LOG_ERROR("Blue disable failed");
150 command
= FLASH_CMD_MASSERASE
;
151 address
= bank
->base
;
152 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
153 LOG_ERROR("Register write failed");
157 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
158 (address
- bank
->base
) >> 2) != ERROR_OK
) {
159 LOG_ERROR("Register write failed");
163 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
164 LOG_ERROR("Register write failed");
168 for (unsigned int i
= 0; i
< 100; i
++) {
170 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
171 LOG_ERROR("Register write failed");
174 if (value
& FLASH_INT_CMDDONE
)
177 LOG_ERROR("Mass erase command failed (timeout)");
183 command
= FLASH_CMD_ERASE_PAGE
;
184 for (int i
= first
; i
<= last
; i
++) {
185 address
= bank
->base
+i
*FLASH_PAGE_SIZE(bluenrgx_info
);
186 LOG_DEBUG("address = %08x, index = %d", address
, i
);
188 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_IRQRAW
, 0x3f) != ERROR_OK
) {
189 LOG_ERROR("Register write failed");
193 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_ADDRESS
,
194 (address
- bank
->base
) >> 2) != ERROR_OK
) {
195 LOG_ERROR("Register write failed");
199 if (bluenrgx_write_flash_reg(bank
, FLASH_REG_COMMAND
, command
) != ERROR_OK
) {
204 for (unsigned int j
= 0; j
< 100; j
++) {
206 if (bluenrgx_read_flash_reg(bank
, FLASH_REG_IRQRAW
, &value
)) {
207 LOG_ERROR("Register write failed");
210 if (value
& FLASH_INT_CMDDONE
)
213 LOG_ERROR("Erase command failed (timeout)");
224 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
225 uint32_t offset
, uint32_t count
)
227 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
228 struct target
*target
= bank
->target
;
229 uint32_t buffer_size
= 16384 + 8;
230 struct working_area
*write_algorithm
;
231 struct working_area
*write_algorithm_sp
;
232 struct working_area
*source
;
233 uint32_t address
= bank
->base
+ offset
;
234 struct reg_param reg_params
[5];
235 struct mem_param mem_params
[1];
236 struct armv7m_algorithm armv7m_info
;
237 int retval
= ERROR_OK
;
239 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
240 * hints how to generate the data!
242 static const uint8_t bluenrgx_flash_write_code
[] = {
243 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
246 /* check preconditions */
247 if (!bluenrgx_info
->probed
)
248 return ERROR_FLASH_BANK_NOT_PROBED
;
250 if ((offset
+ count
) > bank
->size
) {
251 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
254 return ERROR_FLASH_DST_OUT_OF_BANK
;
257 if (bank
->target
->state
!= TARGET_HALTED
) {
258 LOG_ERROR("Target not halted");
259 return ERROR_TARGET_NOT_HALTED
;
262 if (target_alloc_working_area(target
, sizeof(bluenrgx_flash_write_code
),
263 &write_algorithm
) != ERROR_OK
) {
264 LOG_WARNING("no working area available, can't do block memory writes");
265 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
268 retval
= target_write_buffer(target
, write_algorithm
->address
,
269 sizeof(bluenrgx_flash_write_code
),
270 bluenrgx_flash_write_code
);
271 if (retval
!= ERROR_OK
)
275 if (target_alloc_working_area(target
, buffer_size
, &source
)) {
276 LOG_WARNING("no large enough working area available");
277 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
280 /* Stack pointer area */
281 if (target_alloc_working_area(target
, 128,
282 &write_algorithm_sp
) != ERROR_OK
) {
283 LOG_DEBUG("no working area for write code stack pointer");
284 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
287 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
288 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
290 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
291 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
292 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
293 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
294 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
295 /* Put the parameter at the first available stack location */
296 init_mem_param(&mem_params
[0], write_algorithm_sp
->address
+ 80, 32, PARAM_OUT
);
298 /* FIFO start address (first two words used for write and read pointers) */
299 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
300 /* FIFO end address (first two words used for write and read pointers) */
301 buf_set_u32(reg_params
[1].value
, 0, 32, source
->address
+ source
->size
);
302 /* Flash memory address */
303 buf_set_u32(reg_params
[2].value
, 0, 32, address
);
304 /* Number of bytes */
305 buf_set_u32(reg_params
[3].value
, 0, 32, count
);
306 /* Stack pointer for program working area */
307 buf_set_u32(reg_params
[4].value
, 0, 32, write_algorithm_sp
->address
);
308 /* Flash register base address */
309 buf_set_u32(mem_params
[0].value
, 0, 32, bluenrgx_info
->flash_ptr
->flash_regs_base
);
311 LOG_DEBUG("source->address = " TARGET_ADDR_FMT
, source
->address
);
312 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT
, source
->address
+source
->size
);
313 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT
, write_algorithm_sp
->address
);
314 LOG_DEBUG("address = %08x", address
);
315 LOG_DEBUG("count = %08x", count
);
317 retval
= target_run_flash_async_algorithm(target
,
320 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
327 write_algorithm
->address
,
331 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
332 LOG_ERROR("error executing bluenrg-x flash write algorithm");
334 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
337 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
339 if (retval
== ERROR_OK
) {
341 /* Read back rp and check that is valid */
342 retval
= target_read_u32(target
, source
->address
+4, &rp
);
343 if (retval
== ERROR_OK
) {
344 if ((rp
< source
->address
+8) || (rp
> (source
->address
+ source
->size
))) {
345 LOG_ERROR("flash write failed = %08" PRIx32
, rp
);
346 retval
= ERROR_FLASH_OPERATION_FAILED
;
350 target_free_working_area(target
, source
);
351 target_free_working_area(target
, write_algorithm
);
352 target_free_working_area(target
, write_algorithm_sp
);
354 destroy_reg_param(®_params
[0]);
355 destroy_reg_param(®_params
[1]);
356 destroy_reg_param(®_params
[2]);
357 destroy_reg_param(®_params
[3]);
358 destroy_reg_param(®_params
[4]);
359 destroy_mem_param(&mem_params
[0]);
364 static int bluenrgx_probe(struct flash_bank
*bank
)
366 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
367 uint32_t idcode
, size_info
, die_id
;
368 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
370 if (retval
!= ERROR_OK
)
373 if (idcode
!= flash_priv_data_lp
.jtag_idcode
) {
374 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
375 if (retval
!= ERROR_OK
)
379 /* Default device is BlueNRG-1 */
380 bluenrgx_info
->flash_ptr
= &flash_priv_data_1
;
381 bank
->base
= flash_priv_data_1
.flash_base
;
383 for (size_t i
= 0; i
< ARRAY_SIZE(flash_ctrl
); i
++) {
384 if (idcode
== (*flash_ctrl
[i
]).jtag_idcode
) {
385 bluenrgx_info
->flash_ptr
= flash_ctrl
[i
];
386 bank
->base
= (*flash_ctrl
[i
]).flash_base
;
390 retval
= bluenrgx_read_flash_reg(bank
, FLASH_SIZE_REG
, &size_info
);
391 if (retval
!= ERROR_OK
)
394 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
395 if (retval
!= ERROR_OK
)
398 bank
->size
= (size_info
+ 1) * FLASH_WORD_LEN
;
399 bank
->num_sectors
= bank
->size
/FLASH_PAGE_SIZE(bluenrgx_info
);
400 bank
->sectors
= realloc(bank
->sectors
, sizeof(struct flash_sector
) * bank
->num_sectors
);
402 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
403 bank
->sectors
[i
].offset
= i
* FLASH_PAGE_SIZE(bluenrgx_info
);
404 bank
->sectors
[i
].size
= FLASH_PAGE_SIZE(bluenrgx_info
);
405 bank
->sectors
[i
].is_erased
= -1;
406 bank
->sectors
[i
].is_protected
= 0;
409 bluenrgx_info
->probed
= true;
410 bluenrgx_info
->die_id
= die_id
;
415 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
417 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
419 if (bluenrgx_info
->probed
)
422 return bluenrgx_probe(bank
);
425 /* This method must return a string displaying information about the bank */
426 static int bluenrgx_get_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
428 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
429 int mask_number
, cut_number
;
431 if (!bluenrgx_info
->probed
) {
432 int retval
= bluenrgx_probe(bank
);
433 if (retval
!= ERROR_OK
) {
434 snprintf(buf
, buf_size
,
435 "Unable to find bank information.");
440 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
441 cut_number
= bluenrgx_info
->die_id
& 0xF;
443 snprintf(buf
, buf_size
,
444 "%s - Rev: %d.%d", bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
448 const struct flash_driver bluenrgx_flash
= {
450 .flash_bank_command
= bluenrgx_flash_bank_command
,
451 .erase
= bluenrgx_erase
,
453 .write
= bluenrgx_write
,
454 .read
= default_flash_read
,
455 .probe
= bluenrgx_probe
,
456 .erase_check
= default_flash_blank_check
,
457 .protect_check
= NULL
,
458 .auto_probe
= bluenrgx_auto_probe
,
459 .info
= bluenrgx_get_info
,