cortexm: Better cache support for Cortex-M7
- On probe, read CTR for cache presence and minimum line length - Make D-Cache clean a function - Clean before memory reads - Clean and invalidate before memory writes - Flush all I-Cache before resume
This commit is contained in:
parent
0e5b3ab00e
commit
c53a12bfd1
|
@ -78,6 +78,9 @@ struct cortexm_priv {
|
|||
unsigned hw_breakpoint_max;
|
||||
/* Copy of DEMCR for vector-catch */
|
||||
uint32_t demcr;
|
||||
/* Cache parameters */
|
||||
bool has_cache;
|
||||
uint32_t dcache_minline;
|
||||
};
|
||||
|
||||
/* Register number tables */
|
||||
|
@ -179,45 +182,40 @@ ADIv5_AP_t *cortexm_ap(target *t)
|
|||
return ((struct cortexm_priv *)t->priv)->ap;
|
||||
}
|
||||
|
||||
static void cortexm_mem_read(target *t, void *dest, target_addr src, size_t len)
|
||||
static void cortexm_cache_clean(target *t, target_addr addr, size_t len, bool invalidate)
|
||||
{
|
||||
struct cortexm_priv *priv = t->priv;
|
||||
if (!priv->has_cache || (priv->dcache_minline == 0))
|
||||
return;
|
||||
uint32_t cache_reg = invalidate ? CORTEXM_DCCIMVAC : CORTEXM_DCCMVAC;
|
||||
size_t minline = priv->dcache_minline;
|
||||
|
||||
/* flush data cache for RAM regions that intersect requested region */
|
||||
target_addr src_end = src + len; /* following code is NOP if wraparound */
|
||||
target_addr mem_end = addr + len; /* following code is NOP if wraparound */
|
||||
/* requested region is [src, src_end) */
|
||||
for (struct target_ram *r = t->ram; r; r = r->next) {
|
||||
target_addr ram = r->start;
|
||||
target_addr ram_end = r->start + r->length;
|
||||
/* RAM region is [ram, ram_end) */
|
||||
if (src > ram)
|
||||
ram = src;
|
||||
if (src_end < ram_end)
|
||||
ram_end = src_end;
|
||||
if (addr > ram)
|
||||
ram = addr;
|
||||
if (mem_end < ram_end)
|
||||
ram_end = mem_end;
|
||||
/* intersection is [ram, ram_end) */
|
||||
for (ram &= ~0x1f; ram < ram_end; ram += 0x20)
|
||||
adiv5_mem_write(cortexm_ap(t), CORTEXM_DCCIMVAC, &ram, 4);
|
||||
for (ram &= ~(minline-1); ram < ram_end; ram += minline)
|
||||
adiv5_mem_write(cortexm_ap(t), cache_reg, &ram, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void cortexm_mem_read(target *t, void *dest, target_addr src, size_t len)
|
||||
{
|
||||
cortexm_cache_clean(t, src, len, false);
|
||||
adiv5_mem_read(cortexm_ap(t), dest, src, len);
|
||||
}
|
||||
|
||||
static void cortexm_mem_write(target *t, target_addr dest, const void *src, size_t len)
|
||||
{
|
||||
/* flush data cache for RAM regions that intersect requested region */
|
||||
target_addr dest_end = dest + len; /* following code is NOP if wraparound */
|
||||
/* requested region is [dest, dest_end) */
|
||||
for (struct target_ram *r = t->ram; r; r = r->next) {
|
||||
target_addr ram = r->start;
|
||||
target_addr ram_end = r->start + r->length;
|
||||
/* RAM region is [ram, ram_end) */
|
||||
if (dest > ram)
|
||||
ram = dest;
|
||||
if (dest_end < ram_end)
|
||||
ram_end = dest_end;
|
||||
/* intersection is [ram, ram_end) */
|
||||
for (ram &= ~0x1f; ram < ram_end; ram += 0x20)
|
||||
adiv5_mem_write(cortexm_ap(t), CORTEXM_DCCIMVAC, &ram, 4);
|
||||
}
|
||||
|
||||
cortexm_cache_clean(t, dest, len, true);
|
||||
adiv5_mem_write(cortexm_ap(t), dest, src, len);
|
||||
}
|
||||
|
||||
|
@ -283,6 +281,15 @@ bool cortexm_probe(ADIv5_AP_t *ap)
|
|||
priv->demcr = CORTEXM_DEMCR_TRCENA | CORTEXM_DEMCR_VC_HARDERR |
|
||||
CORTEXM_DEMCR_VC_CORERESET;
|
||||
|
||||
/* Check cache type */
|
||||
uint32_t ctr = target_mem_read32(t, CORTEXM_CTR);
|
||||
if ((ctr >> 29) == 4) {
|
||||
priv->has_cache = true;
|
||||
priv->dcache_minline = 4 << (ctr & 0xf);
|
||||
} else {
|
||||
target_check_error(t);
|
||||
}
|
||||
|
||||
#define PROBE(x) \
|
||||
do { if ((x)(t)) return true; else target_check_error(t); } while (0)
|
||||
|
||||
|
@ -583,6 +590,9 @@ void cortexm_halt_resume(target *t, bool step)
|
|||
cortexm_pc_write(t, pc + 2);
|
||||
}
|
||||
|
||||
if (priv->has_cache)
|
||||
target_mem_write32(t, CORTEXM_ICIALLU, 0);
|
||||
|
||||
target_mem_write32(t, CORTEXM_DHCSR, dhcsr);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,15 @@
|
|||
#define CORTEXM_DCRDR (CORTEXM_SCS_BASE + 0xDF8)
|
||||
#define CORTEXM_DEMCR (CORTEXM_SCS_BASE + 0xDFC)
|
||||
|
||||
/* Data cache clean and invalidate by address to the PoC=Point of Coherency */
|
||||
/* Cache identification */
|
||||
#define CORTEXM_CLIDR (CORTEXM_SCS_BASE + 0xD78)
|
||||
#define CORTEXM_CTR (CORTEXM_SCS_BASE + 0xD7C)
|
||||
#define CORTEXM_CCSIDR (CORTEXM_SCS_BASE + 0xD80)
|
||||
#define CORTEXM_CSSELR (CORTEXM_SCS_BASE + 0xD84)
|
||||
|
||||
/* Cache maintenance operations */
|
||||
#define CORTEXM_ICIALLU (CORTEXM_SCS_BASE + 0xF50)
|
||||
#define CORTEXM_DCCMVAC (CORTEXM_SCS_BASE + 0xF68)
|
||||
#define CORTEXM_DCCIMVAC (CORTEXM_SCS_BASE + 0xF70)
|
||||
|
||||
#define CORTEXM_FPB_BASE (CORTEXM_PPB_BASE + 0x2000)
|
||||
|
|
Loading…
Reference in New Issue