psoc6: Run flash algorithm asynchronously to improve performance 72/4472/7
authorBohdan Tymkiv <bhdt@cypress.com>
Wed, 21 Mar 2018 14:13:28 +0000 (16:13 +0200)
committerTomas Vanek <vanekt@fbl.cz>
Mon, 23 Apr 2018 19:42:06 +0000 (20:42 +0100)
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 <bhdt@cypress.com>
Reviewed-on: http://openocd.zylin.com/4472
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
src/flash/nor/psoc6.c
tcl/target/psoc6.cfg

index e5c41976423fd71e079110fdc98c6aeeb65de29d..9352ad41b512123d437c4061a9ccd4c7dc64b5be 100644 (file)
@@ -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(&reg_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, &reg_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(&reg_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(&reg_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(&reg_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, &reg_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(&reg_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",
        },
        {
index ad9aba569d20727511b34a78eaaed2a66e98829e..fc0c71159b66476be0dab6638015a76481fed878 100644 (file)
@@ -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
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)