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:
parent
af1ef670ba
commit
00c4dbfb11
68
src/adiv5.c
68
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;
|
||||
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -175,6 +175,8 @@ struct target_s {
|
|||
int size;
|
||||
struct target_s *next;
|
||||
|
||||
void *priv;
|
||||
void (*priv_free)(void *);
|
||||
};
|
||||
|
||||
struct target_command_s {
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue