1 /***************************************************************************
3 * Copyright (C) 2017 by Bohdan Tymkiv *
4 * bohdan.tymkiv@cypress.com bohdan200@gmail.com *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
27 #include "target/target.h"
28 #include "target/cortex_m.h"
29 #include "target/breakpoints.h"
30 #include "target/target_type.h"
31 #include "time_support.h"
32 #include "target/algorithm.h"
34 /**************************************************************************************************
35 * PSoC6 device definitions
36 *************************************************************************************************/
37 #define MFLASH_SECTOR_SIZE (256u * 1024u)
38 #define WFLASH_SECTOR_SIZE (32u * 1024u)
40 #define MEM_BASE_MFLASH 0x10000000u
41 #define MEM_BASE_WFLASH 0x14000000u
42 #define MEM_WFLASH_SIZE 32768u
43 #define MEM_BASE_SFLASH 0x16000000u
44 #define RAM_STACK_WA_SIZE 2048u
45 #define PSOC6_SPCIF_GEOMETRY 0x4025F00Cu
47 #define PROTECTION_UNKNOWN 0x00u
48 #define PROTECTION_VIRGIN 0x01u
49 #define PROTECTION_NORMAL 0x02u
50 #define PROTECTION_SECURE 0x03u
51 #define PROTECTION_DEAD 0x04u
53 #define MEM_BASE_IPC 0x40230000u
54 #define IPC_STRUCT_SIZE 0x20u
55 #define MEM_IPC(n) (MEM_BASE_IPC + (n) * IPC_STRUCT_SIZE)
56 #define MEM_IPC_ACQUIRE(n) (MEM_IPC(n) + 0x00u)
57 #define MEM_IPC_NOTIFY(n) (MEM_IPC(n) + 0x08u)
58 #define MEM_IPC_DATA(n) (MEM_IPC(n) + 0x0Cu)
59 #define MEM_IPC_LOCK_STATUS(n) (MEM_IPC(n) + 0x10u)
61 #define MEM_BASE_IPC_INTR 0x40231000u
62 #define IPC_INTR_STRUCT_SIZE 0x20u
63 #define MEM_IPC_INTR(n) (MEM_BASE_IPC_INTR + (n) * IPC_INTR_STRUCT_SIZE)
64 #define MEM_IPC_INTR_MASK(n) (MEM_IPC_INTR(n) + 0x08u)
65 #define IPC_ACQUIRE_SUCCESS_MSK 0x80000000u
66 #define IPC_LOCK_ACQUIRED_MSK 0x80000000u
69 #define IPC_INTR_ID 0u
70 #define IPC_TIMEOUT_MS 1000
72 #define SROMAPI_SIID_REQ 0x00000001u
73 #define SROMAPI_SIID_REQ_FAMILY_REVISION (SROMAPI_SIID_REQ | 0x000u)
74 #define SROMAPI_SIID_REQ_SIID_PROTECTION (SROMAPI_SIID_REQ | 0x100u)
75 #define SROMAPI_WRITEROW_REQ 0x05000100u
76 #define SROMAPI_PROGRAMROW_REQ 0x06000100u
77 #define SROMAPI_ERASESECTOR_REQ 0x14000100u
78 #define SROMAPI_ERASEALL_REQ 0x0A000100u
79 #define SROMAPI_ERASEROW_REQ 0x1C000100u
81 #define SROMAPI_STATUS_MSK 0xF0000000u
82 #define SROMAPI_STAT_SUCCESS 0xA0000000u
83 #define SROMAPI_DATA_LOCATION_MSK 0x00000001u
84 #define SROMAPI_CALL_TIMEOUT_MS 1500
86 struct psoc6_target_info {
89 uint32_t main_flash_sz;
104 static struct row_region safe_sflash_regions[] = {
105 {0x16000800, 0x800}, /* SFLASH: User Data */
106 {0x16001A00, 0x200}, /* SFLASH: NAR */
107 {0x16005A00, 0xC00}, /* SFLASH: Public Key */
108 {0x16007C00, 0x400}, /* SFLASH: TOC2 */
111 #define SFLASH_NUM_REGIONS (sizeof(safe_sflash_regions) / sizeof(safe_sflash_regions[0]))
113 static struct working_area *g_stack_area;
114 /**************************************************************************************************
115 * Initializes timeout_s structure with given timeout in milliseconds
116 *************************************************************************************************/
117 static void timeout_init(struct timeout *to, long timeout_ms)
119 to->start_time = timeval_ms();
120 to->timeout_ms = timeout_ms;
123 /**************************************************************************************************
124 * Returns true if given timeout_s object has expired
125 *************************************************************************************************/
126 static bool timeout_expired(struct timeout *to)
128 return (timeval_ms() - to->start_time) > to->timeout_ms;
131 /**************************************************************************************************
132 * Prepares PSoC6 for running pseudo flash algorithm. This function allocates Working Area for
133 * the algorithm and for CPU Stack.
134 *************************************************************************************************/
135 static int sromalgo_prepare(struct target *target)
139 /* Initialize Vector Table Offset register (in case FW modified it) */
140 hr = target_write_u32(target, 0xE000ED08, 0x00000000);
144 /* Allocate Working Area for Stack and Flash algorithm */
145 hr = target_alloc_working_area(target, RAM_STACK_WA_SIZE, &g_stack_area);
149 /* Restore THUMB bit in xPSR register */
150 const struct armv7m_common *cm = target_to_armv7m(target);
151 hr = cm->store_core_reg_u32(target, ARMV7M_xPSR, 0x01000000);
158 /* Something went wrong, free allocated area */
160 target_free_working_area(target, g_stack_area);
167 /**************************************************************************************************
168 * Releases working area
169 *************************************************************************************************/
170 static int sromalgo_release(struct target *target)
174 /* Free Stack/Flash algorithm working area */
176 hr = target_free_working_area(target, g_stack_area);
183 /**************************************************************************************************
184 * Runs pseudo flash algorithm. Algorithm itself consist of couple of NOPs followed by BKPT
185 * instruction. The trick here is that NMI has already been posted to CM0 via IPC structure
186 * prior to calling this function. CM0 will immediately jump to NMI handler and execute
188 * This approach is borrowed from PSoC4 Flash Driver.
189 *************************************************************************************************/
190 static int sromalgo_run(struct target *target)
194 struct armv7m_algorithm armv7m_info;
195 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
196 armv7m_info.core_mode = ARM_MODE_THREAD;
198 struct reg_param reg_params;
199 init_reg_param(®_params, "sp", 32, PARAM_OUT);
200 buf_set_u32(reg_params.value, 0, 32, g_stack_area->address + g_stack_area->size);
202 /* mov r8, r8; mov r8, r8 */
203 hr = target_write_u32(target, g_stack_area->address + 0, 0x46C046C0);
207 /* mov r8, r8; bkpt #0 */
208 hr = target_write_u32(target, g_stack_area->address + 4, 0xBE0046C0);
212 hr = target_run_algorithm(target, 0, NULL, 1, ®_params, g_stack_area->address,
213 0, SROMAPI_CALL_TIMEOUT_MS, &armv7m_info);
215 destroy_reg_param(®_params);
220 /**************************************************************************************************
221 * Waits for expected IPC lock status.
222 * PSoC6 uses IPC structures for inter-core communication. Same IPCs are used to invoke SROM API.
223 * IPC structure must be locked prior to invoking any SROM API. This ensures nothing else in the
224 * system will use same IPC thus corrupting our data. Locking is performed by ipc_acquire(), this
225 * function ensures that IPC is actually in expected state
226 *************************************************************************************************/
227 static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_expected)
233 timeout_init(&to, IPC_TIMEOUT_MS);
235 while (!timeout_expired(&to)) {
236 /* Process any server requests */
239 /* Read IPC Lock status */
240 hr = target_read_u32(target, MEM_IPC_LOCK_STATUS(ipc_id), ®_val);
241 if (hr != ERROR_OK) {
242 LOG_ERROR("Unable to read IPC Lock Status register");
246 bool is_locked = (reg_val & IPC_LOCK_ACQUIRED_MSK) != 0;
248 if (lock_expected == is_locked)
252 if (target->coreid) {
253 LOG_WARNING("SROM API calls via CM4 target are supported on single-core PSoC6 devices only. "
254 "Please perform all Flash-related operations via CM0+ target on dual-core devices.");
257 LOG_ERROR("Timeout polling IPC Lock Status");
258 return ERROR_TARGET_TIMEOUT;
261 /**************************************************************************************************
262 * Acquires IPC structure
263 * PSoC6 uses IPC structures for inter-core communication. Same IPCs are used to invoke SROM API.
264 * IPC structure must be locked prior to invoking any SROM API. This ensures nothing else in the
265 * system will use same IPC thus corrupting our data. This function locks the IPC.
266 *************************************************************************************************/
267 static int ipc_acquire(struct target *target, char ipc_id)
270 bool is_acquired = false;
274 timeout_init(&to, IPC_TIMEOUT_MS);
276 while (!timeout_expired(&to)) {
279 hr = target_write_u32(target, MEM_IPC_ACQUIRE(ipc_id), IPC_ACQUIRE_SUCCESS_MSK);
280 if (hr != ERROR_OK) {
281 LOG_ERROR("Unable to write to IPC Acquire register");
285 /* Check if data is written on first step */
286 hr = target_read_u32(target, MEM_IPC_ACQUIRE(ipc_id), ®_val);
287 if (hr != ERROR_OK) {
288 LOG_ERROR("Unable to read IPC Acquire register");
292 is_acquired = (reg_val & IPC_ACQUIRE_SUCCESS_MSK) != 0;
294 /* If IPC structure is acquired, the lock status should be set */
295 hr = ipc_poll_lock_stat(target, ipc_id, true);
301 LOG_ERROR("Timeout acquiring IPC structure");
306 /**************************************************************************************************
307 * Invokes SROM API functions which are responsible for Flash operations
308 *************************************************************************************************/
309 static int call_sromapi(struct target *target,
310 uint32_t req_and_params,
311 uint32_t working_area,
316 bool is_data_in_ram = (req_and_params & SROMAPI_DATA_LOCATION_MSK) == 0;
318 hr = ipc_acquire(target, IPC_ID);
323 hr = target_write_u32(target, MEM_IPC_DATA(IPC_ID), working_area);
325 hr = target_write_u32(target, MEM_IPC_DATA(IPC_ID), req_and_params);
330 /* Enable notification interrupt of IPC_INTR_STRUCT0(CM0+) for IPC_STRUCT2 */
331 hr = target_write_u32(target, MEM_IPC_INTR_MASK(IPC_INTR_ID), 1u << (16 + IPC_ID));
335 hr = target_write_u32(target, MEM_IPC_NOTIFY(IPC_ID), 1);
339 hr = sromalgo_run(target);
343 /* Poll lock status */
344 hr = ipc_poll_lock_stat(target, IPC_ID, false);
350 hr = target_read_u32(target, working_area, data_out);
352 hr = target_read_u32(target, MEM_IPC_DATA(IPC_ID), data_out);
354 if (hr != ERROR_OK) {
355 LOG_ERROR("Error reading SROM API Status location");
359 bool is_success = (*data_out & SROMAPI_STATUS_MSK) == SROMAPI_STAT_SUCCESS;
361 LOG_ERROR("SROM API execution failed. Status: 0x%08X", (uint32_t)*data_out);
362 return ERROR_TARGET_FAILURE;
368 /**************************************************************************************************
369 * Retrieves SiliconID and Protection status of the target device
370 *************************************************************************************************/
371 static int get_silicon_id(struct target *target, uint32_t *si_id, uint8_t *protection)
374 uint32_t family_rev, siid_prot;
376 hr = sromalgo_prepare(target);
380 /* Read FamilyID and Revision */
381 hr = call_sromapi(target, SROMAPI_SIID_REQ_FAMILY_REVISION, 0, &family_rev);
385 /* Read SiliconID and Protection */
386 hr = call_sromapi(target, SROMAPI_SIID_REQ_SIID_PROTECTION, 0, &siid_prot);
390 *si_id = (siid_prot & 0x0000FFFF) << 16;
391 *si_id |= (family_rev & 0x00FF0000) >> 8;
392 *si_id |= (family_rev & 0x000000FF) >> 0;
394 *protection = (siid_prot & 0x000F0000) >> 0x10;
396 hr = sromalgo_release(target);
400 /**************************************************************************************************
401 * Translates Protection status to openocd-friendly boolean value
402 *************************************************************************************************/
403 static int psoc6_protect_check(struct flash_bank *bank)
407 struct psoc6_target_info *psoc6_info = bank->driver_priv;
408 int hr = get_silicon_id(bank->target, &psoc6_info->silicon_id, &psoc6_info->protection);
412 switch (psoc6_info->protection) {
413 case PROTECTION_VIRGIN:
414 case PROTECTION_NORMAL:
418 case PROTECTION_UNKNOWN:
419 case PROTECTION_SECURE:
420 case PROTECTION_DEAD:
426 for (int i = 0; i < bank->num_sectors; i++)
427 bank->sectors[i].is_protected = is_protected;
432 /**************************************************************************************************
433 * Life Cycle transition is not currently supported
434 *************************************************************************************************/
435 static int psoc6_protect(struct flash_bank *bank, int set, int first, int last)
442 LOG_WARNING("Life Cycle transition for PSoC6 is not supported");
446 /**************************************************************************************************
447 * Translates Protection status to string
448 *************************************************************************************************/
449 static const char *protection_to_str(uint8_t protection)
451 switch (protection) {
452 case PROTECTION_VIRGIN:
455 case PROTECTION_NORMAL:
458 case PROTECTION_SECURE:
461 case PROTECTION_DEAD:
464 case PROTECTION_UNKNOWN:
471 /**************************************************************************************************
472 * Displays human-readable information about acquired device
473 *************************************************************************************************/
474 static int psoc6_get_info(struct flash_bank *bank, char *buf, int buf_size)
476 struct psoc6_target_info *psoc6_info = bank->driver_priv;
478 if (psoc6_info->is_probed == false)
481 int hr = get_silicon_id(bank->target, &psoc6_info->silicon_id, &psoc6_info->protection);
485 snprintf(buf, buf_size,
486 "PSoC6 Silicon ID: 0x%08X\n"
488 "Main Flash size: %d kB\n"
489 "Work Flash size: 32 kB\n",
490 psoc6_info->silicon_id,
491 protection_to_str(psoc6_info->protection),
492 psoc6_info->main_flash_sz / 1024);
497 /**************************************************************************************************
498 * Returns true if flash bank name represents Supervisory Flash
499 *************************************************************************************************/
500 static bool is_sflash_bank(struct flash_bank *bank)
502 for (size_t i = 0; i < SFLASH_NUM_REGIONS; i++) {
503 if (bank->base == safe_sflash_regions[i].addr)
510 /**************************************************************************************************
511 * Returns true if flash bank name represents Work Flash
512 *************************************************************************************************/
513 static inline bool is_wflash_bank(struct flash_bank *bank)
515 return (bank->base == MEM_BASE_WFLASH);
518 /**************************************************************************************************
519 * Returns true if flash bank name represents Main Flash
520 *************************************************************************************************/
521 static inline bool is_mflash_bank(struct flash_bank *bank)
523 return (bank->base == MEM_BASE_MFLASH);
526 /**************************************************************************************************
527 * Probes the device and populates related data structures with target flash geometry data.
528 * This is done in non-intrusive way, no SROM API calls are involved so GDB can safely attach to a
530 * Function assumes that size of Work Flash is 32kB (true for all current part numbers)
531 *************************************************************************************************/
532 static int psoc6_probe(struct flash_bank *bank)
534 struct target *target = bank->target;
535 struct psoc6_target_info *psoc6_info = bank->driver_priv;
539 /* Retrieve data from SPCIF_GEOMATRY */
541 target_read_u32(target, PSOC6_SPCIF_GEOMETRY, &geom);
542 uint32_t row_sz_lg2 = (geom & 0xF0) >> 4;
543 uint32_t row_sz = (0x01 << row_sz_lg2);
544 uint32_t row_cnt = 1 + ((geom & 0x00FFFF00) >> 8);
545 uint32_t bank_cnt = 1 + ((geom & 0xFF000000) >> 24);
547 /* Calculate size of Main Flash*/
548 uint32_t flash_sz_bytes = bank_cnt * row_cnt * row_sz;
552 bank->sectors = NULL;
555 size_t bank_size = 0;
557 if (is_mflash_bank(bank))
558 bank_size = flash_sz_bytes;
559 else if (is_wflash_bank(bank))
560 bank_size = MEM_WFLASH_SIZE;
561 else if (is_sflash_bank(bank)) {
562 for (size_t i = 0; i < SFLASH_NUM_REGIONS; i++) {
563 if (safe_sflash_regions[i].addr == bank->base) {
564 bank_size = safe_sflash_regions[i].size;
570 if (bank_size == 0) {
571 LOG_ERROR("Invalid Flash Bank base address in config file");
572 return ERROR_FLASH_BANK_INVALID;
575 size_t num_sectors = bank_size / row_sz;
576 bank->size = bank_size;
577 bank->chip_width = 4;
579 bank->erased_value = 0;
580 bank->default_padded_value = 0;
582 bank->num_sectors = num_sectors;
583 bank->sectors = calloc(num_sectors, sizeof(struct flash_sector));
584 for (size_t i = 0; i < num_sectors; i++) {
585 bank->sectors[i].size = row_sz;
586 bank->sectors[i].offset = i * row_sz;
587 bank->sectors[i].is_erased = -1;
588 bank->sectors[i].is_protected = -1;
591 psoc6_info->is_probed = true;
592 psoc6_info->main_flash_sz = flash_sz_bytes;
593 psoc6_info->row_sz = row_sz;
598 /**************************************************************************************************
599 * Probes target device only if it hasn't been probed yet
600 *************************************************************************************************/
601 static int psoc6_auto_probe(struct flash_bank *bank)
603 struct psoc6_target_info *psoc6_info = bank->driver_priv;
606 if (psoc6_info->is_probed)
609 hr = psoc6_probe(bank);
614 /**************************************************************************************************
615 * Erases single sector (256k) on target device
616 *************************************************************************************************/
617 static int psoc6_erase_sector(struct flash_bank *bank, struct working_area *wa, uint32_t addr)
619 struct target *target = bank->target;
621 LOG_DEBUG("Erasing SECTOR @%08X", addr);
623 int hr = target_write_u32(target, wa->address, SROMAPI_ERASESECTOR_REQ);
627 hr = target_write_u32(target, wa->address + 0x04, addr);
632 hr = call_sromapi(target, SROMAPI_ERASESECTOR_REQ, wa->address, &data_out);
634 LOG_ERROR("SECTOR @%08X not erased!", addr);
639 /**************************************************************************************************
640 * Erases single row (512b) on target device
641 *************************************************************************************************/
642 static int psoc6_erase_row(struct flash_bank *bank, struct working_area *wa, uint32_t addr)
644 struct target *target = bank->target;
646 LOG_DEBUG("Erasing ROW @%08X", addr);
648 int hr = target_write_u32(target, wa->address, SROMAPI_ERASEROW_REQ);
652 hr = target_write_u32(target, wa->address + 0x04, addr);
657 hr = call_sromapi(target, SROMAPI_ERASEROW_REQ, wa->address, &data_out);
659 LOG_ERROR("ROW @%08X not erased!", addr);
664 /**************************************************************************************************
665 * Performs Erase operation.
666 * Function will try to use biggest erase block possible to speedup the operation
667 *************************************************************************************************/
668 static int psoc6_erase(struct flash_bank *bank, int first, int last)
670 struct target *target = bank->target;
671 struct psoc6_target_info *psoc6_info = bank->driver_priv;
672 const uint32_t sector_size = is_wflash_bank(bank) ? WFLASH_SECTOR_SIZE : MFLASH_SECTOR_SIZE;
675 struct working_area *wa;
677 if (is_sflash_bank(bank)) {
678 LOG_INFO("Erase operation on Supervisory Flash is not required, skipping");
682 hr = sromalgo_prepare(target);
686 hr = target_alloc_working_area(target, psoc6_info->row_sz + 32, &wa);
690 /* Number of rows in single sector */
691 const int rows_in_sector = sector_size / psoc6_info->row_sz;
693 while (last >= first) {
694 /* Erase Sector if we are on sector boundary and erase size covers whole sector */
695 if ((first % rows_in_sector) == 0 &&
696 (last - first + 1) >= rows_in_sector) {
697 hr = psoc6_erase_sector(bank, wa, bank->base + first * psoc6_info->row_sz);
701 for (int i = first; i < first + rows_in_sector; i++)
702 bank->sectors[i].is_erased = 1;
704 first += rows_in_sector;
706 /* Perform Row Erase otherwise */
707 hr = psoc6_erase_row(bank, wa, bank->base + first * psoc6_info->row_sz);
711 bank->sectors[first].is_erased = 1;
717 target_free_working_area(target, wa);
719 sromalgo_release(target);
724 /**************************************************************************************************
725 * Programs single Flash Row
726 *************************************************************************************************/
727 static int psoc6_program_row(struct flash_bank *bank,
729 const uint8_t *buffer,
732 struct target *target = bank->target;
733 struct psoc6_target_info *psoc6_info = bank->driver_priv;
734 struct working_area *wa;
735 const uint32_t sromapi_req = is_sflash ? SROMAPI_WRITEROW_REQ : SROMAPI_PROGRAMROW_REQ;
739 LOG_DEBUG("Programming ROW @%08X", addr);
741 hr = target_alloc_working_area(target, psoc6_info->row_sz + 32, &wa);
745 hr = target_write_u32(target, wa->address, sromapi_req);
749 hr = target_write_u32(target,
755 hr = target_write_u32(target, wa->address + 0x08, addr);
759 hr = target_write_u32(target, wa->address + 0x0C, wa->address + 0x10);
763 hr = target_write_buffer(target, wa->address + 0x10, psoc6_info->row_sz, buffer);
767 hr = call_sromapi(target, sromapi_req, wa->address, &data_out);
770 target_free_working_area(target, wa);
777 /**************************************************************************************************
778 * Programs set of Rows
779 *************************************************************************************************/
780 static int psoc6_program(struct flash_bank *bank,
781 const uint8_t *buffer,
785 struct target *target = bank->target;
786 struct psoc6_target_info *psoc6_info = bank->driver_priv;
787 const bool is_sflash = is_sflash_bank(bank);
790 hr = sromalgo_prepare(target);
794 uint8_t page_buf[psoc6_info->row_sz];
797 uint32_t row_offset = offset % psoc6_info->row_sz;
798 uint32_t aligned_addr = bank->base + offset - row_offset;
799 uint32_t row_bytes = MIN(psoc6_info->row_sz - row_offset, count);
801 memset(page_buf, 0, sizeof(page_buf));
802 memcpy(&page_buf[row_offset], buffer, row_bytes);
804 hr = psoc6_program_row(bank, aligned_addr, page_buf, is_sflash);
805 if (hr != ERROR_OK) {
806 LOG_ERROR("Failed to program Flash at address 0x%08X", aligned_addr);
815 hr = sromalgo_release(target);
819 /**************************************************************************************************
820 * Performs Mass Erase of given flash bank
821 * Syntax: psoc6 mass_erase bank_id
822 *************************************************************************************************/
823 COMMAND_HANDLER(psoc6_handle_mass_erase_command)
826 return ERROR_COMMAND_SYNTAX_ERROR;
828 struct flash_bank *bank;
829 int hr = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
833 hr = psoc6_erase(bank, 0, bank->num_sectors - 1);
838 /**************************************************************************************************
839 * Simulates broken Vector Catch
840 * Function will try to determine entry point of user application. If it succeeds it will set HW
841 * breakpoint at that address, issue SW Reset and remove the breakpoint afterwards.
842 * In case of CM0, SYSRESETREQ is used. This allows to reset all peripherals. Boot code will
843 * reset CM4 anyway, so using SYSRESETREQ is safe here.
844 * In case of CM4, VECTRESET is used instead of SYSRESETREQ to not disturb CM0 core.
845 *************************************************************************************************/
846 int handle_reset_halt(struct target *target)
850 bool is_cm0 = (target->coreid == 0);
852 /* Halt target device */
853 if (target->state != TARGET_HALTED) {
854 hr = target_halt(target);
858 target_wait_state(target, TARGET_HALTED, IPC_TIMEOUT_MS);
863 /* Read Vector Offset register */
865 const uint32_t vt_offset_reg = is_cm0 ? 0x402102B0 : 0x402102C0;
866 hr = target_read_u32(target, vt_offset_reg, &vt_base);
870 /* Invalid value means flash is empty */
871 vt_base &= 0xFFFFFF00;
872 if ((vt_base == 0) || (vt_base == 0xFFFFFF00))
875 /* Read Reset Vector value*/
876 hr = target_read_u32(target, vt_base + 4, &reset_addr);
880 /* Invalid value means flash is empty */
881 if ((reset_addr == 0) || (reset_addr == 0xFFFFFF00))
885 /* Set breakpoint at User Application entry point */
886 hr = breakpoint_add(target, reset_addr, 2, BKPT_HARD);
890 const struct armv7m_common *cm = target_to_armv7m(target);
893 /* Reset the CM0 by asserting SYSRESETREQ. This will also reset CM4 */
894 LOG_INFO("psoc6.cm0: bkpt @0x%08X, issuing SYSRESETREQ", reset_addr);
895 hr = mem_ap_write_atomic_u32(cm->debug_ap,
897 AIRCR_VECTKEY | AIRCR_SYSRESETREQ);
899 /* Wait for bootcode and initialize DAP */
901 dap_dp_init(cm->debug_ap->dap);
903 LOG_INFO("psoc6.cm4: bkpt @0x%08X, issuing VECTRESET", reset_addr);
904 hr = mem_ap_write_atomic_u32(cm->debug_ap,
906 AIRCR_VECTKEY | AIRCR_VECTRESET);
911 target_wait_state(target, TARGET_HALTED, IPC_TIMEOUT_MS);
913 /* Remove the break point */
914 breakpoint_remove(target, reset_addr);
919 COMMAND_HANDLER(psoc6_handle_reset_halt)
922 return ERROR_COMMAND_SYNTAX_ERROR;
924 struct target *target = get_current_target(CMD_CTX);
925 return handle_reset_halt(target);
928 FLASH_BANK_COMMAND_HANDLER(psoc6_flash_bank_command)
930 struct psoc6_target_info *psoc6_info;
934 hr = ERROR_COMMAND_SYNTAX_ERROR;
936 psoc6_info = calloc(1, sizeof(struct psoc6_target_info));
937 psoc6_info->is_probed = false;
938 bank->driver_priv = psoc6_info;
943 static const struct command_registration psoc6_exec_command_handlers[] = {
945 .name = "mass_erase",
946 .handler = psoc6_handle_mass_erase_command,
947 .mode = COMMAND_EXEC,
949 .help = "Erases entire Main Flash",
952 .name = "reset_halt",
953 .handler = psoc6_handle_reset_halt,
954 .mode = COMMAND_EXEC,
956 .help = "Tries to simulate broken Vector Catch",
958 COMMAND_REGISTRATION_DONE
961 static const struct command_registration psoc6_command_handlers[] = {
965 .help = "PSoC 6 flash command group",
967 .chain = psoc6_exec_command_handlers,
969 COMMAND_REGISTRATION_DONE
972 struct flash_driver psoc6_flash = {
974 .commands = psoc6_command_handlers,
975 .flash_bank_command = psoc6_flash_bank_command,
976 .erase = psoc6_erase,
977 .protect = psoc6_protect,
978 .write = psoc6_program,
979 .read = default_flash_read,
980 .probe = psoc6_probe,
981 .auto_probe = psoc6_auto_probe,
982 .erase_check = default_flash_blank_check,
983 .protect_check = psoc6_protect_check,
984 .info = psoc6_get_info,