79821168e460bb0907caa72f97f8508a361fc0a2
[openocd.git] / src / flash / nor / bluenrg-x.c
1 /***************************************************************************
2 * Copyright (C) 2017 by Michele Sardo *
3 * msmttchr@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <target/algorithm.h>
24 #include <target/armv7m.h>
25 #include <target/cortex_m.h>
26 #include "imp.h"
27
28 #define BLUENRG2_IDCODE (0x0200A041)
29 #define BLUENRGLP_IDCODE (0x0201E041)
30 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
31 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
32
33 #define FLASH_SIZE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_size_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_BASE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_base)
37 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
38 #define FLASH_REG_COMMAND(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_reg_command)
39 #define FLASH_REG_IRQRAW(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_reg_irqraw)
40 #define FLASH_REG_ADDRESS(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_reg_address)
41 #define FLASH_REG_DATA(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_reg_data)
42 #define FLASH_CMD_ERASE_PAGE 0x11
43 #define FLASH_CMD_MASSERASE 0x22
44 #define FLASH_CMD_WRITE 0x33
45 #define FLASH_CMD_BURSTWRITE 0xCC
46 #define FLASH_INT_CMDDONE 0x01
47 #define FLASH_WORD_LEN 4
48
49 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
50 * hints how to generate the data!
51 */
52 static const uint8_t bluenrgx_flash_write_code_2[] = {
53 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-2_write.inc"
54 };
55
56 static const uint8_t bluenrgx_flash_write_code_lp[] = {
57 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-lp_write.inc"
58 };
59
60 struct flash_ctrl_priv_data {
61 uint32_t flash_size_reg;
62 uint32_t die_id_reg;
63 uint32_t jtag_idcode_reg;
64 uint32_t flash_base;
65 uint32_t flash_page_size;
66 uint32_t flash_reg_command;
67 uint32_t flash_reg_irqraw;
68 uint32_t flash_reg_address;
69 uint32_t flash_reg_data;
70 uint32_t jtag_idcode;
71 char *part_name;
72 const uint8_t *flash_write_code;
73 uint32_t flash_write_code_size;
74 };
75
76 const struct flash_ctrl_priv_data flash_priv_data_1 = {
77 .flash_size_reg = 0x40100014,
78 .die_id_reg = 0x4090001C,
79 .jtag_idcode_reg = 0x40900028,
80 .flash_base = 0x10040000,
81 .flash_page_size = 2048,
82 .flash_reg_command = 0x40100000,
83 .flash_reg_irqraw = 0x40100010,
84 .flash_reg_address = 0x40100018,
85 .flash_reg_data = 0x40100040,
86 .jtag_idcode = 0x00000000,
87 .part_name = "BLUENRG-1",
88 .flash_write_code = bluenrgx_flash_write_code_2,
89 .flash_write_code_size = sizeof(bluenrgx_flash_write_code_2),
90 };
91
92 const struct flash_ctrl_priv_data flash_priv_data_2 = {
93 .flash_size_reg = 0x40100014,
94 .die_id_reg = 0x4090001C,
95 .jtag_idcode_reg = 0x40900028,
96 .flash_base = 0x10040000,
97 .flash_page_size = 2048,
98 .flash_reg_command = 0x40100000,
99 .flash_reg_irqraw = 0x40100010,
100 .flash_reg_address = 0x40100018,
101 .flash_reg_data = 0x40100040,
102 .jtag_idcode = BLUENRG2_IDCODE,
103 .part_name = "BLUENRG-2",
104 .flash_write_code = bluenrgx_flash_write_code_2,
105 .flash_write_code_size = sizeof(bluenrgx_flash_write_code_2),
106 };
107
108 const struct flash_ctrl_priv_data flash_priv_data_lp = {
109 .flash_size_reg = 0x40001014,
110 .die_id_reg = 0x40000000,
111 .jtag_idcode_reg = 0x40000004,
112 .flash_base = 0x10040000,
113 .flash_page_size = 2048,
114 .flash_reg_command = 0x40001000,
115 .flash_reg_irqraw = 0x40001010,
116 .flash_reg_address = 0x40001018,
117 .flash_reg_data = 0x40001040,
118 .jtag_idcode = BLUENRGLP_IDCODE,
119 .part_name = "BLUENRG-LP",
120 .flash_write_code = bluenrgx_flash_write_code_lp,
121 .flash_write_code_size = sizeof(bluenrgx_flash_write_code_lp),
122 };
123
124 struct bluenrgx_flash_bank {
125 int probed;
126 uint32_t die_id;
127 const struct flash_ctrl_priv_data *flash_ptr;
128 const uint8_t *flash_write_code;
129 uint32_t flash_write_code_size;
130 };
131
132 const struct flash_ctrl_priv_data *flash_ctrl[] = {&flash_priv_data_1, &flash_priv_data_2, &flash_priv_data_lp};
133
134 static int bluenrgx_protect_check(struct flash_bank *bank)
135 {
136 /* Nothing to do. Protection is only handled in SW. */
137 return ERROR_OK;
138 }
139
140 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
141 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
142 {
143 struct bluenrgx_flash_bank *bluenrgx_info;
144 /* Create the bank structure */
145 bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
146
147 /* Check allocation */
148 if (bluenrgx_info == NULL) {
149 LOG_ERROR("failed to allocate bank structure");
150 return ERROR_FAIL;
151 }
152
153 bank->driver_priv = bluenrgx_info;
154
155 bluenrgx_info->probed = 0;
156
157 if (CMD_ARGC < 6)
158 return ERROR_COMMAND_SYNTAX_ERROR;
159
160 return ERROR_OK;
161 }
162
163 static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
164 {
165 int retval = ERROR_OK;
166 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
167 int num_sectors = (last - first + 1);
168 int mass_erase = (num_sectors == bank->num_sectors);
169 struct target *target = bank->target;
170 uint32_t address, command;
171
172 /* check preconditions */
173 if (bluenrgx_info->probed == 0)
174 return ERROR_FLASH_BANK_NOT_PROBED;
175
176 if (bank->target->state != TARGET_HALTED) {
177 LOG_ERROR("Target not halted");
178 return ERROR_TARGET_NOT_HALTED;
179 }
180 /* Disable blue module */
181 if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
182 LOG_ERROR("Blue disable failed");
183 return ERROR_FAIL;
184 }
185
186 if (mass_erase) {
187 command = FLASH_CMD_MASSERASE;
188 address = bank->base;
189 if (target_write_u32(target, FLASH_REG_IRQRAW(bluenrgx_info), 0x3f) != ERROR_OK) {
190 LOG_ERROR("Register write failed");
191 return ERROR_FAIL;
192 }
193
194 if (target_write_u32(target, FLASH_REG_ADDRESS(bluenrgx_info),
195 (address - FLASH_BASE(bluenrgx_info)) >> 2) != ERROR_OK) {
196 LOG_ERROR("Register write failed");
197 return ERROR_FAIL;
198 }
199
200 if (target_write_u32(target, FLASH_REG_COMMAND(bluenrgx_info), command) != ERROR_OK) {
201 LOG_ERROR("Register write failed");
202 return ERROR_FAIL;
203 }
204
205 for (int i = 0; i < 100; i++) {
206 uint32_t value;
207 if (target_read_u32(target, FLASH_REG_IRQRAW(bluenrgx_info), &value)) {
208 LOG_ERROR("Register write failed");
209 return ERROR_FAIL;
210 }
211 if (value & FLASH_INT_CMDDONE)
212 break;
213 if (i == 99) {
214 LOG_ERROR("Mass erase command failed (timeout)");
215 retval = ERROR_FAIL;
216 }
217 }
218
219 } else {
220 command = FLASH_CMD_ERASE_PAGE;
221 for (int i = first; i <= last; i++) {
222 address = bank->base+i*FLASH_PAGE_SIZE(bluenrgx_info);
223 LOG_DEBUG("address = %08x, index = %d", address, i);
224
225 if (target_write_u32(target, FLASH_REG_IRQRAW(bluenrgx_info), 0x3f) != ERROR_OK) {
226 LOG_ERROR("Register write failed");
227 return ERROR_FAIL;
228 }
229
230 if (target_write_u32(target, FLASH_REG_ADDRESS(bluenrgx_info),
231 (address - FLASH_BASE(bluenrgx_info)) >> 2) != ERROR_OK) {
232 LOG_ERROR("Register write failed");
233 return ERROR_FAIL;
234 }
235
236 if (target_write_u32(target, FLASH_REG_COMMAND(bluenrgx_info), command) != ERROR_OK) {
237 LOG_ERROR("Failed");
238 return ERROR_FAIL;
239 }
240
241 for (int j = 0; j < 100; j++) {
242 uint32_t value;
243 if (target_read_u32(target, FLASH_REG_IRQRAW(bluenrgx_info), &value)) {
244 LOG_ERROR("Register write failed");
245 return ERROR_FAIL;
246 }
247 if (value & FLASH_INT_CMDDONE)
248 break;
249 if (j == 99) {
250 LOG_ERROR("Erase command failed (timeout)");
251 retval = ERROR_FAIL;
252 }
253 }
254 }
255 }
256
257 return retval;
258
259 }
260
261 static int bluenrgx_protect(struct flash_bank *bank, int set, int first, int last)
262 {
263 /* Protection is only handled in software: no hardware write protection
264 available in BlueNRG-x devices */
265 int sector;
266
267 for (sector = first; sector <= last; sector++)
268 bank->sectors[sector].is_protected = set;
269 return ERROR_OK;
270 }
271
272 static int bluenrgx_write_word(struct flash_bank *bank, uint32_t address_base, uint8_t *values, uint32_t count)
273 {
274 int retval = ERROR_OK;
275 struct target *target = bank->target;
276 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
277
278 retval = target_write_u32(target, FLASH_REG_IRQRAW(bluenrgx_info), 0x3f);
279 if (retval != ERROR_OK) {
280 LOG_ERROR("Register write failed, error code: %d", retval);
281 return retval;
282 }
283
284 for (uint32_t i = 0; i < count; i++) {
285 uint32_t address = address_base + i * FLASH_WORD_LEN;
286
287 retval = target_write_u32(target, FLASH_REG_ADDRESS(bluenrgx_info),
288 (address - FLASH_BASE(bluenrgx_info)) >> 2);
289 if (retval != ERROR_OK) {
290 LOG_ERROR("Register write failed, error code: %d", retval);
291 return retval;
292 }
293
294 retval = target_write_buffer(target, FLASH_REG_DATA(bluenrgx_info),
295 FLASH_WORD_LEN, values + i * FLASH_WORD_LEN);
296 if (retval != ERROR_OK) {
297 LOG_ERROR("Register write failed, error code: %d", retval);
298 return retval;
299 }
300
301 retval = target_write_u32(target, FLASH_REG_COMMAND(bluenrgx_info), FLASH_CMD_WRITE);
302 if (retval != ERROR_OK) {
303 LOG_ERROR("Register write failed, error code: %d", retval);
304 return retval;
305 }
306
307 for (int j = 0; j < 100; j++) {
308 uint32_t reg_value;
309 retval = target_read_u32(target, FLASH_REG_IRQRAW(bluenrgx_info), &reg_value);
310
311 if (retval != ERROR_OK) {
312 LOG_ERROR("Register read failed, error code: %d", retval);
313 return retval;
314 }
315
316 if (reg_value & FLASH_INT_CMDDONE)
317 break;
318
319 if (j == 99) {
320 LOG_ERROR("Write command failed (timeout)");
321 return ERROR_FAIL;
322 }
323 }
324 }
325 return retval;
326 }
327
328 static int bluenrgx_write_bytes(struct flash_bank *bank, uint32_t address_base, uint8_t *buffer, uint32_t count)
329 {
330 int retval = ERROR_OK;
331 struct target *target = bank->target;
332 uint8_t *new_buffer = NULL;
333 uint32_t pre_bytes = 0, post_bytes = 0, pre_word, post_word, pre_address, post_address;
334
335 if (count == 0) {
336 /* Just return if there are no bytes to write */
337 return retval;
338 }
339
340 if (address_base & 3) {
341 pre_bytes = address_base & 3;
342 pre_address = address_base - pre_bytes;
343 }
344
345 if ((count + pre_bytes) & 3) {
346 post_bytes = ((count + pre_bytes + 3) & ~3) - (count + pre_bytes);
347 post_address = (address_base + count) & ~3;
348 }
349
350 if (pre_bytes || post_bytes) {
351 uint32_t old_count = count;
352
353 count = old_count + pre_bytes + post_bytes;
354
355 new_buffer = malloc(count);
356
357 if (new_buffer == NULL) {
358 LOG_ERROR("odd number of bytes to write and no memory "
359 "for padding buffer");
360 return ERROR_FAIL;
361 }
362
363 LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32 "), extending to %"
364 PRIu32 " ", old_count, count);
365
366 if (pre_bytes) {
367 if (target_read_u32(target, pre_address, &pre_word)) {
368 LOG_ERROR("Memory read failed");
369 free(new_buffer);
370 return ERROR_FAIL;
371 }
372
373 }
374
375 if (post_bytes) {
376 if (target_read_u32(target, post_address, &post_word)) {
377 LOG_ERROR("Memory read failed");
378 free(new_buffer);
379 return ERROR_FAIL;
380 }
381
382 }
383
384 memcpy(new_buffer, &pre_word, pre_bytes);
385 memcpy((new_buffer+((pre_bytes+old_count) & ~3)), &post_word, 4);
386 memcpy(new_buffer+pre_bytes, buffer, old_count);
387 buffer = new_buffer;
388 }
389
390 retval = bluenrgx_write_word(bank, address_base - pre_bytes, buffer, count/4);
391
392 if (new_buffer)
393 free(new_buffer);
394
395 return retval;
396 }
397
398 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
399 uint32_t offset, uint32_t count)
400 {
401 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
402 struct target *target = bank->target;
403 uint32_t buffer_size = 16384 + 8;
404 struct working_area *write_algorithm;
405 struct working_area *write_algorithm_sp;
406 struct working_area *source;
407 uint32_t address = bank->base + offset;
408 struct reg_param reg_params[5];
409 struct armv7m_algorithm armv7m_info;
410 int retval = ERROR_OK;
411 uint32_t pre_size = 0, fast_size = 0, post_size = 0;
412 uint32_t pre_offset = 0, fast_offset = 0, post_offset = 0;
413
414 /* check preconditions */
415 if (bluenrgx_info->probed == 0)
416 return ERROR_FLASH_BANK_NOT_PROBED;
417
418 if ((offset + count) > bank->size) {
419 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
420 (offset + count),
421 bank->size);
422 return ERROR_FLASH_DST_OUT_OF_BANK;
423 }
424
425 if (bank->target->state != TARGET_HALTED) {
426 LOG_ERROR("Target not halted");
427 return ERROR_TARGET_NOT_HALTED;
428 }
429
430 /* We are good here and we need to compute pre_size, fast_size, post_size */
431 pre_size = MIN(count, ((offset+0xF) & ~0xF) - offset);
432 pre_offset = offset;
433 fast_size = 16*((count - pre_size) / 16);
434 fast_offset = offset + pre_size;
435 post_size = (count-pre_size-fast_size) % 16;
436 post_offset = fast_offset + fast_size;
437
438 LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size, pre_offset);
439 LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size, fast_offset);
440 LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size, post_offset);
441
442 /* Program initial chunk not 16 bytes aligned */
443 retval = bluenrgx_write_bytes(bank, bank->base+pre_offset, (uint8_t *) buffer, pre_size);
444 if (retval) {
445 LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
446 return ERROR_FAIL;
447 }
448
449 /* Program chunk 16 bytes aligned in fast mode */
450 if (fast_size) {
451
452 if (target_alloc_working_area(target, bluenrgx_info->flash_write_code_size,
453 &write_algorithm) != ERROR_OK) {
454 LOG_WARNING("no working area available, can't do block memory writes");
455 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
456 }
457
458 retval = target_write_buffer(target, write_algorithm->address,
459 bluenrgx_info->flash_write_code_size,
460 bluenrgx_info->flash_write_code);
461 if (retval != ERROR_OK)
462 return retval;
463
464 /* memory buffer */
465 if (target_alloc_working_area(target, buffer_size, &source)) {
466 LOG_WARNING("no large enough working area available");
467 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
468 }
469
470 /* Stack pointer area */
471 if (target_alloc_working_area(target, 64,
472 &write_algorithm_sp) != ERROR_OK) {
473 LOG_DEBUG("no working area for write code stack pointer");
474 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
475 }
476
477 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
478 armv7m_info.core_mode = ARM_MODE_THREAD;
479
480 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
481 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
482 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
483 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
484 init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
485
486 /* FIFO start address (first two words used for write and read pointers) */
487 buf_set_u32(reg_params[0].value, 0, 32, source->address);
488 /* FIFO end address (first two words used for write and read pointers) */
489 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
490 /* Flash memory address */
491 buf_set_u32(reg_params[2].value, 0, 32, address+pre_size);
492 /* Number of bytes */
493 buf_set_u32(reg_params[3].value, 0, 32, fast_size);
494 /* Stack pointer for program working area */
495 buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
496
497 LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
498 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
499 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
500 LOG_DEBUG("address = %08x", address+pre_size);
501 LOG_DEBUG("count = %08x", count);
502
503 retval = target_run_flash_async_algorithm(target,
504 buffer+pre_size,
505 fast_size/16,
506 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
507 0,
508 NULL,
509 5,
510 reg_params,
511 source->address,
512 source->size,
513 write_algorithm->address,
514 0,
515 &armv7m_info);
516
517 if (retval == ERROR_FLASH_OPERATION_FAILED) {
518 LOG_ERROR("error executing bluenrg-x flash write algorithm");
519
520 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
521
522 if (error != 0)
523 LOG_ERROR("flash write failed = %08" PRIx32, error);
524 }
525 if (retval == ERROR_OK) {
526 uint32_t rp;
527 /* Read back rp and check that is valid */
528 retval = target_read_u32(target, source->address+4, &rp);
529 if (retval == ERROR_OK) {
530 if ((rp < source->address+8) || (rp > (source->address + source->size))) {
531 LOG_ERROR("flash write failed = %08" PRIx32, rp);
532 retval = ERROR_FLASH_OPERATION_FAILED;
533 }
534 }
535 }
536 target_free_working_area(target, source);
537 target_free_working_area(target, write_algorithm);
538 target_free_working_area(target, write_algorithm_sp);
539
540 destroy_reg_param(&reg_params[0]);
541 destroy_reg_param(&reg_params[1]);
542 destroy_reg_param(&reg_params[2]);
543 destroy_reg_param(&reg_params[3]);
544 destroy_reg_param(&reg_params[4]);
545 if (retval != ERROR_OK)
546 return retval;
547
548 }
549
550 /* Program chunk at end, not addressable by fast burst write algorithm */
551 retval = bluenrgx_write_bytes(bank, bank->base+post_offset,
552 (uint8_t *) (buffer+pre_size+fast_size), post_size);
553 if (retval) {
554 LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
555 return ERROR_FAIL;
556 }
557 return retval;
558 }
559
560 static int bluenrgx_probe(struct flash_bank *bank)
561 {
562 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
563 uint32_t idcode, size_info, die_id;
564 int i;
565 int retval = target_read_u32(bank->target, BLUENRGLP_JTAG_REG, &idcode);
566
567 if (retval != ERROR_OK)
568 return retval;
569
570 if (idcode != BLUENRGLP_IDCODE) {
571 retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
572 if (retval != ERROR_OK)
573 return retval;
574 }
575
576 /* Default device is BlueNRG-1 */
577 bluenrgx_info->flash_ptr = &flash_priv_data_1;
578 bluenrgx_info->flash_write_code = flash_priv_data_1.flash_write_code;
579 bluenrgx_info->flash_write_code_size = flash_priv_data_1.flash_write_code_size;
580
581 for (i = 0; i < (int)(sizeof(flash_ctrl)/sizeof(*flash_ctrl)); i++) {
582 if (idcode == (*flash_ctrl[i]).jtag_idcode) {
583 bluenrgx_info->flash_ptr = flash_ctrl[i];
584 bluenrgx_info->flash_write_code = (*flash_ctrl[i]).flash_write_code;
585 bluenrgx_info->flash_write_code_size = (*flash_ctrl[i]).flash_write_code_size;
586 break;
587 }
588 }
589
590 retval = target_read_u32(bank->target, FLASH_SIZE_REG(bluenrgx_info), &size_info);
591 if (retval != ERROR_OK)
592 return retval;
593
594 retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
595 if (retval != ERROR_OK)
596 return retval;
597
598 bank->size = (size_info + 1) * FLASH_WORD_LEN;
599 bank->base = FLASH_BASE(bluenrgx_info);
600 bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
601 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
602
603 for (i = 0; i < bank->num_sectors; i++) {
604 bank->sectors[i].offset = i * FLASH_PAGE_SIZE(bluenrgx_info);
605 bank->sectors[i].size = FLASH_PAGE_SIZE(bluenrgx_info);
606 bank->sectors[i].is_erased = -1;
607 bank->sectors[i].is_protected = 0;
608 }
609
610 bluenrgx_info->probed = 1;
611 bluenrgx_info->die_id = die_id;
612
613 return ERROR_OK;
614 }
615
616 static int bluenrgx_auto_probe(struct flash_bank *bank)
617 {
618 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
619
620 if (bluenrgx_info->probed)
621 return ERROR_OK;
622
623 return bluenrgx_probe(bank);
624 }
625
626 /* This method must return a string displaying information about the bank */
627 static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
628 {
629 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
630 int mask_number, cut_number;
631
632 if (!bluenrgx_info->probed) {
633 int retval = bluenrgx_probe(bank);
634 if (retval != ERROR_OK) {
635 snprintf(buf, buf_size,
636 "Unable to find bank information.");
637 return retval;
638 }
639 }
640
641 mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
642 cut_number = bluenrgx_info->die_id & 0xF;
643
644 snprintf(buf, buf_size,
645 "%s - Rev: %d.%d", bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
646 return ERROR_OK;
647 }
648
649 const struct flash_driver bluenrgx_flash = {
650 .name = "bluenrg-x",
651 .flash_bank_command = bluenrgx_flash_bank_command,
652 .erase = bluenrgx_erase,
653 .protect = bluenrgx_protect,
654 .write = bluenrgx_write,
655 .read = default_flash_read,
656 .probe = bluenrgx_probe,
657 .erase_check = default_flash_blank_check,
658 .protect_check = bluenrgx_protect_check,
659 .auto_probe = bluenrgx_auto_probe,
660 .info = bluenrgx_get_info,
661 };

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)