@@ -2386,6 +2386,20 @@ static int aarch64_target_create(struct target *target, Jim_Interp *interp)
|
||||
return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
|
||||
}
|
||||
|
||||
static void aarch64_deinit_target(struct target *target)
|
||||
{
|
||||
struct aarch64_common *aarch64 = target_to_aarch64(target);
|
||||
struct armv8_common *armv8 = &aarch64->armv8_common;
|
||||
struct arm_dpm *dpm = &armv8->dpm;
|
||||
|
||||
armv8_free_reg_cache(target);
|
||||
free(aarch64->brp_list);
|
||||
free(dpm->dbp);
|
||||
free(dpm->dwp);
|
||||
free(target->private_config);
|
||||
free(aarch64);
|
||||
}
|
||||
|
||||
static int aarch64_mmu(struct target *target, int *enabled)
|
||||
{
|
||||
if (target->state != TARGET_HALTED) {
|
||||
@@ -2658,6 +2672,7 @@ struct target_type aarch64_target = {
|
||||
.target_create = aarch64_target_create,
|
||||
.target_jim_configure = aarch64_jim_configure,
|
||||
.init_target = aarch64_init_target,
|
||||
.deinit_target = aarch64_deinit_target,
|
||||
.examine = aarch64_examine,
|
||||
|
||||
.read_phys_memory = aarch64_read_phys_memory,
|
||||
|
||||
@@ -553,7 +553,7 @@ static int jtagdp_overrun_check(struct adiv5_dap *dap)
|
||||
static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||
{
|
||||
int retval;
|
||||
uint32_t ctrlstat;
|
||||
uint32_t ctrlstat, pwrmask;
|
||||
|
||||
/* too expensive to call keep_alive() here */
|
||||
|
||||
@@ -571,8 +571,10 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
|
||||
if (ctrlstat & SSTICKYERR) {
|
||||
LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat);
|
||||
/* Check power to debug regions */
|
||||
if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) !=
|
||||
(CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) {
|
||||
pwrmask = CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ;
|
||||
if (!dap->ignore_syspwrupack)
|
||||
pwrmask |= CSYSPWRUPACK;
|
||||
if ((ctrlstat & pwrmask) != pwrmask) {
|
||||
LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened");
|
||||
dap->do_reconnect = true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -308,7 +308,7 @@ int armv4_5_run_algorithm_inner(struct target *target,
|
||||
int arm_checksum_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *checksum);
|
||||
int arm_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
|
||||
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value);
|
||||
|
||||
void arm_set_cpsr(struct arm *arm, uint32_t cpsr);
|
||||
struct reg *arm_reg_current(struct arm *arm, unsigned regnum);
|
||||
|
||||
+33
-21
@@ -97,8 +97,7 @@ static uint32_t max_tar_block_size(uint32_t tar_autoincr_block, uint32_t address
|
||||
|
||||
static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw)
|
||||
{
|
||||
csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT |
|
||||
ap->csw_default;
|
||||
csw |= ap->csw_default;
|
||||
|
||||
if (csw != ap->csw_value) {
|
||||
/* LOG_DEBUG("DAP: Set CSW %x",csw); */
|
||||
@@ -676,12 +675,14 @@ int dap_dp_init(struct adiv5_dap *dap)
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
LOG_DEBUG("DAP: wait CSYSPWRUPACK");
|
||||
retval = dap_dp_poll_register(dap, DP_CTRL_STAT,
|
||||
CSYSPWRUPACK, CSYSPWRUPACK,
|
||||
DAP_POWER_DOMAIN_TIMEOUT);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
if (!dap->ignore_syspwrupack) {
|
||||
LOG_DEBUG("DAP: wait CSYSPWRUPACK");
|
||||
retval = dap_dp_poll_register(dap, DP_CTRL_STAT,
|
||||
CSYSPWRUPACK, CSYSPWRUPACK,
|
||||
DAP_POWER_DOMAIN_TIMEOUT);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL);
|
||||
if (retval != ERROR_OK)
|
||||
@@ -1645,22 +1646,33 @@ COMMAND_HANDLER(dap_apcsw_command)
|
||||
{
|
||||
struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
|
||||
uint32_t apcsw = dap->ap[dap->apsel].csw_default;
|
||||
uint32_t sprot = 0;
|
||||
uint32_t csw_val, csw_mask;
|
||||
|
||||
switch (CMD_ARGC) {
|
||||
case 0:
|
||||
command_print(CMD_CTX, "apsel %" PRIi32 " selected, csw 0x%8.8" PRIx32,
|
||||
(dap->apsel), apcsw);
|
||||
break;
|
||||
command_print(CMD_CTX, "ap %" PRIi32 " selected, csw 0x%8.8" PRIx32,
|
||||
dap->apsel, apcsw);
|
||||
return ERROR_OK;
|
||||
case 1:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], sprot);
|
||||
/* AP address is in bits 31:24 of DP_SELECT */
|
||||
if (sprot > 1)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
if (sprot)
|
||||
apcsw |= CSW_SPROT;
|
||||
if (strcmp(CMD_ARGV[0], "default") == 0)
|
||||
csw_val = CSW_DEFAULT;
|
||||
else
|
||||
apcsw &= ~CSW_SPROT;
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], csw_val);
|
||||
|
||||
if (csw_val & (CSW_SIZE_MASK | CSW_ADDRINC_MASK)) {
|
||||
LOG_ERROR("CSW value cannot include 'Size' and 'AddrInc' bit-fields");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
apcsw = csw_val;
|
||||
break;
|
||||
case 2:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], csw_val);
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], csw_mask);
|
||||
if (csw_mask & (CSW_SIZE_MASK | CSW_ADDRINC_MASK)) {
|
||||
LOG_ERROR("CSW mask cannot include 'Size' and 'AddrInc' bit-fields");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
apcsw = (apcsw & ~csw_mask) | (csw_val & csw_mask);
|
||||
break;
|
||||
default:
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
@@ -1784,8 +1796,8 @@ const struct command_registration dap_instance_commands[] = {
|
||||
.name = "apcsw",
|
||||
.handler = dap_apcsw_command,
|
||||
.mode = COMMAND_EXEC,
|
||||
.help = "Set csw access bit ",
|
||||
.usage = "[sprot]",
|
||||
.help = "Set CSW default bits",
|
||||
.usage = "[value [mask]]",
|
||||
},
|
||||
|
||||
{
|
||||
|
||||
+10
-3
@@ -112,13 +112,16 @@
|
||||
#define CSW_ADDRINC_PACKED (2UL << 4)
|
||||
#define CSW_DEVICE_EN (1UL << 6)
|
||||
#define CSW_TRIN_PROG (1UL << 7)
|
||||
/* all fields in bits 12 and above are implementation-defined! */
|
||||
#define CSW_SPIDEN (1UL << 23)
|
||||
/* 30:24 - implementation-defined! */
|
||||
#define CSW_HPROT (1UL << 25) /* ? */
|
||||
#define CSW_MASTER_DEBUG (1UL << 29) /* ? */
|
||||
#define CSW_HPROT1 (1UL << 25) /* AHB: Privileged */
|
||||
#define CSW_MASTER_DEBUG (1UL << 29) /* AHB: set HMASTER signals to AHB-AP ID */
|
||||
#define CSW_SPROT (1UL << 30)
|
||||
#define CSW_DBGSWENABLE (1UL << 31)
|
||||
|
||||
/* initial value of csw_default used for MEM-AP transfers */
|
||||
#define CSW_DEFAULT (CSW_HPROT1 | CSW_MASTER_DEBUG | CSW_DBGSWENABLE)
|
||||
|
||||
/* Fields of the MEM-AP's IDR register */
|
||||
#define IDR_REV (0xFUL << 28)
|
||||
#define IDR_JEP106 (0x7FFUL << 17)
|
||||
@@ -244,6 +247,10 @@ struct adiv5_dap {
|
||||
* should be performed before the next access.
|
||||
*/
|
||||
bool do_reconnect;
|
||||
|
||||
/** Flag saying whether to ignore the syspwrupack flag in DAP. Some devices
|
||||
* do not set this bit until later in the bringup sequence */
|
||||
bool ignore_syspwrupack;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -219,6 +219,18 @@ static int cti_find_reg_offset(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int arm_cti_cleanup_all(void)
|
||||
{
|
||||
struct arm_cti_object *obj, *tmp;
|
||||
|
||||
list_for_each_entry_safe(obj, tmp, &all_cti, lh) {
|
||||
free(obj->name);
|
||||
free(obj);
|
||||
}
|
||||
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
COMMAND_HANDLER(handle_cti_dump)
|
||||
{
|
||||
struct arm_cti_object *obj = CMD_DATA;
|
||||
|
||||
@@ -73,7 +73,7 @@ extern int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *va
|
||||
extern int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel);
|
||||
extern int arm_cti_set_channel(struct arm_cti *self, uint32_t channel);
|
||||
extern int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel);
|
||||
|
||||
extern int arm_cti_cleanup_all(void);
|
||||
extern int cti_register_commands(struct command_context *cmd_ctx);
|
||||
|
||||
#endif /* OPENOCD_TARGET_ARM_CTI_H */
|
||||
|
||||
@@ -55,6 +55,8 @@ static void dap_instance_init(struct adiv5_dap *dap)
|
||||
dap->ap[i].memaccess_tck = 255;
|
||||
/* Number of bits for tar autoincrement, impl. dep. at least 10 */
|
||||
dap->ap[i].tar_autoincr_block = (1<<10);
|
||||
/* default CSW value */
|
||||
dap->ap[i].csw_default = CSW_DEFAULT;
|
||||
}
|
||||
INIT_LIST_HEAD(&dap->cmd_journal);
|
||||
}
|
||||
@@ -141,10 +143,12 @@ int dap_cleanup_all(void)
|
||||
|
||||
enum dap_cfg_param {
|
||||
CFG_CHAIN_POSITION,
|
||||
CFG_IGNORE_SYSPWRUPACK,
|
||||
};
|
||||
|
||||
static const Jim_Nvp nvp_config_opts[] = {
|
||||
{ .name = "-chain-position", .value = CFG_CHAIN_POSITION },
|
||||
{ .name = "-ignore-syspwrupack", .value = CFG_IGNORE_SYSPWRUPACK },
|
||||
{ .name = NULL, .value = -1 }
|
||||
};
|
||||
|
||||
@@ -177,6 +181,9 @@ static int dap_configure(Jim_GetOptInfo *goi, struct arm_dap_object *dap)
|
||||
/* loop for more */
|
||||
break;
|
||||
}
|
||||
case CFG_IGNORE_SYSPWRUPACK:
|
||||
dap->dap.ignore_syspwrupack = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -587,11 +587,13 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
|
||||
goto done;
|
||||
arm->pc->dirty = false;
|
||||
|
||||
/* flush R0 -- it's *very* dirty by now */
|
||||
retval = dpm_write_reg(dpm, &cache->reg_list[0], 0);
|
||||
if (retval != ERROR_OK)
|
||||
goto done;
|
||||
cache->reg_list[0].dirty = false;
|
||||
/* flush R0 and R1 (our scratch registers) */
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
retval = dpm_write_reg(dpm, &cache->reg_list[i], i);
|
||||
if (retval != ERROR_OK)
|
||||
goto done;
|
||||
cache->reg_list[i].dirty = false;
|
||||
}
|
||||
|
||||
/* (void) */ dpm->finish(dpm);
|
||||
done:
|
||||
|
||||
@@ -1663,7 +1663,7 @@ cleanup:
|
||||
*
|
||||
*/
|
||||
int arm_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
|
||||
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
|
||||
{
|
||||
struct working_area *check_algorithm;
|
||||
struct reg_param reg_params[3];
|
||||
@@ -1706,10 +1706,10 @@ int arm_blank_check_memory(struct target *target,
|
||||
arm_algo.core_state = ARM_STATE_ARM;
|
||||
|
||||
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, address);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
|
||||
|
||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, count);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
|
||||
|
||||
init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, erased_value);
|
||||
@@ -1724,7 +1724,7 @@ int arm_blank_check_memory(struct target *target,
|
||||
10000, &arm_algo);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
*blank = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
@@ -1733,7 +1733,10 @@ int arm_blank_check_memory(struct target *target,
|
||||
cleanup:
|
||||
target_free_working_area(target, check_algorithm);
|
||||
|
||||
return retval;
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
return 1; /* only one block has been checked */
|
||||
}
|
||||
|
||||
static int arm_full_context(struct target *target)
|
||||
|
||||
+95
-36
@@ -731,34 +731,23 @@ cleanup:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/** Checks whether a memory region is erased. */
|
||||
/** Checks an array of memory regions whether they are erased. */
|
||||
int armv7m_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
|
||||
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
|
||||
{
|
||||
struct working_area *erase_check_algorithm;
|
||||
struct reg_param reg_params[3];
|
||||
struct working_area *erase_check_params;
|
||||
struct reg_param reg_params[2];
|
||||
struct armv7m_algorithm armv7m_info;
|
||||
const uint8_t *code;
|
||||
uint32_t code_size;
|
||||
int retval;
|
||||
|
||||
static bool timed_out;
|
||||
|
||||
static const uint8_t erase_check_code[] = {
|
||||
#include "../../contrib/loaders/erase_check/armv7m_erase_check.inc"
|
||||
};
|
||||
static const uint8_t zero_erase_check_code[] = {
|
||||
#include "../../contrib/loaders/erase_check/armv7m_0_erase_check.inc"
|
||||
};
|
||||
|
||||
switch (erased_value) {
|
||||
case 0x00:
|
||||
code = zero_erase_check_code;
|
||||
code_size = sizeof(zero_erase_check_code);
|
||||
break;
|
||||
case 0xff:
|
||||
default:
|
||||
code = erase_check_code;
|
||||
code_size = sizeof(erase_check_code);
|
||||
}
|
||||
const uint32_t code_size = sizeof(erase_check_code);
|
||||
|
||||
/* make sure we have a working area */
|
||||
if (target_alloc_working_area(target, code_size,
|
||||
@@ -766,40 +755,110 @@ int armv7m_blank_check_memory(struct target *target,
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
|
||||
retval = target_write_buffer(target, erase_check_algorithm->address,
|
||||
code_size, code);
|
||||
code_size, erase_check_code);
|
||||
if (retval != ERROR_OK)
|
||||
goto cleanup;
|
||||
goto cleanup1;
|
||||
|
||||
/* prepare blocks array for algo */
|
||||
struct algo_block {
|
||||
union {
|
||||
uint32_t size;
|
||||
uint32_t result;
|
||||
};
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
uint32_t avail = target_get_working_area_avail(target);
|
||||
int blocks_to_check = avail / sizeof(struct algo_block) - 1;
|
||||
if (num_blocks < blocks_to_check)
|
||||
blocks_to_check = num_blocks;
|
||||
|
||||
struct algo_block *params = malloc((blocks_to_check+1)*sizeof(struct algo_block));
|
||||
if (params == NULL) {
|
||||
retval = ERROR_FAIL;
|
||||
goto cleanup1;
|
||||
}
|
||||
|
||||
int i;
|
||||
uint32_t total_size = 0;
|
||||
for (i = 0; i < blocks_to_check; i++) {
|
||||
total_size += blocks[i].size;
|
||||
target_buffer_set_u32(target, (uint8_t *)&(params[i].size),
|
||||
blocks[i].size / sizeof(uint32_t));
|
||||
target_buffer_set_u32(target, (uint8_t *)&(params[i].address),
|
||||
blocks[i].address);
|
||||
}
|
||||
target_buffer_set_u32(target, (uint8_t *)&(params[blocks_to_check].size), 0);
|
||||
|
||||
uint32_t param_size = (blocks_to_check + 1) * sizeof(struct algo_block);
|
||||
if (target_alloc_working_area(target, param_size,
|
||||
&erase_check_params) != ERROR_OK) {
|
||||
retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
goto cleanup2;
|
||||
}
|
||||
|
||||
retval = target_write_buffer(target, erase_check_params->address,
|
||||
param_size, (uint8_t *)params);
|
||||
if (retval != ERROR_OK)
|
||||
goto cleanup3;
|
||||
|
||||
uint32_t erased_word = erased_value | (erased_value << 8)
|
||||
| (erased_value << 16) | (erased_value << 24);
|
||||
|
||||
LOG_DEBUG("Starting erase check of %d blocks, parameters@"
|
||||
TARGET_ADDR_FMT, blocks_to_check, erase_check_params->address);
|
||||
|
||||
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
|
||||
armv7m_info.core_mode = ARM_MODE_THREAD;
|
||||
|
||||
init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, address);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, erase_check_params->address);
|
||||
|
||||
init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, count);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, erased_word);
|
||||
|
||||
init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, erased_value);
|
||||
/* assume CPU clk at least 1 MHz */
|
||||
int timeout = (timed_out ? 30000 : 2000) + total_size * 3 / 1000;
|
||||
|
||||
retval = target_run_algorithm(target,
|
||||
0,
|
||||
NULL,
|
||||
3,
|
||||
reg_params,
|
||||
erase_check_algorithm->address,
|
||||
erase_check_algorithm->address + (code_size - 2),
|
||||
10000,
|
||||
&armv7m_info);
|
||||
0, NULL,
|
||||
ARRAY_SIZE(reg_params), reg_params,
|
||||
erase_check_algorithm->address,
|
||||
erase_check_algorithm->address + (code_size - 2),
|
||||
timeout,
|
||||
&armv7m_info);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
*blank = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
timed_out = retval == ERROR_TARGET_TIMEOUT;
|
||||
if (retval != ERROR_OK && !timed_out)
|
||||
goto cleanup4;
|
||||
|
||||
retval = target_read_buffer(target, erase_check_params->address,
|
||||
param_size, (uint8_t *)params);
|
||||
if (retval != ERROR_OK)
|
||||
goto cleanup4;
|
||||
|
||||
for (i = 0; i < blocks_to_check; i++) {
|
||||
uint32_t result = target_buffer_get_u32(target,
|
||||
(uint8_t *)&(params[i].result));
|
||||
if (result != 0 && result != 1)
|
||||
break;
|
||||
|
||||
blocks[i].result = result;
|
||||
}
|
||||
if (i && timed_out)
|
||||
LOG_INFO("Slow CPU clock: %d blocks checked, %d remain. Continuing...", i, num_blocks-i);
|
||||
|
||||
retval = i; /* return number of blocks really checked */
|
||||
|
||||
cleanup4:
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
destroy_reg_param(®_params[2]);
|
||||
|
||||
cleanup:
|
||||
cleanup3:
|
||||
target_free_working_area(target, erase_check_params);
|
||||
cleanup2:
|
||||
free(params);
|
||||
cleanup1:
|
||||
target_free_working_area(target, erase_check_algorithm);
|
||||
|
||||
return retval;
|
||||
|
||||
+1
-1
@@ -225,7 +225,7 @@ int armv7m_restore_context(struct target *target);
|
||||
int armv7m_checksum_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *checksum);
|
||||
int armv7m_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
|
||||
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value);
|
||||
|
||||
int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found);
|
||||
|
||||
|
||||
+40
-6
@@ -1547,15 +1547,14 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
|
||||
} else
|
||||
LOG_ERROR("unable to allocate feature list");
|
||||
|
||||
if (armv8_regs[i].data_type == NULL) {
|
||||
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
|
||||
if (reg_list[i].reg_data_type)
|
||||
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
|
||||
if (reg_list[i].reg_data_type) {
|
||||
if (armv8_regs[i].data_type == NULL)
|
||||
reg_list[i].reg_data_type->type = armv8_regs[i].type;
|
||||
else
|
||||
LOG_ERROR("unable to allocate reg type list");
|
||||
*reg_list[i].reg_data_type = *armv8_regs[i].data_type;
|
||||
} else
|
||||
reg_list[i].reg_data_type = armv8_regs[i].data_type;
|
||||
|
||||
LOG_ERROR("unable to allocate reg type list");
|
||||
}
|
||||
|
||||
arm->cpsr = reg_list + ARMV8_xPSR;
|
||||
@@ -1608,6 +1607,41 @@ struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
|
||||
return r;
|
||||
}
|
||||
|
||||
static void armv8_free_cache(struct reg_cache *cache, bool regs32)
|
||||
{
|
||||
struct reg *reg;
|
||||
unsigned int i;
|
||||
|
||||
if (!cache)
|
||||
return;
|
||||
|
||||
for (i = 0; i < cache->num_regs; i++) {
|
||||
reg = &cache->reg_list[i];
|
||||
|
||||
free(reg->feature);
|
||||
free(reg->reg_data_type);
|
||||
}
|
||||
|
||||
if (!regs32)
|
||||
free(cache->reg_list[0].arch_info);
|
||||
free(cache->reg_list);
|
||||
free(cache);
|
||||
}
|
||||
|
||||
void armv8_free_reg_cache(struct target *target)
|
||||
{
|
||||
struct armv8_common *armv8 = target_to_armv8(target);
|
||||
struct arm *arm = &armv8->arm;
|
||||
struct reg_cache *cache = NULL, *cache32 = NULL;
|
||||
|
||||
cache = arm->core_cache;
|
||||
if (cache != NULL)
|
||||
cache32 = cache->next;
|
||||
armv8_free_cache(cache32, true);
|
||||
armv8_free_cache(cache, false);
|
||||
arm->core_cache = NULL;
|
||||
}
|
||||
|
||||
const struct command_registration armv8_command_handlers[] = {
|
||||
COMMAND_REGISTRATION_DONE
|
||||
};
|
||||
|
||||
@@ -318,6 +318,8 @@ static inline unsigned int armv8_curel_from_core_mode(enum arm_mode core_mode)
|
||||
void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64);
|
||||
int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value);
|
||||
|
||||
extern void armv8_free_reg_cache(struct target *target);
|
||||
|
||||
extern const struct command_registration armv8_command_handlers[];
|
||||
|
||||
#endif /* OPENOCD_TARGET_ARMV8_H */
|
||||
|
||||
+1
-28
@@ -51,11 +51,6 @@
|
||||
* any longer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the type of a break point required by address location
|
||||
*/
|
||||
#define BKPT_TYPE_BY_ADDR(addr) ((addr) < 0x20000000 ? BKPT_HARD : BKPT_SOFT)
|
||||
|
||||
/* forward declarations */
|
||||
static int cortex_m_store_core_reg_u32(struct target *target,
|
||||
uint32_t num, uint32_t value);
|
||||
@@ -868,7 +863,7 @@ static int cortex_m_step(struct target *target, int current,
|
||||
if (breakpoint)
|
||||
retval = cortex_m_set_breakpoint(target, breakpoint);
|
||||
else
|
||||
retval = breakpoint_add(target, pc_value, 2, BKPT_TYPE_BY_ADDR(pc_value));
|
||||
retval = breakpoint_add(target, pc_value, 2, BKPT_HARD);
|
||||
bool tmp_bp_set = (retval == ERROR_OK);
|
||||
|
||||
/* No more breakpoints left, just do a step */
|
||||
@@ -1131,9 +1126,6 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
|
||||
return ERROR_OK;
|
||||
}
|
||||
|
||||
if (cortex_m->auto_bp_type)
|
||||
breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
|
||||
|
||||
if (breakpoint->type == BKPT_HARD) {
|
||||
uint32_t fpcr_value;
|
||||
while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code))
|
||||
@@ -1253,21 +1245,6 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint
|
||||
{
|
||||
struct cortex_m_common *cortex_m = target_to_cm(target);
|
||||
|
||||
if (cortex_m->auto_bp_type)
|
||||
breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
|
||||
|
||||
if (breakpoint->type != BKPT_TYPE_BY_ADDR(breakpoint->address)) {
|
||||
if (breakpoint->type == BKPT_HARD) {
|
||||
LOG_INFO("flash patch comparator requested outside code memory region");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (breakpoint->type == BKPT_SOFT) {
|
||||
LOG_INFO("soft breakpoint requested in code (flash) memory region");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((breakpoint->type == BKPT_HARD) && (cortex_m->fp_code_available < 1)) {
|
||||
LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
@@ -1299,9 +1276,6 @@ int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpo
|
||||
return ERROR_TARGET_NOT_HALTED;
|
||||
}
|
||||
|
||||
if (cortex_m->auto_bp_type)
|
||||
breakpoint->type = BKPT_TYPE_BY_ADDR(breakpoint->address);
|
||||
|
||||
if (breakpoint->set)
|
||||
cortex_m_unset_breakpoint(target, breakpoint);
|
||||
|
||||
@@ -2111,7 +2085,6 @@ int cortex_m_examine(struct target *target)
|
||||
|
||||
/* Setup FPB */
|
||||
target_read_u32(target, FP_CTRL, &fpcr);
|
||||
cortex_m->auto_bp_type = 1;
|
||||
/* bits [14:12] and [7:4] */
|
||||
cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF);
|
||||
cortex_m->fp_num_lit = (fpcr >> 8) & 0xF;
|
||||
|
||||
@@ -175,7 +175,6 @@ struct cortex_m_common {
|
||||
int fp_code_available;
|
||||
int fp_rev;
|
||||
int fpb_enabled;
|
||||
int auto_bp_type;
|
||||
struct cortex_m_fp_comparator *fp_comparator_list;
|
||||
|
||||
/* Data Watchpoint and Trace (DWT) */
|
||||
|
||||
+11
-6
@@ -827,7 +827,8 @@ int mips32_checksum_memory(struct target *target, target_addr_t address,
|
||||
|
||||
/** Checks whether a memory region is erased. */
|
||||
int mips32_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
|
||||
struct target_memory_check_block *blocks, int num_blocks,
|
||||
uint8_t erased_value)
|
||||
{
|
||||
struct working_area *erase_check_algorithm;
|
||||
struct reg_param reg_params[3];
|
||||
@@ -866,16 +867,16 @@ int mips32_blank_check_memory(struct target *target,
|
||||
int retval = target_write_buffer(target, erase_check_algorithm->address,
|
||||
sizeof(erase_check_code), erase_check_code_8);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
goto cleanup;
|
||||
|
||||
mips32_info.common_magic = MIPS32_COMMON_MAGIC;
|
||||
mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32;
|
||||
|
||||
init_reg_param(®_params[0], "r4", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, address);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, blocks[0].address);
|
||||
|
||||
init_reg_param(®_params[1], "r5", 32, PARAM_OUT);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, count);
|
||||
buf_set_u32(reg_params[1].value, 0, 32, blocks[0].size);
|
||||
|
||||
init_reg_param(®_params[2], "r6", 32, PARAM_IN_OUT);
|
||||
buf_set_u32(reg_params[2].value, 0, 32, erased_value);
|
||||
@@ -884,15 +885,19 @@ int mips32_blank_check_memory(struct target *target,
|
||||
erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
*blank = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
blocks[0].result = buf_get_u32(reg_params[2].value, 0, 32);
|
||||
|
||||
destroy_reg_param(®_params[0]);
|
||||
destroy_reg_param(®_params[1]);
|
||||
destroy_reg_param(®_params[2]);
|
||||
|
||||
cleanup:
|
||||
target_free_working_area(target, erase_check_algorithm);
|
||||
|
||||
return retval;
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
return 1; /* only one block has been checked */
|
||||
}
|
||||
|
||||
static int mips32_verify_pointer(struct command_context *cmd_ctx,
|
||||
|
||||
+1
-1
@@ -428,6 +428,6 @@ int mips32_get_gdb_reg_list(struct target *target,
|
||||
int mips32_checksum_memory(struct target *target, target_addr_t address,
|
||||
uint32_t count, uint32_t *checksum);
|
||||
int mips32_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value);
|
||||
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value);
|
||||
|
||||
#endif /* OPENOCD_TARGET_MIPS32_H */
|
||||
|
||||
@@ -953,22 +953,6 @@ static int riscv_checksum_memory(struct target *target,
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/* Should run code on the target to check whether a memory
|
||||
block holds all-ones (because this is generally called on
|
||||
NOR flash which is 1 when "blank")
|
||||
Not yet implemented.
|
||||
*/
|
||||
int riscv_blank_check_memory(struct target *target,
|
||||
target_addr_t address,
|
||||
uint32_t count,
|
||||
uint32_t *blank,
|
||||
uint8_t erased_value)
|
||||
{
|
||||
*blank = 0;
|
||||
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
/*** OpenOCD Helper Functions ***/
|
||||
|
||||
enum riscv_poll_hart {
|
||||
@@ -1549,7 +1533,6 @@ struct target_type riscv_target = {
|
||||
.read_memory = riscv_read_memory,
|
||||
.write_memory = riscv_write_memory,
|
||||
|
||||
.blank_check_memory = riscv_blank_check_memory,
|
||||
.checksum_memory = riscv_checksum_memory,
|
||||
|
||||
.get_gdb_reg_list = riscv_get_gdb_reg_list,
|
||||
|
||||
+8
-5
@@ -1750,7 +1750,7 @@ static int stm8_examine(struct target *target)
|
||||
|
||||
/** Checks whether a memory region is erased. */
|
||||
static int stm8_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value)
|
||||
struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value)
|
||||
{
|
||||
struct working_area *erase_check_algorithm;
|
||||
struct reg_param reg_params[2];
|
||||
@@ -1778,10 +1778,10 @@ static int stm8_blank_check_memory(struct target *target,
|
||||
stm8_info.common_magic = STM8_COMMON_MAGIC;
|
||||
|
||||
init_mem_param(&mem_params[0], 0x0, 3, PARAM_OUT);
|
||||
buf_set_u32(mem_params[0].value, 0, 24, address);
|
||||
buf_set_u32(mem_params[0].value, 0, 24, blocks[0].address);
|
||||
|
||||
init_mem_param(&mem_params[1], 0x3, 3, PARAM_OUT);
|
||||
buf_set_u32(mem_params[1].value, 0, 24, count);
|
||||
buf_set_u32(mem_params[1].value, 0, 24, blocks[0].size);
|
||||
|
||||
init_reg_param(®_params[0], "a", 32, PARAM_IN_OUT);
|
||||
buf_set_u32(reg_params[0].value, 0, 32, erased_value);
|
||||
@@ -1795,7 +1795,7 @@ static int stm8_blank_check_memory(struct target *target,
|
||||
10000, &stm8_info);
|
||||
|
||||
if (retval == ERROR_OK)
|
||||
*blank = (*(reg_params[0].value) == 0xff);
|
||||
blocks[0].result = (*(reg_params[0].value) == 0xff);
|
||||
|
||||
destroy_mem_param(&mem_params[0]);
|
||||
destroy_mem_param(&mem_params[1]);
|
||||
@@ -1803,7 +1803,10 @@ static int stm8_blank_check_memory(struct target *target,
|
||||
|
||||
target_free_working_area(target, erase_check_algorithm);
|
||||
|
||||
return retval;
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
||||
return 1; /* only one block has been checked */
|
||||
}
|
||||
|
||||
static int stm8_checksum_memory(struct target *target, target_addr_t address,
|
||||
|
||||
+16
-6
@@ -1912,6 +1912,18 @@ static void target_destroy(struct target *target)
|
||||
free(target->working_areas);
|
||||
}
|
||||
|
||||
/* release the targets SMP list */
|
||||
if (target->smp) {
|
||||
struct target_list *head = target->head;
|
||||
while (head != NULL) {
|
||||
struct target_list *pos = head->next;
|
||||
head->target->smp = 0;
|
||||
free(head);
|
||||
head = pos;
|
||||
}
|
||||
target->smp = 0;
|
||||
}
|
||||
|
||||
free(target->type);
|
||||
free(target->trace_info);
|
||||
free(target->fileio_info);
|
||||
@@ -2241,21 +2253,19 @@ int target_checksum_memory(struct target *target, target_addr_t address, uint32_
|
||||
return retval;
|
||||
}
|
||||
|
||||
int target_blank_check_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* blank,
|
||||
int target_blank_check_memory(struct target *target,
|
||||
struct target_memory_check_block *blocks, int num_blocks,
|
||||
uint8_t erased_value)
|
||||
{
|
||||
int retval;
|
||||
if (!target_was_examined(target)) {
|
||||
LOG_ERROR("Target not examined yet");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
if (target->type->blank_check_memory == 0)
|
||||
if (target->type->blank_check_memory == NULL)
|
||||
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
|
||||
|
||||
retval = target->type->blank_check_memory(target, address, size, blank, erased_value);
|
||||
|
||||
return retval;
|
||||
return target->type->blank_check_memory(target, blocks, num_blocks, erased_value);
|
||||
}
|
||||
|
||||
int target_read_u64(struct target *target, target_addr_t address, uint64_t *value)
|
||||
|
||||
+8
-1
@@ -312,6 +312,12 @@ struct target_timer_callback {
|
||||
struct target_timer_callback *next;
|
||||
};
|
||||
|
||||
struct target_memory_check_block {
|
||||
target_addr_t address;
|
||||
uint32_t size;
|
||||
uint32_t result;
|
||||
};
|
||||
|
||||
int target_register_commands(struct command_context *cmd_ctx);
|
||||
int target_examine(void);
|
||||
|
||||
@@ -585,7 +591,8 @@ int target_read_buffer(struct target *target,
|
||||
int target_checksum_memory(struct target *target,
|
||||
target_addr_t address, uint32_t size, uint32_t *crc);
|
||||
int target_blank_check_memory(struct target *target,
|
||||
target_addr_t address, uint32_t size, uint32_t *blank, uint8_t erased_value);
|
||||
struct target_memory_check_block *blocks, int num_blocks,
|
||||
uint8_t erased_value);
|
||||
int target_wait_state(struct target *target, enum target_state state, int ms);
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,8 +130,9 @@ struct target_type {
|
||||
|
||||
int (*checksum_memory)(struct target *target, target_addr_t address,
|
||||
uint32_t count, uint32_t *checksum);
|
||||
int (*blank_check_memory)(struct target *target, target_addr_t address,
|
||||
uint32_t count, uint32_t *blank, uint8_t erased_value);
|
||||
int (*blank_check_memory)(struct target *target,
|
||||
struct target_memory_check_block *blocks, int num_blocks,
|
||||
uint8_t erased_value);
|
||||
|
||||
/*
|
||||
* target break-/watchpoint control
|
||||
|
||||
Reference in New Issue
Block a user