From 00c4dbfb11e389176bdb2d45a262eb47229cd80b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 5 Jul 2012 19:23:28 +1200 Subject: 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. --- src/adiv5.c | 64 ++++++++++++++++++++++++++++++++-------------------- src/adiv5_jtagdp.c | 2 +- src/adiv5_swdp.c | 6 +---- src/command.c | 2 +- src/include/adiv5.h | 23 ++++++++----------- src/include/target.h | 2 ++ src/jtag_scan.c | 3 --- src/target.c | 2 ++ 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); -- cgit v1.2.3