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.
This commit is contained in:
Gareth McMullin 2012-07-05 19:23:28 +12:00
parent af1ef670ba
commit 00c4dbfb11
8 changed files with 58 additions and 50 deletions

View File

@ -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;
while(adiv5_dp_list) {
dp = adiv5_dp_list->next;
free(adiv5_dp_list);
adiv5_dp_list = dp;
}
adiv5_ap_count = 0;
dp->refcnt++;
}
void adiv5_ap_ref(ADIv5_AP_t *ap)
{
ap->refcnt++;
}
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)

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -175,6 +175,8 @@ struct target_s {
int size;
struct target_s *next;
void *priv;
void (*priv_free)(void *);
};
struct target_command_s {

View File

@ -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.
*/

View File

@ -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);