flash_driver_t -> struct flash_driver
[openocd.git] / src / flash / str7x.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "str7x.h"
28 #include "armv4_5.h"
29 #include "binarybuffer.h"
30
31
32 str7x_mem_layout_t mem_layout_str7bank0[] = {
33 {0x00000000, 0x02000, 0x01},
34 {0x00002000, 0x02000, 0x02},
35 {0x00004000, 0x02000, 0x04},
36 {0x00006000, 0x02000, 0x08},
37 {0x00008000, 0x08000, 0x10},
38 {0x00010000, 0x10000, 0x20},
39 {0x00020000, 0x10000, 0x40},
40 {0x00030000, 0x10000, 0x80}
41 };
42
43 str7x_mem_layout_t mem_layout_str7bank1[] = {
44 {0x00000000, 0x02000, 0x10000},
45 {0x00002000, 0x02000, 0x20000}
46 };
47
48 static int str7x_get_flash_adr(struct flash_bank_s *bank, uint32_t reg)
49 {
50 str7x_flash_bank_t *str7x_info = bank->driver_priv;
51 return (str7x_info->register_base | reg);
52 }
53
54 static int str7x_build_block_list(struct flash_bank_s *bank)
55 {
56 str7x_flash_bank_t *str7x_info = bank->driver_priv;
57
58 int i;
59 int num_sectors;
60 int b0_sectors = 0, b1_sectors = 0;
61
62 switch (bank->size)
63 {
64 case 16 * 1024:
65 b1_sectors = 2;
66 break;
67 case 64 * 1024:
68 b0_sectors = 5;
69 break;
70 case 128 * 1024:
71 b0_sectors = 6;
72 break;
73 case 256 * 1024:
74 b0_sectors = 8;
75 break;
76 default:
77 LOG_ERROR("BUG: unknown bank->size encountered");
78 exit(-1);
79 }
80
81 num_sectors = b0_sectors + b1_sectors;
82
83 bank->num_sectors = num_sectors;
84 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
85 str7x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
86
87 num_sectors = 0;
88
89 for (i = 0; i < b0_sectors; i++)
90 {
91 bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
92 bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
93 bank->sectors[num_sectors].is_erased = -1;
94 bank->sectors[num_sectors].is_protected = 1;
95 str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
96 }
97
98 for (i = 0; i < b1_sectors; i++)
99 {
100 bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
101 bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
102 bank->sectors[num_sectors].is_erased = -1;
103 bank->sectors[num_sectors].is_protected = 1;
104 str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit;
105 }
106
107 return ERROR_OK;
108 }
109
110 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
111 */
112 FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command)
113 {
114 str7x_flash_bank_t *str7x_info;
115
116 if (argc < 7)
117 {
118 LOG_WARNING("incomplete flash_bank str7x configuration");
119 return ERROR_FLASH_BANK_INVALID;
120 }
121
122 str7x_info = malloc(sizeof(str7x_flash_bank_t));
123 bank->driver_priv = str7x_info;
124
125 /* set default bits for str71x flash */
126 str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA1 | FLASH_BSYA0);
127 str7x_info->disable_bit = (1 << 1);
128
129 if (strcmp(args[6], "STR71x") == 0)
130 {
131 str7x_info->register_base = 0x40100000;
132 }
133 else if (strcmp(args[6], "STR73x") == 0)
134 {
135 str7x_info->register_base = 0x80100000;
136 str7x_info->busy_bits = (FLASH_LOCK | FLASH_BSYA0);
137 }
138 else if (strcmp(args[6], "STR75x") == 0)
139 {
140 str7x_info->register_base = 0x20100000;
141 str7x_info->disable_bit = (1 << 0);
142 }
143 else
144 {
145 LOG_ERROR("unknown STR7x variant: '%s'", args[6]);
146 free(str7x_info);
147 return ERROR_FLASH_BANK_INVALID;
148 }
149
150 str7x_build_block_list(bank);
151
152 str7x_info->write_algorithm = NULL;
153
154 return ERROR_OK;
155 }
156
157 static uint32_t str7x_status(struct flash_bank_s *bank)
158 {
159 target_t *target = bank->target;
160 uint32_t retval;
161
162 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), &retval);
163
164 return retval;
165 }
166
167 static uint32_t str7x_result(struct flash_bank_s *bank)
168 {
169 target_t *target = bank->target;
170 uint32_t retval;
171
172 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_ER), &retval);
173
174 return retval;
175 }
176
177 static int str7x_protect_check(struct flash_bank_s *bank)
178 {
179 str7x_flash_bank_t *str7x_info = bank->driver_priv;
180 target_t *target = bank->target;
181
182 int i;
183 uint32_t retval;
184
185 if (bank->target->state != TARGET_HALTED)
186 {
187 LOG_ERROR("Target not halted");
188 return ERROR_TARGET_NOT_HALTED;
189 }
190
191 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVWPAR), &retval);
192
193 for (i = 0; i < bank->num_sectors; i++)
194 {
195 if (retval & str7x_info->sector_bits[i])
196 bank->sectors[i].is_protected = 0;
197 else
198 bank->sectors[i].is_protected = 1;
199 }
200
201 return ERROR_OK;
202 }
203
204 static int str7x_erase(struct flash_bank_s *bank, int first, int last)
205 {
206 str7x_flash_bank_t *str7x_info = bank->driver_priv;
207 target_t *target = bank->target;
208
209 int i;
210 uint32_t cmd;
211 uint32_t retval;
212 uint32_t sectors = 0;
213
214 if (bank->target->state != TARGET_HALTED)
215 {
216 LOG_ERROR("Target not halted");
217 return ERROR_TARGET_NOT_HALTED;
218 }
219
220 for (i = first; i <= last; i++)
221 {
222 sectors |= str7x_info->sector_bits[i];
223 }
224
225 LOG_DEBUG("sectors: 0x%" PRIx32 "", sectors);
226
227 /* clear FLASH_ER register */
228 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
229
230 cmd = FLASH_SER;
231 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
232
233 cmd = sectors;
234 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR1), cmd);
235
236 cmd = FLASH_SER | FLASH_WMS;
237 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
238
239 while (((retval = str7x_status(bank)) & str7x_info->busy_bits)) {
240 alive_sleep(1);
241 }
242
243 retval = str7x_result(bank);
244
245 if (retval)
246 {
247 LOG_ERROR("error erasing flash bank, FLASH_ER: 0x%" PRIx32 "", retval);
248 return ERROR_FLASH_OPERATION_FAILED;
249 }
250
251 for (i = first; i <= last; i++)
252 bank->sectors[i].is_erased = 1;
253
254 return ERROR_OK;
255 }
256
257 static int str7x_protect(struct flash_bank_s *bank, int set, int first, int last)
258 {
259 str7x_flash_bank_t *str7x_info = bank->driver_priv;
260 target_t *target = bank->target;
261 int i;
262 uint32_t cmd;
263 uint32_t retval;
264 uint32_t protect_blocks;
265
266 if (bank->target->state != TARGET_HALTED)
267 {
268 LOG_ERROR("Target not halted");
269 return ERROR_TARGET_NOT_HALTED;
270 }
271
272 protect_blocks = 0xFFFFFFFF;
273
274 if (set)
275 {
276 for (i = first; i <= last; i++)
277 protect_blocks &= ~(str7x_info->sector_bits[i]);
278 }
279
280 /* clear FLASH_ER register */
281 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
282
283 cmd = FLASH_SPR;
284 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
285
286 cmd = str7x_get_flash_adr(bank, FLASH_NVWPAR);
287 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), cmd);
288
289 cmd = protect_blocks;
290 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), cmd);
291
292 cmd = FLASH_SPR | FLASH_WMS;
293 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
294
295 while (((retval = str7x_status(bank)) & str7x_info->busy_bits)) {
296 alive_sleep(1);
297 }
298
299 retval = str7x_result(bank);
300
301 LOG_DEBUG("retval: 0x%8.8" PRIx32 "", retval);
302
303 if (retval & FLASH_ERER)
304 return ERROR_FLASH_SECTOR_NOT_ERASED;
305 else if (retval & FLASH_WPF)
306 return ERROR_FLASH_OPERATION_FAILED;
307
308 return ERROR_OK;
309 }
310
311 static int str7x_write_block(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
312 {
313 str7x_flash_bank_t *str7x_info = bank->driver_priv;
314 target_t *target = bank->target;
315 uint32_t buffer_size = 8192;
316 working_area_t *source;
317 uint32_t address = bank->base + offset;
318 reg_param_t reg_params[6];
319 armv4_5_algorithm_t armv4_5_info;
320 int retval = ERROR_OK;
321
322 uint32_t str7x_flash_write_code[] = {
323 /* write: */
324 0xe3a04201, /* mov r4, #0x10000000 */
325 0xe5824000, /* str r4, [r2, #0x0] */
326 0xe5821010, /* str r1, [r2, #0x10] */
327 0xe4904004, /* ldr r4, [r0], #4 */
328 0xe5824008, /* str r4, [r2, #0x8] */
329 0xe4904004, /* ldr r4, [r0], #4 */
330 0xe582400c, /* str r4, [r2, #0xc] */
331 0xe3a04209, /* mov r4, #0x90000000 */
332 0xe5824000, /* str r4, [r2, #0x0] */
333 /* busy: */
334 0xe5924000, /* ldr r4, [r2, #0x0] */
335 0xe1140005, /* tst r4, r5 */
336 0x1afffffc, /* bne busy */
337 0xe5924014, /* ldr r4, [r2, #0x14] */
338 0xe31400ff, /* tst r4, #0xff */
339 0x03140c01, /* tsteq r4, #0x100 */
340 0x1a000002, /* bne exit */
341 0xe2811008, /* add r1, r1, #0x8 */
342 0xe2533001, /* subs r3, r3, #1 */
343 0x1affffec, /* bne write */
344 /* exit: */
345 0xeafffffe, /* b exit */
346 };
347
348 /* flash write code */
349 if (target_alloc_working_area(target, 4 * 20, &str7x_info->write_algorithm) != ERROR_OK)
350 {
351 LOG_WARNING("no working area available, can't do block memory writes");
352 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
353 };
354
355 target_write_buffer(target, str7x_info->write_algorithm->address, 20 * 4, (uint8_t*)str7x_flash_write_code);
356
357 /* memory buffer */
358 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
359 {
360 buffer_size /= 2;
361 if (buffer_size <= 256)
362 {
363 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
364 if (str7x_info->write_algorithm)
365 target_free_working_area(target, str7x_info->write_algorithm);
366
367 LOG_WARNING("no large enough working area available, can't do block memory writes");
368 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
369 }
370 }
371
372 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
373 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
374 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
375
376 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
377 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
378 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
379 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
380 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN);
381 init_reg_param(&reg_params[5], "r5", 32, PARAM_OUT);
382
383 while (count > 0)
384 {
385 uint32_t thisrun_count = (count > (buffer_size / 8)) ? (buffer_size / 8) : count;
386
387 target_write_buffer(target, source->address, thisrun_count * 8, buffer);
388
389 buf_set_u32(reg_params[0].value, 0, 32, source->address);
390 buf_set_u32(reg_params[1].value, 0, 32, address);
391 buf_set_u32(reg_params[2].value, 0, 32, str7x_get_flash_adr(bank, FLASH_CR0));
392 buf_set_u32(reg_params[3].value, 0, 32, thisrun_count);
393 buf_set_u32(reg_params[5].value, 0, 32, str7x_info->busy_bits);
394
395 if ((retval = target_run_algorithm(target, 0, NULL, 6, reg_params, str7x_info->write_algorithm->address, str7x_info->write_algorithm->address + (19 * 4), 10000, &armv4_5_info)) != ERROR_OK)
396 {
397 LOG_ERROR("error executing str7x flash write algorithm");
398 retval = ERROR_FLASH_OPERATION_FAILED;
399 break;
400 }
401
402 if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
403 {
404 retval = ERROR_FLASH_OPERATION_FAILED;
405 break;
406 }
407
408 buffer += thisrun_count * 8;
409 address += thisrun_count * 8;
410 count -= thisrun_count;
411 }
412
413 target_free_working_area(target, source);
414 target_free_working_area(target, str7x_info->write_algorithm);
415
416 destroy_reg_param(&reg_params[0]);
417 destroy_reg_param(&reg_params[1]);
418 destroy_reg_param(&reg_params[2]);
419 destroy_reg_param(&reg_params[3]);
420 destroy_reg_param(&reg_params[4]);
421 destroy_reg_param(&reg_params[5]);
422
423 return retval;
424 }
425
426 static int str7x_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
427 {
428 target_t *target = bank->target;
429 str7x_flash_bank_t *str7x_info = bank->driver_priv;
430 uint32_t dwords_remaining = (count / 8);
431 uint32_t bytes_remaining = (count & 0x00000007);
432 uint32_t address = bank->base + offset;
433 uint32_t bytes_written = 0;
434 uint32_t cmd;
435 int retval;
436 uint32_t check_address = offset;
437 int i;
438
439 if (bank->target->state != TARGET_HALTED)
440 {
441 LOG_ERROR("Target not halted");
442 return ERROR_TARGET_NOT_HALTED;
443 }
444
445 if (offset & 0x7)
446 {
447 LOG_WARNING("offset 0x%" PRIx32 " breaks required 8-byte alignment", offset);
448 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
449 }
450
451 for (i = 0; i < bank->num_sectors; i++)
452 {
453 uint32_t sec_start = bank->sectors[i].offset;
454 uint32_t sec_end = sec_start + bank->sectors[i].size;
455
456 /* check if destination falls within the current sector */
457 if ((check_address >= sec_start) && (check_address < sec_end))
458 {
459 /* check if destination ends in the current sector */
460 if (offset + count < sec_end)
461 check_address = offset + count;
462 else
463 check_address = sec_end;
464 }
465 }
466
467 if (check_address != offset + count)
468 return ERROR_FLASH_DST_OUT_OF_BANK;
469
470 /* clear FLASH_ER register */
471 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
472
473 /* multiple dwords (8-byte) to be programmed? */
474 if (dwords_remaining > 0)
475 {
476 /* try using a block write */
477 if ((retval = str7x_write_block(bank, buffer, offset, dwords_remaining)) != ERROR_OK)
478 {
479 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
480 {
481 /* if block write failed (no sufficient working area),
482 * we use normal (slow) single dword accesses */
483 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
484 }
485 else if (retval == ERROR_FLASH_OPERATION_FAILED)
486 {
487 /* if an error occured, we examine the reason, and quit */
488 retval = str7x_result(bank);
489
490 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
491 return ERROR_FLASH_OPERATION_FAILED;
492 }
493 }
494 else
495 {
496 buffer += dwords_remaining * 8;
497 address += dwords_remaining * 8;
498 dwords_remaining = 0;
499 }
500 }
501
502 while (dwords_remaining > 0)
503 {
504 /* command */
505 cmd = FLASH_DWPG;
506 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
507
508 /* address */
509 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
510
511 /* data word 1 */
512 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, buffer + bytes_written);
513 bytes_written += 4;
514
515 /* data word 2 */
516 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, buffer + bytes_written);
517 bytes_written += 4;
518
519 /* start programming cycle */
520 cmd = FLASH_DWPG | FLASH_WMS;
521 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
522
523 while (((retval = str7x_status(bank)) & str7x_info->busy_bits))
524 {
525 alive_sleep(1);
526 }
527
528 retval = str7x_result(bank);
529
530 if (retval & FLASH_PGER)
531 return ERROR_FLASH_OPERATION_FAILED;
532 else if (retval & FLASH_WPF)
533 return ERROR_FLASH_OPERATION_FAILED;
534
535 dwords_remaining--;
536 address += 8;
537 }
538
539 if (bytes_remaining)
540 {
541 uint8_t last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
542 int i = 0;
543
544 while (bytes_remaining > 0)
545 {
546 last_dword[i++] = *(buffer + bytes_written);
547 bytes_remaining--;
548 bytes_written++;
549 }
550
551 /* command */
552 cmd = FLASH_DWPG;
553 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
554
555 /* address */
556 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
557
558 /* data word 1 */
559 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, last_dword);
560 bytes_written += 4;
561
562 /* data word 2 */
563 target_write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, last_dword + 4);
564 bytes_written += 4;
565
566 /* start programming cycle */
567 cmd = FLASH_DWPG | FLASH_WMS;
568 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
569
570 while (((retval = str7x_status(bank)) & str7x_info->busy_bits))
571 {
572 alive_sleep(1);
573 }
574
575 retval = str7x_result(bank);
576
577 if (retval & FLASH_PGER)
578 return ERROR_FLASH_OPERATION_FAILED;
579 else if (retval & FLASH_WPF)
580 return ERROR_FLASH_OPERATION_FAILED;
581 }
582
583 return ERROR_OK;
584 }
585
586 static int str7x_probe(struct flash_bank_s *bank)
587 {
588 return ERROR_OK;
589 }
590
591 #if 0
592 COMMAND_HANDLER(str7x_handle_part_id_command)
593 {
594 return ERROR_OK;
595 }
596 #endif
597
598 static int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
599 {
600 snprintf(buf, buf_size, "str7x flash driver info");
601 return ERROR_OK;
602 }
603
604 COMMAND_HANDLER(str7x_handle_disable_jtag_command)
605 {
606 target_t *target = NULL;
607 str7x_flash_bank_t *str7x_info = NULL;
608
609 uint32_t flash_cmd;
610 uint16_t ProtectionLevel = 0;
611 uint16_t ProtectionRegs;
612
613 if (argc < 1)
614 {
615 command_print(cmd_ctx, "str7x disable_jtag <bank>");
616 return ERROR_OK;
617 }
618
619 flash_bank_t *bank;
620 int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
621 if (ERROR_OK != retval)
622 return retval;
623
624 str7x_info = bank->driver_priv;
625
626 target = bank->target;
627
628 if (target->state != TARGET_HALTED)
629 {
630 LOG_ERROR("Target not halted");
631 return ERROR_TARGET_NOT_HALTED;
632 }
633
634 /* first we get protection status */
635 uint32_t reg;
636 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &reg);
637
638 if (!(reg & str7x_info->disable_bit))
639 {
640 ProtectionLevel = 1;
641 }
642
643 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &reg);
644 ProtectionRegs = ~(reg >> 16);
645
646 while (((ProtectionRegs) != 0) && (ProtectionLevel < 16))
647 {
648 ProtectionRegs >>= 1;
649 ProtectionLevel++;
650 }
651
652 if (ProtectionLevel == 0)
653 {
654 flash_cmd = FLASH_SPR;
655 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
656 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
657 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
658 flash_cmd = FLASH_SPR | FLASH_WMS;
659 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
660 }
661 else
662 {
663 flash_cmd = FLASH_SPR;
664 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
665 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
666 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), ~(1 << (15 + ProtectionLevel)));
667 flash_cmd = FLASH_SPR | FLASH_WMS;
668 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
669 }
670
671 return ERROR_OK;
672 }
673
674 static int str7x_register_commands(struct command_context_s *cmd_ctx)
675 {
676 command_t *str7x_cmd = register_command(cmd_ctx, NULL, "str7x",
677 NULL, COMMAND_ANY, "str7x flash specific commands");
678
679 register_command(cmd_ctx, str7x_cmd, "disable_jtag",
680 str7x_handle_disable_jtag_command, COMMAND_EXEC,
681 "disable jtag access");
682
683 return ERROR_OK;
684 }
685
686 struct flash_driver str7x_flash = {
687 .name = "str7x",
688 .register_commands = &str7x_register_commands,
689 .flash_bank_command = &str7x_flash_bank_command,
690 .erase = &str7x_erase,
691 .protect = &str7x_protect,
692 .write = &str7x_write,
693 .probe = &str7x_probe,
694 .auto_probe = &str7x_probe,
695 .erase_check = &default_flash_blank_check,
696 .protect_check = &str7x_protect_check,
697 .info = &str7x_info,
698 };

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)