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

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)