cortexm: Moved all static data to the heap.

This commit is contained in:
Gareth McMullin 2012-07-05 21:26:26 +12:00
parent 0c379744e9
commit 0433d3d12a
4 changed files with 75 additions and 58 deletions

View File

@ -69,6 +69,8 @@ void adiv5_ap_unref(ADIv5_AP_t *ap)
{ {
if (--(ap->refcnt) == 0) { if (--(ap->refcnt) == 0) {
adiv5_dp_unref(ap->dp); adiv5_dp_unref(ap->dp);
if (ap->priv)
ap->priv_free(ap->priv);
free(ap); free(ap);
} }
} }

View File

@ -30,6 +30,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "general.h" #include "general.h"
#include "jtagtap.h" #include "jtagtap.h"
@ -186,7 +187,7 @@ static int cortexm_regs_write(struct target_s *target, const void *data);
static int cortexm_pc_write(struct target_s *target, const uint32_t val); static int cortexm_pc_write(struct target_s *target, const uint32_t val);
static void cortexm_reset(struct target_s *target); static void cortexm_reset(struct target_s *target);
static void cortexm_halt_resume(struct target_s *target, uint8_t step); static void cortexm_halt_resume(struct target_s *target, bool step);
static int cortexm_halt_wait(struct target_s *target); static int cortexm_halt_wait(struct target_s *target);
static void cortexm_halt_request(struct target_s *target); static void cortexm_halt_request(struct target_s *target);
static int cortexm_fault_unwind(struct target_s *target); static int cortexm_fault_unwind(struct target_s *target);
@ -199,22 +200,25 @@ static int cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t a
static int cortexm_check_hw_wp(struct target_s *target, uint32_t *addr); static int cortexm_check_hw_wp(struct target_s *target, uint32_t *addr);
/* Watchpoint unit status */
#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ #define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */
static struct wp_unit_s {
uint32_t addr;
uint8_t type;
uint8_t size;
} hw_watchpoint[CORTEXM_MAX_WATCHPOINTS];
static unsigned hw_watchpoint_max;
/* Breakpoint unit status */
#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ #define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */
static uint32_t hw_breakpoint[CORTEXM_MAX_BREAKPOINTS];
static unsigned hw_breakpoint_max; struct cortexm_priv {
bool stepping;
/* Watchpoint unit status */
struct wp_unit_s {
uint32_t addr;
uint8_t type;
uint8_t size;
} hw_watchpoint[CORTEXM_MAX_WATCHPOINTS];
unsigned hw_watchpoint_max;
/* Breakpoint unit status */
uint32_t hw_breakpoint[CORTEXM_MAX_BREAKPOINTS];
unsigned hw_breakpoint_max;
};
/* Register number tables */ /* Register number tables */
static uint32_t regnum_cortex_m[] = { static const uint32_t regnum_cortex_m[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* standard r0-r15 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* standard r0-r15 */
0x10, /* xpsr */ 0x10, /* xpsr */
0x11, /* msp */ 0x11, /* msp */
@ -222,7 +226,7 @@ static uint32_t regnum_cortex_m[] = {
0x14 /* special */ 0x14 /* special */
}; };
static uint32_t regnum_cortex_mf[] = { static const uint32_t regnum_cortex_mf[] = {
0x21, /* fpscr */ 0x21, /* fpscr */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* s0-s7 */ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* s0-s7 */
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* s8-s15 */ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* s8-s15 */
@ -340,6 +344,8 @@ cortexm_probe(struct target_s *target)
target->tdesc = tdesc_cortex_mf; target->tdesc = tdesc_cortex_mf;
} }
ap->priv = calloc(1, sizeof(struct cortexm_priv));
ap->priv_free = free;
#define PROBE(x) \ #define PROBE(x) \
do { if (!(x)(target)) return 0; else target_check_error(target); } while (0) do { if (!(x)(target)) return 0; else target_check_error(target); } while (0)
@ -359,6 +365,7 @@ static void
cortexm_attach(struct target_s *target) cortexm_attach(struct target_s *target)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
unsigned i; unsigned i;
uint32_t r; uint32_t r;
@ -377,25 +384,25 @@ cortexm_attach(struct target_s *target)
adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
/* size the break/watchpoint units */ /* size the break/watchpoint units */
hw_breakpoint_max = CORTEXM_MAX_BREAKPOINTS; priv->hw_breakpoint_max = CORTEXM_MAX_BREAKPOINTS;
r = adiv5_ap_mem_read(ap, CORTEXM_FPB_CTRL); r = adiv5_ap_mem_read(ap, CORTEXM_FPB_CTRL);
if (((r >> 4) & 0xf) < hw_breakpoint_max) /* only look at NUM_COMP1 */ if (((r >> 4) & 0xf) < priv->hw_breakpoint_max) /* only look at NUM_COMP1 */
hw_breakpoint_max = (r >> 4) & 0xf; priv->hw_breakpoint_max = (r >> 4) & 0xf;
hw_watchpoint_max = CORTEXM_MAX_WATCHPOINTS; priv->hw_watchpoint_max = CORTEXM_MAX_WATCHPOINTS;
r = adiv5_ap_mem_read(ap, CORTEXM_DWT_CTRL); r = adiv5_ap_mem_read(ap, CORTEXM_DWT_CTRL);
if ((r >> 28) > hw_watchpoint_max) if ((r >> 28) > priv->hw_watchpoint_max)
hw_watchpoint_max = r >> 28; priv->hw_watchpoint_max = r >> 28;
/* Clear any stale breakpoints */ /* Clear any stale breakpoints */
for(i = 0; i < hw_breakpoint_max; i++) { for(i = 0; i < priv->hw_breakpoint_max; i++) {
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0);
hw_breakpoint[i] = 0; priv->hw_breakpoint[i] = 0;
} }
/* Clear any stale watchpoints */ /* Clear any stale watchpoints */
for(i = 0; i < hw_watchpoint_max; i++) { for(i = 0; i < priv->hw_watchpoint_max; i++) {
adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0);
hw_watchpoint[i].type = 0; priv->hw_watchpoint[i].type = 0;
} }
/* Flash Patch Control Register: set ENABLE */ /* Flash Patch Control Register: set ENABLE */
@ -414,14 +421,15 @@ static void
cortexm_detach(struct target_s *target) cortexm_detach(struct target_s *target)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
unsigned i; unsigned i;
/* Clear any stale breakpoints */ /* Clear any stale breakpoints */
for(i = 0; i < hw_breakpoint_max; i++) for(i = 0; i < priv->hw_breakpoint_max; i++)
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0);
/* Clear any stale watchpoints */ /* Clear any stale watchpoints */
for(i = 0; i < hw_watchpoint_max; i++) for(i = 0; i < priv->hw_watchpoint_max; i++)
adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0);
/* Disable debug */ /* Disable debug */
@ -541,13 +549,11 @@ cortexm_halt_request(struct target_s *target)
CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN);
} }
/* FIXME: static here must go! */
static uint8_t old_step = 0;
static int static int
cortexm_halt_wait(struct target_s *target) cortexm_halt_wait(struct target_s *target)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
if (!(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT)) if (!(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT))
return 0; return 0;
@ -562,24 +568,25 @@ cortexm_halt_wait(struct target_s *target)
return SIGTRAP; return SIGTRAP;
if (dfsr & CORTEXM_DFSR_HALTED) if (dfsr & CORTEXM_DFSR_HALTED)
return old_step ? SIGTRAP : SIGINT; return priv->stepping ? SIGTRAP : SIGINT;
return SIGTRAP; return SIGTRAP;
} }
static void static void
cortexm_halt_resume(struct target_s *target, uint8_t step) cortexm_halt_resume(struct target_s *target, bool step)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN; uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN;
if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS; if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS;
/* Disable interrupts while single stepping... */ /* Disable interrupts while single stepping... */
if(step != old_step) { if(step != priv->stepping) {
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT);
old_step = step; priv->stepping = step;
} }
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr); adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr);
@ -638,18 +645,19 @@ static int
cortexm_set_hw_bp(struct target_s *target, uint32_t addr) cortexm_set_hw_bp(struct target_s *target, uint32_t addr)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
uint32_t val = addr & 0x1FFFFFFC; uint32_t val = addr & 0x1FFFFFFC;
unsigned i; unsigned i;
val |= (addr & 2)?0x80000000:0x40000000; val |= (addr & 2)?0x80000000:0x40000000;
val |= 1; val |= 1;
for(i = 0; i < hw_breakpoint_max; i++) for(i = 0; i < priv->hw_breakpoint_max; i++)
if((hw_breakpoint[i] & 1) == 0) break; if((priv->hw_breakpoint[i] & 1) == 0) break;
if(i == hw_breakpoint_max) return -1; if(i == priv->hw_breakpoint_max) return -1;
hw_breakpoint[i] = addr | 1; priv->hw_breakpoint[i] = addr | 1;
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), val); adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), val);
@ -660,14 +668,15 @@ static int
cortexm_clear_hw_bp(struct target_s *target, uint32_t addr) cortexm_clear_hw_bp(struct target_s *target, uint32_t addr)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
unsigned i; unsigned i;
for(i = 0; i < hw_breakpoint_max; i++) for(i = 0; i < priv->hw_breakpoint_max; i++)
if((hw_breakpoint[i] & ~1) == addr) break; if((priv->hw_breakpoint[i] & ~1) == addr) break;
if(i == hw_breakpoint_max) return -1; if(i == priv->hw_breakpoint_max) return -1;
hw_breakpoint[i] = 0; priv->hw_breakpoint[i] = 0;
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0);
@ -682,6 +691,7 @@ static int
cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len) cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
unsigned i; unsigned i;
switch(len) { /* Convert bytes size to mask size */ switch(len) { /* Convert bytes size to mask size */
@ -700,16 +710,16 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t
return -1; return -1;
} }
for(i = 0; i < hw_watchpoint_max; i++) for(i = 0; i < priv->hw_watchpoint_max; i++)
if((hw_watchpoint[i].type == 0) && if((priv->hw_watchpoint[i].type == 0) &&
((adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) & 0xF) == 0)) ((adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) & 0xF) == 0))
break; break;
if(i == hw_watchpoint_max) return -2; if(i == priv->hw_watchpoint_max) return -2;
hw_watchpoint[i].type = type; priv->hw_watchpoint[i].type = type;
hw_watchpoint[i].addr = addr; priv->hw_watchpoint[i].addr = addr;
hw_watchpoint[i].size = len; priv->hw_watchpoint[i].size = len;
adiv5_ap_mem_write(ap, CORTEXM_DWT_COMP(i), addr); adiv5_ap_mem_write(ap, CORTEXM_DWT_COMP(i), addr);
adiv5_ap_mem_write(ap, CORTEXM_DWT_MASK(i), len); adiv5_ap_mem_write(ap, CORTEXM_DWT_MASK(i), len);
@ -723,6 +733,7 @@ static int
cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len) cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
unsigned i; unsigned i;
switch(len) { switch(len) {
@ -741,14 +752,14 @@ cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_
return -1; return -1;
} }
for(i = 0; i < hw_watchpoint_max; i++) for(i = 0; i < priv->hw_watchpoint_max; i++)
if((hw_watchpoint[i].addr == addr) && if((priv->hw_watchpoint[i].addr == addr) &&
(hw_watchpoint[i].type == type) && (priv->hw_watchpoint[i].type == type) &&
(hw_watchpoint[i].size == len)) break; (priv->hw_watchpoint[i].size == len)) break;
if(i == hw_watchpoint_max) return -2; if(i == priv->hw_watchpoint_max) return -2;
hw_watchpoint[i].type = 0; priv->hw_watchpoint[i].type = 0;
adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0);
@ -759,18 +770,19 @@ static int
cortexm_check_hw_wp(struct target_s *target, uint32_t *addr) cortexm_check_hw_wp(struct target_s *target, uint32_t *addr)
{ {
ADIv5_AP_t *ap = adiv5_target_ap(target); ADIv5_AP_t *ap = adiv5_target_ap(target);
struct cortexm_priv *priv = ap->priv;
unsigned i; unsigned i;
for(i = 0; i < hw_watchpoint_max; i++) for(i = 0; i < priv->hw_watchpoint_max; i++)
/* if SET and MATCHED then break */ /* if SET and MATCHED then break */
if(hw_watchpoint[i].type && if(priv->hw_watchpoint[i].type &&
(adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) & (adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) &
CORTEXM_DWT_FUNC_MATCHED)) CORTEXM_DWT_FUNC_MATCHED))
break; break;
if(i == hw_watchpoint_max) return 0; if(i == priv->hw_watchpoint_max) return 0;
*addr = hw_watchpoint[i].addr; *addr = priv->hw_watchpoint[i].addr;
return 1; return 1;
} }

View File

@ -150,6 +150,9 @@ typedef struct ADIv5_AP_s {
uint32_t idr; uint32_t idr;
uint32_t cfg; uint32_t cfg;
uint32_t base; uint32_t base;
void *priv;
void (*priv_free)(void *);
} ADIv5_AP_t; } ADIv5_AP_t;
void adiv5_dp_init(ADIv5_DP_t *dp); void adiv5_dp_init(ADIv5_DP_t *dp);

View File

@ -148,7 +148,7 @@ struct target_s {
void (*reset)(struct target_s *target); void (*reset)(struct target_s *target);
void (*halt_request)(struct target_s *target); void (*halt_request)(struct target_s *target);
int (*halt_wait)(struct target_s *target); int (*halt_wait)(struct target_s *target);
void (*halt_resume)(struct target_s *target, uint8_t step); void (*halt_resume)(struct target_s *target, bool step);
/* Break-/watchpoint functions */ /* Break-/watchpoint functions */
int (*set_hw_bp)(struct target_s *target, uint32_t addr); int (*set_hw_bp)(struct target_s *target, uint32_t addr);