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

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)