OpenOCD
psoc6.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * *
5  * Copyright (C) 2018 by Bohdan Tymkiv *
6  * bohdan.tymkiv@cypress.com bohdan200@gmail.com *
7  ***************************************************************************/
8 
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12 
13 #include <time.h>
14 
15 #include "imp.h"
16 #include "helper/time_support.h"
17 #include "target/arm_adi_v5.h"
18 #include "target/target.h"
19 #include "target/cortex_m.h"
20 #include "target/breakpoints.h"
21 #include "target/algorithm.h"
22 
23 /**************************************************************************************************
24  * PSoC6 device definitions
25  *************************************************************************************************/
26 #define MFLASH_SECTOR_SIZE (256u * 1024u)
27 #define WFLASH_SECTOR_SIZE (32u * 1024u)
28 
29 #define MEM_BASE_MFLASH 0x10000000u
30 #define MEM_BASE_WFLASH 0x14000000u
31 #define MEM_WFLASH_SIZE 32768u
32 #define MEM_BASE_SFLASH 0x16000000u
33 #define RAM_STACK_WA_SIZE 2048u
34 #define PSOC6_SPCIF_GEOMETRY 0x4025F00Cu
35 
36 #define PROTECTION_UNKNOWN 0x00u
37 #define PROTECTION_VIRGIN 0x01u
38 #define PROTECTION_NORMAL 0x02u
39 #define PROTECTION_SECURE 0x03u
40 #define PROTECTION_DEAD 0x04u
41 
42 #define MEM_BASE_IPC 0x40230000u
43 #define IPC_STRUCT_SIZE 0x20u
44 #define MEM_IPC(n) (MEM_BASE_IPC + (n) * IPC_STRUCT_SIZE)
45 #define MEM_IPC_ACQUIRE(n) (MEM_IPC(n) + 0x00u)
46 #define MEM_IPC_NOTIFY(n) (MEM_IPC(n) + 0x08u)
47 #define MEM_IPC_DATA(n) (MEM_IPC(n) + 0x0Cu)
48 #define MEM_IPC_LOCK_STATUS(n) (MEM_IPC(n) + 0x10u)
49 
50 #define MEM_BASE_IPC_INTR 0x40231000u
51 #define IPC_INTR_STRUCT_SIZE 0x20u
52 #define MEM_IPC_INTR(n) (MEM_BASE_IPC_INTR + (n) * IPC_INTR_STRUCT_SIZE)
53 #define MEM_IPC_INTR_MASK(n) (MEM_IPC_INTR(n) + 0x08u)
54 #define IPC_ACQUIRE_SUCCESS_MSK 0x80000000u
55 #define IPC_LOCK_ACQUIRED_MSK 0x80000000u
56 
57 #define IPC_ID 2u
58 #define IPC_INTR_ID 0u
59 #define IPC_TIMEOUT_MS 1000
60 
61 #define SROMAPI_SIID_REQ 0x00000001u
62 #define SROMAPI_SIID_REQ_FAMILY_REVISION (SROMAPI_SIID_REQ | 0x000u)
63 #define SROMAPI_SIID_REQ_SIID_PROTECTION (SROMAPI_SIID_REQ | 0x100u)
64 #define SROMAPI_WRITEROW_REQ 0x05000100u
65 #define SROMAPI_PROGRAMROW_REQ 0x06000100u
66 #define SROMAPI_ERASESECTOR_REQ 0x14000100u
67 #define SROMAPI_ERASEALL_REQ 0x0A000100u
68 #define SROMAPI_ERASEROW_REQ 0x1C000100u
69 
70 #define SROMAPI_STATUS_MSK 0xF0000000u
71 #define SROMAPI_STAT_SUCCESS 0xA0000000u
72 #define SROMAPI_DATA_LOCATION_MSK 0x00000001u
73 #define SROMAPI_CALL_TIMEOUT_MS 1500
74 
76  uint32_t silicon_id;
77  uint8_t protection;
78  uint32_t main_flash_sz;
79  uint32_t row_sz;
80  bool is_probed;
81 };
82 
83 struct timeout {
84  int64_t start_time;
85  long timeout_ms;
86 };
87 
88 struct row_region {
89  uint32_t addr;
90  size_t size;
91 };
92 
93 static const struct row_region safe_sflash_regions[] = {
94  {0x16000800, 0x800}, /* SFLASH: User Data */
95  {0x16001A00, 0x200}, /* SFLASH: NAR */
96  {0x16005A00, 0xC00}, /* SFLASH: Public Key */
97  {0x16007C00, 0x400}, /* SFLASH: TOC2 */
98 };
99 
100 #define SFLASH_NUM_REGIONS ARRAY_SIZE(safe_sflash_regions)
101 
102 static struct working_area *g_stack_area;
103 static struct armv7m_algorithm g_armv7m_info;
104 
110 static void timeout_init(struct timeout *to, long timeout_ms)
111 {
112  to->start_time = timeval_ms();
113  to->timeout_ms = timeout_ms;
114 }
115 
121 static bool timeout_expired(struct timeout *to)
122 {
123  return (timeval_ms() - to->start_time) > to->timeout_ms;
124 }
125 
134 static int sromalgo_prepare(struct target *target)
135 {
136  int hr;
137 
138  /* Initialize Vector Table Offset register (in case FW modified it) */
139  hr = target_write_u32(target, 0xE000ED08, 0x00000000);
140  if (hr != ERROR_OK)
141  return hr;
142 
143  /* Allocate Working Area for Stack and Flash algorithm */
145  if (hr != ERROR_OK)
146  return hr;
147 
150 
151  struct reg_param reg_params;
152  init_reg_param(&reg_params, "sp", 32, PARAM_OUT);
153  buf_set_u32(reg_params.value, 0, 32, g_stack_area->address + g_stack_area->size);
154 
155  /* Write basic infinite loop algorithm to target RAM */
156  hr = target_write_u32(target, g_stack_area->address, 0xFEE7FEE7);
157  if (hr != ERROR_OK)
158  goto destroy_rp_free_wa;
159 
160  hr = target_start_algorithm(target, 0, NULL, 1, &reg_params, g_stack_area->address,
161  0, &g_armv7m_info);
162  if (hr != ERROR_OK)
163  goto destroy_rp_free_wa;
164 
165  destroy_reg_param(&reg_params);
166 
167  return hr;
168 
169 destroy_rp_free_wa:
170  /* Something went wrong, do some cleanup */
171  destroy_reg_param(&reg_params);
172 
174  g_stack_area = NULL;
175 
176  return hr;
177 }
178 
186 static void sromalgo_release(struct target *target)
187 {
188  int hr = ERROR_OK;
189 
190  if (g_stack_area) {
191  /* Stop flash algorithm if it is running */
192  if (target->running_alg) {
193  hr = target_halt(target);
194  if (hr != ERROR_OK)
195  goto exit_free_wa;
196 
197  hr = target_wait_algorithm(target, 0, NULL, 0, NULL, 0,
199  if (hr != ERROR_OK)
200  goto exit_free_wa;
201  }
202 
203 exit_free_wa:
204  /* Free Stack/Flash algorithm working area */
206  g_stack_area = NULL;
207  }
208 }
209 
222 static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_expected)
223 {
224  int hr;
225  uint32_t reg_val;
226  struct armv7m_common *armv7m = target_to_armv7m(target);
227  bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M);
228 
229  struct timeout to;
231 
232  while (!timeout_expired(&to)) {
233  /* Process any server requests */
234  keep_alive();
235 
236  /* Read IPC Lock status */
237  hr = target_read_u32(target, MEM_IPC_LOCK_STATUS(ipc_id), &reg_val);
238  if (hr != ERROR_OK) {
239  LOG_ERROR("Unable to read IPC Lock Status register");
240  return hr;
241  }
242 
243  bool is_locked = (reg_val & IPC_LOCK_ACQUIRED_MSK) != 0;
244 
245  if (lock_expected == is_locked)
246  return ERROR_OK;
247  }
248 
249  if (!is_cm0) {
250  LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. "
251  "Please perform all Flash-related operations via CM0+ target on dual-core devices.");
252  }
253 
254  LOG_ERROR("Timeout polling IPC Lock Status");
255  return ERROR_TARGET_TIMEOUT;
256 }
257 
268 static int ipc_acquire(struct target *target, char ipc_id)
269 {
270  int hr = ERROR_OK;
271  bool is_acquired = false;
272  uint32_t reg_val;
273 
274  struct timeout to;
276 
277  while (!timeout_expired(&to)) {
278  keep_alive();
279 
281  if (hr != ERROR_OK) {
282  LOG_ERROR("Unable to write to IPC Acquire register");
283  return hr;
284  }
285 
286  /* Check if data is written on first step */
287  hr = target_read_u32(target, MEM_IPC_ACQUIRE(ipc_id), &reg_val);
288  if (hr != ERROR_OK) {
289  LOG_ERROR("Unable to read IPC Acquire register");
290  return hr;
291  }
292 
293  is_acquired = (reg_val & IPC_ACQUIRE_SUCCESS_MSK) != 0;
294  if (is_acquired) {
295  /* If IPC structure is acquired, the lock status should be set */
296  hr = ipc_poll_lock_stat(target, ipc_id, true);
297  break;
298  }
299  }
300 
301  if (!is_acquired)
302  LOG_ERROR("Timeout acquiring IPC structure");
303 
304  return hr;
305 }
306 
316 static int call_sromapi(struct target *target,
317  uint32_t req_and_params,
318  uint32_t working_area,
319  uint32_t *data_out)
320 {
321  int hr;
322 
323  bool is_data_in_ram = (req_and_params & SROMAPI_DATA_LOCATION_MSK) == 0;
324 
325  hr = ipc_acquire(target, IPC_ID);
326  if (hr != ERROR_OK)
327  return hr;
328 
329  if (is_data_in_ram)
331  else
332  hr = target_write_u32(target, MEM_IPC_DATA(IPC_ID), req_and_params);
333 
334  if (hr != ERROR_OK)
335  return hr;
336 
337  /* Enable notification interrupt of IPC_INTR_STRUCT0(CM0+) for IPC_STRUCT2 */
339  if (hr != ERROR_OK)
340  return hr;
341 
343  if (hr != ERROR_OK)
344  return hr;
345 
346  /* Poll lock status */
347  hr = ipc_poll_lock_stat(target, IPC_ID, false);
348  if (hr != ERROR_OK)
349  return hr;
350 
351  /* Poll Data byte */
352  if (is_data_in_ram)
353  hr = target_read_u32(target, working_area, data_out);
354  else
355  hr = target_read_u32(target, MEM_IPC_DATA(IPC_ID), data_out);
356 
357  if (hr != ERROR_OK) {
358  LOG_ERROR("Error reading SROM API Status location");
359  return hr;
360  }
361 
362  bool is_success = (*data_out & SROMAPI_STATUS_MSK) == SROMAPI_STAT_SUCCESS;
363  if (!is_success) {
364  LOG_ERROR("SROM API execution failed. Status: 0x%08" PRIX32, *data_out);
365  return ERROR_TARGET_FAILURE;
366  }
367 
368  return ERROR_OK;
369 }
370 
378 static int get_silicon_id(struct target *target, uint32_t *si_id, uint8_t *protection)
379 {
380  int hr;
381  uint32_t family_rev, siid_prot;
382 
383  hr = sromalgo_prepare(target);
384  if (hr != ERROR_OK)
385  goto exit;
386 
387  /* Read FamilyID and Revision */
389  if (hr != ERROR_OK)
390  goto exit;
391 
392  /* Read SiliconID and Protection */
394  if (hr != ERROR_OK)
395  goto exit;
396 
397  *si_id = (siid_prot & 0x0000FFFF) << 16;
398  *si_id |= (family_rev & 0x00FF0000) >> 8;
399  *si_id |= (family_rev & 0x000000FF) >> 0;
400 
401  *protection = (siid_prot & 0x000F0000) >> 0x10;
402 
403 exit:
405  return ERROR_OK;
406 }
407 
414 {
415  int is_protected;
416 
417  struct psoc6_target_info *psoc6_info = bank->driver_priv;
418  int hr = get_silicon_id(bank->target, &psoc6_info->silicon_id, &psoc6_info->protection);
419  if (hr != ERROR_OK)
420  return hr;
421 
422  switch (psoc6_info->protection) {
423  case PROTECTION_VIRGIN:
424  case PROTECTION_NORMAL:
425  is_protected = 0;
426  break;
427 
428  case PROTECTION_UNKNOWN:
429  case PROTECTION_SECURE:
430  case PROTECTION_DEAD:
431  default:
432  is_protected = 1;
433  break;
434  }
435 
436  for (unsigned int i = 0; i < bank->num_sectors; i++)
437  bank->sectors[i].is_protected = is_protected;
438 
439  return ERROR_OK;
440 }
441 
446 static int psoc6_protect(struct flash_bank *bank, int set, unsigned int first,
447  unsigned int last)
448 {
449  (void)bank;
450  (void)set;
451  (void)first;
452  (void)last;
453 
454  LOG_WARNING("Life Cycle transition for PSoC6 is not supported");
455  return ERROR_OK;
456 }
457 
463 static const char *protection_to_str(uint8_t protection)
464 {
465  switch (protection) {
466  case PROTECTION_VIRGIN:
467  return "VIRGIN";
468  case PROTECTION_NORMAL:
469  return "NORMAL";
470  case PROTECTION_SECURE:
471  return "SECURE";
472  case PROTECTION_DEAD:
473  return "DEAD";
474  case PROTECTION_UNKNOWN:
475  default:
476  return "UNKNOWN";
477  }
478 }
479 
487 {
488  struct psoc6_target_info *psoc6_info = bank->driver_priv;
489 
490  if (!psoc6_info->is_probed)
491  return ERROR_FAIL;
492 
493  int hr = get_silicon_id(bank->target, &psoc6_info->silicon_id, &psoc6_info->protection);
494  if (hr != ERROR_OK)
495  return hr;
496 
498  "PSoC6 Silicon ID: 0x%08" PRIX32 "\n"
499  "Protection: %s\n"
500  "Main Flash size: %" PRIu32 " kB\n"
501  "Work Flash size: 32 kB\n",
502  psoc6_info->silicon_id,
503  protection_to_str(psoc6_info->protection),
504  psoc6_info->main_flash_sz / 1024);
505 
506  return ERROR_OK;
507 }
508 
514 static bool is_sflash_bank(struct flash_bank *bank)
515 {
516  for (size_t i = 0; i < SFLASH_NUM_REGIONS; i++) {
517  if (bank->base == safe_sflash_regions[i].addr)
518  return true;
519  }
520 
521  return false;
522 }
523 
529 static inline bool is_wflash_bank(struct flash_bank *bank)
530 {
531  return (bank->base == MEM_BASE_WFLASH);
532 }
533 
539 static inline bool is_mflash_bank(struct flash_bank *bank)
540 {
541  return (bank->base == MEM_BASE_MFLASH);
542 }
543 
552 static int psoc6_probe(struct flash_bank *bank)
553 {
554  struct target *target = bank->target;
555  struct psoc6_target_info *psoc6_info = bank->driver_priv;
556 
557  int hr = ERROR_OK;
558 
559  /* Retrieve data from SPCIF_GEOMETRY */
560  uint32_t geom;
562  uint32_t row_sz_lg2 = (geom & 0xF0) >> 4;
563  uint32_t row_sz = (0x01 << row_sz_lg2);
564  uint32_t row_cnt = 1 + ((geom & 0x00FFFF00) >> 8);
565  uint32_t bank_cnt = 1 + ((geom & 0xFF000000) >> 24);
566 
567  /* Calculate size of Main Flash*/
568  uint32_t flash_sz_bytes = bank_cnt * row_cnt * row_sz;
569 
570  free(bank->sectors);
571  bank->sectors = NULL;
572 
573  size_t bank_size = 0;
574 
575  if (is_mflash_bank(bank))
576  bank_size = flash_sz_bytes;
577  else if (is_wflash_bank(bank))
578  bank_size = MEM_WFLASH_SIZE;
579  else if (is_sflash_bank(bank)) {
580  for (size_t i = 0; i < SFLASH_NUM_REGIONS; i++) {
581  if (safe_sflash_regions[i].addr == bank->base) {
582  bank_size = safe_sflash_regions[i].size;
583  break;
584  }
585  }
586  }
587 
588  if (bank_size == 0) {
589  LOG_ERROR("Invalid Flash Bank base address in config file");
591  }
592 
593  unsigned int num_sectors = bank_size / row_sz;
594  bank->size = bank_size;
595 
596  bank->erased_value = 0;
597  bank->default_padded_value = 0;
598 
599  bank->num_sectors = num_sectors;
600  bank->sectors = calloc(num_sectors, sizeof(struct flash_sector));
601  for (unsigned int i = 0; i < num_sectors; i++) {
602  bank->sectors[i].size = row_sz;
603  bank->sectors[i].offset = i * row_sz;
604  bank->sectors[i].is_erased = -1;
605  bank->sectors[i].is_protected = -1;
606  }
607 
608  psoc6_info->is_probed = true;
609  psoc6_info->main_flash_sz = flash_sz_bytes;
610  psoc6_info->row_sz = row_sz;
611 
612  return hr;
613 }
614 
620 static int psoc6_auto_probe(struct flash_bank *bank)
621 {
622  struct psoc6_target_info *psoc6_info = bank->driver_priv;
623  int hr;
624 
625  if (psoc6_info->is_probed)
626  hr = ERROR_OK;
627  else
628  hr = psoc6_probe(bank);
629 
630  return hr;
631 }
632 
640 static int psoc6_erase_sector(struct flash_bank *bank, struct working_area *wa, uint32_t addr)
641 {
642  struct target *target = bank->target;
643 
644  LOG_DEBUG("Erasing SECTOR @%08" PRIX32, addr);
645 
647  if (hr != ERROR_OK)
648  return hr;
649 
650  hr = target_write_u32(target, wa->address + 0x04, addr);
651  if (hr != ERROR_OK)
652  return hr;
653 
654  uint32_t data_out;
655  hr = call_sromapi(target, SROMAPI_ERASESECTOR_REQ, wa->address, &data_out);
656  if (hr != ERROR_OK)
657  LOG_ERROR("SECTOR @%08" PRIX32 " not erased!", addr);
658 
659  return hr;
660 }
661 
669 static int psoc6_erase_row(struct flash_bank *bank, struct working_area *wa, uint32_t addr)
670 {
671  struct target *target = bank->target;
672 
673  LOG_DEBUG("Erasing ROW @%08" PRIX32, addr);
674 
676  if (hr != ERROR_OK)
677  return hr;
678 
679  hr = target_write_u32(target, wa->address + 0x04, addr);
680  if (hr != ERROR_OK)
681  return hr;
682 
683  uint32_t data_out;
684  hr = call_sromapi(target, SROMAPI_ERASEROW_REQ, wa->address, &data_out);
685  if (hr != ERROR_OK)
686  LOG_ERROR("ROW @%08" PRIX32 " not erased!", addr);
687 
688  return hr;
689 }
690 
700 static int psoc6_erase(struct flash_bank *bank, unsigned int first,
701  unsigned int last)
702 {
703  struct target *target = bank->target;
704  struct psoc6_target_info *psoc6_info = bank->driver_priv;
706 
707  int hr;
708  struct working_area *wa;
709 
710  if (is_sflash_bank(bank)) {
711  LOG_INFO("Erase operation on Supervisory Flash is not required, skipping");
712  return ERROR_OK;
713  }
714 
715  hr = sromalgo_prepare(target);
716  if (hr != ERROR_OK)
717  goto exit;
718 
719  hr = target_alloc_working_area(target, psoc6_info->row_sz + 32, &wa);
720  if (hr != ERROR_OK)
721  goto exit;
722 
723  /* Number of rows in single sector */
724  const unsigned int rows_in_sector = sector_size / psoc6_info->row_sz;
725 
726  while (last >= first) {
727  /* Erase Sector if we are on sector boundary and erase size covers whole sector */
728  if ((first % rows_in_sector) == 0 &&
729  (last - first + 1) >= rows_in_sector) {
730  hr = psoc6_erase_sector(bank, wa, bank->base + first * psoc6_info->row_sz);
731  if (hr != ERROR_OK)
732  goto exit_free_wa;
733 
734  first += rows_in_sector;
735  } else {
736  /* Perform Row Erase otherwise */
737  hr = psoc6_erase_row(bank, wa, bank->base + first * psoc6_info->row_sz);
738  if (hr != ERROR_OK)
739  goto exit_free_wa;
740 
741  first += 1;
742  }
743  }
744 
745 exit_free_wa:
747 exit:
749  return hr;
750 }
751 
760 static int psoc6_program_row(struct flash_bank *bank,
761  uint32_t addr,
762  const uint8_t *buffer,
763  bool is_sflash)
764 {
765  struct target *target = bank->target;
766  struct psoc6_target_info *psoc6_info = bank->driver_priv;
767  struct working_area *wa;
768  const uint32_t sromapi_req = is_sflash ? SROMAPI_WRITEROW_REQ : SROMAPI_PROGRAMROW_REQ;
769  uint32_t data_out;
770  int hr = ERROR_OK;
771 
772  LOG_DEBUG("Programming ROW @%08" PRIX32, addr);
773 
774  hr = target_alloc_working_area(target, psoc6_info->row_sz + 32, &wa);
775  if (hr != ERROR_OK)
776  goto exit;
777 
778  hr = target_write_u32(target, wa->address, sromapi_req);
779  if (hr != ERROR_OK)
780  goto exit_free_wa;
781 
783  wa->address + 0x04,
784  0x106);
785  if (hr != ERROR_OK)
786  goto exit_free_wa;
787 
788  hr = target_write_u32(target, wa->address + 0x08, addr);
789  if (hr != ERROR_OK)
790  goto exit_free_wa;
791 
792  hr = target_write_u32(target, wa->address + 0x0C, wa->address + 0x10);
793  if (hr != ERROR_OK)
794  goto exit_free_wa;
795 
796  hr = target_write_buffer(target, wa->address + 0x10, psoc6_info->row_sz, buffer);
797  if (hr != ERROR_OK)
798  goto exit_free_wa;
799 
800  hr = call_sromapi(target, sromapi_req, wa->address, &data_out);
801 
802 exit_free_wa:
804 
805 exit:
806  return hr;
807 }
808 
817 static int psoc6_program(struct flash_bank *bank,
818  const uint8_t *buffer,
819  uint32_t offset,
820  uint32_t count)
821 {
822  struct target *target = bank->target;
823  struct psoc6_target_info *psoc6_info = bank->driver_priv;
824  const bool is_sflash = is_sflash_bank(bank);
825  int hr;
826 
827  uint8_t page_buf[psoc6_info->row_sz];
828 
829  hr = sromalgo_prepare(target);
830  if (hr != ERROR_OK)
831  goto exit;
832 
833  while (count) {
834  uint32_t row_offset = offset % psoc6_info->row_sz;
835  uint32_t aligned_addr = bank->base + offset - row_offset;
836  uint32_t row_bytes = MIN(psoc6_info->row_sz - row_offset, count);
837 
838  memset(page_buf, 0, sizeof(page_buf));
839  memcpy(&page_buf[row_offset], buffer, row_bytes);
840 
841  hr = psoc6_program_row(bank, aligned_addr, page_buf, is_sflash);
842  if (hr != ERROR_OK) {
843  LOG_ERROR("Failed to program Flash at address 0x%08" PRIX32, aligned_addr);
844  goto exit;
845  }
846 
847  buffer += row_bytes;
848  offset += row_bytes;
849  count -= row_bytes;
850  }
851 
852 exit:
854  return hr;
855 }
856 
861 COMMAND_HANDLER(psoc6_handle_mass_erase_command)
862 {
863  if (CMD_ARGC != 1)
865 
866  struct flash_bank *bank;
867  int hr = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
868  if (hr != ERROR_OK)
869  return hr;
870 
871  hr = psoc6_erase(bank, 0, bank->num_sectors - 1);
872 
873  return hr;
874 }
875 
887 static int handle_reset_halt(struct target *target)
888 {
889  int hr;
890  uint32_t reset_addr;
891  struct armv7m_common *armv7m = target_to_armv7m(target);
892  bool is_cm0 = (armv7m->arm.arch == ARM_ARCH_V6M);
893 
894  /* Halt target device */
895  if (target->state != TARGET_HALTED) {
896  hr = target_halt(target);
897  if (hr != ERROR_OK)
898  return hr;
899 
901  if (hr != ERROR_OK)
902  return hr;
903  }
904 
905  /* Read Vector Offset register */
906  uint32_t vt_base;
907  const uint32_t vt_offset_reg = is_cm0 ? 0x402102B0 : 0x402102C0;
908  hr = target_read_u32(target, vt_offset_reg, &vt_base);
909  if (hr != ERROR_OK)
910  return ERROR_OK;
911 
912  /* Invalid value means flash is empty */
913  vt_base &= 0xFFFFFF00;
914  if ((vt_base == 0) || (vt_base == 0xFFFFFF00))
915  return ERROR_OK;
916 
917  /* Read Reset Vector value*/
918  hr = target_read_u32(target, vt_base + 4, &reset_addr);
919  if (hr != ERROR_OK)
920  return hr;
921 
922  /* Invalid value means flash is empty */
923  if ((reset_addr == 0) || (reset_addr == 0xFFFFFF00))
924  return ERROR_OK;
925 
926 
927  /* Set breakpoint at User Application entry point */
928  hr = breakpoint_add(target, reset_addr, 2, BKPT_HARD);
929  if (hr != ERROR_OK)
930  return hr;
931 
932  const struct armv7m_common *cm = target_to_armv7m(target);
933 
934  /* PSoC6 reboots immediately after issuing SYSRESETREQ / VECTRESET
935  * this disables SWD/JTAG pins momentarily and may break communication
936  * Ignoring return value of mem_ap_write_atomic_u32 seems to be ok here */
937  if (is_cm0) {
938  /* Reset the CM0 by asserting SYSRESETREQ. This will also reset CM4 */
939  LOG_INFO("psoc6.cm0: bkpt @0x%08" PRIX32 ", issuing SYSRESETREQ", reset_addr);
942  } else {
943  LOG_INFO("psoc6.cm4: bkpt @0x%08" PRIX32 ", issuing VECTRESET", reset_addr);
946  }
947 
948  /* Wait 100ms for bootcode and reinitialize DAP */
949  usleep(100000);
950  dap_dp_init(cm->debug_ap->dap);
951 
953 
954  /* Remove the break point */
955  breakpoint_remove(target, reset_addr);
956 
957  return ERROR_OK;
958 }
959 
970 COMMAND_HANDLER(psoc6_handle_reset_halt)
971 {
972  if (CMD_ARGC)
974 
976  return handle_reset_halt(target);
977 }
978 
979 FLASH_BANK_COMMAND_HANDLER(psoc6_flash_bank_command)
980 {
981  struct psoc6_target_info *psoc6_info;
982  int hr = ERROR_OK;
983 
984  if (CMD_ARGC < 6)
986  else {
987  psoc6_info = calloc(1, sizeof(struct psoc6_target_info));
988  psoc6_info->is_probed = false;
989  bank->driver_priv = psoc6_info;
990  }
991  return hr;
992 }
993 
994 static const struct command_registration psoc6_exec_command_handlers[] = {
995  {
996  .name = "mass_erase",
997  .handler = psoc6_handle_mass_erase_command,
998  .mode = COMMAND_EXEC,
999  .usage = "bank",
1000  .help = "Erases entire Main Flash",
1001  },
1002  {
1003  .name = "reset_halt",
1004  .handler = psoc6_handle_reset_halt,
1005  .mode = COMMAND_EXEC,
1006  .usage = "",
1007  .help = "Tries to simulate broken Vector Catch",
1008  },
1010 };
1011 
1012 static const struct command_registration psoc6_command_handlers[] = {
1013  {
1014  .name = "psoc6",
1015  .mode = COMMAND_ANY,
1016  .help = "PSoC 6 flash command group",
1017  .usage = "",
1018  .chain = psoc6_exec_command_handlers,
1019  },
1021 };
1022 
1023 const struct flash_driver psoc6_flash = {
1024  .name = "psoc6",
1025  .commands = psoc6_command_handlers,
1026  .flash_bank_command = psoc6_flash_bank_command,
1027  .erase = psoc6_erase,
1028  .protect = psoc6_protect,
1029  .write = psoc6_program,
1030  .read = default_flash_read,
1031  .probe = psoc6_probe,
1032  .auto_probe = psoc6_auto_probe,
1033  .erase_check = default_flash_blank_check,
1034  .protect_check = psoc6_protect_check,
1035  .info = psoc6_get_info,
1036  .free_driver_priv = default_flash_free_driver_priv,
1037 };
void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction direction)
Definition: algorithm.c:29
void destroy_reg_param(struct reg_param *param)
Definition: algorithm.c:37
@ PARAM_OUT
Definition: algorithm.h:16
@ ARM_ARCH_V6M
Definition: arm.h:56
@ ARM_MODE_THREAD
Definition: arm.h:94
int dap_dp_init(struct adiv5_dap *dap)
Initialize a DAP.
Definition: arm_adi_v5.c:779
int mem_ap_write_atomic_u32(struct adiv5_ap *ap, target_addr_t address, uint32_t value)
Synchronous write of a word to memory or a system register.
Definition: arm_adi_v5.c:318
This defines formats and data structures used to talk to ADIv5 entities.
static struct armv7m_common * target_to_armv7m(struct target *target)
Definition: armv7m.h:262
#define ARMV7M_COMMON_MAGIC
Definition: armv7m.h:220
static void buf_set_u32(uint8_t *_buffer, unsigned int first, unsigned int num, uint32_t value)
Sets num bits in _buffer, starting at the first bit, using the bits in value.
Definition: binarybuffer.h:34
int breakpoint_remove(struct target *target, target_addr_t address)
Definition: breakpoints.c:344
int breakpoint_add(struct target *target, target_addr_t address, unsigned int length, enum breakpoint_type type)
Definition: breakpoints.c:208
@ BKPT_HARD
Definition: breakpoints.h:18
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:420
#define CALL_COMMAND_HANDLER(name, extra ...)
Use this to macro to call a command helper (or a nested handler).
Definition: command.h:118
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:146
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ COMMAND_ANY
Definition: command.h:42
@ COMMAND_EXEC
Definition: command.h:40
#define AIRCR_VECTKEY
Definition: cortex_m.h:174
#define AIRCR_SYSRESETREQ
Definition: cortex_m.h:175
#define AIRCR_VECTRESET
Definition: cortex_m.h:177
#define NVIC_AIRCR
Definition: cortex_m.h:160
uint8_t bank
Definition: esirisc.c:135
static const int sector_size
Definition: faux.c:22
#define ERROR_FLASH_BANK_INVALID
Definition: flash/common.h:28
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
void keep_alive(void)
Definition: log.c:415
#define LOG_WARNING(expr ...)
Definition: log.h:129
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:164
#define SROMAPI_STAT_SUCCESS
Definition: psoc6.c:71
FLASH_BANK_COMMAND_HANDLER(psoc6_flash_bank_command)
Definition: psoc6.c:979
static const struct row_region safe_sflash_regions[]
Definition: psoc6.c:93
#define SROMAPI_PROGRAMROW_REQ
Definition: psoc6.c:65
static int psoc6_probe(struct flash_bank *bank)
Probes the device and populates related data structures with target flash geometry data.
Definition: psoc6.c:552
#define IPC_INTR_ID
Definition: psoc6.c:58
static struct armv7m_algorithm g_armv7m_info
Definition: psoc6.c:103
static int handle_reset_halt(struct target *target)
Simulates broken Vector Catch Function will try to determine entry point of user application.
Definition: psoc6.c:887
#define PROTECTION_SECURE
Definition: psoc6.c:39
static bool is_wflash_bank(struct flash_bank *bank)
Checks if given flash bank belongs to Work Flash.
Definition: psoc6.c:529
#define SFLASH_NUM_REGIONS
Definition: psoc6.c:100
#define PSOC6_SPCIF_GEOMETRY
Definition: psoc6.c:34
static int sromalgo_prepare(struct target *target)
Starts pseudo flash algorithm and leaves it running.
Definition: psoc6.c:134
static struct working_area * g_stack_area
Definition: psoc6.c:102
#define SROMAPI_ERASEROW_REQ
Definition: psoc6.c:68
#define PROTECTION_DEAD
Definition: psoc6.c:40
#define SROMAPI_SIID_REQ_SIID_PROTECTION
Definition: psoc6.c:63
#define IPC_ACQUIRE_SUCCESS_MSK
Definition: psoc6.c:54
#define SROMAPI_WRITEROW_REQ
Definition: psoc6.c:64
#define MEM_IPC_LOCK_STATUS(n)
Definition: psoc6.c:48
static int psoc6_erase_sector(struct flash_bank *bank, struct working_area *wa, uint32_t addr)
Erases single sector (256k) on target device.
Definition: psoc6.c:640
#define MEM_IPC_INTR_MASK(n)
Definition: psoc6.c:53
const struct flash_driver psoc6_flash
Definition: psoc6.c:1023
static void sromalgo_release(struct target *target)
Stops running flash algorithm and releases associated resources.
Definition: psoc6.c:186
#define IPC_ID
Definition: psoc6.c:57
static int psoc6_auto_probe(struct flash_bank *bank)
Probes target device only if it hasn't been probed yet.
Definition: psoc6.c:620
#define SROMAPI_STATUS_MSK
Definition: psoc6.c:70
#define MEM_BASE_WFLASH
Definition: psoc6.c:30
static int call_sromapi(struct target *target, uint32_t req_and_params, uint32_t working_area, uint32_t *data_out)
Invokes SROM API functions which are responsible for Flash operations.
Definition: psoc6.c:316
#define PROTECTION_VIRGIN
Definition: psoc6.c:37
#define WFLASH_SECTOR_SIZE
Definition: psoc6.c:27
static bool timeout_expired(struct timeout *to)
Returns true if given struct timeout structure has expired.
Definition: psoc6.c:121
#define IPC_LOCK_ACQUIRED_MSK
Definition: psoc6.c:55
#define MEM_IPC_NOTIFY(n)
Definition: psoc6.c:46
static int psoc6_program(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Performs Program operation.
Definition: psoc6.c:817
#define MEM_IPC_ACQUIRE(n)
Definition: psoc6.c:45
static void timeout_init(struct timeout *to, long timeout_ms)
Initializes struct timeout structure with given timeout value.
Definition: psoc6.c:110
static int psoc6_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Performs Erase operation.
Definition: psoc6.c:700
static int psoc6_erase_row(struct flash_bank *bank, struct working_area *wa, uint32_t addr)
Erases single row (512b) on target device.
Definition: psoc6.c:669
COMMAND_HANDLER(psoc6_handle_mass_erase_command)
Performs Mass Erase operation.
Definition: psoc6.c:861
#define MEM_BASE_MFLASH
Definition: psoc6.c:29
static bool is_sflash_bank(struct flash_bank *bank)
Checks if given flash bank belongs to Supervisory Flash.
Definition: psoc6.c:514
#define SROMAPI_DATA_LOCATION_MSK
Definition: psoc6.c:72
#define MFLASH_SECTOR_SIZE
Definition: psoc6.c:26
static int psoc6_protect_check(struct flash_bank *bank)
Translates Protection status to openocd-friendly boolean value.
Definition: psoc6.c:413
static int get_silicon_id(struct target *target, uint32_t *si_id, uint8_t *protection)
Retrieves SiliconID and Protection status of the target device.
Definition: psoc6.c:378
#define PROTECTION_UNKNOWN
Definition: psoc6.c:36
#define PROTECTION_NORMAL
Definition: psoc6.c:38
static int psoc6_program_row(struct flash_bank *bank, uint32_t addr, const uint8_t *buffer, bool is_sflash)
Programs single Flash Row.
Definition: psoc6.c:760
#define MEM_IPC_DATA(n)
Definition: psoc6.c:47
static int psoc6_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last)
Dummy function, Life Cycle transition is not currently supported.
Definition: psoc6.c:446
#define RAM_STACK_WA_SIZE
Definition: psoc6.c:33
#define MEM_WFLASH_SIZE
Definition: psoc6.c:31
#define SROMAPI_SIID_REQ_FAMILY_REVISION
Definition: psoc6.c:62
#define SROMAPI_ERASESECTOR_REQ
Definition: psoc6.c:66
static int psoc6_get_info(struct flash_bank *bank, struct command_invocation *cmd)
psoc6_get_info Displays human-readable information about acquired device
Definition: psoc6.c:486
#define IPC_TIMEOUT_MS
Definition: psoc6.c:59
static const char * protection_to_str(uint8_t protection)
Translates Protection status to string.
Definition: psoc6.c:463
static bool is_mflash_bank(struct flash_bank *bank)
Checks if given flash bank belongs to Main Flash.
Definition: psoc6.c:539
static const struct command_registration psoc6_command_handlers[]
Definition: psoc6.c:1012
static const struct command_registration psoc6_exec_command_handlers[]
Definition: psoc6.c:994
static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_expected)
Waits for expected IPC lock status.
Definition: psoc6.c:222
static int ipc_acquire(struct target *target, char ipc_id)
Acquires IPC structure.
Definition: psoc6.c:268
uint8_t protection
Definition: qn908x.c:1
#define MIN(a, b)
Definition: replacements.h:22
target_addr_t addr
Start address to search for the control block.
Definition: rtt/rtt.c:28
struct adiv5_dap * dap
DAP this AP belongs to.
Definition: arm_adi_v5.h:254
enum arm_arch arch
ARM architecture version.
Definition: arm.h:202
unsigned int common_magic
Definition: armv7m.h:295
enum arm_mode core_mode
Definition: armv7m.h:297
struct arm arm
Definition: armv7m.h:225
struct adiv5_ap * debug_ap
Definition: armv7m.h:230
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
const char * name
Definition: command.h:235
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
Definition: nor/driver.h:39
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
Definition: nor/driver.h:44
Describes the geometry and status of a single flash sector within a flash bank.
Definition: nor/core.h:28
uint32_t main_flash_sz
Definition: psoc6.c:78
uint8_t protection
Definition: psoc6.c:77
bool is_probed
Definition: psoc6.c:80
uint32_t row_sz
Definition: psoc6.c:79
uint32_t silicon_id
Definition: psoc6.c:76
uint8_t * value
Definition: algorithm.h:30
uint32_t addr
Definition: psoc6.c:89
size_t size
Definition: psoc6.c:90
Definition: target.h:116
enum target_state state
Definition: target.h:157
bool running_alg
true if the target is currently running a downloaded "algorithm" instead of arbitrary user code.
Definition: target.h:140
Definition: psoc6.c:83
long timeout_ms
Definition: psoc6.c:85
int64_t start_time
Definition: psoc6.c:84
uint32_t size
Definition: target.h:87
target_addr_t address
Definition: target.h:86
int target_halt(struct target *target)
Definition: target.c:507
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2342
int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
Definition: target.c:2060
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2641
int target_free_working_area(struct target *target, struct working_area *area)
Free a working area.
Definition: target.c:2118
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2550
int target_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
Waits for an algorithm started with target_start_algorithm() to complete.
Definition: target.c:858
int target_wait_state(struct target *target, enum target_state state, unsigned int ms)
Definition: target.c:3214
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:458
int target_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, target_addr_t entry_point, target_addr_t exit_point, void *arch_info)
Executes a target-specific native code algorithm and leaves it running.
Definition: target.c:814
@ TARGET_HALTED
Definition: target.h:56
#define ERROR_TARGET_TIMEOUT
Definition: target.h:789
#define ERROR_TARGET_FAILURE
Definition: target.h:791
int64_t timeval_ms(void)
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9
uint8_t count[4]
Definition: vdebug.c:22