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

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)