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>
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)
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
49 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
50 * hints how to generate the data!
52 static const uint8_t bluenrgx_flash_write_code_2
[] = {
53 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-2_write.inc"
56 static const uint8_t bluenrgx_flash_write_code_lp
[] = {
57 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-lp_write.inc"
60 struct flash_ctrl_priv_data
{
61 uint32_t flash_size_reg
;
63 uint32_t jtag_idcode_reg
;
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
;
72 const uint8_t *flash_write_code
;
73 uint32_t flash_write_code_size
;
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
),
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
),
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
),
124 struct bluenrgx_flash_bank
{
127 const struct flash_ctrl_priv_data
*flash_ptr
;
128 const uint8_t *flash_write_code
;
129 uint32_t flash_write_code_size
;
132 const struct flash_ctrl_priv_data
*flash_ctrl
[] = {&flash_priv_data_1
, &flash_priv_data_2
, &flash_priv_data_lp
};
134 static int bluenrgx_protect_check(struct flash_bank
*bank
)
136 /* Nothing to do. Protection is only handled in SW. */
140 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
141 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command
)
143 struct bluenrgx_flash_bank
*bluenrgx_info
;
144 /* Create the bank structure */
145 bluenrgx_info
= calloc(1, sizeof(*bluenrgx_info
));
147 /* Check allocation */
148 if (bluenrgx_info
== NULL
) {
149 LOG_ERROR("failed to allocate bank structure");
153 bank
->driver_priv
= bluenrgx_info
;
155 bluenrgx_info
->probed
= 0;
158 return ERROR_COMMAND_SYNTAX_ERROR
;
163 static int bluenrgx_erase(struct flash_bank
*bank
, int first
, int last
)
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
;
172 /* check preconditions */
173 if (bluenrgx_info
->probed
== 0)
174 return ERROR_FLASH_BANK_NOT_PROBED
;
176 if (bank
->target
->state
!= TARGET_HALTED
) {
177 LOG_ERROR("Target not halted");
178 return ERROR_TARGET_NOT_HALTED
;
180 /* Disable blue module */
181 if (target_write_u32(target
, 0x200000c0, 0) != ERROR_OK
) {
182 LOG_ERROR("Blue disable failed");
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");
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");
200 if (target_write_u32(target
, FLASH_REG_COMMAND(bluenrgx_info
), command
) != ERROR_OK
) {
201 LOG_ERROR("Register write failed");
205 for (int i
= 0; i
< 100; i
++) {
207 if (target_read_u32(target
, FLASH_REG_IRQRAW(bluenrgx_info
), &value
)) {
208 LOG_ERROR("Register write failed");
211 if (value
& FLASH_INT_CMDDONE
)
214 LOG_ERROR("Mass erase command failed (timeout)");
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
);
225 if (target_write_u32(target
, FLASH_REG_IRQRAW(bluenrgx_info
), 0x3f) != ERROR_OK
) {
226 LOG_ERROR("Register write failed");
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");
236 if (target_write_u32(target
, FLASH_REG_COMMAND(bluenrgx_info
), command
) != ERROR_OK
) {
241 for (int j
= 0; j
< 100; j
++) {
243 if (target_read_u32(target
, FLASH_REG_IRQRAW(bluenrgx_info
), &value
)) {
244 LOG_ERROR("Register write failed");
247 if (value
& FLASH_INT_CMDDONE
)
250 LOG_ERROR("Erase command failed (timeout)");
261 static int bluenrgx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
263 /* Protection is only handled in software: no hardware write protection
264 available in BlueNRG-x devices */
267 for (sector
= first
; sector
<= last
; sector
++)
268 bank
->sectors
[sector
].is_protected
= set
;
272 static int bluenrgx_write_word(struct flash_bank
*bank
, uint32_t address_base
, uint8_t *values
, uint32_t count
)
274 int retval
= ERROR_OK
;
275 struct target
*target
= bank
->target
;
276 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
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
);
284 for (uint32_t i
= 0; i
< count
; i
++) {
285 uint32_t address
= address_base
+ i
* FLASH_WORD_LEN
;
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
);
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
);
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
);
307 for (int j
= 0; j
< 100; j
++) {
309 retval
= target_read_u32(target
, FLASH_REG_IRQRAW(bluenrgx_info
), ®_value
);
311 if (retval
!= ERROR_OK
) {
312 LOG_ERROR("Register read failed, error code: %d", retval
);
316 if (reg_value
& FLASH_INT_CMDDONE
)
320 LOG_ERROR("Write command failed (timeout)");
328 static int bluenrgx_write_bytes(struct flash_bank
*bank
, uint32_t address_base
, uint8_t *buffer
, uint32_t count
)
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
;
336 /* Just return if there are no bytes to write */
340 if (address_base
& 3) {
341 pre_bytes
= address_base
& 3;
342 pre_address
= address_base
- pre_bytes
;
345 if ((count
+ pre_bytes
) & 3) {
346 post_bytes
= ((count
+ pre_bytes
+ 3) & ~3) - (count
+ pre_bytes
);
347 post_address
= (address_base
+ count
) & ~3;
350 if (pre_bytes
|| post_bytes
) {
351 uint32_t old_count
= count
;
353 count
= old_count
+ pre_bytes
+ post_bytes
;
355 new_buffer
= malloc(count
);
357 if (new_buffer
== NULL
) {
358 LOG_ERROR("odd number of bytes to write and no memory "
359 "for padding buffer");
363 LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32
"), extending to %"
364 PRIu32
" ", old_count
, count
);
367 if (target_read_u32(target
, pre_address
, &pre_word
)) {
368 LOG_ERROR("Memory read failed");
376 if (target_read_u32(target
, post_address
, &post_word
)) {
377 LOG_ERROR("Memory read failed");
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
);
390 retval
= bluenrgx_write_word(bank
, address_base
- pre_bytes
, buffer
, count
/4);
398 static int bluenrgx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
399 uint32_t offset
, uint32_t count
)
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;
414 /* check preconditions */
415 if (bluenrgx_info
->probed
== 0)
416 return ERROR_FLASH_BANK_NOT_PROBED
;
418 if ((offset
+ count
) > bank
->size
) {
419 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
422 return ERROR_FLASH_DST_OUT_OF_BANK
;
425 if (bank
->target
->state
!= TARGET_HALTED
) {
426 LOG_ERROR("Target not halted");
427 return ERROR_TARGET_NOT_HALTED
;
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
);
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
;
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
);
442 /* Program initial chunk not 16 bytes aligned */
443 retval
= bluenrgx_write_bytes(bank
, bank
->base
+pre_offset
, (uint8_t *) buffer
, pre_size
);
445 LOG_ERROR("bluenrgx_write_bytes failed %d", retval
);
449 /* Program chunk 16 bytes aligned in fast mode */
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
;
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
)
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
;
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
;
477 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
478 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
480 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
481 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
482 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
483 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
484 init_reg_param(®_params
[4], "sp", 32, PARAM_OUT
);
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
);
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
);
503 retval
= target_run_flash_async_algorithm(target
,
506 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
513 write_algorithm
->address
,
517 if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
518 LOG_ERROR("error executing bluenrg-x flash write algorithm");
520 uint32_t error
= buf_get_u32(reg_params
[0].value
, 0, 32);
523 LOG_ERROR("flash write failed = %08" PRIx32
, error
);
525 if (retval
== ERROR_OK
) {
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
;
536 target_free_working_area(target
, source
);
537 target_free_working_area(target
, write_algorithm
);
538 target_free_working_area(target
, write_algorithm_sp
);
540 destroy_reg_param(®_params
[0]);
541 destroy_reg_param(®_params
[1]);
542 destroy_reg_param(®_params
[2]);
543 destroy_reg_param(®_params
[3]);
544 destroy_reg_param(®_params
[4]);
545 if (retval
!= ERROR_OK
)
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
);
554 LOG_ERROR("bluenrgx_write_bytes failed %d", retval
);
560 static int bluenrgx_probe(struct flash_bank
*bank
)
562 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
563 uint32_t idcode
, size_info
, die_id
;
565 int retval
= target_read_u32(bank
->target
, BLUENRGLP_JTAG_REG
, &idcode
);
567 if (retval
!= ERROR_OK
)
570 if (idcode
!= BLUENRGLP_IDCODE
) {
571 retval
= target_read_u32(bank
->target
, BLUENRG2_JTAG_REG
, &idcode
);
572 if (retval
!= ERROR_OK
)
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
;
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
;
590 retval
= target_read_u32(bank
->target
, FLASH_SIZE_REG(bluenrgx_info
), &size_info
);
591 if (retval
!= ERROR_OK
)
594 retval
= target_read_u32(bank
->target
, DIE_ID_REG(bluenrgx_info
), &die_id
);
595 if (retval
!= ERROR_OK
)
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
);
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;
610 bluenrgx_info
->probed
= 1;
611 bluenrgx_info
->die_id
= die_id
;
616 static int bluenrgx_auto_probe(struct flash_bank
*bank
)
618 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
620 if (bluenrgx_info
->probed
)
623 return bluenrgx_probe(bank
);
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
)
629 struct bluenrgx_flash_bank
*bluenrgx_info
= bank
->driver_priv
;
630 int mask_number
, cut_number
;
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.");
641 mask_number
= (bluenrgx_info
->die_id
>> 4) & 0xF;
642 cut_number
= bluenrgx_info
->die_id
& 0xF;
644 snprintf(buf
, buf_size
,
645 "%s - Rev: %d.%d", bluenrgx_info
->flash_ptr
->part_name
, mask_number
, cut_number
);
649 const struct flash_driver bluenrgx_flash
= {
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
,
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)