5c17a6c5e4e1a4dfb5057d1b519cd7b6aacb75c5
[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 retval = ERROR_FLASH_OPERATION_FAILED;
439 break;
440 }
441
442 if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
443 {
444 retval = ERROR_FLASH_OPERATION_FAILED;
445 break;
446 }
447
448 buffer += thisrun_count * 8;
449 address += thisrun_count * 8;
450 count -= thisrun_count;
451 }
452
453 target_free_working_area(target, source);
454 target_free_working_area(target, str7x_info->write_algorithm);
455
456 destroy_reg_param(&reg_params[0]);
457 destroy_reg_param(&reg_params[1]);
458 destroy_reg_param(&reg_params[2]);
459 destroy_reg_param(&reg_params[3]);
460 destroy_reg_param(&reg_params[4]);
461 destroy_reg_param(&reg_params[5]);
462
463 return retval;
464 }
465
466 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
467 {
468 target_t *target = bank->target;
469 str7x_flash_bank_t *str7x_info = bank->driver_priv;
470 u32 dwords_remaining = (count / 8);
471 u32 bytes_remaining = (count & 0x00000007);
472 u32 address = bank->base + offset;
473 u32 bytes_written = 0;
474 u32 cmd;
475 u32 retval;
476 u32 check_address = offset;
477 int i;
478
479 if (bank->target->state != TARGET_HALTED)
480 {
481 return ERROR_TARGET_NOT_HALTED;
482 }
483
484 if (offset & 0x7)
485 {
486 LOG_WARNING("offset 0x%x breaks required 8-byte alignment", offset);
487 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
488 }
489
490 for (i = 0; i < bank->num_sectors; i++)
491 {
492 u32 sec_start = bank->sectors[i].offset;
493 u32 sec_end = sec_start + bank->sectors[i].size;
494
495 /* check if destination falls within the current sector */
496 if ((check_address >= sec_start) && (check_address < sec_end))
497 {
498 /* check if destination ends in the current sector */
499 if (offset + count < sec_end)
500 check_address = offset + count;
501 else
502 check_address = sec_end;
503 }
504 }
505
506 if (check_address != offset + count)
507 return ERROR_FLASH_DST_OUT_OF_BANK;
508
509 /* clear FLASH_ER register */
510 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
511
512 /* multiple dwords (8-byte) to be programmed? */
513 if (dwords_remaining > 0)
514 {
515 /* try using a block write */
516 if ((retval = str7x_write_block(bank, buffer, offset, dwords_remaining)) != ERROR_OK)
517 {
518 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
519 {
520 /* if block write failed (no sufficient working area),
521 * we use normal (slow) single dword accesses */
522 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
523 }
524 else if (retval == ERROR_FLASH_OPERATION_FAILED)
525 {
526 /* if an error occured, we examine the reason, and quit */
527 retval = str7x_result(bank);
528
529 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
530 return ERROR_FLASH_OPERATION_FAILED;
531 }
532 }
533 else
534 {
535 buffer += dwords_remaining * 8;
536 address += dwords_remaining * 8;
537 dwords_remaining = 0;
538 }
539 }
540
541 while (dwords_remaining > 0)
542 {
543 /* command */
544 cmd = FLASH_DWPG;
545 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
546
547 /* address */
548 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
549
550 /* data word 1 */
551 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, buffer + bytes_written);
552 bytes_written += 4;
553
554 /* data word 2 */
555 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, buffer + bytes_written);
556 bytes_written += 4;
557
558 /* start programming cycle */
559 cmd = FLASH_DWPG | FLASH_WMS;
560 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
561
562 while (((retval = str7x_status(bank)) & str7x_info->busy_bits))
563 {
564 usleep(1000);
565 }
566
567 retval = str7x_result(bank);
568
569 if (retval & FLASH_PGER)
570 return ERROR_FLASH_OPERATION_FAILED;
571 else if (retval & FLASH_WPF)
572 return ERROR_FLASH_OPERATION_FAILED;
573
574 dwords_remaining--;
575 address += 8;
576 }
577
578 if (bytes_remaining)
579 {
580 u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
581 int i = 0;
582
583 while(bytes_remaining > 0)
584 {
585 last_dword[i++] = *(buffer + bytes_written);
586 bytes_remaining--;
587 bytes_written++;
588 }
589
590 /* command */
591 cmd = FLASH_DWPG;
592 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
593
594 /* address */
595 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
596
597 /* data word 1 */
598 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, last_dword);
599 bytes_written += 4;
600
601 /* data word 2 */
602 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, last_dword + 4);
603 bytes_written += 4;
604
605 /* start programming cycle */
606 cmd = FLASH_DWPG | FLASH_WMS;
607 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
608
609 while (((retval = str7x_status(bank)) & str7x_info->busy_bits))
610 {
611 usleep(1000);
612 }
613
614 retval = str7x_result(bank);
615
616 if (retval & FLASH_PGER)
617 return ERROR_FLASH_OPERATION_FAILED;
618 else if (retval & FLASH_WPF)
619 return ERROR_FLASH_OPERATION_FAILED;
620 }
621
622 return ERROR_OK;
623 }
624
625 int str7x_probe(struct flash_bank_s *bank)
626 {
627 return ERROR_OK;
628 }
629
630 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
631 {
632 return ERROR_OK;
633 }
634
635 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
636 {
637 snprintf(buf, buf_size, "str7x flash driver info" );
638 return ERROR_OK;
639 }
640
641 int str7x_handle_disable_jtag_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
642 {
643 flash_bank_t *bank;
644 target_t *target = NULL;
645 str7x_flash_bank_t *str7x_info = NULL;
646
647 u32 flash_cmd;
648 u32 retval;
649 u16 ProtectionLevel = 0;
650 u16 ProtectionRegs;
651
652 if (argc < 1)
653 {
654 command_print(cmd_ctx, "str7x disable_jtag <bank>");
655 return ERROR_OK;
656 }
657
658 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
659 if (!bank)
660 {
661 command_print(cmd_ctx, "str7x disable_jtag <bank> ok");
662 return ERROR_OK;
663 }
664
665 str7x_info = bank->driver_priv;
666
667 target = bank->target;
668
669 if (target->state != TARGET_HALTED)
670 {
671 return ERROR_TARGET_NOT_HALTED;
672 }
673
674 /* first we get protection status */
675 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR0), &retval);
676
677 if (!(retval & str7x_info->disable_bit))
678 {
679 ProtectionLevel = 1;
680 }
681
682 target_read_u32(target, str7x_get_flash_adr(bank, FLASH_NVAPR1), &retval);
683 ProtectionRegs = ~(retval >> 16);
684
685 while (((ProtectionRegs) != 0) && (ProtectionLevel < 16))
686 {
687 ProtectionRegs >>= 1;
688 ProtectionLevel++;
689 }
690
691 if (ProtectionLevel == 0)
692 {
693 flash_cmd = FLASH_SPR;
694 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
695 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFB8);
696 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), 0xFFFFFFFD);
697 flash_cmd = FLASH_SPR | FLASH_WMS;
698 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
699 }
700 else
701 {
702 flash_cmd = FLASH_SPR;
703 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
704 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), 0x4010DFBC);
705 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_DR0), ~(1<<(15+ProtectionLevel)));
706 flash_cmd = FLASH_SPR | FLASH_WMS;
707 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), flash_cmd);
708 }
709
710 return ERROR_OK;
711 }
712

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)