- str9x flash support (Thanks to Spencer Oliver)
[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;
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 return ERROR_FLASH_OPERATION_FAILED;
541 }
542
543 if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
544 {
545 return ERROR_FLASH_OPERATION_FAILED;
546 }
547
548 buffer += thisrun_count * 8;
549 address += thisrun_count * 8;
550 count -= thisrun_count;
551 }
552
553 target_free_working_area(target, source);
554
555 destroy_reg_param(&reg_params[0]);
556 destroy_reg_param(&reg_params[1]);
557 destroy_reg_param(&reg_params[2]);
558 destroy_reg_param(&reg_params[3]);
559 destroy_reg_param(&reg_params[4]);
560
561 return ERROR_OK;
562 }
563
564 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
565 {
566 str7x_flash_bank_t *str7x_info = bank->driver_priv;
567 target_t *target = str7x_info->target;
568 u32 dwords_remaining = (count / 8);
569 u32 bytes_remaining = (count & 0x00000007);
570 u32 address = bank->base + offset;
571 u32 bytes_written = 0;
572 u32 cmd;
573 u32 retval;
574 u32 check_address = offset;
575 int i;
576
577 if (str7x_info->target->state != TARGET_HALTED)
578 {
579 return ERROR_TARGET_NOT_HALTED;
580 }
581
582 if (offset & 0x7)
583 {
584 WARNING("offset 0x%x breaks required 8-byte alignment", offset);
585 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
586 }
587
588 for (i = 0; i < bank->num_sectors; i++)
589 {
590 u32 sec_start = bank->sectors[i].offset;
591 u32 sec_end = sec_start + bank->sectors[i].size;
592
593 /* check if destination falls within the current sector */
594 if ((check_address >= sec_start) && (check_address < sec_end))
595 {
596 /* check if destination ends in the current sector */
597 if (offset + count < sec_end)
598 check_address = offset + count;
599 else
600 check_address = sec_end;
601 }
602 }
603
604 if (check_address != offset + count)
605 return ERROR_FLASH_DST_OUT_OF_BANK;
606
607 /* clear FLASH_ER register */
608 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_ER), 0x0);
609
610 /* multiple dwords (8-byte) to be programmed? */
611 if (dwords_remaining > 0)
612 {
613 /* try using a block write */
614 if ((retval = str7x_write_block(bank, buffer, offset, dwords_remaining)) != ERROR_OK)
615 {
616 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
617 {
618 /* if block write failed (no sufficient working area),
619 * we use normal (slow) single dword accesses */
620 WARNING("couldn't use block writes, falling back to single memory accesses");
621 }
622 else if (retval == ERROR_FLASH_OPERATION_FAILED)
623 {
624 /* if an error occured, we examine the reason, and quit */
625 retval = str7x_result(bank);
626
627 ERROR("flash writing failed with error code: 0x%x", retval);
628 return ERROR_FLASH_OPERATION_FAILED;
629 }
630 }
631 else
632 {
633 buffer += dwords_remaining * 8;
634 address += dwords_remaining * 8;
635 dwords_remaining = 0;
636 }
637 }
638
639 while (dwords_remaining > 0)
640 {
641 // command
642 cmd = FLASH_DWPG;
643 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
644
645 // address
646 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
647
648 // data word 1
649 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, buffer + bytes_written);
650 bytes_written += 4;
651
652 // data word 2
653 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, buffer + bytes_written);
654 bytes_written += 4;
655
656 /* start programming cycle */
657 cmd = FLASH_DWPG | FLASH_WMS;
658 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
659
660 while (((retval = str7x_status(bank)) & (FLASH_BSYA1 | FLASH_BSYA2)))
661 {
662 usleep(1000);
663 }
664
665 retval = str7x_result(bank);
666
667 if (retval & FLASH_PGER)
668 return ERROR_FLASH_OPERATION_FAILED;
669 else if (retval & FLASH_WPF)
670 return ERROR_FLASH_OPERATION_FAILED;
671
672 dwords_remaining--;
673 address += 8;
674 }
675
676 if (bytes_remaining)
677 {
678 u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
679 int i = 0;
680
681 while(bytes_remaining > 0)
682 {
683 last_dword[i++] = *(buffer + bytes_written);
684 bytes_remaining--;
685 bytes_written++;
686 }
687
688 // command
689 cmd = FLASH_DWPG;
690 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
691
692 // address
693 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_AR), address);
694
695 // data word 1
696 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR0), 4, 1, last_dword);
697 bytes_written += 4;
698
699 // data word 2
700 target->type->write_memory(target, str7x_get_flash_adr(bank, FLASH_DR1), 4, 1, last_dword + 4);
701 bytes_written += 4;
702
703 /* start programming cycle */
704 cmd = FLASH_DWPG | FLASH_WMS;
705 target_write_u32(target, str7x_get_flash_adr(bank, FLASH_CR0), cmd);
706
707 while (((retval = str7x_status(bank)) & (FLASH_BSYA1 | FLASH_BSYA2)))
708 {
709 usleep(1000);
710 }
711
712 retval = str7x_result(bank);
713
714 if (retval & FLASH_PGER)
715 return ERROR_FLASH_OPERATION_FAILED;
716 else if (retval & FLASH_WPF)
717 return ERROR_FLASH_OPERATION_FAILED;
718 }
719
720 return ERROR_OK;
721 }
722
723 int str7x_probe(struct flash_bank_s *bank)
724 {
725 return ERROR_OK;
726 }
727
728 int str7x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
729 {
730 return ERROR_OK;
731 }
732
733 int str7x_erase_check(struct flash_bank_s *bank)
734 {
735 return str7x_blank_check(bank, 0, bank->num_sectors - 1);
736 }
737
738 int str7x_info(struct flash_bank_s *bank, char *buf, int buf_size)
739 {
740 snprintf(buf, buf_size, "str7x flash driver info" );
741 return ERROR_OK;
742 }

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)