adiv6: use struct adiv5_ap->ap_num to contain the AP base address
ADIv5 DAP can only have 256 AP, while ADIv6 can provide till 2**40 (1,099,511,627,776) AP per DAP. Reuse the field ap_num in struct adiv5_ap, currently used on ADIv5 to hold the ADIv5 AP number (apsel), to contain the ADIv6 AP base address. Convert struct adiv5_ap->ap_num to 64 bit and initialize it to DP_APSEL_INVALID for unused AP. Restrict dap_find_get_ap() to ADIv5 only. To be enhanced. On ADIv6, let dap_get_ap() return an already allocated AP, or allocate and return an unused AP. Add function is_ap_num_valid() and use it. Change-Id: Ib2fe8c7ec0d08393cd91c29fdac5d632dfc1e438 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: https://review.openocd.org/c/openocd/+/6461 Reviewed-by: Daniel Goehring <dgoehrin@os.amperecomputing.com> Tested-by: jenkins
This commit is contained in:
parent
72fb88613f
commit
3f4bc6ce7f
|
@ -4680,6 +4680,8 @@ for TCL scripting.
|
|||
@deffn {Command} {dap info} [num]
|
||||
Displays the ROM table for MEM-AP @var{num},
|
||||
defaulting to the currently selected AP of the currently selected target.
|
||||
On ADIv5 DAP @var{num} is the numeric index of the AP.
|
||||
On ADIv6 DAP @var{num} is the base address of the AP.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {dap init}
|
||||
|
@ -4693,21 +4695,29 @@ The following commands exist as subcommands of DAP instances:
|
|||
@deffn {Command} {$dap_name info} [num]
|
||||
Displays the ROM table for MEM-AP @var{num},
|
||||
defaulting to the currently selected AP.
|
||||
On ADIv5 DAP @var{num} is the numeric index of the AP.
|
||||
On ADIv6 DAP @var{num} is the base address of the AP.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {$dap_name apid} [num]
|
||||
Displays ID register from AP @var{num}, defaulting to the currently selected AP.
|
||||
On ADIv5 DAP @var{num} is the numeric index of the AP.
|
||||
On ADIv6 DAP @var{num} is the base address of the AP.
|
||||
@end deffn
|
||||
|
||||
@anchor{DAP subcommand apreg}
|
||||
@deffn {Command} {$dap_name apreg} ap_num reg [value]
|
||||
Displays content of a register @var{reg} from AP @var{ap_num}
|
||||
or set a new value @var{value}.
|
||||
On ADIv5 DAP @var{ap_num} is the numeric index of the AP.
|
||||
On ADIv6 DAP @var{ap_num} is the base address of the AP.
|
||||
@var{reg} is byte address of a word register, 0, 4, 8 ... 0xfc.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {$dap_name apsel} [num]
|
||||
Select AP @var{num}, defaulting to 0.
|
||||
On ADIv5 DAP @var{num} is the numeric index of the AP.
|
||||
On ADIv6 DAP @var{num} is the base address of the AP.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {$dap_name dpreg} reg [value]
|
||||
|
@ -4725,6 +4735,8 @@ background activity by OpenOCD while you are operating at such low-level.
|
|||
@deffn {Command} {$dap_name baseaddr} [num]
|
||||
Displays debug base address from MEM-AP @var{num},
|
||||
defaulting to the currently selected AP.
|
||||
On ADIv5 DAP @var{num} is the numeric index of the AP.
|
||||
On ADIv6 DAP @var{num} is the base address of the AP.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {$dap_name memaccess} [value]
|
||||
|
@ -5098,8 +5110,9 @@ The value should normally correspond to a static mapping for the
|
|||
scan and after a reset. A manual call to arp_examine is required to
|
||||
access the target for debugging.
|
||||
|
||||
@item @code{-ap-num} @var{ap_number} -- set DAP access port for target,
|
||||
@var{ap_number} is the numeric index of the DAP AP the target is connected to.
|
||||
@item @code{-ap-num} @var{ap_number} -- set DAP access port for target.
|
||||
On ADIv5 DAP @var{ap_number} is the numeric index of the DAP AP the target is connected to.
|
||||
On ADIv6 DAP @var{ap_number} is the base address of the DAP AP the target is connected to.
|
||||
Use this option with systems where multiple, independent cores are connected
|
||||
to separate access ports of the same DAP.
|
||||
|
||||
|
@ -9449,7 +9462,10 @@ the @emph{cti} group of commands.
|
|||
|
||||
@deffn {Command} {cti create} cti_name @option{-dap} dap_name @option{-ap-num} apn @option{-baseaddr} base_address
|
||||
Creates a CTI instance @var{cti_name} on the DAP instance @var{dap_name} on MEM-AP
|
||||
@var{apn}. The @var{base_address} must match the base address of the CTI
|
||||
@var{apn}.
|
||||
On ADIv5 DAP @var{apn} is the numeric index of the DAP AP the CTI is connected to.
|
||||
On ADIv6 DAP @var{apn} is the base address of the DAP AP the CTI is connected to.
|
||||
The @var{base_address} must match the base address of the CTI
|
||||
on the respective MEM-AP. All arguments are mandatory. This creates a
|
||||
new command @command{$cti_name} which is used for various purposes
|
||||
including additional configuration.
|
||||
|
@ -10114,8 +10130,9 @@ using the @command{$tpiu_name cget} command.
|
|||
@item @code{-dap} @var{dap_name} -- names the DAP used to access this
|
||||
TPIU. @xref{dapdeclaration,,DAP declaration}, on how to create and manage DAP instances.
|
||||
|
||||
@item @code{-ap-num} @var{ap_number} -- sets DAP access port for TPIU,
|
||||
@var{ap_number} is the numeric index of the DAP AP the TPIU is connected to.
|
||||
@item @code{-ap-num} @var{ap_number} -- sets DAP access port for TPIU.
|
||||
On ADIv5 DAP @var{ap_number} is the numeric index of the DAP AP the TPIU is connected to.
|
||||
On ADIv6 DAP @var{ap_number} is the base address of the DAP AP the TPIU is connected to.
|
||||
|
||||
@item @code{-baseaddr} @var{base_address} -- sets the TPIU @var{base_address} where
|
||||
to access the TPIU in the DAP AP memory space.
|
||||
|
|
|
@ -4152,7 +4152,7 @@ static int stlink_dap_reinit_interface(void)
|
|||
stlink_dap_handle->reconnect_pending = false;
|
||||
/* on new FW, calling mode-leave closes all the opened AP; reopen them! */
|
||||
if (stlink_dap_handle->version.flags & STLINK_F_HAS_AP_INIT)
|
||||
for (int apsel = 0; apsel <= DP_APSEL_MAX; apsel++)
|
||||
for (unsigned int apsel = 0; apsel <= DP_APSEL_MAX; apsel++)
|
||||
if (test_bit(apsel, opened_ap)) {
|
||||
clear_bit(apsel, opened_ap);
|
||||
stlink_dap_open_ap(apsel);
|
||||
|
@ -4348,7 +4348,7 @@ static int stlink_usb_misc_rw_segment(void *handle, const struct dap_queue *q, u
|
|||
|
||||
LOG_DEBUG("Queue: %u commands in %u items", len, items);
|
||||
|
||||
int ap_num = DP_APSEL_INVALID;
|
||||
uint32_t ap_num = DP_APSEL_INVALID;
|
||||
unsigned int cmd_index = 0;
|
||||
unsigned int val_index = ALIGN_UP(items, 4);
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
|
@ -4497,7 +4497,7 @@ static int stlink_usb_count_misc_rw_queue(void *handle, const struct dap_queue *
|
|||
{
|
||||
struct stlink_usb_handle_s *h = handle;
|
||||
unsigned int i, items = 0;
|
||||
int ap_num = DP_APSEL_INVALID;
|
||||
uint32_t ap_num = DP_APSEL_INVALID;
|
||||
unsigned int misc_max_items = (h->version.stlink == 2) ? STLINK_V2_RW_MISC_SIZE : STLINK_V3_RW_MISC_SIZE;
|
||||
|
||||
if (!(h->version.flags & STLINK_F_HAS_RW_MISC))
|
||||
|
@ -4864,9 +4864,10 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg,
|
|||
q->ap_w.reg = reg;
|
||||
q->ap_w.ap = ap;
|
||||
q->ap_w.data = data;
|
||||
if (reg == ADIV5_MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap->ap_num]) {
|
||||
uint8_t ap_num = ap->ap_num;
|
||||
if (reg == ADIV5_MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap_num]) {
|
||||
q->ap_w.changes_csw_default = true;
|
||||
last_csw_default[ap->ap_num] = ap->csw_default;
|
||||
last_csw_default[ap_num] = ap->csw_default;
|
||||
} else {
|
||||
q->ap_w.changes_csw_default = false;
|
||||
}
|
||||
|
|
|
@ -966,16 +966,45 @@ static const char *ap_type_to_description(enum ap_type type)
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
bool is_ap_num_valid(struct adiv5_dap *dap, uint64_t ap_num)
|
||||
{
|
||||
if (!dap)
|
||||
return false;
|
||||
|
||||
/* no autodetection, by now, so uninitialized is equivalent to ADIv5 for
|
||||
* backward compatibility */
|
||||
if (!is_adiv6(dap)) {
|
||||
if (ap_num > DP_APSEL_MAX)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_adiv6(dap)) {
|
||||
if (ap_num & 0x0fffULL)
|
||||
return false;
|
||||
if (dap->asize != 0)
|
||||
if (ap_num & ((~0ULL) << dap->asize))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks the ID for each access port to find the requested Access Port type
|
||||
* It also calls dap_get_ap() to increment the AP refcount
|
||||
*/
|
||||
int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out)
|
||||
{
|
||||
int ap_num;
|
||||
if (is_adiv6(dap)) {
|
||||
/* TODO: scan the ROM table and detect the AP available */
|
||||
LOG_DEBUG("On ADIv6 we cannot scan all the possible AP");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
/* Maximum AP number is 255 since the SELECT register is 8 bits */
|
||||
for (ap_num = 0; ap_num <= DP_APSEL_MAX; ap_num++) {
|
||||
for (unsigned int ap_num = 0; ap_num <= DP_APSEL_MAX; ap_num++) {
|
||||
struct adiv5_ap *ap = dap_get_ap(dap, ap_num);
|
||||
if (!ap)
|
||||
continue;
|
||||
|
@ -1014,33 +1043,55 @@ static inline bool is_ap_in_use(struct adiv5_ap *ap)
|
|||
return ap->refcount > 0 || ap->config_ap_never_release;
|
||||
}
|
||||
|
||||
static struct adiv5_ap *_dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num)
|
||||
static struct adiv5_ap *_dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num)
|
||||
{
|
||||
if (ap_num > DP_APSEL_MAX) {
|
||||
LOG_ERROR("Invalid AP#%u", ap_num);
|
||||
if (!is_ap_num_valid(dap, ap_num)) {
|
||||
LOG_ERROR("Invalid AP#0x%" PRIx64, ap_num);
|
||||
return NULL;
|
||||
}
|
||||
if (is_adiv6(dap)) {
|
||||
for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) {
|
||||
struct adiv5_ap *ap = &dap->ap[i];
|
||||
if (is_ap_in_use(ap) && ap->ap_num == ap_num) {
|
||||
++ap->refcount;
|
||||
return ap;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i <= DP_APSEL_MAX; i++) {
|
||||
struct adiv5_ap *ap = &dap->ap[i];
|
||||
if (!is_ap_in_use(ap)) {
|
||||
ap->ap_num = ap_num;
|
||||
++ap->refcount;
|
||||
return ap;
|
||||
}
|
||||
}
|
||||
LOG_ERROR("No more AP available!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ADIv5 */
|
||||
struct adiv5_ap *ap = &dap->ap[ap_num];
|
||||
ap->ap_num = ap_num;
|
||||
++ap->refcount;
|
||||
return ap;
|
||||
}
|
||||
|
||||
/* Return AP with specified ap_num. Increment AP refcount */
|
||||
struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num)
|
||||
struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num)
|
||||
{
|
||||
struct adiv5_ap *ap = _dap_get_ap(dap, ap_num);
|
||||
if (ap)
|
||||
LOG_DEBUG("refcount AP#%u get %u", ap_num, ap->refcount);
|
||||
LOG_DEBUG("refcount AP#0x%" PRIx64 " get %u", ap_num, ap->refcount);
|
||||
return ap;
|
||||
}
|
||||
|
||||
/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */
|
||||
struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num)
|
||||
struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, uint64_t ap_num)
|
||||
{
|
||||
struct adiv5_ap *ap = _dap_get_ap(dap, ap_num);
|
||||
if (ap) {
|
||||
ap->config_ap_never_release = true;
|
||||
LOG_DEBUG("refcount AP#%u get_config %u", ap_num, ap->refcount);
|
||||
LOG_DEBUG("refcount AP#0x%" PRIx64 " get_config %u", ap_num, ap->refcount);
|
||||
}
|
||||
return ap;
|
||||
}
|
||||
|
@ -1049,15 +1100,16 @@ struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num)
|
|||
int dap_put_ap(struct adiv5_ap *ap)
|
||||
{
|
||||
if (ap->refcount == 0) {
|
||||
LOG_ERROR("BUG: refcount AP#%" PRIu8 " put underflow", ap->ap_num);
|
||||
LOG_ERROR("BUG: refcount AP#0x%" PRIx64 " put underflow", ap->ap_num);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
--ap->refcount;
|
||||
|
||||
LOG_DEBUG("refcount AP#%" PRIu8 " put %u", ap->ap_num, ap->refcount);
|
||||
LOG_DEBUG("refcount AP#0x%" PRIx64 " put %u", ap->ap_num, ap->refcount);
|
||||
if (!is_ap_in_use(ap)) {
|
||||
/* defaults from dap_instance_init() */
|
||||
ap->ap_num = DP_APSEL_INVALID;
|
||||
ap->memaccess_tck = 255;
|
||||
ap->tar_autoincr_block = (1 << 10);
|
||||
ap->csw_default = CSW_AHB_DEFAULT;
|
||||
|
@ -1756,7 +1808,7 @@ static int dap_info_mem_ap_header(int retval, struct adiv5_ap *ap,
|
|||
|
||||
command_print(cmd, "AP ID register 0x%8.8" PRIx32, apid);
|
||||
if (apid == 0) {
|
||||
command_print(cmd, "No AP found at this ap 0x%x", ap->ap_num);
|
||||
command_print(cmd, "No AP found at this AP#0x%" PRIx64, ap->ap_num);
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
|
||||
|
@ -2000,7 +2052,7 @@ static const struct jim_nvp nvp_config_opts[] = {
|
|||
};
|
||||
|
||||
static int adiv5_jim_spot_configure(struct jim_getopt_info *goi,
|
||||
struct adiv5_dap **dap_p, int *ap_num_p, uint32_t *base_p)
|
||||
struct adiv5_dap **dap_p, uint64_t *ap_num_p, uint32_t *base_p)
|
||||
{
|
||||
assert(dap_p && ap_num_p);
|
||||
|
||||
|
@ -2055,11 +2107,13 @@ static int adiv5_jim_spot_configure(struct jim_getopt_info *goi,
|
|||
|
||||
case CFG_AP_NUM:
|
||||
if (goi->isconfigure) {
|
||||
/* jim_wide is a signed 64 bits int, ap_num is unsigned with max 52 bits */
|
||||
jim_wide ap_num;
|
||||
e = jim_getopt_wide(goi, &ap_num);
|
||||
if (e != JIM_OK)
|
||||
return e;
|
||||
if (ap_num < 0 || ap_num > DP_APSEL_MAX) {
|
||||
/* we still don't know dap->adi_version */
|
||||
if (ap_num < 0 || (ap_num > DP_APSEL_MAX && (ap_num & 0xfff))) {
|
||||
Jim_SetResultString(goi->interp, "Invalid AP number!", -1);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
@ -2164,15 +2218,15 @@ int adiv5_mem_ap_spot_init(struct adiv5_mem_ap_spot *p)
|
|||
COMMAND_HANDLER(handle_dap_info_command)
|
||||
{
|
||||
struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
|
||||
uint32_t apsel;
|
||||
uint64_t apsel;
|
||||
|
||||
switch (CMD_ARGC) {
|
||||
case 0:
|
||||
apsel = dap->apsel;
|
||||
break;
|
||||
case 1:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
|
||||
if (apsel > DP_APSEL_MAX) {
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
|
||||
if (!is_ap_num_valid(dap, apsel)) {
|
||||
command_print(CMD, "Invalid AP number");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
@ -2195,7 +2249,8 @@ COMMAND_HANDLER(handle_dap_info_command)
|
|||
COMMAND_HANDLER(dap_baseaddr_command)
|
||||
{
|
||||
struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
|
||||
uint32_t apsel, baseaddr_lower, baseaddr_upper;
|
||||
uint64_t apsel;
|
||||
uint32_t baseaddr_lower, baseaddr_upper;
|
||||
struct adiv5_ap *ap;
|
||||
target_addr_t baseaddr;
|
||||
int retval;
|
||||
|
@ -2207,9 +2262,8 @@ COMMAND_HANDLER(dap_baseaddr_command)
|
|||
apsel = dap->apsel;
|
||||
break;
|
||||
case 1:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
|
||||
/* AP address is in bits 31:24 of DP_SELECT */
|
||||
if (apsel > DP_APSEL_MAX) {
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
|
||||
if (!is_ap_num_valid(dap, apsel)) {
|
||||
command_print(CMD, "Invalid AP number");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
@ -2294,16 +2348,15 @@ COMMAND_HANDLER(dap_memaccess_command)
|
|||
COMMAND_HANDLER(dap_apsel_command)
|
||||
{
|
||||
struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
|
||||
uint32_t apsel;
|
||||
uint64_t apsel;
|
||||
|
||||
switch (CMD_ARGC) {
|
||||
case 0:
|
||||
command_print(CMD, "%" PRIu32, dap->apsel);
|
||||
command_print(CMD, "0x%" PRIx64, dap->apsel);
|
||||
return ERROR_OK;
|
||||
case 1:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
|
||||
/* AP address is in bits 31:24 of DP_SELECT */
|
||||
if (apsel > DP_APSEL_MAX) {
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
|
||||
if (!is_ap_num_valid(dap, apsel)) {
|
||||
command_print(CMD, "Invalid AP number");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
@ -2329,7 +2382,7 @@ COMMAND_HANDLER(dap_apcsw_command)
|
|||
command_print(CMD, "Cannot get AP");
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
command_print(CMD, "ap %" PRIu32 " selected, csw 0x%8.8" PRIx32,
|
||||
command_print(CMD, "AP#0x%" PRIx64 " selected, csw 0x%8.8" PRIx32,
|
||||
dap->apsel, ap->csw_default);
|
||||
break;
|
||||
case 1:
|
||||
|
@ -2376,7 +2429,8 @@ COMMAND_HANDLER(dap_apcsw_command)
|
|||
COMMAND_HANDLER(dap_apid_command)
|
||||
{
|
||||
struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
|
||||
uint32_t apsel, apid;
|
||||
uint64_t apsel;
|
||||
uint32_t apid;
|
||||
int retval;
|
||||
|
||||
switch (CMD_ARGC) {
|
||||
|
@ -2384,9 +2438,8 @@ COMMAND_HANDLER(dap_apid_command)
|
|||
apsel = dap->apsel;
|
||||
break;
|
||||
case 1:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
|
||||
/* AP address is in bits 31:24 of DP_SELECT */
|
||||
if (apsel > DP_APSEL_MAX) {
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
|
||||
if (!is_ap_num_valid(dap, apsel)) {
|
||||
command_print(CMD, "Invalid AP number");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
@ -2418,23 +2471,30 @@ COMMAND_HANDLER(dap_apid_command)
|
|||
COMMAND_HANDLER(dap_apreg_command)
|
||||
{
|
||||
struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
|
||||
uint32_t apsel, reg, value;
|
||||
uint64_t apsel;
|
||||
uint32_t reg, value;
|
||||
int retval;
|
||||
|
||||
if (CMD_ARGC < 2 || CMD_ARGC > 3)
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
|
||||
/* AP address is in bits 31:24 of DP_SELECT */
|
||||
if (apsel > DP_APSEL_MAX) {
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
|
||||
if (!is_ap_num_valid(dap, apsel)) {
|
||||
command_print(CMD, "Invalid AP number");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg);
|
||||
if (reg >= 256 || (reg & 3)) {
|
||||
command_print(CMD, "Invalid reg value (should be less than 256 and 4 bytes aligned)");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
if (is_adiv6(dap)) {
|
||||
if (reg >= 4096 || (reg & 3)) {
|
||||
command_print(CMD, "Invalid reg value (should be less than 4096 and 4 bytes aligned)");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
} else { /* ADI version 5 */
|
||||
if (reg >= 256 || (reg & 3)) {
|
||||
command_print(CMD, "Invalid reg value (should be less than 256 and 4 bytes aligned)");
|
||||
return ERROR_COMMAND_ARGUMENT_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
struct adiv5_ap *ap = dap_get_ap(dap, apsel);
|
||||
|
|
|
@ -110,8 +110,8 @@
|
|||
#define DP_SELECT_DPBANK 0x0000000F
|
||||
#define DP_SELECT_INVALID 0x00FFFF00 /* Reserved bits one */
|
||||
|
||||
#define DP_APSEL_MAX (255)
|
||||
#define DP_APSEL_INVALID (-1)
|
||||
#define DP_APSEL_MAX (255) /* for ADIv5 only */
|
||||
#define DP_APSEL_INVALID 0xF00 /* more than DP_APSEL_MAX and not ADIv6 aligned 4k */
|
||||
|
||||
#define DP_TARGETSEL_INVALID 0xFFFFFFFFU
|
||||
#define DP_TARGETSEL_DPID_MASK 0x0FFFFFFFU
|
||||
|
@ -255,9 +255,11 @@ struct adiv5_ap {
|
|||
struct adiv5_dap *dap;
|
||||
|
||||
/**
|
||||
* Number of this AP.
|
||||
* ADIv5: Number of this AP (0~255)
|
||||
* ADIv6: Base address of this AP (4k aligned)
|
||||
* TODO: to be more coherent, it should be renamed apsel
|
||||
*/
|
||||
uint8_t ap_num;
|
||||
uint64_t ap_num;
|
||||
|
||||
/**
|
||||
* Default value for (MEM-AP) AP_REG_CSW register.
|
||||
|
@ -342,7 +344,7 @@ struct adiv5_dap {
|
|||
struct adiv5_ap ap[DP_APSEL_MAX + 1];
|
||||
|
||||
/* The current manually selected AP by the "dap apsel" command */
|
||||
uint32_t apsel;
|
||||
uint64_t apsel;
|
||||
|
||||
/**
|
||||
* Cache for DP_SELECT register. A value of DP_SELECT_INVALID
|
||||
|
@ -551,7 +553,7 @@ static inline int dap_queue_ap_read(struct adiv5_ap *ap,
|
|||
assert(ap->dap->ops);
|
||||
if (ap->refcount == 0) {
|
||||
ap->refcount = 1;
|
||||
LOG_ERROR("BUG: refcount AP#%" PRIu8 " used without get", ap->ap_num);
|
||||
LOG_ERROR("BUG: refcount AP#0x%" PRIx64 " used without get", ap->ap_num);
|
||||
}
|
||||
return ap->dap->ops->queue_ap_read(ap, reg, data);
|
||||
}
|
||||
|
@ -571,7 +573,7 @@ static inline int dap_queue_ap_write(struct adiv5_ap *ap,
|
|||
assert(ap->dap->ops);
|
||||
if (ap->refcount == 0) {
|
||||
ap->refcount = 1;
|
||||
LOG_ERROR("BUG: refcount AP#%" PRIu8 " used without get", ap->ap_num);
|
||||
LOG_ERROR("BUG: refcount AP#0x%" PRIx64 " used without get", ap->ap_num);
|
||||
}
|
||||
return ap->dap->ops->queue_ap_write(ap, reg, data);
|
||||
}
|
||||
|
@ -690,16 +692,19 @@ int mem_ap_init(struct adiv5_ap *ap);
|
|||
/* Invalidate cached DP select and cached TAR and CSW of all APs */
|
||||
void dap_invalidate_cache(struct adiv5_dap *dap);
|
||||
|
||||
/* test if ap_num is valid, based on current knowledge of dap */
|
||||
bool is_ap_num_valid(struct adiv5_dap *dap, uint64_t ap_num);
|
||||
|
||||
/* Probe Access Ports to find a particular type. Increment AP refcount */
|
||||
int dap_find_get_ap(struct adiv5_dap *dap,
|
||||
enum ap_type type_to_find,
|
||||
struct adiv5_ap **ap_out);
|
||||
|
||||
/* Return AP with specified ap_num. Increment AP refcount */
|
||||
struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, unsigned int ap_num);
|
||||
struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num);
|
||||
|
||||
/* Return AP with specified ap_num. Increment AP refcount and keep it non-zero */
|
||||
struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, unsigned int ap_num);
|
||||
struct adiv5_ap *dap_get_config_ap(struct adiv5_dap *dap, uint64_t ap_num);
|
||||
|
||||
/* Decrement AP refcount and release the AP when refcount reaches zero */
|
||||
int dap_put_ap(struct adiv5_ap *ap);
|
||||
|
@ -735,7 +740,7 @@ extern const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self);
|
|||
extern int dap_cleanup_all(void);
|
||||
|
||||
struct adiv5_private_config {
|
||||
int ap_num;
|
||||
uint64_t ap_num;
|
||||
struct adiv5_dap *dap;
|
||||
};
|
||||
|
||||
|
@ -744,7 +749,7 @@ extern int adiv5_jim_configure(struct target *target, struct jim_getopt_info *go
|
|||
|
||||
struct adiv5_mem_ap_spot {
|
||||
struct adiv5_dap *dap;
|
||||
int ap_num;
|
||||
uint64_t ap_num;
|
||||
uint32_t base;
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ static void dap_instance_init(struct adiv5_dap *dap)
|
|||
/* Set up with safe defaults */
|
||||
for (i = 0; i <= DP_APSEL_MAX; i++) {
|
||||
dap->ap[i].dap = dap;
|
||||
dap->ap[i].ap_num = i;
|
||||
dap->ap[i].ap_num = DP_APSEL_INVALID;
|
||||
/* memaccess_tck max is 255 */
|
||||
dap->ap[i].memaccess_tck = 255;
|
||||
/* Number of bits for tar autoincrement, impl. dep. at least 10 */
|
||||
|
@ -459,7 +459,7 @@ COMMAND_HANDLER(handle_dap_info_command)
|
|||
struct target *target = get_current_target(CMD_CTX);
|
||||
struct arm *arm = target_to_arm(target);
|
||||
struct adiv5_dap *dap = arm->dap;
|
||||
uint32_t apsel;
|
||||
uint64_t apsel;
|
||||
|
||||
if (!dap) {
|
||||
LOG_ERROR("DAP instance not available. Probably a HLA target...");
|
||||
|
@ -471,8 +471,8 @@ COMMAND_HANDLER(handle_dap_info_command)
|
|||
apsel = dap->apsel;
|
||||
break;
|
||||
case 1:
|
||||
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
|
||||
if (apsel > DP_APSEL_MAX)
|
||||
COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], apsel);
|
||||
if (!is_ap_num_valid(dap, apsel))
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -617,8 +617,8 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
|
|||
if (obj->enabled)
|
||||
return JIM_OK;
|
||||
|
||||
if (transport_is_hla() && obj->spot.ap_num > 0) {
|
||||
LOG_ERROR("Invalid access port %d. Only AP#0 allowed with hla transport", obj->spot.ap_num);
|
||||
if (transport_is_hla() && obj->spot.ap_num != 0) {
|
||||
LOG_ERROR("Invalid access port 0x%" PRIx64 ". Only AP#0 allowed with hla transport", obj->spot.ap_num);
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
|
@ -650,8 +650,8 @@ static int jim_arm_tpiu_swo_enable(Jim_Interp *interp, int argc, Jim_Obj *const
|
|||
if (obj->spot.ap_num == 0)
|
||||
LOG_INFO(MSG "Confirmed TPIU %s is on AP 0", obj->name);
|
||||
else
|
||||
LOG_INFO(MSG "Target %s is on AP %d. Revised command is "
|
||||
"\'tpiu create %s -dap %s -ap-num %d\'",
|
||||
LOG_INFO(MSG "Target %s is on AP#0x%" PRIx64 ". Revised command is "
|
||||
"\'tpiu create %s -dap %s -ap-num 0x%" PRIx64 "\'",
|
||||
target_name(target), obj->spot.ap_num,
|
||||
obj->name, adiv5_dap_name(obj->spot.dap), obj->spot.ap_num);
|
||||
}
|
||||
|
@ -1047,7 +1047,7 @@ COMMAND_HANDLER(handle_tpiu_deprecated_config_command)
|
|||
struct cortex_m_common *cm = target_to_cm(target);
|
||||
struct adiv5_private_config *pc = target->private_config;
|
||||
struct adiv5_dap *dap = pc->dap;
|
||||
int ap_num = pc->ap_num;
|
||||
uint64_t ap_num = pc->ap_num;
|
||||
bool set_recheck_ap_cur_target = false;
|
||||
|
||||
LOG_INFO(MSG "Adding a TPIU \'%s.tpiu\' in the configuration", target_name(target));
|
||||
|
@ -1065,10 +1065,10 @@ COMMAND_HANDLER(handle_tpiu_deprecated_config_command)
|
|||
set_recheck_ap_cur_target = true;
|
||||
}
|
||||
|
||||
LOG_INFO(MSG "Running: \'tpiu create %s.tpiu -dap %s -ap-num %d\'",
|
||||
LOG_INFO(MSG "Running: \'tpiu create %s.tpiu -dap %s -ap-num 0x%" PRIx64 "\'",
|
||||
target_name(target), adiv5_dap_name(dap), ap_num);
|
||||
|
||||
retval = command_run_linef(CMD_CTX, "tpiu create %s.tpiu -dap %s -ap-num %d",
|
||||
retval = command_run_linef(CMD_CTX, "tpiu create %s.tpiu -dap %s -ap-num 0x%" PRIx64,
|
||||
target_name(target), adiv5_dap_name(dap), ap_num);
|
||||
if (retval != ERROR_OK)
|
||||
return retval;
|
||||
|
|
|
@ -241,7 +241,7 @@ struct cortex_m_common {
|
|||
|
||||
bool slow_register_read; /* A register has not been ready, poll S_REGRDY */
|
||||
|
||||
int apsel;
|
||||
uint64_t apsel;
|
||||
|
||||
/* Whether this target has the erratum that makes C_MASKINTS not apply to
|
||||
* already pending interrupts */
|
||||
|
|
|
@ -203,7 +203,7 @@ static int adapter_target_create(struct target *target,
|
|||
{
|
||||
LOG_DEBUG("%s", __func__);
|
||||
struct adiv5_private_config *pc = target->private_config;
|
||||
if (pc && pc->ap_num > 0) {
|
||||
if (pc && pc->ap_num != DP_APSEL_INVALID && pc->ap_num != 0) {
|
||||
LOG_ERROR("hla_target: invalid parameter -ap-num (> 0)");
|
||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ struct mem_ap {
|
|||
int common_magic;
|
||||
struct adiv5_dap *dap;
|
||||
struct adiv5_ap *ap;
|
||||
int ap_num;
|
||||
uint64_t ap_num;
|
||||
};
|
||||
|
||||
static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
|
||||
|
|
Loading…
Reference in New Issue