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

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)