aboutsummaryrefslogtreecommitdiff
path: root/src/flash
diff options
context:
space:
mode:
authorAntonio Borneo <borneo.antonio@gmail.com>2021-08-04 23:07:57 +0200
committerAntonio Borneo <borneo.antonio@gmail.com>2022-06-24 21:33:23 +0000
commit35a503b08d145edbd81519f9471b480292062bb5 (patch)
tree30d36cad8e681e28e6b4d6d81c3389f87f46139e /src/flash
parent480d4e17727864f75dc60e22cb1a42e022cb1db3 (diff)
downloadriscv-openocd-35a503b08d145edbd81519f9471b480292062bb5.zip
riscv-openocd-35a503b08d145edbd81519f9471b480292062bb5.tar.gz
riscv-openocd-35a503b08d145edbd81519f9471b480292062bb5.tar.bz2
arm_adi_v5: add ap refcount and add get/put around ap use
While an ADIv5 DAP can only have 256 AP, ADIv6 can provide till 2**40 (1,099,511,627,776) AP per DAP. The actual trivial code implementation for ADIv5 (that uses an array of 256 ap in the struct adiv5_dap) cannot be extended as-is to handle ADIv6. The simple array of 256 AP can be reused as a dynamic storage for ADIv6 ap: - the ADIv5 AP number is replaced by the ADIv6 base address; - the index of the array (equal to ADIv5 AP number) has no link to any ADIv6 property; - the ADIv6 base_address has to be searched in the array of AP. The 256 elements in the AP array should be enough for any device available today. In future it can be easily increased, if needed. To efficiently use the 256 elements in the AP array, the code should associate one element of the array to an ADIv6 AP (through the AP base address), then cancel the association when the AP is not anymore needed. This is important to avoid saturating the AP array while exploring the device through 'dap apreg' commands. Add a reference counter in the struct adiv5_ap to track how many times the struct has been associated with the same base address. Introduce the function dap_get_ap() to associate and return the struct, and dap_put_ap() to release the struct. For the moment the code covers ADIv5 only, so the association is through the index. Use the two functions above and dap_find_get_ap() throughout the code. Check the return value of dap_get_ap(). It is always not NULL in the current ADIv5-only implementation, but can be NULL for ADIv6 when there are no more available AP in the array. Instrument dap_queue_ap_read() and dap_queue_ap_write() to log an error message if the AP has reference counter zero, meaning that the AP has not been 'get' yet. This helps identifying AP used without get/put, e.g. code missed by this patch, or merged later. Instrument dap_cleanup_all() to log an error message if an AP has reference counter not zero at openocd exit, meaning that the AP has not been 'put' yet. Change-Id: I98316eb42b9f3d9c9bbbb6c73b1091b53f629092 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: https://review.openocd.org/c/openocd/+/6455 Reviewed-by: Daniel Goehring <dgoehrin@os.amperecomputing.com> Tested-by: jenkins
Diffstat (limited to 'src/flash')
-rw-r--r--src/flash/nor/kinetis.c29
-rw-r--r--src/flash/nor/kinetis_ke.c22
-rw-r--r--src/flash/nor/sim3x.c21
3 files changed, 59 insertions, 13 deletions
diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c
index edb4eb5..c1a49fd 100644
--- a/src/flash/nor/kinetis.c
+++ b/src/flash/nor/kinetis.c
@@ -402,16 +402,23 @@ static int kinetis_auto_probe(struct flash_bank *bank);
static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
{
- int retval;
LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
- retval = dap_queue_ap_write(dap_ap(dap, MDM_AP), reg, value);
+ struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP);
+ if (!ap) {
+ LOG_DEBUG("MDM: failed to get AP");
+ return ERROR_FAIL;
+ }
+
+ int retval = dap_queue_ap_write(ap, reg, value);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: failed to queue a write request");
+ dap_put_ap(ap);
return retval;
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: dap_run failed");
return retval;
@@ -423,15 +430,21 @@ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint3
static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
{
- int retval;
+ struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP);
+ if (!ap) {
+ LOG_DEBUG("MDM: failed to get AP");
+ return ERROR_FAIL;
+ }
- retval = dap_queue_ap_read(dap_ap(dap, MDM_AP), reg, result);
+ int retval = dap_queue_ap_read(ap, reg, result);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: failed to queue a read request");
+ dap_put_ap(ap);
return retval;
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: dap_run failed");
return retval;
@@ -787,12 +800,18 @@ COMMAND_HANDLER(kinetis_check_flash_security_status)
if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) {
uint32_t stats[32];
+ struct adiv5_ap *ap = dap_get_ap(dap, MDM_AP);
+ if (!ap) {
+ LOG_ERROR("MDM: failed to get AP");
+ return ERROR_OK;
+ }
for (unsigned int i = 0; i < 32; i++) {
stats[i] = MDM_STAT_FREADY;
- dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]);
+ dap_queue_ap_read(ap, MDM_REG_STAT, &stats[i]);
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: dap_run failed when validating secured state");
return ERROR_OK;
diff --git a/src/flash/nor/kinetis_ke.c b/src/flash/nor/kinetis_ke.c
index 48749e6..fe20728 100644
--- a/src/flash/nor/kinetis_ke.c
+++ b/src/flash/nor/kinetis_ke.c
@@ -147,16 +147,23 @@ struct kinetis_ke_flash_bank {
static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
{
- int retval;
LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value);
- retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value);
+ struct adiv5_ap *ap = dap_get_ap(dap, 1);
+ if (!ap) {
+ LOG_DEBUG("MDM: failed to get AP");
+ return ERROR_FAIL;
+ }
+
+ int retval = dap_queue_ap_write(ap, reg, value);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: failed to queue a write request");
+ dap_put_ap(ap);
return retval;
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: dap_run failed");
return retval;
@@ -167,14 +174,21 @@ static int kinetis_ke_mdm_write_register(struct adiv5_dap *dap, unsigned reg, ui
static int kinetis_ke_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
{
- int retval;
- retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result);
+ struct adiv5_ap *ap = dap_get_ap(dap, 1);
+ if (!ap) {
+ LOG_DEBUG("MDM: failed to get AP");
+ return ERROR_FAIL;
+ }
+
+ int retval = dap_queue_ap_read(ap, reg, result);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: failed to queue a read request");
+ dap_put_ap(ap);
return retval;
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("MDM: dap_run failed");
return retval;
diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c
index 8913838..1d42ffe 100644
--- a/src/flash/nor/sim3x.c
+++ b/src/flash/nor/sim3x.c
@@ -872,16 +872,23 @@ static int sim3x_flash_info(struct flash_bank *bank, struct command_invocation *
*/
static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value)
{
- int retval;
LOG_DEBUG("DAP_REG[0x%02x] <- %08" PRIX32, reg, value);
- retval = dap_queue_ap_write(dap_ap(dap, SIM3X_AP), reg, value);
+ struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP);
+ if (!ap) {
+ LOG_DEBUG("DAP: failed to get AP");
+ return ERROR_FAIL;
+ }
+
+ int retval = dap_queue_ap_write(ap, reg, value);
if (retval != ERROR_OK) {
LOG_DEBUG("DAP: failed to queue a write request");
+ dap_put_ap(ap);
return retval;
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("DAP: dap_run failed");
return retval;
@@ -892,15 +899,21 @@ static int ap_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value
static int ap_read_register(struct adiv5_dap *dap, unsigned reg, uint32_t *result)
{
- int retval;
+ struct adiv5_ap *ap = dap_get_ap(dap, SIM3X_AP);
+ if (!ap) {
+ LOG_DEBUG("DAP: failed to get AP");
+ return ERROR_FAIL;
+ }
- retval = dap_queue_ap_read(dap_ap(dap, SIM3X_AP), reg, result);
+ int retval = dap_queue_ap_read(ap, reg, result);
if (retval != ERROR_OK) {
LOG_DEBUG("DAP: failed to queue a read request");
+ dap_put_ap(ap);
return retval;
}
retval = dap_run(dap);
+ dap_put_ap(ap);
if (retval != ERROR_OK) {
LOG_DEBUG("DAP: dap_run failed");
return retval;