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

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)