psoc4: update for 4x00BLE, L, M, S and PRoC BLE devices

Flash ROM API command PSOC4_CMD_SET_IMO48 is now optional on new devices.
Also code tidy up:
- improved system ROM call error detection
- probe does not require the target to be halted
- default_padded_value and erased_value set to 0
- fixed endianess problem in flash write and protection setting
- removed fancy chip detection table as it would be updated too often
- psoc4 flash_autoerase is now on by default to ease programming

psoc4.cfg distinguishes chip family and uses either proprietary acquire
function of a KitProg adapter or TEST_MODE workaround to "reset halt"

Change-Id: I2c75ec46ed0a95e09274fad70b62d6eed7b9ecdf
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: http://openocd.zylin.com/3807
Tested-by: jenkins
Reviewed-by: David Girault <david.f.girault@gmail.com>
This commit is contained in:
Tomas Vanek 2016-08-26 21:03:27 +02:00
parent 5830bf09a7
commit 38030e0115
2 changed files with 455 additions and 267 deletions

View File

@ -41,24 +41,65 @@
Document Number: 001-87197 Rev. *B Revised August 29, 2013 Document Number: 001-87197 Rev. *B Revised August 29, 2013
PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM PSoC 4100/4200 Family PSoC(R) 4 Architecture TRM
Document No. 001-85634 Rev. *C March 25, 2014 Document No. 001-85634 Rev. *E June 28, 2016
PSoC(R) 4 Registers TRM Spec. PSoC(R) 4 Registers TRM Spec.
Document No. 001-85847 Rev. *A June 25, 2013 Document No. 001-85847 Rev. *A June 25, 2013
PSoC 4000 Family PSoC(R) 4 Technical Reference Manual
Document No. 001-89309 Rev. *B May 9, 2016
PSoC 41XX_BLE/42XX_BLE Family PSoC 4 BLE Architecture TRM
Document No. 001-92738 Rev. *C February 12, 2016
PSoC 4200L Family PSoC 4 Architecture TRM
Document No. 001-97952 Rev. *A December 15, 2015
PSoC 4200L Family PSoC 4 Registers TRM
Document No. 001-98126 Rev. *A December 16, 2015
PSoC 4100M/4200M Family PSoC 4 Architecture TRM
Document No. 001-95223 Rev. *B July 29, 2015
PSoC 4100S Family PSoC 4 Architecture TRM
Document No. 002-10621 Rev. *A July 29, 2016
PSoC 4100S Family PSoC 4 Registers TRM
Document No. 002-10523 Rev. *A July 20, 2016
PSoC Analog Coprocessor Architecture TRM
Document No. 002-10404 Rev. ** December 18, 2015
CY8C4Axx PSoC Analog Coprocessor Registers TRM
Document No. 002-10405 Rev. ** December 18, 2015
CY8C41xx, CY8C42xx Programming Specifications CY8C41xx, CY8C42xx Programming Specifications
Document No. 001-81799 Rev. *C March 4, 2014 Document No. 001-81799 Rev. *C March 4, 2014
CYBL10x6x, CY8C4127_BL, CY8C4247_BL Programming Specifications
Document No. 001-91508 Rev. *B September 22, 2014
*/ */
/* register locations */ /* register locations */
#define PSOC4_CPUSS_SYSREQ 0x40000004 #define PSOC4_SFLASH_MACRO0 0x0FFFF000
#define PSOC4_CPUSS_SYSARG 0x40000008
#define PSOC4_TEST_MODE 0x40030014 #define PSOC4_CPUSS_SYSREQ_LEGACY 0x40000004
#define PSOC4_SPCIF_GEOMETRY 0x400E0000 #define PSOC4_CPUSS_SYSARG_LEGACY 0x40000008
#define PSOC4_SPCIF_GEOMETRY_LEGACY 0x400E0000
#define PSOC4_CPUSS_SYSREQ_NEW 0x40100004
#define PSOC4_CPUSS_SYSARG_NEW 0x40100008
#define PSOC4_SPCIF_GEOMETRY_NEW 0x40110000
#define PSOC4_TEST_MODE 0x40030014
#define PSOC4_ROMTABLE_PID0 0xF0000FE0
#define PSOC4_SFLASH_MACRO 0x0ffff000
/* constants */ /* constants */
#define PSOC4_SFLASH_MACRO_SIZE 0x400
#define PSOC4_ROWS_PER_MACRO 512
#define PSOC4_SROM_KEY1 0xb6 #define PSOC4_SROM_KEY1 0xb6
#define PSOC4_SROM_KEY2 0xd3 #define PSOC4_SROM_KEY2 0xd3
#define PSOC4_SROM_SYSREQ_BIT (1<<31) #define PSOC4_SROM_SYSREQ_BIT (1<<31)
@ -66,6 +107,10 @@
#define PSOC4_SROM_PRIVILEGED_BIT (1<<28) #define PSOC4_SROM_PRIVILEGED_BIT (1<<28)
#define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000 #define PSOC4_SROM_STATUS_SUCCEEDED 0xa0000000
#define PSOC4_SROM_STATUS_FAILED 0xf0000000 #define PSOC4_SROM_STATUS_FAILED 0xf0000000
#define PSOC4_SROM_STATUS_MASK 0xf0000000
/* not documented in any TRM */
#define PSOC4_SROM_ERR_IMO_NOT_IMPLEM 0xf0000013
#define PSOC4_CMD_GET_SILICON_ID 0 #define PSOC4_CMD_GET_SILICON_ID 0
#define PSOC4_CMD_LOAD_LATCH 4 #define PSOC4_CMD_LOAD_LATCH 4
@ -74,76 +119,60 @@
#define PSOC4_CMD_ERASE_ALL 0xa #define PSOC4_CMD_ERASE_ALL 0xa
#define PSOC4_CMD_CHECKSUM 0xb #define PSOC4_CMD_CHECKSUM 0xb
#define PSOC4_CMD_WRITE_PROTECTION 0xd #define PSOC4_CMD_WRITE_PROTECTION 0xd
#define PSOC4_CMD_SET_IMO48 0x15
#define PSOC4_CMD_WRITE_SFLASH_ROW 0x18
#define PSOC4_CHIP_PROT_VIRGIN 0x0 #define PSOC4_CHIP_PROT_VIRGIN 0x0
#define PSOC4_CHIP_PROT_OPEN 0x1 #define PSOC4_CHIP_PROT_OPEN 0x1
#define PSOC4_CHIP_PROT_PROTECTED 0x2 #define PSOC4_CHIP_PROT_PROTECTED 0x2
#define PSOC4_CHIP_PROT_KILL 0x4 #define PSOC4_CHIP_PROT_KILL 0x4
#define PSOC4_ROMTABLE_DESIGNER_CHECK 0xb4
struct psoc4_chip_details { #define PSOC4_FAMILY_FLAG_LEGACY 1
struct psoc4_chip_family {
uint16_t id; uint16_t id;
const char *type; const char *name;
const char *package; uint32_t flags;
uint32_t flash_size_in_kb;
}; };
/* list of PSoC 4 chips const struct psoc4_chip_family psoc4_families[] = {
* flash_size_in_kb is not necessary as it can be decoded from SPCIF_GEOMETRY { 0x93, "PSoC4100/4200", .flags = PSOC4_FAMILY_FLAG_LEGACY },
*/ { 0x9A, "PSoC4000", .flags = 0 },
const struct psoc4_chip_details psoc4_devices[] = { { 0x9E, "PSoC/PRoC BLE (119E)", .flags = 0 },
/* 4200 series */ { 0xA0, "PSoC4200L", .flags = 0 },
{ 0x04A6, "CY8C4245PVI-482", "SSOP-28", .flash_size_in_kb = 32 }, { 0xA1, "PSoC4100M/4200M", .flags = 0 },
{ 0x04B6, "CY8C4245LQI-483", "QFN-40", .flash_size_in_kb = 32 }, { 0xA3, "PSoC/PRoC BLE (11A3)", .flags = 0 },
{ 0x04C8, "CY8C4245AXI-483", "TQFP-44", .flash_size_in_kb = 32 }, { 0xA9, "PSoC4000S", .flags = 0 },
{ 0x04FB, "CY8C4245AXI-473", "TQFP-44", .flash_size_in_kb = 32 }, { 0xAA, "PSoC/PRoC BLE (11AA)", .flags = 0 },
{ 0x04F0, "CY8C4244PVI-432", "SSOP-28", .flash_size_in_kb = 16 }, { 0xAB, "PSoC4100S", .flags = 0 },
{ 0x04F1, "CY8C4244PVI-442", "SSOP-28", .flash_size_in_kb = 16 }, { 0xAC, "PSoC Analog Coprocessor", .flags = 0 },
{ 0x04F6, "CY8C4244LQI-443", "QFN-40", .flash_size_in_kb = 16 }, { 0, "Unknown", .flags = 0 }
{ 0x04FA, "CY8C4244AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
/* 4100 series */
{ 0x0410, "CY8C4124PVI-432", "SSOP-28", .flash_size_in_kb = 16 },
{ 0x0411, "CY8C4124PVI-442", "SSOP-28", .flash_size_in_kb = 16 },
{ 0x041C, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 },
{ 0x041A, "CY8C4124AXI-443", "TQFP-44", .flash_size_in_kb = 16 },
{ 0x041B, "CY8C4125AXI-473", "TQFP-44", .flash_size_in_kb = 32 },
{ 0x0412, "CY8C4125PVI-482", "SSOP-28", .flash_size_in_kb = 32 },
{ 0x0417, "CY8C4125LQI-483", "QFN-40", .flash_size_in_kb = 32 },
{ 0x0416, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 },
/* CCG1 series */
{ 0x0490, "CYPD1103-35FNXI", "CSP-35", .flash_size_in_kb = 32 },
{ 0x0489, "CYPD1121-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
{ 0x048A, "CYPD1122-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
{ 0x0491, "CYPD1131-35FNXI", "CSP-35", .flash_size_in_kb = 32 },
{ 0x0498, "CYPD1132-16SXI", "SOIC-16", .flash_size_in_kb = 32 },
{ 0x0481, "CYPD1134-28PVXI", "SSOP-28", .flash_size_in_kb = 32 },
{ 0x048B, "CYPD1134-40LQXI", "QFN-40", .flash_size_in_kb = 32 },
}; };
struct psoc4_flash_bank { struct psoc4_flash_bank {
uint32_t row_size; uint32_t row_size;
uint32_t user_bank_size; uint32_t user_bank_size;
int probed; int num_macros;
uint32_t silicon_id; bool probed;
uint8_t chip_protection;
uint8_t cmd_program_row; uint8_t cmd_program_row;
uint16_t family_id;
bool legacy_family;
uint32_t cpuss_sysreq_addr;
uint32_t cpuss_sysarg_addr;
uint32_t spcif_geometry_addr;
}; };
static const struct psoc4_chip_details *psoc4_details_by_id(uint32_t silicon_id) static const struct psoc4_chip_family *psoc4_family_by_id(uint16_t family_id)
{ {
const struct psoc4_chip_details *p = psoc4_devices; const struct psoc4_chip_family *p = psoc4_families;
unsigned int i; while (p->id && p->id != family_id)
uint16_t id = silicon_id >> 16; /* ignore die revision */ p++;
for (i = 0; i < sizeof(psoc4_devices)/sizeof(psoc4_devices[0]); i++, p++) {
if (p->id == id) return p;
return p;
}
LOG_DEBUG("Unknown PSoC 4 device silicon id 0x%08" PRIx32 ".", silicon_id);
return NULL;
} }
static const char *psoc4_decode_chip_protection(uint8_t protection) static const char *psoc4_decode_chip_protection(uint8_t protection)
@ -176,7 +205,9 @@ FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank)); psoc4_info = calloc(1, sizeof(struct psoc4_flash_bank));
bank->driver_priv = psoc4_info; bank->driver_priv = psoc4_info;
bank->default_padded_value = bank->erased_value = 0x00;
psoc4_info->user_bank_size = bank->size; psoc4_info->user_bank_size = bank->size;
psoc4_info->cmd_program_row = PSOC4_CMD_WRITE_ROW;
return ERROR_OK; return ERROR_OK;
} }
@ -189,9 +220,14 @@ FLASH_BANK_COMMAND_HANDLER(psoc4_flash_bank_command)
* Otherwise address of memory parameter block is set in CPUSS_SYSARG * Otherwise address of memory parameter block is set in CPUSS_SYSARG
* and the first parameter is written to the first word of parameter block * and the first parameter is written to the first word of parameter block
*/ */
static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param, static int psoc4_sysreq(struct flash_bank *bank, uint8_t cmd,
uint32_t *sysreq_params, uint32_t sysreq_params_size) uint16_t cmd_param,
uint32_t *sysreq_params, uint32_t sysreq_params_size,
uint32_t *sysarg_out)
{ {
struct target *target = bank->target;
struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
struct working_area *sysreq_wait_algorithm; struct working_area *sysreq_wait_algorithm;
struct working_area *sysreq_mem; struct working_area *sysreq_mem;
@ -212,8 +248,8 @@ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4; const int code_words = (sizeof(psoc4_sysreq_wait_code) + 3) / 4;
/* stack must be aligned */ /* stack must be aligned */
const int stack_size = 196; const int stack_size = 256;
/* tested stack sizes on PSoC 4: /* tested stack sizes on PSoC4200:
ERASE_ALL 144 ERASE_ALL 144
PROGRAM_ROW 112 PROGRAM_ROW 112
other sysreq 68 other sysreq 68
@ -238,6 +274,8 @@ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
} }
if (sysreq_params_size) { if (sysreq_params_size) {
LOG_DEBUG("SYSREQ %02" PRIx8 " %04" PRIx16 " %08" PRIx32 " %08" PRIx32 " size %" PRIu32,
cmd, cmd_param, param1, sysreq_params[0], sysreq_params_size);
/* Allocate memory for sysreq_params */ /* Allocate memory for sysreq_params */
retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem); retval = target_alloc_working_area(target, sysreq_params_size, &sysreq_mem);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
@ -250,21 +288,23 @@ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
} }
/* Write sysreq_params */ /* Write sysreq_params */
sysreq_params[0] = param1; target_buffer_set_u32(target, (uint8_t *)sysreq_params, param1);
retval = target_write_buffer(target, sysreq_mem->address, retval = target_write_buffer(target, sysreq_mem->address,
sysreq_params_size, (uint8_t *)sysreq_params); sysreq_params_size, (uint8_t *)sysreq_params);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto cleanup_mem; goto cleanup_mem;
/* Set address of sysreq parameters block */ /* Set address of sysreq parameters block */
retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, sysreq_mem->address); retval = target_write_u32(target, psoc4_info->cpuss_sysarg_addr, sysreq_mem->address);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto cleanup_mem; goto cleanup_mem;
} else { } else {
/* Sysreq without memory block of parameters */ /* Sysreq without memory block of parameters */
LOG_DEBUG("SYSREQ %02" PRIx8 " %04" PRIx16 " %08" PRIx32,
cmd, cmd_param, param1);
/* Set register parameter */ /* Set register parameter */
retval = target_write_u32(target, PSOC4_CPUSS_SYSARG, param1); retval = target_write_u32(target, psoc4_info->cpuss_sysarg_addr, param1);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto cleanup_mem; goto cleanup_mem;
} }
@ -279,14 +319,13 @@ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
struct armv7m_common *armv7m = target_to_armv7m(target); struct armv7m_common *armv7m = target_to_armv7m(target);
if (armv7m == NULL) { if (armv7m == NULL) {
/* something is very wrong if armv7m is NULL */ /* something is very wrong if armv7m is NULL */
LOG_ERROR("unable to get armv7m target"); LOG_ERROR("unable to get armv7m target");
goto cleanup; goto cleanup;
} }
/* Set SROM request */ /* Set SROM request */
retval = target_write_u32(target, PSOC4_CPUSS_SYSREQ, retval = target_write_u32(target, psoc4_info->cpuss_sysreq_addr,
PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd); PSOC4_SROM_SYSREQ_BIT | PSOC4_SROM_HMASTER_BIT | cmd);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto cleanup; goto cleanup;
@ -295,9 +334,23 @@ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param,
retval = target_run_algorithm(target, 0, NULL, retval = target_run_algorithm(target, 0, NULL,
sizeof(reg_params) / sizeof(*reg_params), reg_params, sizeof(reg_params) / sizeof(*reg_params), reg_params,
sysreq_wait_algorithm->address, 0, 1000, &armv7m_info); sysreq_wait_algorithm->address, 0, 1000, &armv7m_info);
if (retval != ERROR_OK) if (retval != ERROR_OK) {
LOG_ERROR("sysreq wait code execution failed"); LOG_ERROR("sysreq wait code execution failed");
goto cleanup;
}
uint32_t sysarg_out_tmp;
retval = target_read_u32(target, psoc4_info->cpuss_sysarg_addr, &sysarg_out_tmp);
if (retval != ERROR_OK)
goto cleanup;
if (sysarg_out) {
*sysarg_out = sysarg_out_tmp;
/* If result is an error, do not show now, let caller to decide */
} else if ((sysarg_out_tmp & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
LOG_ERROR("sysreq error 0x%" PRIx32, sysarg_out_tmp);
retval = ERROR_FAIL;
}
cleanup: cleanup:
destroy_reg_param(&reg_params[0]); destroy_reg_param(&reg_params[0]);
@ -313,42 +366,123 @@ cleanup_algo:
/* helper routine to get silicon ID from a PSoC 4 chip */ /* helper routine to get silicon ID from a PSoC 4 chip */
static int psoc4_get_silicon_id(struct target *target, uint32_t *silicon_id, uint8_t *protection) static int psoc4_get_silicon_id(struct flash_bank *bank, uint32_t *silicon_id, uint16_t *family_id, uint8_t *protection)
{ {
uint32_t params = PSOC4_SROM_KEY1 struct target *target = bank->target;
| ((PSOC4_SROM_KEY2 + PSOC4_CMD_GET_SILICON_ID) << 8); struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
uint32_t part0, part1; uint32_t part0, part1;
int retval = psoc4_sysreq(target, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0); int retval = psoc4_sysreq(bank, PSOC4_CMD_GET_SILICON_ID, 0, NULL, 0, &part0);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
retval = target_read_u32(target, PSOC4_CPUSS_SYSARG, &part0); if ((part0 & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
if (retval != ERROR_OK) LOG_ERROR("sysreq error 0x%" PRIx32, part0);
return retval;
if (part0 == params) {
LOG_ERROR("sysreq silicon id request not served");
return ERROR_FAIL; return ERROR_FAIL;
} }
retval = target_read_u32(target, PSOC4_CPUSS_SYSREQ, &part1); retval = target_read_u32(target, psoc4_info->cpuss_sysreq_addr, &part1);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
uint32_t silicon = ((part0 & 0xffff) << 16) /* build ID as Cypress sw does:
| (((part0 >> 16) & 0xff) << 8) * bit 31..16 silicon ID
| (part1 & 0xff); * bit 15..8 revision ID (so far 0x11 for all devices)
uint8_t prot = (part1 >> 12) & 0xff; * bit 7..0 family ID (lowes 8 bits)
*/
if (silicon_id) if (silicon_id)
*silicon_id = silicon; *silicon_id = ((part0 & 0x0000ffff) << 16)
if (protection) | ((part0 & 0x00ff0000) >> 8)
*protection = prot; | (part1 & 0x000000ff);
LOG_DEBUG("silicon id: 0x%08" PRIx32 "", silicon); if (family_id)
LOG_DEBUG("protection: 0x%02" PRIx8 "", prot); *family_id = part1 & 0x0fff;
return retval;
if (protection)
*protection = (part1 >> 12) & 0x0f;
return ERROR_OK;
}
static int psoc4_get_family(struct target *target, uint16_t *family_id)
{
int retval, i;
uint32_t pidbf[3];
uint8_t pid[3];
retval = target_read_memory(target, PSOC4_ROMTABLE_PID0, 4, 3, (uint8_t *)pidbf);
if (retval != ERROR_OK)
return retval;
for (i = 0; i < 3; i++) {
uint32_t tmp = target_buffer_get_u32(target, (uint8_t *)(pidbf + i));
if (tmp & 0xffffff00) {
LOG_ERROR("Unexpected data in ROMTABLE");
return ERROR_FAIL;
}
pid[i] = tmp & 0xff;
}
uint16_t family = pid[0] | ((pid[1] & 0xf) << 8);
uint32_t designer = ((pid[1] & 0xf0) >> 4) | ((pid[2] & 0xf) << 4);
if (designer != PSOC4_ROMTABLE_DESIGNER_CHECK) {
LOG_ERROR("ROMTABLE designer is not Cypress");
return ERROR_FAIL;
}
*family_id = family;
return ERROR_OK;
}
static int psoc4_flash_prepare(struct flash_bank *bank)
{
struct target *target = bank->target;
struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
uint16_t family_id;
int retval;
/* get family ID from SROM call */
retval = psoc4_get_silicon_id(bank, NULL, &family_id, NULL);
if (retval != ERROR_OK)
return retval;
/* and check with family ID from ROMTABLE */
if (family_id != psoc4_info->family_id) {
LOG_ERROR("Family mismatch");
return ERROR_FAIL;
}
if (!psoc4_info->legacy_family) {
uint32_t sysreq_status;
retval = psoc4_sysreq(bank, PSOC4_CMD_SET_IMO48, 0, NULL, 0, &sysreq_status);
if (retval != ERROR_OK)
return retval;
if ((sysreq_status & PSOC4_SROM_STATUS_MASK) != PSOC4_SROM_STATUS_SUCCEEDED) {
/* This undocumented error code is returned probably when
* PSOC4_CMD_SET_IMO48 command is not implemented.
* Can be safely ignored, programming works.
*/
if (sysreq_status == PSOC4_SROM_ERR_IMO_NOT_IMPLEM)
LOG_INFO("PSOC4_CMD_SET_IMO48 is not implemented on this device.");
else {
LOG_ERROR("sysreq error 0x%" PRIx32, sysreq_status);
return ERROR_FAIL;
}
}
}
return ERROR_OK;
} }
@ -357,48 +491,37 @@ static int psoc4_protect_check(struct flash_bank *bank)
struct target *target = bank->target; struct target *target = bank->target;
struct psoc4_flash_bank *psoc4_info = bank->driver_priv; struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
uint32_t prot_addr = PSOC4_SFLASH_MACRO; uint32_t prot_addr = PSOC4_SFLASH_MACRO0;
uint32_t protection; int retval;
int i, s; int s = 0;
int num_bits; int m, i;
int retval = ERROR_OK; uint8_t bf[PSOC4_ROWS_PER_MACRO/8];
num_bits = bank->num_sectors; for (m = 0; m < psoc4_info->num_macros; m++, prot_addr += PSOC4_SFLASH_MACRO_SIZE) {
retval = target_read_memory(target, prot_addr, 4, PSOC4_ROWS_PER_MACRO/32, bf);
for (i = 0; i < num_bits; i += 32) {
retval = target_read_u32(target, prot_addr, &protection);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
prot_addr += 4; for (i = 0; i < PSOC4_ROWS_PER_MACRO && s < bank->num_sectors; i++, s++)
bank->sectors[s].is_protected = bf[i/8] & (1 << (i%8)) ? 1 : 0;
for (s = 0; s < 32; s++) {
if (i + s >= num_bits)
break;
bank->sectors[i + s].is_protected = (protection & (1 << s)) ? 1 : 0;
}
} }
retval = psoc4_get_silicon_id(target, NULL, &(psoc4_info->chip_protection)); return ERROR_OK;
return retval;
} }
static int psoc4_mass_erase(struct flash_bank *bank) static int psoc4_mass_erase(struct flash_bank *bank)
{ {
struct target *target = bank->target;
int i; int i;
int retval = psoc4_flash_prepare(bank);
if (bank->target->state != TARGET_HALTED) { if (retval != ERROR_OK)
LOG_ERROR("Target not halted"); return retval;
return ERROR_TARGET_NOT_HALTED;
}
/* Call "Erase All" system ROM API */ /* Call "Erase All" system ROM API */
uint32_t param; uint32_t param = 0;
int retval = psoc4_sysreq(target, PSOC4_CMD_ERASE_ALL, retval = psoc4_sysreq(bank, PSOC4_CMD_ERASE_ALL,
0, 0,
&param, sizeof(param)); &param, sizeof(param), NULL);
if (retval == ERROR_OK) if (retval == ERROR_OK)
/* set all sectors as erased */ /* set all sectors as erased */
@ -420,7 +543,7 @@ static int psoc4_erase(struct flash_bank *bank, int first, int last)
if ((first == 0) && (last == (bank->num_sectors - 1))) if ((first == 0) && (last == (bank->num_sectors - 1)))
return psoc4_mass_erase(bank); return psoc4_mass_erase(bank);
LOG_ERROR("Only mass erase available"); LOG_ERROR("Only mass erase available! Consider using 'psoc4 flash_autoerase 0 on'");
return ERROR_FAIL; return ERROR_FAIL;
} }
@ -431,22 +554,23 @@ static int psoc4_protect(struct flash_bank *bank, int set, int first, int last)
struct target *target = bank->target; struct target *target = bank->target;
struct psoc4_flash_bank *psoc4_info = bank->driver_priv; struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
if (psoc4_info->probed == 0) if (!psoc4_info->probed)
return ERROR_FAIL; return ERROR_FAIL;
if (target->state != TARGET_HALTED) { int retval = psoc4_flash_prepare(bank);
LOG_ERROR("Target not halted"); if (retval != ERROR_OK)
return ERROR_TARGET_NOT_HALTED; return retval;
}
uint32_t *sysrq_buffer = NULL; uint32_t *sysrq_buffer = NULL;
int retval;
int num_bits = bank->num_sectors;
const int param_sz = 8; const int param_sz = 8;
int prot_sz = num_bits / 8;
int chip_prot = PSOC4_CHIP_PROT_OPEN; int chip_prot = PSOC4_CHIP_PROT_OPEN;
int flash_macro = 0; /* PSoC 42xx has only macro 0 */ int i, m;
int i; int num_bits = bank->num_sectors;
if (num_bits > PSOC4_ROWS_PER_MACRO)
num_bits = PSOC4_ROWS_PER_MACRO;
int prot_sz = num_bits / 8;
sysrq_buffer = calloc(1, param_sz + prot_sz); sysrq_buffer = calloc(1, param_sz + prot_sz);
if (sysrq_buffer == NULL) { if (sysrq_buffer == NULL) {
@ -454,33 +578,38 @@ static int psoc4_protect(struct flash_bank *bank, int set, int first, int last)
return ERROR_FAIL; return ERROR_FAIL;
} }
for (i = first; i < num_bits && i <= last; i++) for (i = first; i <= last && i < bank->num_sectors; i++)
bank->sectors[i].is_protected = set; bank->sectors[i].is_protected = set;
uint32_t *p = sysrq_buffer + 2; for (m = 0; m < psoc4_info->num_macros; m++) {
for (i = 0; i < num_bits; i++) { uint8_t *p = (uint8_t *)(sysrq_buffer + 2);
if (bank->sectors[i].is_protected) for (i = 0; i < num_bits && i < bank->num_sectors; i++) {
p[i / 32] |= 1 << (i % 32); if (bank->sectors[i].is_protected)
p[i/8] |= 1 << (i%8);
}
/* Call "Load Latch" system ROM API */
target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
prot_sz - 1);
retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
0 /* Byte number in latch from what to write */
| (m << 8), /* flash macro index */
sysrq_buffer, param_sz + psoc4_info->row_size,
NULL);
if (retval != ERROR_OK)
break;
/* Call "Write Protection" system ROM API */
retval = psoc4_sysreq(bank, PSOC4_CMD_WRITE_PROTECTION,
chip_prot | (m << 8), NULL, 0, NULL);
if (retval != ERROR_OK)
break;
} }
/* Call "Load Latch" system ROM API */
sysrq_buffer[1] = prot_sz - 1;
retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH,
0, /* Byte number in latch from what to write */
sysrq_buffer, param_sz + psoc4_info->row_size);
if (retval != ERROR_OK)
goto cleanup;
/* Call "Write Protection" system ROM API */
retval = psoc4_sysreq(target, PSOC4_CMD_WRITE_PROTECTION,
chip_prot | (flash_macro << 8), NULL, 0);
cleanup:
if (retval != ERROR_OK)
psoc4_protect_check(bank);
if (sysrq_buffer) if (sysrq_buffer)
free(sysrq_buffer); free(sysrq_buffer);
psoc4_protect_check(bank);
return retval; return retval;
} }
@ -516,21 +645,14 @@ COMMAND_HANDLER(psoc4_handle_flash_autoerase_command)
static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer, static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t offset, uint32_t count) uint32_t offset, uint32_t count)
{ {
struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
struct target *target = bank->target; struct target *target = bank->target;
struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
uint32_t *sysrq_buffer = NULL; uint32_t *sysrq_buffer = NULL;
int retval = ERROR_OK;
const int param_sz = 8; const int param_sz = 8;
if (bank->target->state != TARGET_HALTED) { int retval = psoc4_flash_prepare(bank);
LOG_ERROR("Target not halted"); if (retval != ERROR_OK)
return ERROR_TARGET_NOT_HALTED; return retval;
}
if (offset & 0x1) {
LOG_ERROR("offset 0x%08" PRIx32 " breaks required 2-byte alignment", offset);
return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
sysrq_buffer = malloc(param_sz + psoc4_info->row_size); sysrq_buffer = malloc(param_sz + psoc4_info->row_size);
if (sysrq_buffer == NULL) { if (sysrq_buffer == NULL) {
@ -542,7 +664,7 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t row_num = offset / psoc4_info->row_size; uint32_t row_num = offset / psoc4_info->row_size;
uint32_t row_offset = offset - row_num * psoc4_info->row_size; uint32_t row_offset = offset - row_num * psoc4_info->row_size;
if (row_offset) if (row_offset)
memset(row_buffer, 0, row_offset); memset(row_buffer, bank->default_padded_value, row_offset);
bool save_poll = jtag_poll_get_enabled(); bool save_poll = jtag_poll_get_enabled();
jtag_poll_set_enabled(false); jtag_poll_set_enabled(false);
@ -551,25 +673,31 @@ static int psoc4_write(struct flash_bank *bank, const uint8_t *buffer,
uint32_t chunk_size = psoc4_info->row_size - row_offset; uint32_t chunk_size = psoc4_info->row_size - row_offset;
if (chunk_size > count) { if (chunk_size > count) {
chunk_size = count; chunk_size = count;
memset(row_buffer + chunk_size, 0, psoc4_info->row_size - chunk_size); memset(row_buffer + chunk_size, bank->default_padded_value, psoc4_info->row_size - chunk_size);
} }
memcpy(row_buffer + row_offset, buffer, chunk_size); memcpy(row_buffer + row_offset, buffer, chunk_size);
LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "", LOG_DEBUG("offset / row: 0x%08" PRIx32 " / %" PRIu32 ", size %" PRIu32 "",
offset, row_offset, chunk_size); offset, row_offset, chunk_size);
uint32_t macro_idx = row_num / PSOC4_ROWS_PER_MACRO;
/* Call "Load Latch" system ROM API */ /* Call "Load Latch" system ROM API */
sysrq_buffer[1] = psoc4_info->row_size - 1; target_buffer_set_u32(target, (uint8_t *)(sysrq_buffer + 1),
retval = psoc4_sysreq(target, PSOC4_CMD_LOAD_LATCH, psoc4_info->row_size - 1);
0, /* Byte number in latch from what to write */ retval = psoc4_sysreq(bank, PSOC4_CMD_LOAD_LATCH,
sysrq_buffer, param_sz + psoc4_info->row_size); 0 /* Byte number in latch from what to write */
| (macro_idx << 8),
sysrq_buffer, param_sz + psoc4_info->row_size,
NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto cleanup; goto cleanup;
/* Call "Program Row" or "Write Row" system ROM API */ /* Call "Program Row" or "Write Row" system ROM API */
uint32_t sysrq_param; uint32_t sysrq_param;
retval = psoc4_sysreq(target, psoc4_info->cmd_program_row, retval = psoc4_sysreq(bank, psoc4_info->cmd_program_row,
row_num & 0xffff, row_num & 0xffff,
&sysrq_param, sizeof(sysrq_param)); &sysrq_param, sizeof(sysrq_param),
NULL);
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto cleanup; goto cleanup;
@ -593,80 +721,62 @@ static int psoc4_probe(struct flash_bank *bank)
{ {
struct psoc4_flash_bank *psoc4_info = bank->driver_priv; struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
struct target *target = bank->target; struct target *target = bank->target;
uint32_t flash_size_in_kb = 0;
uint32_t max_flash_size_in_kb;
uint32_t cpu_id;
uint32_t silicon_id;
uint32_t row_size;
uint32_t base_address = 0x00000000;
uint8_t protection;
if (target->state != TARGET_HALTED) { int retval;
LOG_ERROR("Target not halted"); uint16_t family_id;
return ERROR_TARGET_NOT_HALTED;
}
psoc4_info->probed = 0; psoc4_info->probed = false;
psoc4_info->cmd_program_row = PSOC4_CMD_PROGRAM_ROW;
/* Get the CPUID from the ARM Core retval = psoc4_get_family(target, &family_id);
* http://infocenter.arm.com/help/topic/com.arm.doc.ddi0432c/DDI0432C_cortex_m0_r0p0_trm.pdf 4.2.1 */
int retval = target_read_u32(target, 0xE000ED00, &cpu_id);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
LOG_DEBUG("cpu id = 0x%08" PRIx32 "", cpu_id); const struct psoc4_chip_family *family = psoc4_family_by_id(family_id);
/* set page size, protection granularity and max flash size depending on family */ if (family->id == 0) {
switch ((cpu_id >> 4) & 0xFFF) { LOG_ERROR("Cannot identify PSoC 4 family.");
case 0xc20: /* M0 -> PSoC4 */
row_size = 128;
max_flash_size_in_kb = 32;
break;
default:
LOG_WARNING("Cannot identify target as a PSoC 4 family.");
return ERROR_FAIL; return ERROR_FAIL;
} }
uint32_t spcif_geometry; if (family->flags & PSOC4_FAMILY_FLAG_LEGACY) {
retval = target_read_u32(target, PSOC4_SPCIF_GEOMETRY, &spcif_geometry); LOG_INFO("%s legacy family detected.", family->name);
if (retval == ERROR_OK) { psoc4_info->legacy_family = true;
row_size = 128 * ((spcif_geometry >> 22) & 3); psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_LEGACY;
flash_size_in_kb = (spcif_geometry & 0xffff) * 256 / 1024; psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_LEGACY;
LOG_INFO("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.", psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_LEGACY;
flash_size_in_kb, row_size); } else {
LOG_INFO("%s family detected.", family->name);
psoc4_info->legacy_family = false;
psoc4_info->cpuss_sysreq_addr = PSOC4_CPUSS_SYSREQ_NEW;
psoc4_info->cpuss_sysarg_addr = PSOC4_CPUSS_SYSARG_NEW;
psoc4_info->spcif_geometry_addr = PSOC4_SPCIF_GEOMETRY_NEW;
} }
/* Early revisions of ST-Link v2 have some problem reading PSOC4_SPCIF_GEOMETRY uint32_t spcif_geometry;
and an error is reported late. Dummy read gets this error. */ retval = target_read_u32(target, psoc4_info->spcif_geometry_addr, &spcif_geometry);
uint32_t dummy;
target_read_u32(target, PSOC4_CPUSS_SYSREQ, &dummy);
/* get silicon ID from target. */
retval = psoc4_get_silicon_id(target, &silicon_id, &protection);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
const struct psoc4_chip_details *details = psoc4_details_by_id(silicon_id); uint32_t flash_size_in_kb = spcif_geometry & 0x3fff;
if (details) { /* TRM of legacy, M and L version describes FLASH field as 16-bit.
LOG_INFO("%s device detected.", details->type); * S-series and PSoC Analog Coprocessor changes spec to 14-bit only.
if (flash_size_in_kb == 0) * Impose PSoC Analog Coprocessor limit to all devices as it
flash_size_in_kb = details->flash_size_in_kb; * does not make any harm: flash size is safely below 4 MByte limit
else if (flash_size_in_kb != details->flash_size_in_kb) */
LOG_ERROR("Flash size mismatch"); uint32_t row_size = (spcif_geometry >> 22) & 3;
uint32_t num_macros = (spcif_geometry >> 20) & 3;
if (psoc4_info->legacy_family) {
flash_size_in_kb = flash_size_in_kb * 256 / 1024;
row_size *= 128;
} else {
flash_size_in_kb = (flash_size_in_kb + 1) * 256 / 1024;
row_size = 64 * (row_size + 1);
num_macros++;
} }
psoc4_info->row_size = row_size; LOG_DEBUG("SPCIF geometry: %" PRIu32 " kb flash, row %" PRIu32 " bytes.",
psoc4_info->silicon_id = silicon_id; flash_size_in_kb, row_size);
psoc4_info->chip_protection = protection;
/* failed reading flash size or flash size invalid (early silicon),
* default to max target family */
if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) {
LOG_WARNING("PSoC 4 flash size failed, probe inaccurate - assuming %" PRIu32 " k flash",
max_flash_size_in_kb);
flash_size_in_kb = max_flash_size_in_kb;
}
/* if the user sets the size manually then ignore the probed value /* if the user sets the size manually then ignore the probed value
* this allows us to work around devices that have a invalid flash size register value */ * this allows us to work around devices that have a invalid flash size register value */
@ -675,37 +785,35 @@ static int psoc4_probe(struct flash_bank *bank)
flash_size_in_kb = psoc4_info->user_bank_size / 1024; flash_size_in_kb = psoc4_info->user_bank_size / 1024;
} }
LOG_INFO("flash size = %" PRIu32 " kbytes", flash_size_in_kb); char macros_txt[20] = "";
if (num_macros > 1)
snprintf(macros_txt, sizeof(macros_txt), " in %" PRIu32 " macros", num_macros);
/* did we assign flash size? */ LOG_INFO("flash size = %" PRIu32 " kbytes%s", flash_size_in_kb, macros_txt);
assert(flash_size_in_kb != 0xffff);
/* calculate numbers of pages */ /* calculate number of pages */
uint32_t num_rows = flash_size_in_kb * 1024 / row_size; uint32_t num_rows = flash_size_in_kb * 1024 / row_size;
/* check that calculation result makes sense */ /* check number of flash macros */
assert(num_rows > 0); if (num_macros != (num_rows + PSOC4_ROWS_PER_MACRO - 1) / PSOC4_ROWS_PER_MACRO)
LOG_WARNING("Number of macros does not correspond with flash size!");
if (bank->sectors) { if (bank->sectors) {
free(bank->sectors); free(bank->sectors);
bank->sectors = NULL;
} }
bank->base = base_address; psoc4_info->family_id = family_id;
psoc4_info->num_macros = num_macros;
psoc4_info->row_size = row_size;
bank->base = 0x00000000;
bank->size = num_rows * row_size; bank->size = num_rows * row_size;
bank->num_sectors = num_rows; bank->num_sectors = num_rows;
bank->sectors = malloc(sizeof(struct flash_sector) * num_rows); bank->sectors = alloc_block_array(0, row_size, num_rows);
if (bank->sectors == NULL)
return ERROR_FAIL;
uint32_t i; LOG_DEBUG("flash bank set %" PRIu32 " rows", num_rows);
for (i = 0; i < num_rows; i++) { psoc4_info->probed = true;
bank->sectors[i].offset = i * row_size;
bank->sectors[i].size = row_size;
bank->sectors[i].is_erased = -1;
bank->sectors[i].is_protected = 1;
}
LOG_INFO("flash bank set %" PRIu32 " rows", num_rows);
psoc4_info->probed = 1;
return ERROR_OK; return ERROR_OK;
} }
@ -721,28 +829,45 @@ static int psoc4_auto_probe(struct flash_bank *bank)
static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size) static int get_psoc4_info(struct flash_bank *bank, char *buf, int buf_size)
{ {
struct target *target = bank->target;
struct psoc4_flash_bank *psoc4_info = bank->driver_priv; struct psoc4_flash_bank *psoc4_info = bank->driver_priv;
int printed = 0;
if (psoc4_info->probed == 0) if (!psoc4_info->probed)
return ERROR_FAIL; return ERROR_FAIL;
const struct psoc4_chip_details *details = psoc4_details_by_id(psoc4_info->silicon_id); const struct psoc4_chip_family *family = psoc4_family_by_id(psoc4_info->family_id);
uint32_t size_in_kb = bank->size / 1024;
if (details) { if (target->state != TARGET_HALTED) {
uint32_t chip_revision = psoc4_info->silicon_id & 0xffff; snprintf(buf, buf_size, "%s, flash %" PRIu32 " kb"
printed = snprintf(buf, buf_size, "PSoC 4 %s rev 0x%04" PRIx32 " package %s", " (halt target to see details)", family->name, size_in_kb);
details->type, chip_revision, details->package); return ERROR_OK;
} else }
printed = snprintf(buf, buf_size, "PSoC 4 silicon id 0x%08" PRIx32 "",
psoc4_info->silicon_id); int retval;
int printed = 0;
uint32_t silicon_id;
uint16_t family_id;
uint8_t protection;
retval = psoc4_get_silicon_id(bank, &silicon_id, &family_id, &protection);
if (retval != ERROR_OK)
return retval;
if (family_id != psoc4_info->family_id)
printed = snprintf(buf, buf_size, "Family id mismatch 0x%02" PRIx16
"/0x%02" PRIx16 ", silicon id 0x%08" PRIx32,
psoc4_info->family_id, family_id, silicon_id);
else {
printed = snprintf(buf, buf_size, "%s silicon id 0x%08" PRIx32 "",
family->name, silicon_id);
}
buf += printed; buf += printed;
buf_size -= printed; buf_size -= printed;
const char *prot_txt = psoc4_decode_chip_protection(psoc4_info->chip_protection); const char *prot_txt = psoc4_decode_chip_protection(protection);
uint32_t size_in_kb = bank->size / 1024; snprintf(buf, buf_size, ", flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
snprintf(buf, buf_size, " flash %" PRIu32 " kb %s", size_in_kb, prot_txt);
return ERROR_OK; return ERROR_OK;
} }

View File

@ -1,4 +1,4 @@
# script for Cypress PSoC 41xx/42xx family # script for Cypress PSoC 4 devices
# #
# PSoC 4 devices support SWD transports only. # PSoC 4 devices support SWD transports only.
@ -53,8 +53,14 @@ adapter_khz 1500
# set in time frame 400 usec delayed about 1 msec from reset. # set in time frame 400 usec delayed about 1 msec from reset.
# #
# OpenOCD have no standard way how to set TEST_MODE in specified time frame. # OpenOCD have no standard way how to set TEST_MODE in specified time frame.
# TEST_MODE flag is set before reset instead. It worked for tested chips # As a workaround the TEST_MODE flag is set before reset instead.
# despite it is not guaranteed by specification. # It worked for the oldest family PSoC4100/4200 even though it is not guaranteed
# by specification.
#
# Newer families like PSoC 4000, 4100M, 4200M, 4100L, 4200L and PSoC 4 BLE
# clear TEST_MODE flag during device reset so workaround is not possible.
# Use a KitProg adapter for theese devices or "reset halt" will not stop
# before executing user code.
# #
# 3) SWD cannot be connected during system initialization after reset. # 3) SWD cannot be connected during system initialization after reset.
# This might be a reason for unconnecting ST-Link v2 when deasserting reset. # This might be a reason for unconnecting ST-Link v2 when deasserting reset.
@ -66,11 +72,34 @@ if {![using_hla]} {
cortex_m reset_config sysresetreq cortex_m reset_config sysresetreq
} }
proc ocd_process_reset_inner { MODE } { proc psoc4_get_family_id {} {
if { 0 != [string compare psoc4.cpu [target names]] } { set err [catch "mem2array romtable_pid 32 0xF0000FE0 3"]
return -code error "PSoC 4 reset can handle only one psoc4.cpu target"; if { $err } {
return 0
} }
set t psoc4.cpu if { [expr $romtable_pid(0) & 0xffffff00 ]
|| [expr $romtable_pid(1) & 0xffffff00 ]
|| [expr $romtable_pid(2) & 0xffffff00 ] } {
echo "Unexpected data in ROMTABLE"
return 0
}
set designer_id [expr (( $romtable_pid(1) & 0xf0 ) >> 4) | (( $romtable_pid(2) & 0xf ) << 4 ) ]
if { $designer_id != 0xb4 } {
echo [format "ROMTABLE Designer ID 0x%02x is not Cypress" $designer_id]
return 0
}
set family_id [expr ( $romtable_pid(0) & 0xff ) | (( $romtable_pid(1) & 0xf ) << 8 ) ]
return $family_id
}
proc ocd_process_reset_inner { MODE } {
global PSOC4_USE_ACQUIRE PSOC4_TEST_MODE_WORKAROUND
global _TARGETNAME
if { 0 != [string compare $_TARGETNAME [target names]] } {
return -code error "PSoC 4 reset can handle only one $_TARGETNAME target";
}
set t $_TARGETNAME
# If this target must be halted... # If this target must be halted...
set halt -1 set halt -1
@ -87,17 +116,42 @@ proc ocd_process_reset_inner { MODE } {
return -code error "Invalid mode: $MODE, must be one of: halt, init, or run"; return -code error "Invalid mode: $MODE, must be one of: halt, init, or run";
} }
if { ! [info exists PSOC4_USE_ACQUIRE] } {
if { 0 == [string compare [adapter_name] kitprog ] } {
set PSOC4_USE_ACQUIRE 1
} else {
set PSOC4_USE_ACQUIRE 0
}
}
if { $PSOC4_USE_ACQUIRE } {
set PSOC4_TEST_MODE_WORKAROUND 0
} elseif { ! [info exists PSOC4_TEST_MODE_WORKAROUND] } {
if { [psoc4_get_family_id] == 0x93 } {
set PSOC4_TEST_MODE_WORKAROUND 1
} else {
set PSOC4_TEST_MODE_WORKAROUND 0
}
}
#$t invoke-event reset-start #$t invoke-event reset-start
$t invoke-event reset-assert-pre $t invoke-event reset-assert-pre
set TEST_MODE 0x40030014 if { $halt && $PSOC4_USE_ACQUIRE } {
if { $halt == 1 } { catch { [adapter_name] acquire_psoc }
mww $TEST_MODE 0x80000000 $t arp_examine
} else { } else {
mww $TEST_MODE 0 if { $PSOC4_TEST_MODE_WORKAROUND } {
set TEST_MODE 0x40030014
if { $halt == 1 } {
catch { mww $TEST_MODE 0x80000000 }
} else {
catch { mww $TEST_MODE 0 }
}
}
$t arp_reset assert 0
} }
$t arp_reset assert 0
$t invoke-event reset-assert-post $t invoke-event reset-assert-post
$t invoke-event reset-deassert-pre $t invoke-event reset-deassert-pre
if {![using_hla]} { # workaround ST-Link v2 fails and forcing reconnect if {![using_hla]} { # workaround ST-Link v2 fails and forcing reconnect
@ -127,7 +181,14 @@ proc ocd_process_reset_inner { MODE } {
set pc [ocd_reg pc] set pc [ocd_reg pc]
regsub {pc[^:]*: } $pc "" pc regsub {pc[^:]*: } $pc "" pc
if { $pc < 0x10000000 || $pc > 0x1000ffff } { if { $pc < 0x10000000 || $pc > 0x1000ffff } {
return -code error [format "TARGET: %s - Not halted in system ROM, use 'reset_config none'" $t] set hint ""
set family_id [psoc4_get_family_id]
if { $family_id == 0x93 } {
set hint ", use 'reset_config none'"
} elseif { $family_id > 0x93 } {
set hint ", use a KitProg adapter"
}
return -code error [format "TARGET: %s - Not halted in system ROM%s" $t $hint]
} }
# Set registers to reset vector values # Set registers to reset vector values
@ -135,7 +196,9 @@ proc ocd_process_reset_inner { MODE } {
reg pc [expr $value(1) & 0xfffffffe ] reg pc [expr $value(1) & 0xfffffffe ]
reg msp $value(0) reg msp $value(0)
mww $TEST_MODE 0 if { $PSOC4_TEST_MODE_WORKAROUND } {
catch { mww $TEST_MODE 0 }
}
} }
#Pass 2 - if needed "init" #Pass 2 - if needed "init"