From 4440bf1fcddce3501781496e2d6a9d0f12cba08d Mon Sep 17 00:00:00 2001 From: Bohdan Tymkiv Date: Wed, 21 Mar 2018 16:13:28 +0200 Subject: [PATCH] psoc6: Run flash algorithm asynchronously to improve performance Existing psoc6 driver starts flash algorithm for each Flash row. This is suboptimal from performance point of view, starting/stopping flash algorithm for each row adds significant overhead. This change starts flash algorithm and leaves it running asynchronously while driver performs flash operations. Performance gain is 170...250% depending on probe: flash write_image img_256k.bin | w/o this change | with this change | ----------------------------------|-----------------|------------------| KitProg2/CMSIS-DAP, SWD @ 1 MHz | 4 KiB/s | 10 KiB/s | J-Link Ultra, SWD @ 1 MHz | 17 KiB/s | 31 KiB/s | J-Link Ultra, SWD @ 4 MHz | 33 KiB/s | 57 KiB/s | Change-Id: I5bd582584b35af67600c4d197829eb7aeeec7e3f Signed-off-by: Bohdan Tymkiv Reviewed-on: http://openocd.zylin.com/4472 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/psoc6.c | 361 +++++++++++++++++++++++++----------------- tcl/target/psoc6.cfg | 17 +- 2 files changed, 236 insertions(+), 142 deletions(-) diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index e5c4197642..9352ad41b5 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -1,6 +1,6 @@ /*************************************************************************** * * - * Copyright (C) 2017 by Bohdan Tymkiv * + * Copyright (C) 2018 by Bohdan Tymkiv * * bohdan.tymkiv@cypress.com bohdan200@gmail.com * * * * This program is free software; you can redistribute it and/or modify * @@ -101,7 +101,7 @@ struct row_region { size_t size; }; -static struct row_region safe_sflash_regions[] = { +static const struct row_region safe_sflash_regions[] = { {0x16000800, 0x800}, /* SFLASH: User Data */ {0x16001A00, 0x200}, /* SFLASH: NAR */ {0x16005A00, 0xC00}, /* SFLASH: Public Key */ @@ -111,8 +111,12 @@ static struct row_region safe_sflash_regions[] = { #define SFLASH_NUM_REGIONS (sizeof(safe_sflash_regions) / sizeof(safe_sflash_regions[0])) static struct working_area *g_stack_area; -/************************************************************************************************** - * Initializes timeout_s structure with given timeout in milliseconds +static struct armv7m_algorithm g_armv7m_info; + +/** *********************************************************************************************** + * @brief Initializes `struct timeout` structure with given timeout value + * @param to pointer to `struct timeout` structure + * @param timeout_ms timeout, in milliseconds *************************************************************************************************/ static void timeout_init(struct timeout *to, long timeout_ms) { @@ -120,17 +124,23 @@ static void timeout_init(struct timeout *to, long timeout_ms) to->timeout_ms = timeout_ms; } -/************************************************************************************************** - * Returns true if given timeout_s object has expired +/** *********************************************************************************************** + * @brief Returns true if given `struct timeout` structure has expired + * @param to pointer to `struct timeout` structure + * @return true if timeout expired *************************************************************************************************/ static bool timeout_expired(struct timeout *to) { return (timeval_ms() - to->start_time) > to->timeout_ms; } -/************************************************************************************************** - * Prepares PSoC6 for running pseudo flash algorithm. This function allocates Working Area for - * the algorithm and for CPU Stack. +/** *********************************************************************************************** + * @brief Starts pseudo flash algorithm and leaves it running. Function allocates working area for + * algorithm code and CPU stack, adjusts stack pointer, uploads and starts the algorithm. + * Algorithm (a basic infinite loop) runs asynchronously while driver performs Flash operations. + * + * @param target target for the algorithm + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int sromalgo_prepare(struct target *target) { @@ -141,88 +151,92 @@ static int sromalgo_prepare(struct target *target) if (hr != ERROR_OK) return hr; + /* Restore THUMB bit in xPSR register */ + const struct armv7m_common *cm = target_to_armv7m(target); + hr = cm->store_core_reg_u32(target, ARMV7M_xPSR, 0x01000000); + if (hr != ERROR_OK) + return hr; + /* Allocate Working Area for Stack and Flash algorithm */ hr = target_alloc_working_area(target, RAM_STACK_WA_SIZE, &g_stack_area); if (hr != ERROR_OK) return hr; - /* Restore THUMB bit in xPSR register */ - const struct armv7m_common *cm = target_to_armv7m(target); - hr = cm->store_core_reg_u32(target, ARMV7M_xPSR, 0x01000000); + g_armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + g_armv7m_info.core_mode = ARM_MODE_THREAD; + + struct reg_param reg_params; + init_reg_param(®_params, "sp", 32, PARAM_OUT); + buf_set_u32(reg_params.value, 0, 32, g_stack_area->address + g_stack_area->size); + + /* Write basic infinite loop algorithm to target RAM */ + hr = target_write_u32(target, g_stack_area->address, 0xFEE7FEE7); if (hr != ERROR_OK) - goto exit_free_wa; + goto destroy_rp_free_wa; - return ERROR_OK; + hr = target_start_algorithm(target, 0, NULL, 1, ®_params, g_stack_area->address, + 0, &g_armv7m_info); + if (hr != ERROR_OK) + goto destroy_rp_free_wa; -exit_free_wa: - /* Something went wrong, free allocated area */ - if (g_stack_area) { - target_free_working_area(target, g_stack_area); - g_stack_area = NULL; - } + destroy_reg_param(®_params); return hr; -} -/************************************************************************************************** - * Releases working area - *************************************************************************************************/ -static int sromalgo_release(struct target *target) -{ - int hr = ERROR_OK; +destroy_rp_free_wa: + /* Something went wrong, do some cleanup */ + destroy_reg_param(®_params); - /* Free Stack/Flash algorithm working area */ if (g_stack_area) { - hr = target_free_working_area(target, g_stack_area); + target_free_working_area(target, g_stack_area); g_stack_area = NULL; } return hr; } -/************************************************************************************************** - * Runs pseudo flash algorithm. Algorithm itself consist of couple of NOPs followed by BKPT - * instruction. The trick here is that NMI has already been posted to CM0 via IPC structure - * prior to calling this function. CM0 will immediately jump to NMI handler and execute - * SROM API code. - * This approach is borrowed from PSoC4 Flash Driver. +/** *********************************************************************************************** + * @brief Stops running flash algorithm and releases associated resources. + * This function is also used for cleanup in case of errors so g_stack_area may be NULL. + * These cases have to be handled gracefully. + * + * @param target current target *************************************************************************************************/ -static int sromalgo_run(struct target *target) +static void sromalgo_release(struct target *target) { - int hr; - - struct armv7m_algorithm armv7m_info; - armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARM_MODE_THREAD; - - struct reg_param reg_params; - init_reg_param(®_params, "sp", 32, PARAM_OUT); - buf_set_u32(reg_params.value, 0, 32, g_stack_area->address + g_stack_area->size); - - /* mov r8, r8; mov r8, r8 */ - hr = target_write_u32(target, g_stack_area->address + 0, 0x46C046C0); - if (hr != ERROR_OK) - return hr; - - /* mov r8, r8; bkpt #0 */ - hr = target_write_u32(target, g_stack_area->address + 4, 0xBE0046C0); - if (hr != ERROR_OK) - return hr; + int hr = ERROR_OK; - hr = target_run_algorithm(target, 0, NULL, 1, ®_params, g_stack_area->address, - 0, SROMAPI_CALL_TIMEOUT_MS, &armv7m_info); + if (g_stack_area) { + /* Stop flash algorithm if it is running */ + if (target->running_alg) { + hr = target_halt(target); + if (hr != ERROR_OK) + goto exit_free_wa; - destroy_reg_param(®_params); + hr = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, + IPC_TIMEOUT_MS, &g_armv7m_info); + if (hr != ERROR_OK) + goto exit_free_wa; + } - return hr; +exit_free_wa: + /* Free Stack/Flash algorithm working area */ + target_free_working_area(target, g_stack_area); + g_stack_area = NULL; + } } -/************************************************************************************************** - * Waits for expected IPC lock status. - * PSoC6 uses IPC structures for inter-core communication. Same IPCs are used to invoke SROM API. - * IPC structure must be locked prior to invoking any SROM API. This ensures nothing else in the - * system will use same IPC thus corrupting our data. Locking is performed by ipc_acquire(), this - * function ensures that IPC is actually in expected state +/** *********************************************************************************************** + * @brief Waits for expected IPC lock status. PSoC6 uses IPC structures for inter-core + * communication. Same IPCs are used to invoke SROM API. IPC structure must be locked prior to + * invoking any SROM API. This ensures nothing else in the system will use same IPC thus corrupting + * our data. Locking is performed by ipc_acquire(), this function ensures that IPC is actually + * in expected state + * + * @param target current target + * @param ipc_id IPC index to poll. IPC #2 is dedicated for DAP access + * @param lock_expected expected lock status + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_expected) { @@ -258,11 +272,15 @@ static int ipc_poll_lock_stat(struct target *target, uint32_t ipc_id, bool lock_ return ERROR_TARGET_TIMEOUT; } -/************************************************************************************************** - * Acquires IPC structure - * PSoC6 uses IPC structures for inter-core communication. Same IPCs are used to invoke SROM API. - * IPC structure must be locked prior to invoking any SROM API. This ensures nothing else in the - * system will use same IPC thus corrupting our data. This function locks the IPC. +/** *********************************************************************************************** + * @brief Acquires IPC structure. PSoC6 uses IPC structures for inter-core communication. + * Same IPCs are used to invoke SROM API. IPC structure must be locked prior to invoking any SROM API. + * This ensures nothing else in the system will use same IPC thus corrupting our data. + * This function locks the IPC. + * + * @param target current target + * @param ipc_id ipc_id IPC index to acquire. IPC #2 is dedicated for DAP access + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int ipc_acquire(struct target *target, char ipc_id) { @@ -303,8 +321,14 @@ static int ipc_acquire(struct target *target, char ipc_id) return hr; } -/************************************************************************************************** - * Invokes SROM API functions which are responsible for Flash operations +/** *********************************************************************************************** + * @brief Invokes SROM API functions which are responsible for Flash operations + * + * @param target current target + * @param req_and_params requect id of the function to invoke + * @param working_area address of memory buffer in target's memory space for SROM API parameters + * @param data_out pointer to variable which will be populated with execution status + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int call_sromapi(struct target *target, uint32_t req_and_params, @@ -336,10 +360,6 @@ static int call_sromapi(struct target *target, if (hr != ERROR_OK) return hr; - hr = sromalgo_run(target); - if (hr != ERROR_OK) - return hr; - /* Poll lock status */ hr = ipc_poll_lock_stat(target, IPC_ID, false); if (hr != ERROR_OK) @@ -365,8 +385,12 @@ static int call_sromapi(struct target *target, return ERROR_OK; } -/************************************************************************************************** - * Retrieves SiliconID and Protection status of the target device +/** *********************************************************************************************** + * @brief Retrieves SiliconID and Protection status of the target device + * @param target current target + * @param si_id pointer to variable, will be populated with SiliconID + * @param protection pointer to variable, will be populated with protection status + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int get_silicon_id(struct target *target, uint32_t *si_id, uint8_t *protection) { @@ -375,17 +399,17 @@ static int get_silicon_id(struct target *target, uint32_t *si_id, uint8_t *prote hr = sromalgo_prepare(target); if (hr != ERROR_OK) - return hr; + goto exit; /* Read FamilyID and Revision */ hr = call_sromapi(target, SROMAPI_SIID_REQ_FAMILY_REVISION, 0, &family_rev); if (hr != ERROR_OK) - return hr; + goto exit; /* Read SiliconID and Protection */ hr = call_sromapi(target, SROMAPI_SIID_REQ_SIID_PROTECTION, 0, &siid_prot); if (hr != ERROR_OK) - return hr; + goto exit; *si_id = (siid_prot & 0x0000FFFF) << 16; *si_id |= (family_rev & 0x00FF0000) >> 8; @@ -393,12 +417,15 @@ static int get_silicon_id(struct target *target, uint32_t *si_id, uint8_t *prote *protection = (siid_prot & 0x000F0000) >> 0x10; - hr = sromalgo_release(target); - return hr; +exit: + sromalgo_release(target); + return ERROR_OK; } -/************************************************************************************************** - * Translates Protection status to openocd-friendly boolean value +/** *********************************************************************************************** + * @brief Translates Protection status to openocd-friendly boolean value + * @param bank current flash bank + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_protect_check(struct flash_bank *bank) { @@ -429,8 +456,9 @@ static int psoc6_protect_check(struct flash_bank *bank) return ERROR_OK; } -/************************************************************************************************** - * Life Cycle transition is not currently supported +/** *********************************************************************************************** + * @brief Dummy function, Life Cycle transition is not currently supported + * @return ERROR_OK always *************************************************************************************************/ static int psoc6_protect(struct flash_bank *bank, int set, int first, int last) { @@ -443,8 +471,10 @@ static int psoc6_protect(struct flash_bank *bank, int set, int first, int last) return ERROR_OK; } -/************************************************************************************************** - * Translates Protection status to string +/** *********************************************************************************************** + * @brief Translates Protection status to string + * @param protection protection value + * @return pointer to const string describintg protection status *************************************************************************************************/ static const char *protection_to_str(uint8_t protection) { @@ -468,8 +498,12 @@ static const char *protection_to_str(uint8_t protection) } } -/************************************************************************************************** - * Displays human-readable information about acquired device +/** *********************************************************************************************** + * @brief psoc6_get_info Displays human-readable information about acquired device + * @param bank current flash bank + * @param buf pointer to buffer for human-readable text + * @param buf_size size of the buffer + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_get_info(struct flash_bank *bank, char *buf, int buf_size) { @@ -494,8 +528,10 @@ static int psoc6_get_info(struct flash_bank *bank, char *buf, int buf_size) return ERROR_OK; } -/************************************************************************************************** - * Returns true if flash bank name represents Supervisory Flash +/** *********************************************************************************************** + * @brief Checks if given flash bank belongs to Supervisory Flash + * @param bank current flash bank + * @return true if flash bank belongs to Supervisory Flash *************************************************************************************************/ static bool is_sflash_bank(struct flash_bank *bank) { @@ -507,27 +543,33 @@ static bool is_sflash_bank(struct flash_bank *bank) return false; } -/************************************************************************************************** - * Returns true if flash bank name represents Work Flash +/** *********************************************************************************************** + * @brief Checks if given flash bank belongs to Work Flash + * @param bank current flash bank + * @return true if flash bank belongs to Work Flash *************************************************************************************************/ static inline bool is_wflash_bank(struct flash_bank *bank) { return (bank->base == MEM_BASE_WFLASH); } -/************************************************************************************************** - * Returns true if flash bank name represents Main Flash +/** *********************************************************************************************** + * @brief Checks if given flash bank belongs to Main Flash + * @param bank current flash bank + * @return true if flash bank belongs to Main Flash *************************************************************************************************/ static inline bool is_mflash_bank(struct flash_bank *bank) { return (bank->base == MEM_BASE_MFLASH); } -/************************************************************************************************** - * Probes the device and populates related data structures with target flash geometry data. +/** *********************************************************************************************** + * @brief Probes the device and populates related data structures with target flash geometry data. * This is done in non-intrusive way, no SROM API calls are involved so GDB can safely attach to a - * running target. - * Function assumes that size of Work Flash is 32kB (true for all current part numbers) + * running target. Function assumes that size of Work Flash is 32kB (true for all current part numbers) + * + * @param bank current flash bank + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_probe(struct flash_bank *bank) { @@ -595,8 +637,10 @@ static int psoc6_probe(struct flash_bank *bank) return hr; } -/************************************************************************************************** - * Probes target device only if it hasn't been probed yet +/** *********************************************************************************************** + * @brief Probes target device only if it hasn't been probed yet + * @param bank current flash bank + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_auto_probe(struct flash_bank *bank) { @@ -611,8 +655,12 @@ static int psoc6_auto_probe(struct flash_bank *bank) return hr; } -/************************************************************************************************** - * Erases single sector (256k) on target device +/** *********************************************************************************************** + * @brief Erases single sector (256k) on target device + * @param bank current flash bank + * @param wa working area for SROM API parameters + * @param addr starting address of the sector + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_erase_sector(struct flash_bank *bank, struct working_area *wa, uint32_t addr) { @@ -636,8 +684,12 @@ static int psoc6_erase_sector(struct flash_bank *bank, struct working_area *wa, return hr; } -/************************************************************************************************** - * Erases single row (512b) on target device +/** *********************************************************************************************** + * @brief Erases single row (512b) on target device + * @param bank current flash bank + * @param wa working area for SROM API parameters + * @param addr starting address of the flash row + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_erase_row(struct flash_bank *bank, struct working_area *wa, uint32_t addr) { @@ -661,9 +713,14 @@ static int psoc6_erase_row(struct flash_bank *bank, struct working_area *wa, uin return hr; } -/************************************************************************************************** - * Performs Erase operation. - * Function will try to use biggest erase block possible to speedup the operation +/** *********************************************************************************************** + * @brief Performs Erase operation. Function will try to use biggest erase block possible to + * speedup the operation. + * + * @param bank current flash bank + * @param first first sector to erase + * @param last last sector to erase + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_erase(struct flash_bank *bank, int first, int last) { @@ -681,7 +738,7 @@ static int psoc6_erase(struct flash_bank *bank, int first, int last) hr = sromalgo_prepare(target); if (hr != ERROR_OK) - return hr; + goto exit; hr = target_alloc_working_area(target, psoc6_info->row_sz + 32, &wa); if (hr != ERROR_OK) @@ -720,9 +777,13 @@ exit: return hr; } - -/************************************************************************************************** - * Programs single Flash Row +/** *********************************************************************************************** + * @brief Programs single Flash Row + * @param bank current flash bank + * @param addr address of the flash row + * @param buffer pointer to the buffer with data + * @param is_sflash true if current flash bank belongs to Supervisory Flash + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_program_row(struct flash_bank *bank, uint32_t addr, @@ -773,9 +834,13 @@ exit: return hr; } - -/************************************************************************************************** - * Programs set of Rows +/** *********************************************************************************************** + * @brief Performs Program operation + * @param bank current flash bank + * @param buffer pointer to the buffer with data + * @param offset starting offset in falsh bank + * @param count number of bytes in buffer + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ static int psoc6_program(struct flash_bank *bank, const uint8_t *buffer, @@ -787,11 +852,11 @@ static int psoc6_program(struct flash_bank *bank, const bool is_sflash = is_sflash_bank(bank); int hr; + uint8_t page_buf[psoc6_info->row_sz]; + hr = sromalgo_prepare(target); if (hr != ERROR_OK) - return hr; - - uint8_t page_buf[psoc6_info->row_sz]; + goto exit; while (count) { uint32_t row_offset = offset % psoc6_info->row_sz; @@ -804,7 +869,7 @@ static int psoc6_program(struct flash_bank *bank, hr = psoc6_program_row(bank, aligned_addr, page_buf, is_sflash); if (hr != ERROR_OK) { LOG_ERROR("Failed to program Flash at address 0x%08X", aligned_addr); - break; + goto exit; } buffer += row_bytes; @@ -812,13 +877,15 @@ static int psoc6_program(struct flash_bank *bank, count -= row_bytes; } - hr = sromalgo_release(target); +exit: + sromalgo_release(target); return hr; } -/************************************************************************************************** - * Performs Mass Erase of given flash bank - * Syntax: psoc6 mass_erase bank_id +/** *********************************************************************************************** + * @brief Performs Mass Erase operation + * @param bank flash bank index to erase + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ COMMAND_HANDLER(psoc6_handle_mass_erase_command) { @@ -835,13 +902,16 @@ COMMAND_HANDLER(psoc6_handle_mass_erase_command) return hr; } -/************************************************************************************************** - * Simulates broken Vector Catch +/** *********************************************************************************************** + * @brief Simulates broken Vector Catch * Function will try to determine entry point of user application. If it succeeds it will set HW * breakpoint at that address, issue SW Reset and remove the breakpoint afterwards. * In case of CM0, SYSRESETREQ is used. This allows to reset all peripherals. Boot code will * reset CM4 anyway, so using SYSRESETREQ is safe here. * In case of CM4, VECTRESET is used instead of SYSRESETREQ to not disturb CM0 core. + * + * @param target current target + * @return ERROR_OK in case of success, ERROR_XXX code otherwise *************************************************************************************************/ int handle_reset_halt(struct target *target) { @@ -889,33 +959,42 @@ int handle_reset_halt(struct target *target) const struct armv7m_common *cm = target_to_armv7m(target); + /* PSoC6 reboots immediatelly after issuing SYSRESETREQ / VECTRESET + * this disables SWD/JTAG pins momentarily and may break communication + * Ignoring return value of mem_ap_write_atomic_u32 seems to be ok here */ if (is_cm0) { /* Reset the CM0 by asserting SYSRESETREQ. This will also reset CM4 */ LOG_INFO("psoc6.cm0: bkpt @0x%08X, issuing SYSRESETREQ", reset_addr); - hr = mem_ap_write_atomic_u32(cm->debug_ap, - NVIC_AIRCR, - AIRCR_VECTKEY | AIRCR_SYSRESETREQ); - - /* Wait for bootcode and initialize DAP */ - usleep(3000); - dap_dp_init(cm->debug_ap->dap); + mem_ap_write_atomic_u32(cm->debug_ap, NVIC_AIRCR, + AIRCR_VECTKEY | AIRCR_SYSRESETREQ); } else { LOG_INFO("psoc6.cm4: bkpt @0x%08X, issuing VECTRESET", reset_addr); - hr = mem_ap_write_atomic_u32(cm->debug_ap, - NVIC_AIRCR, - AIRCR_VECTKEY | AIRCR_VECTRESET); - if (hr != ERROR_OK) - return hr; + mem_ap_write_atomic_u32(cm->debug_ap, NVIC_AIRCR, + AIRCR_VECTKEY | AIRCR_VECTRESET); } + /* Wait 100ms for bootcode and reinitialize DAP */ + usleep(100000); + dap_dp_init(cm->debug_ap->dap); + target_wait_state(target, TARGET_HALTED, IPC_TIMEOUT_MS); /* Remove the break point */ breakpoint_remove(target, reset_addr); - return hr; + return ERROR_OK; } +/** *********************************************************************************************** + * @brief Simulates broken Vector Catch + * Function will try to determine entry point of user application. If it succeeds it will set HW + * breakpoint at that address, issue SW Reset and remove the breakpoint afterwards. + * In case of CM0, SYSRESETREQ is used. This allows to reset all peripherals. Boot code will + * reset CM4 anyway, so using SYSRESETREQ is safe here. + * In case of CM4, VECTRESET is used instead of SYSRESETREQ to not disturb CM0 core. + * + * @return ERROR_OK in case of success, ERROR_XXX code otherwise + *************************************************************************************************/ COMMAND_HANDLER(psoc6_handle_reset_halt) { if (CMD_ARGC) @@ -945,7 +1024,7 @@ static const struct command_registration psoc6_exec_command_handlers[] = { .name = "mass_erase", .handler = psoc6_handle_mass_erase_command, .mode = COMMAND_EXEC, - .usage = NULL, + .usage = "bank", .help = "Erases entire Main Flash", }, { diff --git a/tcl/target/psoc6.cfg b/tcl/target/psoc6.cfg index ad9aba569d..fc0c71159b 100644 --- a/tcl/target/psoc6.cfg +++ b/tcl/target/psoc6.cfg @@ -82,19 +82,30 @@ proc psoc6_deassert_post { target } { $target arp_examine global RESET_MODE + global TARGET + if { $RESET_MODE ne "run" } { $target arp_poll $target arp_poll set st [$target curstate] + if { $st eq "reset" } { # we assume running state follows # if reset accidentally halts, waiting is useless catch { $target arp_waitstate running 100 } set st [$target curstate] } + if { $st eq "running" } { echo "$target: Ran after reset and before halt..." - $target arp_halt + if { $target eq "${TARGET}.cm0" } { + # Try to cleanly reset whole system + # and halt the CM0 at entry point + psoc6 reset_halt + $target arp_waitstate halted 100 + } else { + $target arp_halt + } } } } @@ -133,3 +144,7 @@ if { $_ENABLE_CM0 } { # Use CM0+ by default on dual-core devices targets ${TARGET}.cm0 } + +if {[using_jtag]} { + swj_newdap $_CHIPNAME bs -irlen 18 -expected-id 0x2e200069 +} -- 2.30.2