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

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)