flash/nor: improved API of flash_driver.info & fixed buffer overruns
[openocd.git] / src / flash / nor / sim3x.c
1 /***************************************************************************
2 * Copyright (C) 2014 by Ladislav Bábel *
3 * ladababel@seznam.cz *
4 * *
5 * Copyright (C) 2015 by Andreas Bomholtz *
6 * andreas@seluxit.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "imp.h"
27 #include <helper/binarybuffer.h>
28 #include <helper/time_support.h>
29 #include <target/algorithm.h>
30 #include <target/cortex_m.h>
31
32 /* SI32_DEVICEID0 */
33 #define DEVICEID0_DEVICEID0 (0x400490C0)
34 #define DEVICEID0_DEVICEID1 (0x400490D0)
35 #define DEVICEID0_DEVICEID2 (0x400490E0)
36 #define DEVICEID0_DEVICEID3 (0x400490F0)
37
38 /* cortex_m CPUID */
39 #define CPUID_CHECK_VALUE (0x410FC230)
40 #define CPUID_CHECK_VALUE_MASK (0xFF0FFFF0)
41
42 /* Flash */
43 #define FLASH_BASE_ADDRESS (0x00000000)
44 #define LOCK_WORD_ADDRESS (0x0003FFFC)
45
46 #define LOCK_WORD_MCU_UNLOCKED (0xFFFFFFFF)
47 /* Can't by locked again without erase, because LOCK_WORD is in FLASH */
48 #define LOCK_WORD_MCU_UNLOCKED_BY_FIRMWARE (0x00000000)
49
50 /* SI32_FLASHCTRL_0 */
51 #define FLASHCTRL0_CONFIG_ALL (0x4002E000)
52 #define FLASHCTRL0_CONFIG_SET (0x4002E004)
53 #define FLASHCTRL0_CONFIG_CLR (0x4002E008)
54 #define FLASHCTRL0_CONFIG_ERASEEN_MASK (0x00040000)
55 #define FLASHCTRL0_CONFIG_BUSYF_MASK (0x00100000)
56
57 #define FLASHCTRL0_WRADDR (0x4002E0A0)
58 #define FLASHCTRL0_WRDATA (0x4002E0B0)
59
60 #define FLASHCTRL0_KEY (0x4002E0C0)
61 #define FLASHCTRL0_KEY_INITIAL_UNLOCK (0x000000A5)
62 #define FLASHCTRL0_KEY_SINGLE_UNLOCK (0x000000F1)
63 #define FLASHCTRL0_KEY_MULTIPLE_UNLOCK (0x000000F2)
64 #define FLASHCTRL0_KEY_MULTIPLE_LOCK (0x0000005A)
65
66 #define FLASH_BUSY_TIMEOUT (100)
67
68 /* SI32_RSTSRC_0 */
69 #define RSTSRC0_RESETEN_ALL (0x4002D060)
70 #define RSTSRC0_RESETEN_SET (0x4002D064)
71 #define RSTSRC0_RESETEN_CLR (0x4002D068)
72 #define RSTSRC0_RESETEN_VMONREN_MASK (0x00000004)
73 #define RSTSRC0_RESETEN_SWREN_MASK (0x00000040)
74
75 /* SI32_VMON_0 */
76 #define VMON0_CONTROL_ALL (0x4002F000)
77 #define VMON0_CONTROL_SET (0x4002F004)
78 #define VMON0_CONTROL_CLR (0x4002F008)
79 #define VMON0_CONTROL_VMONEN_MASK (0x80000000)
80
81 /* SI32_CLKCTRL_0 */
82 #define CLKCTRL0_APBCLKG0_ALL (0x4002D020)
83 #define CLKCTRL0_APBCLKG0_SET (0x4002D024)
84 #define CLKCTRL0_APBCLKG0_CLR (0x4002D028)
85 #define CLKCTRL0_APBCLKG0_FLCTRLCEN_MASK (0x40000000)
86
87 /* SI32_WDTIMER_0 */
88 #define WDTIMER0_CONTROL_ALL (0x40030000)
89 #define WDTIMER0_CONTROL_SET (0x40030004)
90 #define WDTIMER0_CONTROL_CLR (0x40030008)
91 #define WDTIMER0_CONTROL_DBGMD_MASK (0x00000002)
92
93 #define WDTIMER0_STATUS_ALL (0x40030010)
94 #define WDTIMER0_STATUS_SET (0x40030014)
95 #define WDTIMER0_STATUS_CLR (0x40030018)
96 #define WDTIMER0_STATUS_KEYSTS_MASK (0x00000001)
97 #define WDTIMER0_STATUS_PRIVSTS_MASK (0x00000002)
98
99 #define WDTIMER0_THRESHOLD (0x40030020)
100
101 #define WDTIMER0_WDTKEY (0x40030030)
102 #define WDTIMER0_KEY_ATTN (0x000000A5)
103 #define WDTIMER0_KEY_WRITE (0x000000F1)
104 #define WDTIMER0_KEY_RESET (0x000000CC)
105 #define WDTIMER0_KEY_DISABLE (0x000000DD)
106 #define WDTIMER0_KEY_START (0x000000EE)
107 #define WDTIMER0_KEY_LOCK (0x000000FF)
108
109 /* DAP */
110 #define SIM3X_AP (0x0A)
111
112 #define SIM3X_AP_CTRL1 (0x00)
113 #define SIM3X_AP_CTRL2 (0x04)
114 #define SIM3X_AP_LOCK (0x08)
115 #define SIM3X_AP_CRC (0x0C)
116
117 #define SIM3X_AP_INIT_STAT (0x10)
118 #define SIM3X_AP_DAP_IN (0x14)
119 #define SIM3X_AP_DAP_OUT (0x18)
120
121 #define SIM3X_AP_ID (0xFC)
122
123 /* DAP register values */
124 #define SIM3X_AP_CTRL1_MASS_ERASE_REQ (0x00000001)
125 #define SIM3X_AP_CTRL1_RESET_REQ (0x00000008)
126 /* this bit is set if MCU is locked */
127 #define SIM3X_AP_INIT_STAT_LOCK (0x00000004)
128 /* expected value inside SIM3X_AP_ID */
129 #define SIM3X_AP_ID_VALUE (0x2430002)
130
131 #define SIM3X_FLASH_PAGE_SIZE 1024
132
133 struct sim3x_info {
134 uint16_t flash_size_kb;
135 uint16_t part_number;
136 char part_family;
137 uint8_t device_revision;
138 char device_package[4];
139 bool probed;
140 bool need_init;
141 bool flash_locked;
142 };
143
144 /* flash bank sim3x 0 0 0 0 <target#> */
145 FLASH_BANK_COMMAND_HANDLER(sim3x_flash_bank_command)
146 {
147 struct sim3x_info *sim3x_info;
148
149 if (CMD_ARGC < 6)
150 return ERROR_COMMAND_SYNTAX_ERROR;
151
152 /* Init sim3x_info struct */
153 sim3x_info = malloc(sizeof(struct sim3x_info));
154 sim3x_info->probed = false;
155 sim3x_info->need_init = true;
156 sim3x_info->device_revision = 0;
157 memset(sim3x_info->device_package, 0, 4);
158 bank->driver_priv = sim3x_info;
159
160 return ERROR_OK;
161 }
162
163 static int sim3x_init(struct flash_bank *bank)
164 {
165 int ret;
166 struct target *target;
167 struct sim3x_info *sim3x_info;
168
169 target = bank->target;
170
171 /* Disable watchdog timer */
172 ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_ATTN);
173 if (ret != ERROR_OK)
174 return ret;
175
176 ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_DISABLE);
177 if (ret != ERROR_OK)
178 return ret;
179
180 /* Enable one write command */
181 ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_ATTN);
182 if (ret != ERROR_OK)
183 return ret;
184
185 ret = target_write_u32(target, WDTIMER0_WDTKEY, WDTIMER0_KEY_WRITE);
186 if (ret != ERROR_OK)
187 return ret;
188
189 /* Watchdog Timer Debug Mode */
190 ret = target_write_u32(target, WDTIMER0_CONTROL_SET,
191 WDTIMER0_CONTROL_DBGMD_MASK);
192 if (ret != ERROR_OK)
193 return ret;
194
195 /* Enable VDD Supply Monitor */
196 ret = target_write_u32(target, VMON0_CONTROL_SET,
197 VMON0_CONTROL_VMONEN_MASK);
198 if (ret != ERROR_OK)
199 return ret;
200
201 /* Set VDD Supply Monitor as a reset source */
202 ret = target_write_u32(target, RSTSRC0_RESETEN_SET,
203 RSTSRC0_RESETEN_VMONREN_MASK);
204 if (ret != ERROR_OK)
205 return ret;
206
207 /* Flash Controller Clock Enable */
208 ret = target_write_u32(target, CLKCTRL0_APBCLKG0_SET,
209 CLKCTRL0_APBCLKG0_FLCTRLCEN_MASK);
210 if (ret != ERROR_OK)
211 return ret;
212
213 /* Disable Flash Erase Mode */
214 ret = target_write_u32(target, FLASHCTRL0_CONFIG_CLR,
215 FLASHCTRL0_CONFIG_ERASEEN_MASK);
216 if (ret != ERROR_OK)
217 return ret;
218
219 sim3x_info = bank->driver_priv;
220 sim3x_info->need_init = 0;
221 return ERROR_OK;
222 }
223
224 static int sim3x_erase_page(struct flash_bank *bank, uint32_t addr)
225 {
226 int ret, i;
227 uint32_t temp;
228 struct target *target;
229
230 target = bank->target;
231
232 for (i = 0; i < FLASH_BUSY_TIMEOUT; i++) {
233 ret = target_read_u32(target, FLASHCTRL0_CONFIG_ALL, &temp);
234 if (ret != ERROR_OK)
235 return ret;
236
237 /* If is not busy */
238 if ((temp & FLASHCTRL0_CONFIG_BUSYF_MASK) == 0) {
239 /* If erase is not enabled */
240 if ((temp & FLASHCTRL0_CONFIG_ERASEEN_MASK) == 0) {
241 /* Enter Flash Erase Mode */
242 ret = target_write_u32(target, FLASHCTRL0_CONFIG_SET,
243 FLASHCTRL0_CONFIG_ERASEEN_MASK);
244 if (ret != ERROR_OK)
245 return ret;
246 }
247
248 /* Write the address of the Flash page to WRADDR */
249 ret = target_write_u32(target, FLASHCTRL0_WRADDR, addr);
250 if (ret != ERROR_OK)
251 return ret;
252
253 /* Write the initial unlock value to KEY */
254 ret = target_write_u32(target, FLASHCTRL0_KEY,
255 FLASHCTRL0_KEY_INITIAL_UNLOCK);
256 if (ret != ERROR_OK)
257 return ret;
258
259 /* Write the single unlock value to KEY */
260 ret = target_write_u32(target, FLASHCTRL0_KEY,
261 FLASHCTRL0_KEY_SINGLE_UNLOCK);
262 if (ret != ERROR_OK)
263 return ret;
264
265 /* Write any value to WRDATA to initiate the page erase */
266 ret = target_write_u32(target, FLASHCTRL0_WRDATA, 0);
267 if (ret != ERROR_OK)
268 return ret;
269
270 return ERROR_OK;
271 }
272
273 alive_sleep(1);
274 }
275
276 LOG_ERROR("timed out waiting for FLASHCTRL0_CONFIG_BUSYF");
277 return ERROR_FAIL;
278 }
279
280 static int sim3x_flash_erase(struct flash_bank *bank, unsigned int first,
281 unsigned int last)
282 {
283 int ret;
284 uint32_t temp;
285 struct sim3x_info *sim3x_info;
286 struct target *target;
287
288 /* Check if target is halted */
289 if (bank->target->state != TARGET_HALTED) {
290 LOG_ERROR("Target not halted");
291 return ERROR_TARGET_NOT_HALTED;
292 }
293
294 sim3x_info = bank->driver_priv;
295
296 /* Init MCU after reset */
297 if (sim3x_info->need_init) {
298 ret = sim3x_init(bank);
299 if (ret != ERROR_OK) {
300 LOG_ERROR("Failed to init MCU");
301 return ret;
302 }
303 }
304
305 /* erase pages */
306 for (unsigned int i = first; i <= last; i++) {
307 ret = sim3x_erase_page(bank, bank->sectors[i].offset);
308 if (ret != ERROR_OK)
309 return ret;
310 }
311
312 target = bank->target;
313
314 /* Wait until busy */
315 for (unsigned int i = 0; i < FLASH_BUSY_TIMEOUT; i++) {
316 ret = target_read_u32(target, FLASHCTRL0_CONFIG_ALL, &temp);
317 if (ret != ERROR_OK)
318 return ret;
319
320 if ((temp & FLASHCTRL0_CONFIG_BUSYF_MASK) == 0) { /* If is not busy */
321 if ((temp & FLASHCTRL0_CONFIG_ERASEEN_MASK) != 0) { /* If erase is enabled */
322 /* Disable Flash Erase Mode */
323 ret = target_write_u32(target, FLASHCTRL0_CONFIG_CLR,
324 FLASHCTRL0_CONFIG_ERASEEN_MASK);
325 if (ret != ERROR_OK)
326 return ret;
327 }
328
329 return ERROR_OK;
330 }
331
332 alive_sleep(1);
333 }
334
335 LOG_ERROR("timed out waiting for FLASHCTRL0_CONFIG_BUSYF");
336 return ERROR_FAIL;
337 }
338
339 static int sim3x_write_block(struct flash_bank *bank, const uint8_t *buf,
340 uint32_t offset, uint32_t count) /* count is count of half words (2 bytes)! */
341 {
342 struct target *target = bank->target;
343 uint32_t buffer_size = 16384;
344 struct working_area *write_algorithm;
345 struct working_area *source;
346 uint32_t address = bank->base + offset;
347 struct reg_param reg_params[5];
348 struct armv7m_algorithm armv7m_info;
349 int ret = ERROR_OK;
350
351 /* see contrib/loaders/flash/sim3x.s for src */
352
353 static const uint8_t sim3x_flash_write_code[] = {
354 /* Write the initial unlock value to KEY (0xA5) */
355 0xA5, 0x26, /* movs r6, #INITIAL_UNLOCK */
356 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */
357
358 /* Write the multiple unlock value to KEY (0xF2) */
359 0xF2, 0x26, /* movs r6, #MULTIPLE_UNLOCK */
360 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */
361
362 /* wait_fifo: */
363 0x16, 0x68, /* ldr r6, [r2, #0] */
364 0x00, 0x2E, /* cmp r6, #0 */
365 0x16, 0xD0, /* beq exit */
366 0x55, 0x68, /* ldr r5, [r2, #4] */
367 0xB5, 0x42, /* cmp r5, r6 */
368 0xF9, 0xD0, /* beq wait_fifo */
369
370 /* wait for BUSYF flag */
371 /* wait_busy1: */
372 0x06, 0x68, /* ldr r6, [r0, #FLASHCTRL_CONFIG] */
373 0x16, 0xF4, 0x80, 0x1F, /* tst r6, #BUSYF */
374 0xFB, 0xD1, /* bne wait_busy1 */
375
376 /* Write the destination address to WRADDR */
377 0xC0, 0xF8, 0xA0, 0x40, /* str r4, [r0, #FLASHCTRL_WRADDR] */
378
379 /* Write the data half-word to WRDATA in right-justified format */
380 0x2E, 0x88, /* ldrh r6, [r5] */
381 0xC0, 0xF8, 0xB0, 0x60, /* str r6, [r0, #FLASHCTRL_WRDATA] */
382
383 0x02, 0x35, /* adds r5, #2 */
384 0x02, 0x34, /* adds r4, #2 */
385
386 /* wrap rp at end of buffer */
387 0x9D, 0x42, /* cmp r5, r3 */
388 0x01, 0xD3, /* bcc no_wrap */
389 0x15, 0x46, /* mov r5, r2 */
390 0x08, 0x35, /* adds r5, #8 */
391
392 /* no_wrap: */
393 0x55, 0x60, /* str r5, [r2, #4] */
394 0x49, 0x1E, /* subs r1, r1, #1 */
395 0x00, 0x29, /* cmp r1, #0 */
396 0x00, 0xD0, /* beq exit */
397 0xE5, 0xE7, /* b wait_fifo */
398
399 /* exit: */
400 0x5A, 0x26, /* movs r6, #MULTIPLE_LOCK */
401 0xC0, 0xF8, 0xC0, 0x60, /* str r6, [r0, #FLASHCTRL_KEY] */
402
403 /* wait for BUSYF flag */
404 /* wait_busy2: */
405 0x06, 0x68, /* ldr r6, [r0, #FLASHCTRL_CONFIG] */
406 0x16, 0xF4, 0x80, 0x1F, /* tst r6, #BUSYF */
407 0xFB, 0xD1, /* bne wait_busy2 */
408
409 0x00, 0xBE /* bkpt #0 */
410 };
411
412 /* flash write code */
413 if (target_alloc_working_area(target, sizeof(sim3x_flash_write_code),
414 &write_algorithm) != ERROR_OK) {
415 LOG_WARNING("no working area available, can't do block memory writes");
416 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
417 }
418
419 ret = target_write_buffer(target, write_algorithm->address,
420 sizeof(sim3x_flash_write_code), sim3x_flash_write_code);
421 if (ret != ERROR_OK)
422 return ret;
423
424 /* memory buffer */
425 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
426 buffer_size /= 2;
427 buffer_size &= ~1UL; /* Make sure it's 2 byte aligned */
428 if (buffer_size <= 256) {
429 /* we already allocated the writing code, but failed to get a
430 * buffer, free the algorithm
431 */
432 target_free_working_area(target, write_algorithm);
433
434 LOG_WARNING("no large enough working area available, can't do block memory writes");
435 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
436 }
437 }
438
439 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* flash base */
440 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count */
441 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
442 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
443 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
444
445 buf_set_u32(reg_params[0].value, 0, 32, FLASHCTRL0_CONFIG_ALL);
446 buf_set_u32(reg_params[1].value, 0, 32, count);
447 buf_set_u32(reg_params[2].value, 0, 32, source->address);
448 buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
449 buf_set_u32(reg_params[4].value, 0, 32, address);
450
451 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
452 armv7m_info.core_mode = ARM_MODE_THREAD;
453
454 ret = target_run_flash_async_algorithm(target, buf, count, 2, 0, NULL, 5,
455 reg_params, source->address, source->size, write_algorithm->address,
456 0, &armv7m_info);
457
458 if (ret == ERROR_FLASH_OPERATION_FAILED) {
459 LOG_ERROR("flash write failed at address 0x%"PRIx32,
460 buf_get_u32(reg_params[4].value, 0, 32));
461 }
462
463 target_free_working_area(target, source);
464 target_free_working_area(target, write_algorithm);
465
466 destroy_reg_param(&reg_params[0]);
467 destroy_reg_param(&reg_params[1]);
468 destroy_reg_param(&reg_params[2]);
469 destroy_reg_param(&reg_params[3]);
470 destroy_reg_param(&reg_params[4]);
471
472 return ret;
473 }
474
475 static int sim3x_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
476 {
477 int ret;
478 struct target *target;
479 struct sim3x_info *sim3x_info;
480 uint8_t *new_buffer = NULL;
481
482 target = bank->target;
483
484 /* Check if target is halted */
485 if (target->state != TARGET_HALTED) {
486 LOG_ERROR("Target not halted");
487 return ERROR_TARGET_NOT_HALTED;
488 }
489
490 sim3x_info = bank->driver_priv;
491
492 if (sim3x_info->flash_locked) {
493 LOG_ERROR("Flash is locked");
494 return ERROR_FAIL;
495 }
496
497 /* Init MCU after reset */
498 if (sim3x_info->need_init) {
499 ret = sim3x_init(bank);
500 if (ret != ERROR_OK)
501 return ret;
502 }
503
504 if (offset & 0x1) {
505 LOG_ERROR("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
506 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
507 }
508
509 if (count & 0x1) {
510 uint32_t old_count = count;
511 count++;
512 new_buffer = malloc(count);
513
514 if (new_buffer == NULL) {
515 LOG_ERROR("odd number of bytes to write and no memory "
516 "for padding buffer");
517 return ERROR_FAIL;
518 }
519 LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32
520 " and padding with 0xff", old_count, count);
521
522 new_buffer[count - 1] = 0xff;
523 buffer = memcpy(new_buffer, buffer, old_count);
524 }
525
526 ret = sim3x_write_block(bank, buffer, offset, count / 2);
527 free(new_buffer);
528 return ret;
529 }
530
531 static int sim3x_flash_lock_check(struct flash_bank *bank)
532 {
533 int ret;
534 uint32_t lock_word;
535 struct sim3x_info *sim3x_info;
536
537 ret = target_read_u32(bank->target, LOCK_WORD_ADDRESS, &lock_word);
538 if (ret != ERROR_OK) {
539 LOG_ERROR("Can not read Lock Word");
540 return ret;
541 }
542
543 sim3x_info = bank->driver_priv;
544 sim3x_info->flash_locked = (lock_word != 0xFFFFFFFF);
545
546 return ERROR_OK;
547 }
548
549 static int sim3x_flash_protect_check(struct flash_bank *bank)
550 {
551 int ret;
552 struct sim3x_info *sim3x_info;
553
554 /* Check if target is halted */
555 if (bank->target->state != TARGET_HALTED) {
556 LOG_ERROR("Target not halted");
557 return ERROR_TARGET_NOT_HALTED;
558 }
559
560 ret = sim3x_flash_lock_check(bank);
561 if (ret != ERROR_OK)
562 return ret;
563
564 sim3x_info = bank->driver_priv;
565
566 for (unsigned int i = 0; i < bank->num_sectors; i++)
567 bank->sectors[i].is_protected = sim3x_info->flash_locked;
568
569 return ERROR_OK;
570 }
571
572 static int sim3x_flash_protect(struct flash_bank *bank, int set,
573 unsigned int first, unsigned int last)
574 {
575 int ret;
576 uint8_t lock_word[4];
577 struct sim3x_info *sim3x_info;
578 struct target *target;
579
580 target = bank->target;
581
582 /* Check if target is halted */
583 if (target->state != TARGET_HALTED) {
584 LOG_ERROR("Target not halted");
585 return ERROR_TARGET_NOT_HALTED;
586 }
587
588 if (first != 0 || last != bank->num_sectors - 1) {
589 LOG_ERROR("Flash does not support finer granularity");
590 return ERROR_FAIL;
591 }
592
593 sim3x_info = bank->driver_priv;
594
595 if (set) {
596 if (sim3x_info->flash_locked) {
597 LOG_INFO("Flash is already locked");
598 return ERROR_OK;
599 }
600
601 /* Lock Flash */
602 target_buffer_set_u32(target, lock_word, 0xFFFFFFFE);
603 ret = sim3x_flash_write(bank, lock_word, LOCK_WORD_ADDRESS, 4);
604 if (ret != ERROR_OK)
605 return ret;
606
607 } else {
608 /* Flash is unlocked by an erase operation */
609 ret = sim3x_flash_erase(bank, 0, 0);
610 if (ret != ERROR_OK)
611 return ret;
612 }
613
614 ret = sim3x_flash_protect_check(bank);
615 if (ret != ERROR_OK)
616 return ret;
617
618 if (set) {
619 if (sim3x_info->flash_locked) {
620 LOG_INFO("Flash locked");
621 return ERROR_OK;
622 } else {
623 LOG_ERROR("Flash lock error");
624 return ERROR_FAIL;
625 }
626 } else {
627 if (sim3x_info->flash_locked) {
628 LOG_ERROR("Flash unlock error");
629 return ERROR_FAIL;
630 } else {
631 LOG_INFO("Flash unlocked");
632 return ERROR_OK;
633 }
634 }
635 }
636
637 static int sim3x_read_deviceid(struct flash_bank *bank)
638 {
639 int ret;
640 struct sim3x_info *sim3x_info;
641
642 uint32_t device_id;
643 int part_number;
644 char part_num_string[4];
645
646 sim3x_info = bank->driver_priv;
647
648 /* MCU check */
649 ret = target_read_u32(bank->target, DEVICEID0_DEVICEID2, &device_id);
650 if (ret != ERROR_OK)
651 return ret;
652
653 /* Device ID should be 'M3' */
654 if (device_id != 0x00004D33)
655 return ERROR_FAIL;
656
657 /* Family and Part number */
658 ret = target_read_u32(bank->target, DEVICEID0_DEVICEID1, &device_id);
659 if (ret != ERROR_OK)
660 return ret;
661
662 part_num_string[0] = device_id >> 16;
663 part_num_string[1] = device_id >> 8;
664 part_num_string[2] = device_id;
665 part_num_string[3] = 0;
666
667 part_number = atoi(part_num_string);
668
669 /* Part Number should be between 100 and 999 */
670 if (!isalpha(device_id >> 24) || part_number < 100 || part_number > 999)
671 return ERROR_FAIL;
672
673 sim3x_info->part_family = device_id >> 24;
674 sim3x_info->part_number = part_number;
675
676 /* Package and Revision */
677 ret = target_read_u32(bank->target, DEVICEID0_DEVICEID0, &device_id);
678 if (ret != ERROR_OK)
679 return ret;
680
681 sim3x_info->device_package[0] = device_id >> 24;
682 sim3x_info->device_package[1] = device_id >> 16;
683 sim3x_info->device_package[2] = device_id >> 8;
684 sim3x_info->device_package[3] = 0;
685
686 sim3x_info->device_revision = device_id;
687
688 return ERROR_OK;
689 }
690
691 static int sim3x_parse_part_info(struct sim3x_info *sim3x_info)
692 {
693 switch (sim3x_info->part_number) {
694 case 134:
695 case 136:
696 sim3x_info->flash_size_kb = 32;
697 break;
698 case 144:
699 case 146:
700 sim3x_info->flash_size_kb = 64;
701 break;
702 case 154:
703 case 156:
704 case 157:
705 sim3x_info->flash_size_kb = 128;
706 break;
707 case 164:
708 case 166:
709 case 167:
710 sim3x_info->flash_size_kb = 256;
711 break;
712 default:
713 LOG_ERROR("Unknown Part number %d", sim3x_info->part_number);
714 sim3x_info->part_number = 0;
715 return ERROR_FAIL;
716 }
717
718 switch (sim3x_info->part_family) {
719 case 'c':
720 case 'C':
721 LOG_INFO("SiM3C%d detected", sim3x_info->part_number);
722 break;
723 case 'u':
724 case 'U':
725 LOG_INFO("SiM3U%d detected", sim3x_info->part_number);
726 break;
727 case 'l':
728 case 'L':
729 LOG_INFO("SiM3L%d detected", sim3x_info->part_number);
730 break;
731 default:
732 LOG_ERROR("Unsupported MCU family %c", sim3x_info->part_family);
733 sim3x_info->part_family = 0;
734 return ERROR_FAIL;
735 }
736
737 return ERROR_OK;
738 }
739
740 static int sim3x_read_info(struct flash_bank *bank)
741 {
742 int ret;
743 struct sim3x_info *sim3x_info;
744 uint32_t cpuid;
745
746 sim3x_info = bank->driver_priv;
747
748 /* Core check */
749 ret = target_read_u32(bank->target, CPUID, &cpuid);
750 if (ret != ERROR_OK) {
751 LOG_ERROR("Failed to read CPU ID");
752 return ret;
753 }
754
755 if (((cpuid >> 4) & 0xfff) != 0xc23) {
756 LOG_ERROR("Target is not Cortex-M3");
757 return ERROR_FAIL;
758 }
759
760 /* Read info from chip */
761 ret = sim3x_read_deviceid(bank);
762 if (ret == ERROR_OK) {
763 ret = sim3x_parse_part_info(sim3x_info);
764 if (ret != ERROR_OK) {
765 LOG_ERROR("Failed to parse info from MCU");
766 return ERROR_FAIL;
767 }
768 } else {
769 LOG_WARNING("Failed to read info from MCU, using info from flash bank parameters");
770
771 /* Check if flash size is given in flash bank command */
772 if (!bank->size) {
773 LOG_ERROR("Flash size not set in the flash bank command");
774 return ERROR_FAIL;
775 }
776
777 /* Convert bank size to kb */
778 sim3x_info->flash_size_kb = bank->size / 1024;
779 }
780
781 LOG_INFO("Flash size = %dKB", sim3x_info->flash_size_kb);
782
783 return ERROR_OK;
784 }
785
786 static int sim3x_probe(struct flash_bank *bank)
787 {
788 int ret, i;
789 struct sim3x_info *sim3x_info;
790
791 sim3x_info = bank->driver_priv;
792 sim3x_info->probed = false;
793 sim3x_info->need_init = true;
794
795 /* Read info from chip */
796 ret = sim3x_read_info(bank);
797 if (ret != ERROR_OK)
798 return ret;
799
800 ret = sim3x_flash_lock_check(bank);
801 if (ret != ERROR_OK)
802 return ret;
803
804 free(bank->sectors);
805
806 bank->base = FLASH_BASE_ADDRESS;
807 bank->size = sim3x_info->flash_size_kb * SIM3X_FLASH_PAGE_SIZE;
808 bank->num_sectors = SIM3X_FLASH_PAGE_SIZE;
809 bank->sectors = malloc(sizeof(struct flash_sector) * sim3x_info->flash_size_kb);
810
811 for (i = 0; i < sim3x_info->flash_size_kb; i++) {
812 bank->sectors[i].offset = i * SIM3X_FLASH_PAGE_SIZE;
813 bank->sectors[i].size = SIM3X_FLASH_PAGE_SIZE;
814 bank->sectors[i].is_erased = -1;
815 bank->sectors[i].is_protected = sim3x_info->flash_locked;
816 }
817
818 sim3x_info->probed = true;
819
820 return ERROR_OK;
821 }
822
823 static int sim3x_auto_probe(struct flash_bank *bank)
824 {
825 struct sim3x_info *sim3x_info;
826
827 sim3x_info = bank->driver_priv;
828
829 if (sim3x_info->probed) {
830 sim3x_info->need_init = true;
831 return ERROR_OK;
832 } else {
833 return sim3x_probe(bank);
834 }
835 }
836
837 static int sim3x_flash_info(struct flash_bank *bank, struct command_invocation *cmd)
838 {
839 struct sim3x_info *sim3x_info;
840
841 sim3x_info = bank->driver_priv;
842
843 /* Read info about chip */
844 int ret = sim3x_read_info(bank);
845 if (ret != ERROR_OK)
846 return ret;
847
848 /* Part */
849 if (sim3x_info->part_family && sim3x_info->part_number) {
850 command_print_sameline(cmd, "SiM3%c%d", sim3x_info->part_family, sim3x_info->part_number);
851
852 /* Revision */
853 if (sim3x_info->device_revision && sim3x_info->device_revision <= 'Z' - 'A') {
854 command_print_sameline(cmd, "-%c", sim3x_info->device_revision + 'A');
855
856 /* Package */
857 command_print_sameline(cmd, "-G%s", sim3x_info->device_package);
858 }
859 }
860
861 /* Print flash size */
862 command_print_sameline(cmd, " flash_size = %dKB", sim3x_info->flash_size_kb);
863
864 return ERROR_OK;
865 }
866 /**
867 * reg 31:8 - no effect
868 * reg 7:4 - bank
869 * reg 3:2 - register
870 * reg 1:0 - no effect
871 */
872 static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
873 {
874 int retval;
875 LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value);
876
877 retval = dap_queue_ap_write(dap_ap(dap, SIM3X_AP), reg, value);
878 if (retval != ERROR_OK) {
879 LOG_DEBUG("DAP: failed to queue a write request");
880 return retval;
881 }
882
883 retval = dap_run(dap);
884 if (retval != ERROR_OK) {
885 LOG_DEBUG("DAP: dap_run failed");
886 return retval;
887 }
888
889 return ERROR_OK;
890 }
891
892 static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
893 {
894 int retval;
895
896 retval = dap_queue_ap_read(dap_ap(dap, SIM3X_AP), reg, result);
897 if (retval != ERROR_OK) {
898 LOG_DEBUG("DAP: failed to queue a read request");
899 return retval;
900 }
901
902 retval = dap_run(dap);
903 if (retval != ERROR_OK) {
904 LOG_DEBUG("DAP: dap_run failed");
905 return retval;
906 }
907
908 LOG_DEBUG("DAP_REG[0x%02x]: %08" PRIX32, reg, *result);
909 return ERROR_OK;
910 }
911
912 static int ap_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value, int timeout)
913 {
914 uint32_t val;
915 int retval;
916
917 do {
918 retval = ap_read_register(dap, reg, &val);
919 if (retval != ERROR_OK || (val & mask) == value)
920 return retval;
921
922 alive_sleep(1);
923 } while (timeout--);
924
925 LOG_DEBUG("DAP: polling timed out");
926 return ERROR_FAIL;
927 }
928
929 COMMAND_HANDLER(sim3x_mass_erase)
930 {
931 uint32_t val;
932 int ret;
933
934 struct target *target = get_current_target(CMD_CTX);
935 struct cortex_m_common *cortex_m = target_to_cm(target);
936 struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
937
938 if (dap == NULL) {
939 /* Used debug interface doesn't support direct DAP access */
940 LOG_ERROR("mass_erase can't be used by this debug interface");
941 return ERROR_FAIL;
942 }
943
944 ret = ap_read_register(dap, SIM3X_AP_ID, &val);
945 if (ret != ERROR_OK)
946 return ret;
947
948 if (val != SIM3X_AP_ID_VALUE) {
949 LOG_ERROR("Wrong SIM3X_AP_ID");
950 return ERROR_FAIL;
951 }
952
953 /* Mass erase sequence */
954 ret = ap_write_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_RESET_REQ);
955 if (ret != ERROR_OK)
956 return ret;
957
958 ret = ap_write_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_RESET_REQ | SIM3X_AP_CTRL1_MASS_ERASE_REQ);
959 if (ret != ERROR_OK)
960 return ret;
961
962 ret = ap_poll_register(dap, SIM3X_AP_CTRL1, SIM3X_AP_CTRL1_MASS_ERASE_REQ, 0x00000000, FLASH_BUSY_TIMEOUT);
963 if (ret != ERROR_OK)
964 return ret;
965
966 ret = ap_write_register(dap, SIM3X_AP_CTRL1, 0x00000000); /* clear SIM3X_AP_CTRL1_RESET_REQ */
967 if (ret != ERROR_OK)
968 return ret;
969
970 LOG_INFO("Mass erase success");
971 return ERROR_OK;
972 }
973
974 COMMAND_HANDLER(sim3x_lock)
975 {
976 uint32_t val;
977 int ret;
978
979 struct target *target = get_current_target(CMD_CTX);
980 struct cortex_m_common *cortex_m = target_to_cm(target);
981 struct adiv5_dap *dap = cortex_m->armv7m.arm.dap;
982
983 if (dap == NULL) {
984 /* Used debug interface doesn't support direct DAP access */
985 LOG_INFO("Target can't by unlocked by this debug interface");
986
987 /* Core check */
988 ret = target_read_u32(target, CPUID, &val);
989 if (ret != ERROR_OK)
990 return ret;
991
992 if ((val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) {
993 LOG_ERROR("Target is not ARM Cortex-M3 or is already locked");
994 return ERROR_FAIL;
995 }
996 } else {
997 /* check SIM3X_AP_ID */
998 ret = ap_read_register(dap, SIM3X_AP_ID, &val);
999 if (ret != ERROR_OK)
1000 return ret;
1001
1002 if (val != SIM3X_AP_ID_VALUE) {
1003 LOG_ERROR("Wrong SIM3X_AP_ID");
1004 return ERROR_FAIL;
1005 }
1006
1007 /* check if locked */
1008 ret = target_read_u32(target, CPUID, &val);
1009 /* if correct value is read, then it will continue */
1010 if (ret != ERROR_OK || (val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) {
1011 /* if correct value isn't read, then it will check SIM3X_AP_INIT_STAT register */
1012 ret = ap_read_register(dap, SIM3X_AP_INIT_STAT, &val);
1013 if (ret != ERROR_OK)
1014 return ret;
1015
1016 if (val & SIM3X_AP_INIT_STAT_LOCK) {
1017 LOG_INFO("Target is already locked");
1018 return ERROR_OK;
1019 } else {
1020 LOG_ERROR("Target doesn't seem to be locked but memory was not read correct");
1021 return ERROR_FAIL;
1022 }
1023 }
1024 }
1025
1026 ret = target_read_u32(target, LOCK_WORD_ADDRESS, &val);
1027 if (ret != ERROR_OK)
1028 return ret;
1029
1030 if (val == LOCK_WORD_MCU_UNLOCKED) {
1031 /* Lock Flash */
1032 uint8_t lock_word[4];
1033 target_buffer_set_u32(target, lock_word, 0xFFFFFFFE);
1034
1035 /* Get Flash Bank */
1036 struct flash_bank *bank;
1037 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
1038 if (retval != ERROR_OK)
1039 return retval;
1040
1041 ret = sim3x_flash_write(bank, lock_word, LOCK_WORD_ADDRESS, 4);
1042 if (ERROR_OK != ret)
1043 return ret;
1044
1045 LOG_INFO("Target is successfully locked");
1046 return ERROR_OK;
1047 } else if (val == LOCK_WORD_MCU_UNLOCKED_BY_FIRMWARE) {
1048 /* Can't by locked again without erase, because LOCK_WORD is in FLASH */
1049 LOG_ERROR("Target is unlocked by firmware and can't by locked again without the lock page erase or mass erase");
1050 return ERROR_FAIL;
1051 } else {
1052 LOG_ERROR("Unexpected lock word value");
1053
1054 /* SIM3X_AP_ID_VALUE is not checked */
1055 if (dap == NULL)
1056 LOG_INFO("Maybe this isn't a SiM3x MCU");
1057
1058 return ERROR_FAIL;
1059 }
1060 }
1061
1062 static const struct command_registration sim3x_exec_command_handlers[] = {
1063 {
1064 .name = "mass_erase",
1065 .mode = COMMAND_EXEC,
1066 .help = "Erase the complete flash",
1067 .usage = "",
1068 .handler = sim3x_mass_erase,
1069 },
1070 {
1071 .name = "lock",
1072 .mode = COMMAND_EXEC,
1073 .help = "Locks the flash. Unlock by mass erase",
1074 .usage = "",
1075 .handler = sim3x_lock,
1076 },
1077 COMMAND_REGISTRATION_DONE
1078 };
1079
1080 static const struct command_registration sim3x_command_handlers[] = {
1081 {
1082 .name = "sim3x",
1083 .mode = COMMAND_ANY,
1084 .help = "sim3x flash command group",
1085 .usage = "",
1086 .chain = sim3x_exec_command_handlers,
1087 },
1088 COMMAND_REGISTRATION_DONE
1089 };
1090
1091 const struct flash_driver sim3x_flash = {
1092 .name = "sim3x",
1093 .commands = sim3x_command_handlers,
1094 .flash_bank_command = sim3x_flash_bank_command,
1095 .erase = sim3x_flash_erase,
1096 .protect = sim3x_flash_protect,
1097 .write = sim3x_flash_write,
1098 .read = default_flash_read,
1099 .probe = sim3x_probe,
1100 .auto_probe = sim3x_auto_probe,
1101 .erase_check = default_flash_blank_check,
1102 .protect_check = sim3x_flash_protect_check,
1103 .info = sim3x_flash_info,
1104 .free_driver_priv = default_flash_free_driver_priv,
1105 };

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)