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/binarybuffer.h>
24 #include "helper/types.h"
25 #include <target/algorithm.h>
26 #include <target/armv7m.h>
27 #include <target/cortex_m.h>
29 #include "bluenrg-x.h"
31 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
32 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
34 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
35 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
36 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
38 #define FLASH_SIZE_REG_MASK (0xFFFF)
40 struct flash_ctrl_priv_data {
42 uint32_t jtag_idcode_reg;
44 uint32_t flash_regs_base;
45 uint32_t flash_page_size;
50 static const struct flash_ctrl_priv_data flash_priv_data_1 = {
51 .die_id_reg = 0x4090001C,
52 .jtag_idcode_reg = 0x40900028,
53 .flash_base = 0x10040000,
54 .flash_regs_base = 0x40100000,
55 .flash_page_size = 2048,
56 .jtag_idcode = 0x00000000,
57 .part_name = "BLUENRG-1",
60 static const struct flash_ctrl_priv_data flash_priv_data_2 = {
61 .die_id_reg = 0x4090001C,
62 .jtag_idcode_reg = 0x40900028,
63 .flash_base = 0x10040000,
64 .flash_regs_base = 0x40100000,
65 .flash_page_size = 2048,
66 .jtag_idcode = 0x0200A041,
67 .part_name = "BLUENRG-2",
70 static const struct flash_ctrl_priv_data flash_priv_data_lp = {
71 .die_id_reg = 0x40000000,
72 .jtag_idcode_reg = 0x40000004,
73 .flash_base = 0x10040000,
74 .flash_regs_base = 0x40001000,
75 .flash_page_size = 2048,
76 .jtag_idcode = 0x0201E041,
77 .part_name = "BLUENRG-LP",
80 static const struct flash_ctrl_priv_data flash_priv_data_lps = {
81 .die_id_reg = 0x40000000,
82 .jtag_idcode_reg = 0x40000004,
83 .flash_base = 0x10040000,
84 .flash_regs_base = 0x40001000,
85 .flash_page_size = 2048,
86 .jtag_idcode = 0x02028041,
87 .part_name = "BLUENRG-LPS",
90 struct bluenrgx_flash_bank {
93 const struct flash_ctrl_priv_data *flash_ptr;
96 static const struct flash_ctrl_priv_data *flash_ctrl[] = {
100 &flash_priv_data_lps};
102 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
103 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
105 struct bluenrgx_flash_bank *bluenrgx_info;
106 /* Create the bank structure */
107 bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
109 /* Check allocation */
110 if (!bluenrgx_info) {
111 LOG_ERROR("failed to allocate bank structure");
115 bank->write_start_alignment = 16;
116 bank->write_end_alignment = 16;
118 bank->driver_priv = bluenrgx_info;
120 bluenrgx_info->probed = false;
123 return ERROR_COMMAND_SYNTAX_ERROR;
128 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
130 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
131 return bluenrgx_info->flash_ptr->flash_regs_base + reg_offset;
134 static inline int bluenrgx_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value)
136 return target_read_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
139 static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value)
141 return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
144 static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
147 int retval = ERROR_OK;
148 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
149 unsigned int num_sectors = (last - first + 1);
150 const bool mass_erase = (num_sectors == bank->num_sectors);
151 struct target *target = bank->target;
152 uint32_t address, command;
154 /* check preconditions */
155 if (!bluenrgx_info->probed)
156 return ERROR_FLASH_BANK_NOT_PROBED;
158 if (bank->target->state != TARGET_HALTED) {
159 LOG_ERROR("Target not halted");
160 return ERROR_TARGET_NOT_HALTED;
162 /* Disable blue module */
163 if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
164 LOG_ERROR("Blue disable failed");
169 command = FLASH_CMD_MASSERASE;
170 address = bank->base;
171 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
172 LOG_ERROR("Register write failed");
176 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
177 (address - bank->base) >> 2) != ERROR_OK) {
178 LOG_ERROR("Register write failed");
182 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
183 LOG_ERROR("Register write failed");
187 for (unsigned int i = 0; i < 100; i++) {
189 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
190 LOG_ERROR("Register write failed");
193 if (value & FLASH_INT_CMDDONE)
196 LOG_ERROR("Mass erase command failed (timeout)");
202 command = FLASH_CMD_ERASE_PAGE;
203 for (unsigned int i = first; i <= last; i++) {
204 address = bank->base+i*FLASH_PAGE_SIZE(bluenrgx_info);
205 LOG_DEBUG("address = %08" PRIx32 ", index = %u", address, i);
207 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
208 LOG_ERROR("Register write failed");
212 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
213 (address - bank->base) >> 2) != ERROR_OK) {
214 LOG_ERROR("Register write failed");
218 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
223 for (unsigned int j = 0; j < 100; j++) {
225 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
226 LOG_ERROR("Register write failed");
229 if (value & FLASH_INT_CMDDONE)
232 LOG_ERROR("Erase command failed (timeout)");
243 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
244 uint32_t offset, uint32_t count)
246 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
247 struct target *target = bank->target;
248 uint32_t buffer_size = 16384 + 8;
249 struct working_area *write_algorithm;
250 struct working_area *write_algorithm_sp;
251 struct working_area *source;
252 uint32_t address = bank->base + offset;
253 struct reg_param reg_params[5];
254 struct mem_param mem_params[1];
255 struct armv7m_algorithm armv7m_info;
256 int retval = ERROR_OK;
258 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
259 * hints how to generate the data!
261 static const uint8_t bluenrgx_flash_write_code[] = {
262 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
265 /* check preconditions */
266 if (!bluenrgx_info->probed)
267 return ERROR_FLASH_BANK_NOT_PROBED;
269 if ((offset + count) > bank->size) {
270 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32,
273 return ERROR_FLASH_DST_OUT_OF_BANK;
276 if (bank->target->state != TARGET_HALTED) {
277 LOG_ERROR("Target not halted");
278 return ERROR_TARGET_NOT_HALTED;
281 if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
282 &write_algorithm) != ERROR_OK) {
283 LOG_WARNING("no working area available, can't do block memory writes");
284 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
287 retval = target_write_buffer(target, write_algorithm->address,
288 sizeof(bluenrgx_flash_write_code),
289 bluenrgx_flash_write_code);
290 if (retval != ERROR_OK)
294 if (target_alloc_working_area(target, buffer_size, &source)) {
295 LOG_WARNING("no large enough working area available");
296 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
299 /* Stack pointer area */
300 if (target_alloc_working_area(target, 128,
301 &write_algorithm_sp) != ERROR_OK) {
302 LOG_DEBUG("no working area for write code stack pointer");
303 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
306 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
307 armv7m_info.core_mode = ARM_MODE_THREAD;
309 init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
310 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
311 init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
312 init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
313 init_reg_param(®_params[4], "sp", 32, PARAM_OUT);
314 /* Put the parameter at the first available stack location */
315 init_mem_param(&mem_params[0], write_algorithm_sp->address + 80, 32, PARAM_OUT);
317 /* FIFO start address (first two words used for write and read pointers) */
318 buf_set_u32(reg_params[0].value, 0, 32, source->address);
319 /* FIFO end address (first two words used for write and read pointers) */
320 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
321 /* Flash memory address */
322 buf_set_u32(reg_params[2].value, 0, 32, address);
323 /* Number of bytes */
324 buf_set_u32(reg_params[3].value, 0, 32, count);
325 /* Stack pointer for program working area */
326 buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
327 /* Flash register base address */
328 buf_set_u32(mem_params[0].value, 0, 32, bluenrgx_info->flash_ptr->flash_regs_base);
330 LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
331 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
332 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
333 LOG_DEBUG("address = %08" PRIx32, address);
334 LOG_DEBUG("count = %08" PRIx32, count);
336 retval = target_run_flash_async_algorithm(target,
339 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
346 write_algorithm->address,
350 if (retval == ERROR_FLASH_OPERATION_FAILED) {
351 LOG_ERROR("error executing bluenrg-x flash write algorithm");
353 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
356 LOG_ERROR("flash write failed = %08" PRIx32, error);
358 if (retval == ERROR_OK) {
360 /* Read back rp and check that is valid */
361 retval = target_read_u32(target, source->address+4, &rp);
362 if (retval == ERROR_OK) {
363 if ((rp < source->address+8) || (rp > (source->address + source->size))) {
364 LOG_ERROR("flash write failed = %08" PRIx32, rp);
365 retval = ERROR_FLASH_OPERATION_FAILED;
369 target_free_working_area(target, source);
370 target_free_working_area(target, write_algorithm);
371 target_free_working_area(target, write_algorithm_sp);
373 destroy_reg_param(®_params[0]);
374 destroy_reg_param(®_params[1]);
375 destroy_reg_param(®_params[2]);
376 destroy_reg_param(®_params[3]);
377 destroy_reg_param(®_params[4]);
378 destroy_mem_param(&mem_params[0]);
383 static int bluenrgx_probe(struct flash_bank *bank)
385 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
386 uint32_t idcode, size_info, die_id;
387 int retval = target_read_u32(bank->target, BLUENRGLP_JTAG_REG, &idcode);
389 if (retval != ERROR_OK)
392 if ((idcode != flash_priv_data_lp.jtag_idcode) && (idcode != flash_priv_data_lps.jtag_idcode)) {
393 retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
394 if (retval != ERROR_OK)
398 /* Default device is BlueNRG-1 */
399 bluenrgx_info->flash_ptr = &flash_priv_data_1;
400 bank->base = flash_priv_data_1.flash_base;
402 for (size_t i = 0; i < ARRAY_SIZE(flash_ctrl); i++) {
403 if (idcode == (*flash_ctrl[i]).jtag_idcode) {
404 bluenrgx_info->flash_ptr = flash_ctrl[i];
405 bank->base = (*flash_ctrl[i]).flash_base;
409 retval = bluenrgx_read_flash_reg(bank, FLASH_SIZE_REG, &size_info);
410 size_info = size_info & FLASH_SIZE_REG_MASK;
411 if (retval != ERROR_OK)
414 retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
415 if (retval != ERROR_OK)
418 bank->size = (size_info + 1) * FLASH_WORD_LEN;
419 bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
420 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
422 for (unsigned int i = 0; i < bank->num_sectors; i++) {
423 bank->sectors[i].offset = i * FLASH_PAGE_SIZE(bluenrgx_info);
424 bank->sectors[i].size = FLASH_PAGE_SIZE(bluenrgx_info);
425 bank->sectors[i].is_erased = -1;
426 bank->sectors[i].is_protected = 0;
429 bluenrgx_info->probed = true;
430 bluenrgx_info->die_id = die_id;
435 static int bluenrgx_auto_probe(struct flash_bank *bank)
437 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
439 if (bluenrgx_info->probed)
442 return bluenrgx_probe(bank);
445 /* This method must return a string displaying information about the bank */
446 static int bluenrgx_get_info(struct flash_bank *bank, struct command_invocation *cmd)
448 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
449 int mask_number, cut_number;
451 if (!bluenrgx_info->probed) {
452 int retval = bluenrgx_probe(bank);
453 if (retval != ERROR_OK) {
454 command_print_sameline(cmd, "Unable to find bank information.");
459 mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
460 cut_number = bluenrgx_info->die_id & 0xF;
462 command_print_sameline(cmd, "%s - Rev: %d.%d",
463 bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
467 const struct flash_driver bluenrgx_flash = {
469 .flash_bank_command = bluenrgx_flash_bank_command,
470 .erase = bluenrgx_erase,
472 .write = bluenrgx_write,
473 .read = default_flash_read,
474 .probe = bluenrgx_probe,
475 .erase_check = default_flash_blank_check,
476 .protect_check = NULL,
477 .auto_probe = bluenrgx_auto_probe,
478 .info = bluenrgx_get_info,