stlink: dequeue CSW write only if it doesn't change csw_default

The stlink commands for buffer read/write carry the associated CSW
value that has to be used. We can dequeue any CSW write request
and add the CSW in the following buffer read/write.

In preparation to next patch that uses stlink commands misc-rw
(commands that don't handle CSW value), let's dequeue only those
CSW write that don't change csw_default.

Keep a local cache of last csw_default.
Tag the queued CSW writes that change csw_default.
Dequeue only the un-tagged CSW writes.

On buffer read/write commands, limiting the dequeued CSW write
surely adds a performance penalty. But csw_default is not changed
often so the penalty is not significant.

Change-Id: I538d257fe3c434fc97587846d759951384327f02
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6606
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
This commit is contained in:
Antonio Borneo 2021-07-29 18:38:20 +02:00
parent 9a534c4bb2
commit 22c76a4fd5
1 changed files with 17 additions and 4 deletions

View File

@ -227,6 +227,7 @@ struct dap_queue {
unsigned int reg;
struct adiv5_ap *ap;
uint32_t data;
bool changes_csw_default;
} ap_w;
struct mem_ap {
uint32_t addr;
@ -3960,6 +3961,7 @@ struct hl_layout_api_s stlink_usb_layout_api = {
static struct stlink_usb_handle_s *stlink_dap_handle;
static struct hl_interface_param_s stlink_dap_param;
static DECLARE_BITMAP(opened_ap, DP_APSEL_MAX + 1);
static uint32_t last_csw_default[DP_APSEL_MAX + 1];
static int stlink_dap_error = ERROR_OK;
/** */
@ -4004,6 +4006,7 @@ static int stlink_usb_open_ap(void *handle, unsigned short apsel)
LOG_DEBUG("AP %d enabled", apsel);
set_bit(apsel, opened_ap);
last_csw_default[apsel] = 0;
return ERROR_OK;
}
@ -4087,6 +4090,8 @@ static int stlink_dap_op_connect(struct adiv5_dap *dap)
dap->do_reconnect = false;
dap_invalidate_cache(dap);
for (unsigned int i = 0; i <= DP_APSEL_MAX; i++)
last_csw_default[i] = 0;
retval = dap_dp_init(dap);
if (retval != ERROR_OK) {
@ -4504,8 +4509,9 @@ static int stlink_dap_op_queue_ap_read(struct adiv5_ap *ap, unsigned int reg,
q = prev_q;
prev_q--;
}
/* de-queue previous write-CSW */
if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW) {
/* de-queue previous write-CSW if it didn't changed ap->csw_default */
if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW &&
!prev_q->ap_w.changes_csw_default) {
stlink_dap_handle->queue_index = i;
q = prev_q;
}
@ -4568,8 +4574,9 @@ static int stlink_dap_op_queue_ap_write(struct adiv5_ap *ap, unsigned int reg,
q = prev_q;
prev_q--;
}
/* de-queue previous write-CSW */
if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW) {
/* de-queue previous write-CSW if it didn't changed ap->csw_default */
if (i && prev_q->cmd == CMD_AP_WRITE && prev_q->ap_w.ap == ap && prev_q->ap_w.reg == MEM_AP_REG_CSW &&
!prev_q->ap_w.changes_csw_default) {
stlink_dap_handle->queue_index = i;
q = prev_q;
}
@ -4603,6 +4610,12 @@ 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 == MEM_AP_REG_CSW && ap->csw_default != last_csw_default[ap->ap_num]) {
q->ap_w.changes_csw_default = true;
last_csw_default[ap->ap_num] = ap->csw_default;
} else {
q->ap_w.changes_csw_default = false;
}
}
if (i == MAX_QUEUE_DEPTH - 1)