openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / psoc6.c
index 259d6679d82bf7f21343dcc83a05b6ee143a3329..b7ba1027ed49e45760ebfcc1726df4d66254ae43 100644 (file)
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 /***************************************************************************
  *                                                                         *
- *   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  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 
 #ifdef HAVE_CONFIG_H
 #include <time.h>
 
 #include "imp.h"
+#include "helper/time_support.h"
+#include "target/arm_adi_v5.h"
 #include "target/target.h"
 #include "target/cortex_m.h"
 #include "target/breakpoints.h"
 #include "target/target_type.h"
-#include "time_support.h"
 #include "target/algorithm.h"
 
 /**************************************************************************************************
@@ -101,18 +91,22 @@ 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 */
        {0x16007C00, 0x400},    /* SFLASH: TOC2 */
 };
 
-#define SFLASH_NUM_REGIONS (sizeof(safe_sflash_regions) / sizeof(safe_sflash_regions[0]))
+#define SFLASH_NUM_REGIONS ARRAY_SIZE(safe_sflash_regions)
 
 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 +114,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)
 {
@@ -146,83 +146,79 @@ 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);
+       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);
-               g_stack_area = NULL;
-       }
+       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 +254,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 +303,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 request 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 +342,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)
@@ -358,15 +360,19 @@ static int call_sromapi(struct target *target,
 
        bool is_success = (*data_out & SROMAPI_STATUS_MSK) == SROMAPI_STAT_SUCCESS;
        if (!is_success) {
-               LOG_ERROR("SROM API execution failed. Status: 0x%08X", (uint32_t)*data_out);
+               LOG_ERROR("SROM API execution failed. Status: 0x%08" PRIX32, *data_out);
                return ERROR_TARGET_FAILURE;
        }
 
        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 +381,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 +399,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)
 {
@@ -423,16 +432,18 @@ static int psoc6_protect_check(struct flash_bank *bank)
                        break;
        }
 
-       for (int i = 0; i < bank->num_sectors; i++)
+       for (unsigned int i = 0; i < bank->num_sectors; i++)
                bank->sectors[i].is_protected = is_protected;
 
        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)
+static int psoc6_protect(struct flash_bank *bank, int set, unsigned int first,
+               unsigned int last)
 {
        (void)bank;
        (void)set;
@@ -443,35 +454,35 @@ 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 describing protection status
  *************************************************************************************************/
 static const char *protection_to_str(uint8_t protection)
 {
        switch (protection) {
                case PROTECTION_VIRGIN:
                        return "VIRGIN";
-                       break;
                case PROTECTION_NORMAL:
                        return "NORMAL";
-                       break;
                case PROTECTION_SECURE:
                        return "SECURE";
-                       break;
                case PROTECTION_DEAD:
                        return "DEAD";
-                       break;
                case PROTECTION_UNKNOWN:
                default:
                        return "UNKNOWN";
-                       break;
        }
 }
 
-/**************************************************************************************************
- * Displays human-readable information about acquired device
+/** ***********************************************************************************************
+ * @brief psoc6_get_info Displays human-readable information about acquired device
+ * @param bank current flash bank
+ * @param cmd pointer to command invocation instance
+ * @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)
+static int psoc6_get_info(struct flash_bank *bank, struct command_invocation *cmd)
 {
        struct psoc6_target_info *psoc6_info = bank->driver_priv;
 
@@ -482,10 +493,10 @@ static int psoc6_get_info(struct flash_bank *bank, char *buf, int buf_size)
        if (hr != ERROR_OK)
                return hr;
 
-       snprintf(buf, buf_size,
-               "PSoC6 Silicon ID: 0x%08X\n"
+       command_print_sameline(cmd,
+               "PSoC6 Silicon ID: 0x%08" PRIX32 "\n"
                "Protection: %s\n"
-               "Main Flash size: %d kB\n"
+               "Main Flash size: %" PRIu32 " kB\n"
                "Work Flash size: 32 kB\n",
                psoc6_info->silicon_id,
                protection_to_str(psoc6_info->protection),
@@ -494,8 +505,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 +520,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)
 {
@@ -536,7 +555,7 @@ static int psoc6_probe(struct flash_bank *bank)
 
        int hr = ERROR_OK;
 
-       /* Retrieve data from SPCIF_GEOMATRY */
+       /* Retrieve data from SPCIF_GEOMETRY */
        uint32_t geom;
        target_read_u32(target, PSOC6_SPCIF_GEOMETRY, &geom);
        uint32_t row_sz_lg2 = (geom & 0xF0) >> 4;
@@ -547,10 +566,8 @@ static int psoc6_probe(struct flash_bank *bank)
        /* Calculate size of Main Flash*/
        uint32_t flash_sz_bytes = bank_cnt * row_cnt * row_sz;
 
-       if (bank->sectors) {
-               free(bank->sectors);
-               bank->sectors = NULL;
-       }
+       free(bank->sectors);
+       bank->sectors = NULL;
 
        size_t bank_size = 0;
 
@@ -572,16 +589,15 @@ static int psoc6_probe(struct flash_bank *bank)
                return ERROR_FLASH_BANK_INVALID;
        }
 
-       size_t num_sectors = bank_size / row_sz;
+       unsigned int num_sectors = bank_size / row_sz;
        bank->size = bank_size;
-       bank->chip_width = 4;
-       bank->bus_width = 4;
+
        bank->erased_value = 0;
        bank->default_padded_value = 0;
 
        bank->num_sectors = num_sectors;
        bank->sectors = calloc(num_sectors, sizeof(struct flash_sector));
-       for (size_t i = 0; i < num_sectors; i++) {
+       for (unsigned int i = 0; i < num_sectors; i++) {
                bank->sectors[i].size = row_sz;
                bank->sectors[i].offset = i * row_sz;
                bank->sectors[i].is_erased = -1;
@@ -595,8 +611,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,14 +629,18 @@ 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)
 {
        struct target *target = bank->target;
 
-       LOG_DEBUG("Erasing SECTOR @%08X", addr);
+       LOG_DEBUG("Erasing SECTOR @%08" PRIX32, addr);
 
        int hr = target_write_u32(target, wa->address, SROMAPI_ERASESECTOR_REQ);
        if (hr != ERROR_OK)
@@ -631,19 +653,23 @@ static int psoc6_erase_sector(struct flash_bank *bank, struct working_area *wa,
        uint32_t data_out;
        hr = call_sromapi(target, SROMAPI_ERASESECTOR_REQ, wa->address, &data_out);
        if (hr != ERROR_OK)
-               LOG_ERROR("SECTOR @%08X not erased!", addr);
+               LOG_ERROR("SECTOR @%08" PRIX32 " not erased!", addr);
 
        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)
 {
        struct target *target = bank->target;
 
-       LOG_DEBUG("Erasing ROW @%08X", addr);
+       LOG_DEBUG("Erasing ROW @%08" PRIX32, addr);
 
        int hr = target_write_u32(target, wa->address, SROMAPI_ERASEROW_REQ);
        if (hr != ERROR_OK)
@@ -656,16 +682,22 @@ static int psoc6_erase_row(struct flash_bank *bank, struct working_area *wa, uin
        uint32_t data_out;
        hr = call_sromapi(target, SROMAPI_ERASEROW_REQ, wa->address, &data_out);
        if (hr != ERROR_OK)
-               LOG_ERROR("ROW @%08X not erased!", addr);
+               LOG_ERROR("ROW @%08" PRIX32 " not erased!", addr);
 
        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)
+static int psoc6_erase(struct flash_bank *bank, unsigned int first,
+               unsigned int last)
 {
        struct target *target = bank->target;
        struct psoc6_target_info *psoc6_info = bank->driver_priv;
@@ -681,14 +713,14 @@ 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)
                goto exit;
 
        /* Number of rows in single sector */
-       const int rows_in_sector = sector_size / psoc6_info->row_sz;
+       const unsigned int rows_in_sector = sector_size / psoc6_info->row_sz;
 
        while (last >= first) {
                /* Erase Sector if we are on sector boundary and erase size covers whole sector */
@@ -698,9 +730,6 @@ static int psoc6_erase(struct flash_bank *bank, int first, int last)
                        if (hr != ERROR_OK)
                                goto exit_free_wa;
 
-                       for (int i = first; i < first + rows_in_sector; i++)
-                               bank->sectors[i].is_erased = 1;
-
                        first += rows_in_sector;
                } else {
                        /* Perform Row Erase otherwise */
@@ -708,7 +737,6 @@ static int psoc6_erase(struct flash_bank *bank, int first, int last)
                        if (hr != ERROR_OK)
                                goto exit_free_wa;
 
-                       bank->sectors[first].is_erased = 1;
                        first += 1;
                }
        }
@@ -720,9 +748,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,
@@ -736,7 +768,7 @@ static int psoc6_program_row(struct flash_bank *bank,
        uint32_t data_out;
        int hr = ERROR_OK;
 
-       LOG_DEBUG("Programming ROW @%08X", addr);
+       LOG_DEBUG("Programming ROW @%08" PRIX32, addr);
 
        hr = target_alloc_working_area(target, psoc6_info->row_sz + 32, &wa);
        if (hr != ERROR_OK)
@@ -773,9 +805,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 flash 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 +823,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;
@@ -803,8 +839,8 @@ 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;
+                       LOG_ERROR("Failed to program Flash at address 0x%08" PRIX32, aligned_addr);
+                       goto exit;
                }
 
                buffer += row_bytes;
@@ -812,13 +848,14 @@ 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
+ * @return ERROR_OK in case of success, ERROR_XXX code otherwise
  *************************************************************************************************/
 COMMAND_HANDLER(psoc6_handle_mass_erase_command)
 {
@@ -835,15 +872,18 @@ 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)
+static int handle_reset_halt(struct target *target)
 {
        int hr;
        uint32_t reset_addr;
@@ -889,33 +929,42 @@ int handle_reset_halt(struct target *target)
 
        const struct armv7m_common *cm = target_to_armv7m(target);
 
+       /* PSoC6 reboots immediately 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);
+               LOG_INFO("psoc6.cm0: bkpt @0x%08" PRIX32 ", issuing SYSRESETREQ", reset_addr);
+               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;
+               LOG_INFO("psoc6.cm4: bkpt @0x%08" PRIX32 ", issuing VECTRESET", reset_addr);
+               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,14 +994,14 @@ 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",
        },
        {
                .name = "reset_halt",
                .handler = psoc6_handle_reset_halt,
                .mode = COMMAND_EXEC,
-               .usage = NULL,
+               .usage = "",
                .help = "Tries to simulate broken Vector Catch",
        },
        COMMAND_REGISTRATION_DONE
@@ -969,7 +1018,7 @@ static const struct command_registration psoc6_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
-struct flash_driver psoc6_flash = {
+const struct flash_driver psoc6_flash = {
        .name = "psoc6",
        .commands = psoc6_command_handlers,
        .flash_bank_command = psoc6_flash_bank_command,
@@ -982,4 +1031,5 @@ struct flash_driver psoc6_flash = {
        .erase_check = default_flash_blank_check,
        .protect_check = psoc6_protect_check,
        .info = psoc6_get_info,
+       .free_driver_priv = default_flash_free_driver_priv,
 };