aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth McMullin2012-07-05 19:23:28 +1200
committerGareth McMullin2012-07-05 19:23:28 +1200
commit00c4dbfb11e389176bdb2d45a262eb47229cd80b (patch)
treefcd39820419eaece7a4a8a5ed81fefc1702bac66
parentaf1ef670ba50a29546fa165f159f66fe5d2d0868 (diff)
ADIv5 AP and DP are now allocated on the heap and reference counted.
They are unref'd and free'd automatically when the target list is destroyed.
-rw-r--r--src/adiv5.c64
-rw-r--r--src/adiv5_jtagdp.c2
-rw-r--r--src/adiv5_swdp.c6
-rw-r--r--src/command.c2
-rw-r--r--src/include/adiv5.h23
-rw-r--r--src/include/target.h2
-rw-r--r--src/jtag_scan.c3
-rw-r--r--src/target.c2
8 files changed, 56 insertions, 48 deletions
diff --git a/src/adiv5.c b/src/adiv5.c
index 22b9965..04a9b88 100644
--- a/src/adiv5.c
+++ b/src/adiv5.c
@@ -42,10 +42,6 @@
static const char adiv5_driver_str[] = "ARM ADIv5 MEM-AP";
-ADIv5_DP_t *adiv5_dp_list;
-ADIv5_AP_t adiv5_aps[5];
-int adiv5_ap_count;
-
static int ap_check_error(struct target_s *target);
static int ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len);
@@ -53,26 +49,35 @@ static int ap_mem_write_words(struct target_s *target, uint32_t dest, const uint
static int ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len);
static int ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, int len);
-void adiv5_free_all(void)
+void adiv5_dp_ref(ADIv5_DP_t *dp)
{
- ADIv5_DP_t *dp;
+ dp->refcnt++;
+}
- while(adiv5_dp_list) {
- dp = adiv5_dp_list->next;
- free(adiv5_dp_list);
- adiv5_dp_list = dp;
- }
+void adiv5_ap_ref(ADIv5_AP_t *ap)
+{
+ ap->refcnt++;
+}
- adiv5_ap_count = 0;
+void adiv5_dp_unref(ADIv5_DP_t *dp)
+{
+ if (--(dp->refcnt) == 0)
+ free(dp);
}
+void adiv5_ap_unref(ADIv5_AP_t *ap)
+{
+ if (--(ap->refcnt) == 0) {
+ adiv5_dp_unref(ap->dp);
+ free(ap);
+ }
+}
void adiv5_dp_init(ADIv5_DP_t *dp)
{
uint32_t ctrlstat;
- dp->next = adiv5_dp_list;
- adiv5_dp_list = dp;
+ adiv5_dp_ref(dp);
ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
@@ -108,25 +113,35 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
/* Probe for APs on this DP */
for(int i = 0; i < 256; i++) {
- ADIv5_AP_t *ap = &adiv5_aps[adiv5_ap_count];
+ ADIv5_AP_t *ap, tmpap;
target *t;
/* Assume valid and try to read IDR */
- ap->dp = dp;
- ap->apsel = i;
- ap->idr = adiv5_ap_read(ap, ADIV5_AP_IDR);
+ memset(&tmpap, 0, sizeof(tmpap));
+ tmpap.dp = dp;
+ tmpap.apsel = i;
+ tmpap.idr = adiv5_ap_read(&tmpap, ADIV5_AP_IDR);
- if(!ap->idr) /* IDR Invalid - Should we not continue here? */
+ if(!tmpap.idr) /* IDR Invalid - Should we not continue here? */
break;
- /* We have a valid AP, adding to list */
+ /* It's valid to so create a heap copy */
+ ap = malloc(sizeof(*ap));
+ memcpy(ap, &tmpap, sizeof(*ap));
+ adiv5_dp_ref(dp);
+
ap->cfg = adiv5_ap_read(ap, ADIV5_AP_CFG);
ap->base = adiv5_ap_read(ap, ADIV5_AP_BASE);
- /* Should probe further here... */
+
+ /* Should probe further here to make sure it's a valid target.
+ * AP should be unref'd if not valid.
+ */
/* Prepend to target list... */
- t = target_new(sizeof(struct target_ap_s));
- ((struct target_ap_s *)t)->ap = ap;
+ t = target_new(sizeof(*t));
+ adiv5_ap_ref(ap);
+ t->priv = ap;
+ t->priv_free = (void (*)(void *))adiv5_ap_unref;
t->driver = adiv5_driver_str;
t->check_error = ap_check_error;
@@ -138,9 +153,8 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
/* The rest sould only be added after checking ROM table */
cortexm_probe(t);
-
- adiv5_ap_count++;
}
+ adiv5_dp_unref(dp);
}
void adiv5_dp_write_ap(ADIv5_DP_t *dp, uint8_t addr, uint32_t value)
diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c
index e85462b..68bcddd 100644
--- a/src/adiv5_jtagdp.c
+++ b/src/adiv5_jtagdp.c
@@ -49,7 +49,7 @@ static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t R
void adiv5_jtag_dp_handler(jtag_dev_t *dev)
{
- ADIv5_DP_t *dp = (void*)calloc(1, sizeof(ADIv5_DP_t));
+ ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
dp->dev = dev;
dp->idcode = dev->idcode;
diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c
index f1e4bf4..06d5446 100644
--- a/src/adiv5_swdp.c
+++ b/src/adiv5_swdp.c
@@ -47,14 +47,10 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW
int adiv5_swdp_scan(void)
{
- ADIv5_DP_t *dp;
uint8_t ack;
target_list_free();
-#warning "These should be elsewhere!"
- adiv5_free_all();
-
- dp = (void*)calloc(1, sizeof(ADIv5_DP_t));
+ ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
swdptap_init();
/* Read the SW-DP IDCODE register to syncronise */
diff --git a/src/command.c b/src/command.c
index 74551d3..46163fd 100644
--- a/src/command.c
+++ b/src/command.c
@@ -172,7 +172,7 @@ bool cmd_swdp_scan(void)
return false;
}
- gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode);
+ //gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode);
cmd_targets(NULL);
return true;
diff --git a/src/include/adiv5.h b/src/include/adiv5.h
index 4c98223..75c185b 100644
--- a/src/include/adiv5.h
+++ b/src/include/adiv5.h
@@ -102,7 +102,8 @@
/* Try to keep this somewhat absract for later adding SW-DP */
typedef struct ADIv5_DP_s {
- struct ADIv5_DP_s *next;
+ int refcnt;
+
uint32_t idcode;
void (*dp_write)(struct ADIv5_DP_s *dp, uint8_t addr, uint32_t value);
@@ -140,9 +141,9 @@ static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP,
return dp->low_access(dp, APnDP, RnW, addr, value);
}
-extern ADIv5_DP_t *adiv5_dp_list;
-
typedef struct ADIv5_AP_s {
+ int refcnt;
+
ADIv5_DP_t *dp;
uint8_t apsel;
@@ -151,17 +152,13 @@ typedef struct ADIv5_AP_s {
uint32_t base;
} ADIv5_AP_t;
-struct target_ap_s {
- target t;
- ADIv5_AP_t *ap;
-};
-
-extern ADIv5_AP_t adiv5_aps[5];
-extern int adiv5_ap_count;
-
-void adiv5_free_all(void);
void adiv5_dp_init(ADIv5_DP_t *dp);
+void adiv5_dp_ref(ADIv5_DP_t *dp);
+void adiv5_ap_ref(ADIv5_AP_t *ap);
+void adiv5_dp_unref(ADIv5_DP_t *dp);
+void adiv5_ap_unref(ADIv5_AP_t *ap);
+
void adiv5_dp_write_ap(ADIv5_DP_t *dp, uint8_t addr, uint32_t value);
uint32_t adiv5_dp_read_ap(ADIv5_DP_t *dp, uint8_t addr);
@@ -177,7 +174,7 @@ int adiv5_swdp_scan(void);
static inline ADIv5_AP_t *adiv5_target_ap(target *target)
{
- return ((struct target_ap_s *)target)->ap;
+ return target->priv;
}
#endif
diff --git a/src/include/target.h b/src/include/target.h
index d2af706..70f6969 100644
--- a/src/include/target.h
+++ b/src/include/target.h
@@ -175,6 +175,8 @@ struct target_s {
int size;
struct target_s *next;
+ void *priv;
+ void (*priv_free)(void *);
};
struct target_command_s {
diff --git a/src/jtag_scan.c b/src/jtag_scan.c
index 0084e2e..6f733de 100644
--- a/src/jtag_scan.c
+++ b/src/jtag_scan.c
@@ -107,9 +107,6 @@ int jtag_scan(const uint8_t *irlens)
jtag_dev_count = 0;
memset(&jtag_devs, 0, sizeof(jtag_devs));
-#warning "These should be elsewhere!"
- adiv5_free_all();
-
/* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is
* in SW-DP mode.
*/
diff --git a/src/target.c b/src/target.c
index 5189929..a28c55f 100644
--- a/src/target.c
+++ b/src/target.c
@@ -42,6 +42,8 @@ void target_list_free(void)
target *t = target_list->next;
if (target_list->destroy_callback)
target_list->destroy_callback(target_list);
+ if (target_list->priv)
+ target_list->priv_free(target_list->priv);
while (target_list->commands) {
tc = target_list->commands->next;
free(target_list->commands);