72541d5dc6ac719c2ef1c02de40cb9d5e291d84c
[openocd.git] / src / flash / nor / psoc4.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2011 by Andreas Fritiofson *
9 * andreas.fritiofson@gmail.com *
10 * *
11 * Copyright (C) 2014 by Tomas Vanek (PSoC 4 support derived from STM32) *
12 * vanekt@fbl.cz *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 ***************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "imp.h"
30 #include <helper/binarybuffer.h>
31 #include <jtag/jtag.h>
32 #include <target/algorithm.h>
33 #include <target/armv7m.h>
34
35 /* device documets:
36
37 PSoC(R) 4: PSoC 4200 Family Datasheet
38 Document Number: 001-87197 Rev. *B Revised August 29, 2013
39
40 PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM
41 Document No. 001-85634 Rev. *C March 25, 2014
42
43 PSoC(R) 4 Registers TRM Spec.
44 Document No. 001-85847 Rev. *A June 25, 2013
45
46 CY8C41xx, CY8C42xx Programming Specifications
47 Document No. 001-81799 Rev. *C March 4, 2014
48 */
49
50 /* register locations */
51 #define PSOC4_CPUSS_SYSREQ 0x40000004
52 #define PSOC4_CPUSS_SYSARG 0x40000008
53 #define PSOC4_TEST_MODE 0x40030014
54 #define PSOC4_SPCIF_GEOMETRY 0x400E0000
55
56 #define PSOC4_SFLASH_MACRO 0x0ffff000
57
58 /* constants */
59 #define PSOC4_SROM_KEY1 0xb6
60 #define PSOC4_SROM_KEY2 0xd3
61 #define PSOC4_SROM_SYSREQ_BIT (1<<31)
62 #define PSOC4_SROM_HMASTER_BIT (1<<30)
63 #define PSOC4_SROM_PRIVILEGED_BIT (1<<28)
64 #define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000
65 #define PSOC4_SROM_STATUS_FAILED 0xf0000000
66
67 #define PSOC4_CMD_GET_SILICON_ID 0
68 #define PSOC4_CMD_LOAD_LATCH 4
69 #define PSOC4_CMD_WRITE_ROW 5
70 #define PSOC4_CMD_PROGRAM_ROW 6
71 #define PSOC4_CMD_ERASE_ALL 0xa
72 #define PSOC4_CMD_CHECKSUM 0xb
73 #define PSOC4_CMD_WRITE_PROTECTION 0xd
74
75 #define PSOC4_CHIP_PROT_VIRGIN 0x0
76 #define PSOC4_CHIP_PROT_OPEN 0x1
77 #define PSOC4_CHIP_PROT_PROTECTED 0x2
78 #define PSOC4_CHIP_PROT_KILL 0x4
79
80
81 struct psoc4_chip_details {
82 uint16_t id;
83 const char *type;
84 const char *package;
85 uint32_t flash_size_in_kb;
86 };
87
88 /* list of PSoC 4 chips
89 * flash_size_in_kb is not necessary as it can be decoded from SPCIF_GEOMETRY
90 */
91 const struct psoc4_chip_details psoc4_devices[] = {
92 /* 4200 series */
93 { 0x04A6, "CY8C4245PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
94 { 0x04B6, "CY8C4245LQI-483", "QFN-40", .flash_size_in_kb = 32 },
95 { 0x04C8, "CY8C4245AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
96 { 0x04FB, "CY8C4245AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
97 { 0x04F0, "CY8C4244PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
98 { 0x04F1, "CY8C4244PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
99 { 0x04F6, "CY8C4244LQI-443", "QFN-40", .flash_size_in_kb = 16 },
100 { 0x04FA, "CY8C4244AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
101
102 /* 4100 series */
103 { 0x0410, "CY8C4124PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
104 { 0x0411, "CY8C4124PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
105 { 0x0416, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 },
106 { 0x041A, "CY8C4124AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
107 { 0x041B, "CY8C4125AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
108 { 0x0412, "CY8C4125PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
109 { 0x0417, "CY8C4125LQI-483", "QFN-40", .flash_size_in_kb = 32 },
110 { 0x041C, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
111
112 /* CCG1 series */
113 { 0x0490, "CYPD1103-35FNXI", "CSP-35", .flash_size_in_kb = 32 },
114 { 0x0489, "CYPD1121-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
115 { 0x048A, "CYPD1122-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
116 { 0x0491, "CYPD1131-35FNXI", "CSP-35", .flash_size_in_kb = 32 },
117 { 0x0498, "CYPD1132-16SXI", "SOIC-16", .flash_size_in_kb = 32 },
118 { 0x0481, "CYPD1134-28PVXI", "SSOP-28", .flash_size_in_kb = 32 },
119 { 0x048B, "CYPD1134-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
120 };
121
122
123 struct psoc4_flash_bank {
124 uint32_t row_size;
125 uint32_t user_bank_size;
126 int probed;
127 uint32_t silicon_id;
128 uint8_t chip_protection;
129 uint8_t cmd_program_row;
130 };
131
132
133 static const struct psoc4_chip_details *psoc4_details_by_id(uint32_t silicon_id)
134 {
135 const struct psoc4_chip_details *p = psoc4_devices;
136 unsigned int i;
137 uint16_t id = silicon_id >> 16; /* ignore die revision */
138 for (i = 0; i < sizeof(psoc4_devices)/sizeof(psoc4_devices[0]); i++, p++) {
139 if (p->id == id)
140 return p;
141 }
142 LOG_DEBUG("Unknown PSoC 4 device silicon id 0x%08" PRIx32 ".", silicon_id);
143 return NULL;
144 }
145
146 static const char *psoc4_decode_chip_protection(uint8_t protection)
147 {
148 switch (protection) {
149 case PSOC4_CHIP_PROT_VIRGIN:
150 return "protection VIRGIN";
151 case PSOC4_CHIP_PROT_OPEN:
152 return "protection open";
153 case PSOC4_CHIP_PROT_PROTECTED:
154 return "PROTECTED";
155 case PSOC4_CHIP_PROT_KILL:
156 return "protection KILL";
157 default:
158 LOG_WARNING("Unknown protection state 0x%02" PRIx8 "", protection);
159 return "";
160 }
161 }
162
163
164 /* flash bank <name> psoc <base> <size> 0 0 <target#>
165 */
166 FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
167 {
168 struct psoc4_flash_bank *psoc4_info;
169
170 if (CMD_ARGC < 6)
171 return ERROR_COMMAND_SYNTAX_ERROR;
172
173 psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
174
175 bank->driver_priv = psoc4_info;
176 psoc4_info->user_bank_size = bank->size;
177
178 return ERROR_OK;
179 }
180
181
182 /* PSoC 4 system ROM request
183 * Setting SROM_SYSREQ_BIT in CPUSS_SYSREQ register runs NMI service
184 * in sysrem ROM. Algorithm just waits for NMI to finish.
185 * When sysreq_params_size == 0 only one parameter is passed in CPUSS_SYSARG register.
186 * Otherwise address of memory parameter block is set in CPUSS_SYSARG
187 * and the first parameter is written to the first word of parameter block
188 */
189 static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
190 uint32_t *sysreq_params, uint32_t sysreq_params_size)
191 {
192 struct working_area *sysreq_wait_algorithm;
193 struct working_area *sysreq_mem;
194
195 struct reg_param reg_params[1];
196 struct armv7m_algorithm armv7m_info;
197
198 int retval = ERROR_OK;
199
200 uint32_t param1 = PSOC4_SROM_KEY1
201 | ((PSOC4_SROM_KEY2 + cmd) << 8)
202 | (cmd_param << 16);
203
204 static uint8_t psoc4_sysreq_wait_code[] = {
205 /* system request NMI is served immediately after algo run
206 now we are done: break */
207 0x00, 0xbe, /* bkpt 0 */
208 };
209
210 const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4;
211 /* stack must be aligned */
212 const int stack_size = 196;
213 /* tested stack sizes on PSoC 4:
214 ERASE_ALL 144
215 PROGRAM_ROW 112
216 other sysreq 68
217 */
218
219 /* allocate area for sysreq wait code and stack */
220 if (target_alloc_working_area(target, code_words * 4 + stack_size,
221 &sysreq_wait_algorithm) != ERROR_OK) {
222 LOG_DEBUG("no working area for sysreq code");
223 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
224 };
225
226 /* Write the code */
227 retval = target_write_buffer(target,
228 sysreq_wait_algorithm->address,
229 sizeof(psoc4_sysreq_wait_code),
230 psoc4_sysreq_wait_code);
231 if (retval != ERROR_OK) {
232 /* we already allocated the writing code, but failed to get a
233 * buffer, free the algorithm */
234 goto cleanup_algo;
235 }
236
237 if (sysreq_params_size) {
238 /* Allocate memory for sysreq_params */
239 retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem);
240 if (retval != ERROR_OK) {
241 LOG_WARNING("no working area for sysreq parameters");
242
243 /* we already allocated the writing code, but failed to get a
244 * buffer, free the algorithm */
245 retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
246 goto cleanup_algo;
247 }
248
249 /* Write sysreq_params */
250 sysreq_params[0] = param1;
251 retval = target_write_buffer(target, sysreq_mem->address,
252 sysreq_params_size, (uint8_t *)sysreq_params);
253 if (retval != ERROR_OK)
254 goto cleanup_mem;
255
256 /* Set address of sysreq parameters block */
257 retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, sysreq_mem->address);
258 if (retval != ERROR_OK)
259 goto cleanup_mem;
260
261 } else {
262 /* Sysreq without memory block of parameters */
263 /* Set register parameter */
264 retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, param1);
265 if (retval != ERROR_OK)
266 goto cleanup_mem;
267 }
268
269 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
270 armv7m_info.core_mode = ARM_MODE_THREAD;
271
272 /* sysreq stack */
273 init_reg_param(&reg_params[0], "sp", 32, PARAM_OUT);
274 buf_set_u32(reg_params[0].value, 0, 32,
275 sysreq_wait_algorithm->address + sysreq_wait_algorithm->size);
276
277 struct armv7m_common *armv7m = target_to_armv7m(target);
278 if (armv7m == NULL) {
279
280 /* something is very wrong if armv7m is NULL */
281 LOG_ERROR("unable to get armv7m target");
282 goto cleanup;
283 }
284
285 /* Set SROM request */
286 retval = target_write_u32(target, PSOC4_CPUSS_SYSREQ,
287 PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd);
288 if (retval != ERROR_OK)
289 goto cleanup;
290
291 /* Execute wait code */
292 retval = target_run_algorithm(target, 0, NULL,
293 sizeof(reg_params) / sizeof(*reg_params), reg_params,
294 sysreq_wait_algorithm->address, 0, 1000, &armv7m_info);
295 if (retval != ERROR_OK)
296 LOG_ERROR("sysreq wait code execution failed");
297
298 cleanup:
299 destroy_reg_param(&reg_params[0]);
300
301 cleanup_mem:
302 if (sysreq_params_size)
303 target_free_working_area(target, sysreq_mem);
304
305 cleanup_algo:
306 target_free_working_area(target, sysreq_wait_algorithm);
307
308 return retval;
309 }
310
311
312 /* helper routine to get silicon ID from a PSoC 4 chip */
313 static int psoc4_get_silicon_id(struct target *target, uint32_t *silicon_id, uint8_t *protection)
314 {
315 uint32_t params = PSOC4_SROM_KEY1
316 | ((PSOC4_SROM_KEY2 + PSOC4_CMD_GET_SILICON_ID) << 8);
317 uint32_t part0, part1;
318
319 int retval = psoc4_sysreq(target, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0);
320 if (retval != ERROR_OK)
321 return retval;
322
323 retval = target_read_u32(target, PSOC4_CPUSS_SYSARG, &part0);
324 if (retval != ERROR_OK)
325 return retval;
326
327 if (part0 == params) {
328 LOG_ERROR("sysreq silicon id request not served");
329 return ERROR_FAIL;
330 }
331
332 retval = target_read_u32(target, PSOC4_CPUSS_SYSREQ, &part1);
333 if (retval != ERROR_OK)
334 return retval;
335
336 uint32_t silicon = ((part0 & 0xffff) << 16)
337 | (((part0 >> 16) & 0xff) << 8)
338 | (part1 & 0xff);
339 uint8_t prot = (part1 >> 12) & 0xff;
340
341 if (silicon_id)
342 *silicon_id = silicon;
343 if (protection)
344 *protection = prot;
345
346 LOG_DEBUG("silicon id: 0x%08" PRIx32 "", silicon);
347 LOG_DEBUG("protection: 0x%02" PRIx8 "", prot);
348 return retval;
349 }
350
351
352 static int psoc4_protect_check(struct flash_bank *bank)
353 {
354 struct target *target = bank->target;
355 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
356
357 uint32_t prot_addr = PSOC4_SFLASH_MACRO;
358 uint32_t protection;
359 int i, s;
360 int num_bits;
361 int retval = ERROR_OK;
362
363 num_bits = bank->num_sectors;
364
365 for (i = 0; i < num_bits; i += 32) {
366 retval = target_read_u32(target, prot_addr, &protection);
367 if (retval != ERROR_OK)
368 return retval;
369
370 prot_addr += 4;
371
372 for (s = 0; s < 32; s++) {
373 if (i + s >= num_bits)
374 break;
375 bank->sectors[i + s].is_protected = (protection & (1 << s)) ? 1 : 0;
376 }
377 }
378
379 retval = psoc4_get_silicon_id(target, NULL, &(psoc4_info->chip_protection));
380 return retval;
381 }
382
383
384 static int psoc4_mass_erase(struct flash_bank *bank)
385 {
386 struct target *target = bank->target;
387 int i;
388
389 if (bank->target->state != TARGET_HALTED) {
390 LOG_ERROR("Target not halted");
391 return ERROR_TARGET_NOT_HALTED;
392 }
393
394 /* Call "Erase All" system ROM API */
395 uint32_t param;
396 int retval = psoc4_sysreq(target, PSOC4_CMD_ERASE_ALL,
397 0,
398 &param, sizeof(param));
399
400 if (retval == ERROR_OK)
401 /* set all sectors as erased */
402 for (i = 0; i < bank->num_sectors; i++)
403 bank->sectors[i].is_erased = 1;
404
405 return retval;
406 }
407
408
409 static int psoc4_erase(struct flash_bank *bank, int first, int last)
410 {
411 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
412 if (psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW) {
413 LOG_INFO("Autoerase enabled, erase command ignored");
414 return ERROR_OK;
415 }
416
417 if ((first == 0) && (last == (bank->num_sectors - 1)))
418 return psoc4_mass_erase(bank);
419
420 LOG_ERROR("Only mass erase available");
421
422 return ERROR_FAIL;
423 }
424
425
426 static int psoc4_protect(struct flash_bank *bank, int set, int first, int last)
427 {
428 struct target *target = bank->target;
429 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
430
431 if (psoc4_info->probed == 0)
432 return ERROR_FAIL;
433
434 if (target->state != TARGET_HALTED) {
435 LOG_ERROR("Target not halted");
436 return ERROR_TARGET_NOT_HALTED;
437 }
438
439 uint32_t *sysrq_buffer = NULL;
440 int retval;
441 int num_bits = bank->num_sectors;
442 const int param_sz = 8;
443 int prot_sz = num_bits / 8;
444 int chip_prot = PSOC4_CHIP_PROT_OPEN;
445 int flash_macro = 0; /* PSoC 42xx has only macro 0 */
446 int i;
447
448 sysrq_buffer = calloc(1, param_sz + prot_sz);
449 if (sysrq_buffer == NULL) {
450 LOG_ERROR("no memory for row buffer");
451 return ERROR_FAIL;
452 }
453
454 for (i = first; i < num_bits && i <= last; i++)
455 bank->sectors[i].is_protected = set;
456
457 uint32_t *p = sysrq_buffer + 2;
458 for (i = 0; i < num_bits; i++) {
459 if (bank->sectors[i].is_protected)
460 p[i / 32] |= 1 << (i % 32);
461 }
462
463 /* Call "Load Latch" system ROM API */
464 sysrq_buffer[1] = prot_sz - 1;
465 retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
466 0, /* Byte number in latch from what to write */
467 sysrq_buffer, param_sz + psoc4_info->row_size);
468 if (retval != ERROR_OK)
469 goto cleanup;
470
471 /* Call "Write Protection" system ROM API */
472 retval = psoc4_sysreq(target, PSOC4_CMD_WRITE_PROTECTION,
473 chip_prot | (flash_macro << 8), NULL, 0);
474 cleanup:
475 if (retval != ERROR_OK)
476 psoc4_protect_check(bank);
477
478 if (sysrq_buffer)
479 free(sysrq_buffer);
480
481 return retval;
482 }
483
484
485 COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
486 {
487 if (CMD_ARGC < 1)
488 return ERROR_COMMAND_SYNTAX_ERROR;
489
490 struct flash_bank *bank;
491 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
492 if (ERROR_OK != retval)
493 return retval;
494
495 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
496 bool enable = psoc4_info->cmd_program_row == PSOC4_CMD_WRITE_ROW;
497
498 if (CMD_ARGC >= 2)
499 COMMAND_PARSE_ON_OFF(CMD_ARGV[1], enable);
500
501 if (enable) {
502 psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
503 LOG_INFO("Flash auto-erase enabled, non mass erase commands will be ignored.");
504 } else {
505 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
506 LOG_INFO("Flash auto-erase disabled. Use psoc mass_erase before flash programming.");
507 }
508
509 return retval;
510 }
511
512
513 static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
514 uint32_t offset, uint32_t count)
515 {
516 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
517 struct target *target = bank->target;
518 uint32_t *sysrq_buffer = NULL;
519 int retval = ERROR_OK;
520 const int param_sz = 8;
521
522 if (bank->target->state != TARGET_HALTED) {
523 LOG_ERROR("Target not halted");
524 return ERROR_TARGET_NOT_HALTED;
525 }
526
527 if (offset & 0x1) {
528 LOG_ERROR("offset 0x%08" PRIx32 " breaks required 2-byte alignment", offset);
529 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
530 }
531
532 sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
533 if (sysrq_buffer == NULL) {
534 LOG_ERROR("no memory for row buffer");
535 return ERROR_FAIL;
536 }
537
538 uint8_t *row_buffer = (uint8_t *)sysrq_buffer + param_sz;
539 uint32_t row_num = offset / psoc4_info->row_size;
540 uint32_t row_offset = offset - row_num * psoc4_info->row_size;
541 if (row_offset)
542 memset(row_buffer, 0, row_offset);
543
544 bool save_poll = jtag_poll_get_enabled();
545 jtag_poll_set_enabled(false);
546
547 while (count) {
548 uint32_t chunk_size = psoc4_info->row_size - row_offset;
549 if (chunk_size > count) {
550 chunk_size = count;
551 memset(row_buffer + chunk_size, 0, psoc4_info->row_size - chunk_size);
552 }
553 memcpy(row_buffer + row_offset, buffer, chunk_size);
554 LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
555 offset, row_offset, chunk_size);
556
557 /* Call "Load Latch" system ROM API */
558 sysrq_buffer[1] = psoc4_info->row_size - 1;
559 retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
560 0, /* Byte number in latch from what to write */
561 sysrq_buffer, param_sz + psoc4_info->row_size);
562 if (retval != ERROR_OK)
563 goto cleanup;
564
565 /* Call "Program Row" or "Write Row" system ROM API */
566 uint32_t sysrq_param;
567 retval = psoc4_sysreq(target, psoc4_info->cmd_program_row,
568 row_num & 0xffff,
569 &sysrq_param, sizeof(sysrq_param));
570 if (retval != ERROR_OK)
571 goto cleanup;
572
573 buffer += chunk_size;
574 row_num++;
575 row_offset = 0;
576 count -= chunk_size;
577 }
578
579 cleanup:
580 jtag_poll_set_enabled(save_poll);
581
582 if (sysrq_buffer)
583 free(sysrq_buffer);
584
585 return retval;
586 }
587
588
589 static int psoc4_probe(struct flash_bank *bank)
590 {
591 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
592 struct target *target = bank->target;
593 uint32_t flash_size_in_kb = 0;
594 uint32_t max_flash_size_in_kb;
595 uint32_t cpu_id;
596 uint32_t silicon_id;
597 uint32_t row_size;
598 uint32_t base_address = 0x00000000;
599 uint8_t protection;
600
601 if (target->state != TARGET_HALTED) {
602 LOG_ERROR("Target not halted");
603 return ERROR_TARGET_NOT_HALTED;
604 }
605
606 psoc4_info->probed = 0;
607 psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
608
609 /* Get the CPUID from the ARM Core
610 * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
611 int retval = target_read_u32(target, 0xE000ED00, &cpu_id);
612 if (retval != ERROR_OK)
613 return retval;
614
615 LOG_DEBUG("cpu id = 0x%08" PRIx32 "", cpu_id);
616
617 /* set page size, protection granularity and max flash size depending on family */
618 switch ((cpu_id >> 4) & 0xFFF) {
619 case 0xc20: /* M0 -> PSoC4 */
620 row_size = 128;
621 max_flash_size_in_kb = 32;
622 break;
623 default:
624 LOG_WARNING("Cannot identify target as a PSoC 4 family.");
625 return ERROR_FAIL;
626 }
627
628 uint32_t spcif_geometry;
629 retval = target_read_u32(target, PSOC4_SPCIF_GEOMETRY, &spcif_geometry);
630 if (retval == ERROR_OK) {
631 row_size = 128 * ((spcif_geometry >> 22) & 3);
632 flash_size_in_kb = (spcif_geometry & 0xffff) * 256 / 1024;
633 LOG_INFO("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.",
634 flash_size_in_kb, row_size);
635 }
636
637 /* Early revisions of ST-Link v2 have some problem reading PSOC4_SPCIF_GEOMETRY
638 and an error is reported late. Dummy read gets this error. */
639 uint32_t dummy;
640 target_read_u32(target, PSOC4_CPUSS_SYSREQ, &dummy);
641
642 /* get silicon ID from target. */
643 retval = psoc4_get_silicon_id(target, &silicon_id, &protection);
644 if (retval != ERROR_OK)
645 return retval;
646
647 const struct psoc4_chip_details *details = psoc4_details_by_id(silicon_id);
648 if (details) {
649 LOG_INFO("%s device detected.", details->type);
650 if (flash_size_in_kb == 0)
651 flash_size_in_kb = details->flash_size_in_kb;
652 else if (flash_size_in_kb != details->flash_size_in_kb)
653 LOG_ERROR("Flash size mismatch");
654 }
655
656 psoc4_info->row_size = row_size;
657 psoc4_info->silicon_id = silicon_id;
658 psoc4_info->chip_protection = protection;
659
660 /* failed reading flash size or flash size invalid (early silicon),
661 * default to max target family */
662 if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
663 LOG_WARNING("PSoC 4 flash size failed, probe inaccurate - assuming %" PRIu32 " k flash",
664 max_flash_size_in_kb);
665 flash_size_in_kb = max_flash_size_in_kb;
666 }
667
668 /* if the user sets the size manually then ignore the probed value
669 * this allows us to work around devices that have a invalid flash size register value */
670 if (psoc4_info->user_bank_size) {
671 LOG_INFO("ignoring flash probed value, using configured bank size");
672 flash_size_in_kb = psoc4_info->user_bank_size / 1024;
673 }
674
675 LOG_INFO("flash size = %" PRIu32 " kbytes", flash_size_in_kb);
676
677 /* did we assign flash size? */
678 assert(flash_size_in_kb != 0xffff);
679
680 /* calculate numbers of pages */
681 uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
682
683 /* check that calculation result makes sense */
684 assert(num_rows > 0);
685
686 if (bank->sectors) {
687 free(bank->sectors);
688 bank->sectors = NULL;
689 }
690
691 bank->base = base_address;
692 bank->size = num_rows * row_size;
693 bank->num_sectors = num_rows;
694 bank->sectors = malloc(sizeof(struct flash_sector) * num_rows);
695
696 uint32_t i;
697 for (i = 0; i < num_rows; i++) {
698 bank->sectors[i].offset = i * row_size;
699 bank->sectors[i].size = row_size;
700 bank->sectors[i].is_erased = -1;
701 bank->sectors[i].is_protected = 1;
702 }
703
704 LOG_INFO("flash bank set %" PRIu32 " rows", num_rows);
705 psoc4_info->probed = 1;
706
707 return ERROR_OK;
708 }
709
710 static int psoc4_auto_probe(struct flash_bank *bank)
711 {
712 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
713 if (psoc4_info->probed)
714 return ERROR_OK;
715 return psoc4_probe(bank);
716 }
717
718
719 static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size)
720 {
721 struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
722 int printed = 0;
723
724 if (psoc4_info->probed == 0)
725 return ERROR_FAIL;
726
727 const struct psoc4_chip_details *details = psoc4_details_by_id(psoc4_info->silicon_id);
728
729 if (details) {
730 uint32_t chip_revision = psoc4_info->silicon_id & 0xffff;
731 printed = snprintf(buf, buf_size, "PSoC 4 %s rev 0x%04" PRIx32 " package %s",
732 details->type, chip_revision, details->package);
733 } else
734 printed = snprintf(buf, buf_size, "PSoC 4 silicon id 0x%08" PRIx32 "",
735 psoc4_info->silicon_id);
736
737 buf += printed;
738 buf_size -= printed;
739
740 const char *prot_txt = psoc4_decode_chip_protection(psoc4_info->chip_protection);
741 uint32_t size_in_kb = bank->size / 1024;
742 snprintf(buf, buf_size, " flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
743 return ERROR_OK;
744 }
745
746
747 COMMAND_HANDLER(psoc4_handle_mass_erase_command)
748 {
749 if (CMD_ARGC < 1)
750 return ERROR_COMMAND_SYNTAX_ERROR;
751
752 struct flash_bank *bank;
753 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
754 if (ERROR_OK != retval)
755 return retval;
756
757 retval = psoc4_mass_erase(bank);
758 if (retval == ERROR_OK)
759 command_print(CMD_CTX, "psoc mass erase complete");
760 else
761 command_print(CMD_CTX, "psoc mass erase failed");
762
763 return retval;
764 }
765
766
767 static const struct command_registration psoc4_exec_command_handlers[] = {
768 {
769 .name = "mass_erase",
770 .handler = psoc4_handle_mass_erase_command,
771 .mode = COMMAND_EXEC,
772 .usage = "bank_id",
773 .help = "Erase entire flash device.",
774 },
775 {
776 .name = "flash_autoerase",
777 .handler = psoc4_handle_flash_autoerase_command,
778 .mode = COMMAND_EXEC,
779 .usage = "bank_id on|off",
780 .help = "Set autoerase mode for flash bank.",
781 },
782 COMMAND_REGISTRATION_DONE
783 };
784
785 static const struct command_registration psoc4_command_handlers[] = {
786 {
787 .name = "psoc4",
788 .mode = COMMAND_ANY,
789 .help = "PSoC 4 flash command group",
790 .usage = "",
791 .chain = psoc4_exec_command_handlers,
792 },
793 COMMAND_REGISTRATION_DONE
794 };
795
796 struct flash_driver psoc4_flash = {
797 .name = "psoc4",
798 .commands = psoc4_command_handlers,
799 .flash_bank_command = psoc4_flash_bank_command,
800 .erase = psoc4_erase,
801 .protect = psoc4_protect,
802 .write = psoc4_write,
803 .read = default_flash_read,
804 .probe = psoc4_probe,
805 .auto_probe = psoc4_auto_probe,
806 .erase_check = default_flash_blank_check,
807 .protect_check = psoc4_protect_check,
808 .info = get_psoc4_info,
809 };

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)