Replace adiv5_ap_mem* functions with inline wrappers to target mem*.
This commit is contained in:
parent
ee3af96a73
commit
2bf54f9a72
60
src/adiv5.c
60
src/adiv5.c
|
@ -273,66 +273,6 @@ ap_mem_write(struct target_s *target, uint32_t dest, const void *src, size_t len
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr)
|
||||
{
|
||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||
ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||
adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
|
||||
return adiv5_ap_read(ap, ADIV5_AP_DRW);
|
||||
}
|
||||
|
||||
void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value)
|
||||
{
|
||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||
ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||
adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
|
||||
adiv5_ap_write(ap, ADIV5_AP_DRW, value);
|
||||
}
|
||||
|
||||
uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr)
|
||||
{
|
||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||
ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||
adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
|
||||
uint32_t v = adiv5_ap_read(ap, ADIV5_AP_DRW);
|
||||
if (addr & 2)
|
||||
return v >> 16;
|
||||
else
|
||||
return v & 0xFFFF;
|
||||
}
|
||||
|
||||
void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value)
|
||||
{
|
||||
uint32_t v = value;
|
||||
if (addr & 2)
|
||||
v <<= 16;
|
||||
|
||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||
ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||
adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
|
||||
adiv5_ap_write(ap, ADIV5_AP_DRW, v);
|
||||
}
|
||||
|
||||
uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr)
|
||||
{
|
||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||
ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||
adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
|
||||
uint32_t v = adiv5_ap_read(ap, ADIV5_AP_DRW);
|
||||
|
||||
return v >> ((addr & 3) * 8);
|
||||
}
|
||||
|
||||
void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value)
|
||||
{
|
||||
uint32_t v = value << ((addr & 3) * 8);
|
||||
|
||||
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw |
|
||||
ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE);
|
||||
adiv5_ap_write(ap, ADIV5_AP_TAR, addr);
|
||||
adiv5_ap_write(ap, ADIV5_AP_DRW, v);
|
||||
}
|
||||
|
||||
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
|
||||
{
|
||||
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
|
||||
|
|
100
src/cortexm.c
100
src/cortexm.c
|
@ -228,16 +228,16 @@ cortexm_probe(struct target_s *target)
|
|||
target_add_commands(target, cortexm_cmd_list, cortexm_driver_str);
|
||||
|
||||
/* Probe for FP extension */
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint32_t cpacr = adiv5_ap_mem_read(ap, CORTEXM_CPACR);
|
||||
uint32_t cpacr = target_mem_read32(target, CORTEXM_CPACR);
|
||||
cpacr |= 0x00F00000; /* CP10 = 0b11, CP11 = 0b11 */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_CPACR, cpacr);
|
||||
if (adiv5_ap_mem_read(ap, CORTEXM_CPACR) == cpacr) {
|
||||
target_mem_write32(target, CORTEXM_CPACR, cpacr);
|
||||
if (target_mem_read32(target, CORTEXM_CPACR) == cpacr) {
|
||||
target->target_options |= TOPT_FLAVOUR_V7MF;
|
||||
target->regs_size += sizeof(regnum_cortex_mf);
|
||||
target->tdesc = tdesc_cortex_mf;
|
||||
}
|
||||
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
struct cortexm_priv *priv = calloc(1, sizeof(*priv));
|
||||
ap->priv = priv;
|
||||
ap->priv_free = free;
|
||||
|
@ -284,35 +284,35 @@ bool cortexm_attach(struct target_s *target)
|
|||
return false;
|
||||
|
||||
/* Request halt on reset */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DEMCR, priv->demcr);
|
||||
target_mem_write32(target, CORTEXM_DEMCR, priv->demcr);
|
||||
|
||||
/* Reset DFSR flags */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
|
||||
target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
|
||||
|
||||
/* size the break/watchpoint units */
|
||||
priv->hw_breakpoint_max = CORTEXM_MAX_BREAKPOINTS;
|
||||
r = adiv5_ap_mem_read(ap, CORTEXM_FPB_CTRL);
|
||||
r = target_mem_read32(target, CORTEXM_FPB_CTRL);
|
||||
if (((r >> 4) & 0xf) < priv->hw_breakpoint_max) /* only look at NUM_COMP1 */
|
||||
priv->hw_breakpoint_max = (r >> 4) & 0xf;
|
||||
priv->hw_watchpoint_max = CORTEXM_MAX_WATCHPOINTS;
|
||||
r = adiv5_ap_mem_read(ap, CORTEXM_DWT_CTRL);
|
||||
r = target_mem_read32(target, CORTEXM_DWT_CTRL);
|
||||
if ((r >> 28) > priv->hw_watchpoint_max)
|
||||
priv->hw_watchpoint_max = r >> 28;
|
||||
|
||||
/* Clear any stale breakpoints */
|
||||
for(i = 0; i < priv->hw_breakpoint_max; i++) {
|
||||
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0);
|
||||
target_mem_write32(target, CORTEXM_FPB_COMP(i), 0);
|
||||
priv->hw_breakpoint[i] = 0;
|
||||
}
|
||||
|
||||
/* Clear any stale watchpoints */
|
||||
for(i = 0; i < priv->hw_watchpoint_max; i++) {
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0);
|
||||
target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0);
|
||||
priv->hw_watchpoint[i].type = 0;
|
||||
}
|
||||
|
||||
/* Flash Patch Control Register: set ENABLE */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_FPB_CTRL,
|
||||
target_mem_write32(target, CORTEXM_FPB_CTRL,
|
||||
CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE);
|
||||
target->set_hw_bp = cortexm_set_hw_bp;
|
||||
target->clear_hw_bp = cortexm_clear_hw_bp;
|
||||
|
@ -336,14 +336,14 @@ void cortexm_detach(struct target_s *target)
|
|||
|
||||
/* Clear any stale breakpoints */
|
||||
for(i = 0; i < priv->hw_breakpoint_max; i++)
|
||||
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0);
|
||||
target_mem_write32(target, CORTEXM_FPB_COMP(i), 0);
|
||||
|
||||
/* Clear any stale watchpoints */
|
||||
for(i = 0; i < priv->hw_watchpoint_max; i++)
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0);
|
||||
target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0);
|
||||
|
||||
/* Disable debug */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY);
|
||||
target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -422,10 +422,8 @@ cortexm_regs_write(struct target_s *target, const void *data)
|
|||
static uint32_t
|
||||
cortexm_pc_read(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DCRSR, 0x0F);
|
||||
return adiv5_ap_mem_read(ap, CORTEXM_DCRDR);
|
||||
target_mem_write32(target, CORTEXM_DCRSR, 0x0F);
|
||||
return target_mem_read32(target, CORTEXM_DCRDR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -433,10 +431,8 @@ cortexm_pc_read(struct target_s *target)
|
|||
static int
|
||||
cortexm_pc_write(struct target_s *target, const uint32_t val)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DCRDR, val);
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F);
|
||||
target_mem_write32(target, CORTEXM_DCRDR, val);
|
||||
target_mem_write32(target, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -446,26 +442,24 @@ cortexm_pc_write(struct target_s *target, const uint32_t val)
|
|||
static void
|
||||
cortexm_reset(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
jtagtap_srst(true);
|
||||
jtagtap_srst(false);
|
||||
|
||||
/* Read DHCSR here to clear S_RESET_ST bit before reset */
|
||||
adiv5_ap_mem_read(ap, CORTEXM_DHCSR);
|
||||
target_mem_read32(target, CORTEXM_DHCSR);
|
||||
|
||||
/* Request system reset from NVIC: SRST doesn't work correctly */
|
||||
/* This could be VECTRESET: 0x05FA0001 (reset only core)
|
||||
* or SYSRESETREQ: 0x05FA0004 (system reset)
|
||||
*/
|
||||
adiv5_ap_mem_write(ap, CORTEXM_AIRCR,
|
||||
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
|
||||
target_mem_write32(target, CORTEXM_AIRCR,
|
||||
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
|
||||
|
||||
/* Poll for release from reset */
|
||||
while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST);
|
||||
while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST);
|
||||
|
||||
/* Reset DFSR flags */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
|
||||
target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -474,8 +468,9 @@ cortexm_halt_request(struct target_s *target)
|
|||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
ap->dp->allow_timeout = false;
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DHCSR,
|
||||
CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN);
|
||||
target_mem_write32(target, CORTEXM_DHCSR,
|
||||
CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT |
|
||||
CORTEXM_DHCSR_C_DEBUGEN);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -483,14 +478,14 @@ cortexm_halt_wait(struct target_s *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 (!(target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT))
|
||||
return 0;
|
||||
|
||||
ap->dp->allow_timeout = false;
|
||||
|
||||
/* We've halted. Let's find out why. */
|
||||
uint32_t dfsr = adiv5_ap_mem_read(ap, CORTEXM_DFSR);
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DFSR, dfsr); /* write back to reset */
|
||||
uint32_t dfsr = target_mem_read32(target, CORTEXM_DFSR);
|
||||
target_mem_write32(target, CORTEXM_DFSR, dfsr); /* write back to reset */
|
||||
|
||||
if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(target))
|
||||
return SIGSEGV;
|
||||
|
@ -502,7 +497,7 @@ cortexm_halt_wait(struct target_s *target)
|
|||
* call. */
|
||||
uint32_t pc = cortexm_pc_read(target);
|
||||
uint16_t bkpt_instr;
|
||||
target_mem_read(target, &bkpt_instr, pc, 2);
|
||||
bkpt_instr = target_mem_read16(target, pc);
|
||||
if (bkpt_instr == 0xBEAB) {
|
||||
int n = cortexm_hostio_request(target);
|
||||
if (n > 0) {
|
||||
|
@ -535,27 +530,26 @@ void cortexm_halt_resume(struct target_s *target, bool step)
|
|||
|
||||
/* Disable interrupts while single stepping... */
|
||||
if(step != priv->stepping) {
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT);
|
||||
target_mem_write32(target, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT);
|
||||
priv->stepping = step;
|
||||
}
|
||||
|
||||
if (priv->on_bkpt) {
|
||||
uint32_t pc = cortexm_pc_read(target);
|
||||
if ((adiv5_ap_mem_read_halfword(ap, pc) & 0xFF00) == 0xBE00)
|
||||
if ((target_mem_read16(target, pc) & 0xFF00) == 0xBE00)
|
||||
cortexm_pc_write(target, pc + 2);
|
||||
}
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr);
|
||||
target_mem_write32(target, CORTEXM_DHCSR, dhcsr);
|
||||
ap->dp->allow_timeout = true;
|
||||
}
|
||||
|
||||
static int cortexm_fault_unwind(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint32_t hfsr = adiv5_ap_mem_read(ap, CORTEXM_HFSR);
|
||||
uint32_t cfsr = adiv5_ap_mem_read(ap, CORTEXM_CFSR);
|
||||
adiv5_ap_mem_write(ap, CORTEXM_HFSR, hfsr);/* write back to reset */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_CFSR, cfsr);/* write back to reset */
|
||||
uint32_t hfsr = target_mem_read32(target, CORTEXM_HFSR);
|
||||
uint32_t cfsr = target_mem_read32(target, CORTEXM_CFSR);
|
||||
target_mem_write32(target, CORTEXM_HFSR, hfsr);/* write back to reset */
|
||||
target_mem_write32(target, CORTEXM_CFSR, cfsr);/* write back to reset */
|
||||
/* We check for FORCED in the HardFault Status Register or
|
||||
* for a configurable fault to avoid catching core resets */
|
||||
if((hfsr & CORTEXM_HFSR_FORCED) || cfsr) {
|
||||
|
@ -598,7 +592,7 @@ static int cortexm_fault_unwind(struct target_s *target)
|
|||
/* Reset exception state to allow resuming from restored
|
||||
* state.
|
||||
*/
|
||||
adiv5_ap_mem_write(ap, CORTEXM_AIRCR,
|
||||
target_mem_write32(target, CORTEXM_AIRCR,
|
||||
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_VECTCLRACTIVE);
|
||||
|
||||
/* Write pre-exception registers back to core */
|
||||
|
@ -630,7 +624,7 @@ cortexm_set_hw_bp(struct target_s *target, uint32_t addr)
|
|||
|
||||
priv->hw_breakpoint[i] = addr | 1;
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), val);
|
||||
target_mem_write32(target, CORTEXM_FPB_COMP(i), val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -649,7 +643,7 @@ cortexm_clear_hw_bp(struct target_s *target, uint32_t addr)
|
|||
|
||||
priv->hw_breakpoint[i] = 0;
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0);
|
||||
target_mem_write32(target, CORTEXM_FPB_COMP(i), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -683,7 +677,7 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t
|
|||
|
||||
for(i = 0; i < priv->hw_watchpoint_max; i++)
|
||||
if((priv->hw_watchpoint[i].type == 0) &&
|
||||
((adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) & 0xF) == 0))
|
||||
((target_mem_read32(target, CORTEXM_DWT_FUNC(i)) & 0xF) == 0))
|
||||
break;
|
||||
|
||||
if(i == priv->hw_watchpoint_max) return -2;
|
||||
|
@ -692,9 +686,9 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t
|
|||
priv->hw_watchpoint[i].addr = addr;
|
||||
priv->hw_watchpoint[i].size = len;
|
||||
|
||||
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_FUNC(i), type |
|
||||
target_mem_write32(target, CORTEXM_DWT_COMP(i), addr);
|
||||
target_mem_write32(target, CORTEXM_DWT_MASK(i), len);
|
||||
target_mem_write32(target, CORTEXM_DWT_FUNC(i), type |
|
||||
((target->target_options & TOPT_FLAVOUR_V6M) ? 0: CORTEXM_DWT_FUNC_DATAVSIZE_WORD));
|
||||
|
||||
return 0;
|
||||
|
@ -732,7 +726,7 @@ cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_
|
|||
|
||||
priv->hw_watchpoint[i].type = 0;
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0);
|
||||
target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -747,7 +741,7 @@ cortexm_check_hw_wp(struct target_s *target, uint32_t *addr)
|
|||
for(i = 0; i < priv->hw_watchpoint_max; i++)
|
||||
/* if SET and MATCHED then break */
|
||||
if(priv->hw_watchpoint[i].type &&
|
||||
(adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) &
|
||||
(target_mem_read32(target, CORTEXM_DWT_FUNC(i)) &
|
||||
CORTEXM_DWT_FUNC_MATCHED))
|
||||
break;
|
||||
|
||||
|
@ -781,7 +775,7 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[])
|
|||
else
|
||||
priv->demcr &= ~tmp;
|
||||
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DEMCR, priv->demcr);
|
||||
target_mem_write32(t, CORTEXM_DEMCR, priv->demcr);
|
||||
}
|
||||
|
||||
gdb_out("Catching vectors: ");
|
||||
|
|
|
@ -100,7 +100,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
|
|||
uint8_t byte;
|
||||
|
||||
while (len--) {
|
||||
target_mem_read(target, &byte, base, 1);
|
||||
byte = target_mem_read8(target, base);
|
||||
|
||||
crc = crc32_calc(crc, byte);
|
||||
base++;
|
||||
|
@ -118,7 +118,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
|
|||
CRC_CR |= CRC_CR_RESET;
|
||||
|
||||
while (len > 3) {
|
||||
target_mem_read(target, &data, base, 4);
|
||||
data = target_mem_read32(target, base);
|
||||
|
||||
CRC_DR = __builtin_bswap32(data);
|
||||
base += 4;
|
||||
|
@ -128,7 +128,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len)
|
|||
crc = CRC_DR;
|
||||
|
||||
while (len--) {
|
||||
target_mem_read(target, &data, base++, 1);
|
||||
data = target_mem_read8(target, base++);
|
||||
|
||||
crc ^= data << 24;
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
|
|
@ -166,13 +166,6 @@ void adiv5_ap_ref(ADIv5_AP_t *ap);
|
|||
void adiv5_dp_unref(ADIv5_DP_t *dp);
|
||||
void adiv5_ap_unref(ADIv5_AP_t *ap);
|
||||
|
||||
uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr);
|
||||
void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value);
|
||||
uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr);
|
||||
void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value);
|
||||
uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr);
|
||||
void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value);
|
||||
|
||||
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
|
||||
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr);
|
||||
|
||||
|
|
|
@ -111,7 +111,6 @@ target *target_attach(target *t, target_destroy_callback destroy_cb);
|
|||
#define target_hostio_reply(target, recode, errcode) \
|
||||
(target)->hostio_reply((target), (retcode), (errcode))
|
||||
|
||||
|
||||
struct target_s {
|
||||
/* Notify controlling debugger if target is lost */
|
||||
target_destroy_callback destroy_callback;
|
||||
|
@ -187,6 +186,43 @@ target *target_new(unsigned size);
|
|||
void target_list_free(void);
|
||||
void target_add_commands(target *t, const struct command_s *cmds, const char *name);
|
||||
|
||||
static inline uint32_t target_mem_read32(target *t, uint32_t addr)
|
||||
{
|
||||
uint32_t ret;
|
||||
target_mem_read(t, &ret, addr, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void target_mem_write32(target *t, uint32_t addr, uint32_t value)
|
||||
{
|
||||
target_mem_write(t, addr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
static inline uint16_t target_mem_read16(target *t, uint32_t addr)
|
||||
{
|
||||
uint16_t ret;
|
||||
target_mem_read(t, &ret, addr, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void target_mem_write16(target *t, uint32_t addr, uint16_t value)
|
||||
{
|
||||
target_mem_write(t, addr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
static inline uint8_t target_mem_read8(target *t, uint32_t addr)
|
||||
{
|
||||
uint8_t ret;
|
||||
target_mem_read(t, &ret, addr, sizeof(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void target_mem_write8(target *t, uint32_t addr, uint8_t value)
|
||||
{
|
||||
target_mem_write(t, addr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
|
||||
/* Probe for various targets.
|
||||
* Actual functions implemented in their respective drivers.
|
||||
*/
|
||||
|
|
|
@ -72,7 +72,7 @@ static const char kl25_xml_memory_map[] = "<?xml version=\"1.0\"?>"
|
|||
|
||||
bool kinetis_probe(struct target_s *t)
|
||||
{
|
||||
uint32_t sdid = adiv5_ap_mem_read(adiv5_target_ap(t), SIM_SDID);
|
||||
uint32_t sdid = target_mem_read32(t, SIM_SDID);
|
||||
switch (sdid >> 20) {
|
||||
case 0x251:
|
||||
t->driver = "KL25";
|
||||
|
@ -87,12 +87,11 @@ bool kinetis_probe(struct target_s *t)
|
|||
static bool
|
||||
kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[8])
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
uint8_t fstat;
|
||||
|
||||
/* Wait for CCIF to be high */
|
||||
do {
|
||||
fstat = adiv5_ap_mem_read_byte(ap, FTFA_FSTAT);
|
||||
fstat = target_mem_read8(t, FTFA_FSTAT);
|
||||
/* Check ACCERR and FPVIOL are zero in FSTAT */
|
||||
if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL))
|
||||
return false;
|
||||
|
@ -101,18 +100,18 @@ kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[
|
|||
/* Write command to FCCOB */
|
||||
addr &= 0xffffff;
|
||||
addr |= (uint32_t)cmd << 24;
|
||||
adiv5_ap_mem_write(ap, FTFA_FCCOB(0), addr);
|
||||
target_mem_write32(t, FTFA_FCCOB(0), addr);
|
||||
if (data) {
|
||||
adiv5_ap_mem_write(ap, FTFA_FCCOB(4), *(uint32_t*)&data[0]);
|
||||
adiv5_ap_mem_write(ap, FTFA_FCCOB(8), *(uint32_t*)&data[4]);
|
||||
target_mem_write32(t, FTFA_FCCOB(4), *(uint32_t*)&data[0]);
|
||||
target_mem_write32(t, FTFA_FCCOB(8), *(uint32_t*)&data[4]);
|
||||
}
|
||||
|
||||
/* Enable execution by clearing CCIF */
|
||||
adiv5_ap_mem_write_byte(ap, FTFA_FSTAT, FTFA_FSTAT_CCIF);
|
||||
target_mem_write8(t, FTFA_FSTAT, FTFA_FSTAT_CCIF);
|
||||
|
||||
/* Wait for execution to complete */
|
||||
do {
|
||||
fstat = adiv5_ap_mem_read_byte(ap, FTFA_FSTAT);
|
||||
fstat = target_mem_read8(t, FTFA_FSTAT);
|
||||
/* Check ACCERR and FPVIOL are zero in FSTAT */
|
||||
if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL))
|
||||
return false;
|
||||
|
|
|
@ -100,7 +100,7 @@ static const uint16_t lmi_flash_write_stub[] = {
|
|||
|
||||
bool lmi_probe(struct target_s *target)
|
||||
{
|
||||
uint32_t did1 = adiv5_ap_mem_read(adiv5_target_ap(target), 0x400FE004);
|
||||
uint32_t did1 = target_mem_read32(target, 0x400FE004);
|
||||
switch (did1 >> 16) {
|
||||
case 0x1049: /* LM3S3748 */
|
||||
target->driver = lmi_driver_str;
|
||||
|
|
|
@ -108,7 +108,7 @@ lpc11xx_probe(struct target_s *target)
|
|||
uint32_t idcode;
|
||||
|
||||
/* read the device ID register */
|
||||
idcode = adiv5_ap_mem_read(adiv5_target_ap(target), 0x400483F4);
|
||||
idcode = target_mem_read32(target, 0x400483F4);
|
||||
|
||||
switch (idcode) {
|
||||
|
||||
|
|
|
@ -170,8 +170,8 @@ bool lpc43xx_probe(struct target_s *target)
|
|||
{
|
||||
uint32_t chipid, cpuid;
|
||||
|
||||
chipid = adiv5_ap_mem_read(adiv5_target_ap(target), LPC43XX_CHIPID);
|
||||
cpuid = adiv5_ap_mem_read(adiv5_target_ap(target), ARM_CPUID);
|
||||
chipid = target_mem_read32(target, LPC43XX_CHIPID);
|
||||
cpuid = target_mem_read32(target, ARM_CPUID);
|
||||
|
||||
switch(chipid) {
|
||||
case 0x4906002B: /* Parts with on-chip flash */
|
||||
|
|
60
src/nrf51.c
60
src/nrf51.c
|
@ -136,9 +136,7 @@ static const uint16_t nrf51_flash_write_stub[] = {
|
|||
|
||||
bool nrf51_probe(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) & 0xFFFF;
|
||||
target->idcode = target_mem_read32(target, NRF51_FICR_CONFIGID) & 0xFFFF;
|
||||
|
||||
switch (target->idcode) {
|
||||
case 0x001D:
|
||||
|
@ -165,32 +163,29 @@ bool nrf51_probe(struct target_s *target)
|
|||
|
||||
static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
||||
{
|
||||
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
addr &= ~(NRF51_PAGE_SIZE - 1);
|
||||
len &= ~(NRF51_PAGE_SIZE - 1);
|
||||
|
||||
/* Enable erase */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN);
|
||||
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN);
|
||||
|
||||
/* Poll for NVMC_READY */
|
||||
while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0)
|
||||
while (target_mem_read32(target, NRF51_NVMC_READY) == 0)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
while (len) {
|
||||
if (addr == NRF51_UICR) { // Special Case
|
||||
/* Write to the ERASE_UICR register to erase */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEUICR, 0x1);
|
||||
target_mem_write32(target, NRF51_NVMC_ERASEUICR, 0x1);
|
||||
|
||||
} else { // Standard Flash Page
|
||||
/* Write address of first word in page to erase it */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEPAGE, addr);
|
||||
target_mem_write32(target, NRF51_NVMC_ERASEPAGE, addr);
|
||||
}
|
||||
|
||||
/* Poll for NVMC_READY */
|
||||
while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0)
|
||||
while (target_mem_read32(target, NRF51_NVMC_READY) == 0)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -199,10 +194,10 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
|||
}
|
||||
|
||||
/* Return to read-only */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN);
|
||||
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN);
|
||||
|
||||
/* Poll for NVMC_READY */
|
||||
while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0)
|
||||
while (target_mem_read32(target, NRF51_NVMC_READY) == 0)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -212,7 +207,6 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
|||
static int nrf51_flash_write(struct target_s *target, uint32_t dest,
|
||||
const uint8_t *src, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint32_t offset = dest % 4;
|
||||
uint32_t words = (offset + len + 3) / 4;
|
||||
uint32_t data[2 + words];
|
||||
|
@ -225,10 +219,10 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest,
|
|||
memcpy((uint8_t *)&data[2] + offset, src, len);
|
||||
|
||||
/* Enable write */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN);
|
||||
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN);
|
||||
|
||||
/* Poll for NVMC_READY */
|
||||
while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0)
|
||||
while (target_mem_read32(target, NRF51_NVMC_READY) == 0)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -244,30 +238,28 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest,
|
|||
while(!target_halt_wait(target));
|
||||
|
||||
/* Return to read-only */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN);
|
||||
target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool nrf51_cmd_erase_all(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
gdb_out("erase..\n");
|
||||
|
||||
/* Enable erase */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN);
|
||||
target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN);
|
||||
|
||||
/* Poll for NVMC_READY */
|
||||
while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0)
|
||||
while (target_mem_read32(t, NRF51_NVMC_READY) == 0)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
|
||||
/* Erase all */
|
||||
adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEALL, 1);
|
||||
target_mem_write32(t, NRF51_NVMC_ERASEALL, 1);
|
||||
|
||||
/* Poll for NVMC_READY */
|
||||
while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0)
|
||||
while (target_mem_read32(t, NRF51_NVMC_READY) == 0)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
|
||||
|
@ -276,28 +268,22 @@ static bool nrf51_cmd_erase_all(target *t)
|
|||
|
||||
static bool nrf51_cmd_read_hwid(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
uint32_t hwid = adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) & 0xFFFF;
|
||||
uint32_t hwid = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF;
|
||||
gdb_outf("Hardware ID: 0x%04X\n", hwid);
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool nrf51_cmd_read_fwid(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
uint32_t fwid = (adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) >> 16) & 0xFFFF;
|
||||
uint32_t fwid = (target_mem_read32(t, NRF51_FICR_CONFIGID) >> 16) & 0xFFFF;
|
||||
gdb_outf("Firmware ID: 0x%04X\n", fwid);
|
||||
|
||||
return true;
|
||||
}
|
||||
static bool nrf51_cmd_read_deviceid(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
uint32_t deviceid_low = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEID_LOW);
|
||||
uint32_t deviceid_high = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEID_HIGH);
|
||||
uint32_t deviceid_low = target_mem_read32(t, NRF51_FICR_DEVICEID_LOW);
|
||||
uint32_t deviceid_high = target_mem_read32(t, NRF51_FICR_DEVICEID_HIGH);
|
||||
|
||||
gdb_outf("Device ID: 0x%08X%08X\n", deviceid_high, deviceid_low);
|
||||
|
||||
|
@ -305,11 +291,9 @@ static bool nrf51_cmd_read_deviceid(target *t)
|
|||
}
|
||||
static bool nrf51_cmd_read_deviceaddr(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
uint32_t addr_type = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDRTYPE);
|
||||
uint32_t addr_low = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDR_LOW);
|
||||
uint32_t addr_high = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDR_HIGH) & 0xFFFF;
|
||||
uint32_t addr_type = target_mem_read32(t, NRF51_FICR_DEVICEADDRTYPE);
|
||||
uint32_t addr_low = target_mem_read32(t, NRF51_FICR_DEVICEADDR_LOW);
|
||||
uint32_t addr_high = target_mem_read32(t, NRF51_FICR_DEVICEADDR_HIGH) & 0xFFFF;
|
||||
|
||||
if ((addr_type & 1) == 0) {
|
||||
gdb_outf("Publicly Listed Address: 0x%04X%08X\n", addr_high, addr_low);
|
||||
|
|
47
src/sam3x.c
47
src/sam3x.c
|
@ -148,9 +148,7 @@ static const char sam4s_xml_memory_map[] = "<?xml version=\"1.0\"?>"
|
|||
|
||||
bool sam3x_probe(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(ap, SAM3X_CHIPID_CIDR);
|
||||
target->idcode = target_mem_read32(target, SAM3X_CHIPID_CIDR);
|
||||
|
||||
/* FIXME: Check for all variants with similar flash interface */
|
||||
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
|
@ -165,7 +163,7 @@ bool sam3x_probe(struct target_s *target)
|
|||
return true;
|
||||
}
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(ap, SAM3N_CHIPID_CIDR);
|
||||
target->idcode = target_mem_read32(target, SAM3N_CHIPID_CIDR);
|
||||
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3:
|
||||
|
@ -177,21 +175,21 @@ bool sam3x_probe(struct target_s *target)
|
|||
target_add_commands(target, sam3x_cmd_list, "SAM3N");
|
||||
return true;
|
||||
}
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(ap, SAM3S_CHIPID_CIDR);
|
||||
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3:
|
||||
target->driver = "Atmel SAM3S";
|
||||
target->xml_mem_map = sam3n_xml_memory_map;
|
||||
target->flash_erase = sam3x_flash_erase;
|
||||
target->flash_write = sam3x_flash_write;
|
||||
target_add_commands(target, sam3x_cmd_list, "SAM3S");
|
||||
return true;
|
||||
}
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(ap, SAM4S_CHIPID_CIDR);
|
||||
target->idcode = target_mem_read32(target, SAM3S_CHIPID_CIDR);
|
||||
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3:
|
||||
case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3:
|
||||
target->driver = "Atmel SAM3S";
|
||||
target->xml_mem_map = sam3n_xml_memory_map;
|
||||
target->flash_erase = sam3x_flash_erase;
|
||||
target->flash_write = sam3x_flash_write;
|
||||
target_add_commands(target, sam3x_cmd_list, "SAM3S");
|
||||
return true;
|
||||
}
|
||||
|
||||
target->idcode = target_mem_read32(target, SAM4S_CHIPID_CIDR);
|
||||
switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) {
|
||||
case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4:
|
||||
case CHIPID_CIDR_ARCH_SAM4SxB | CHIPID_CIDR_EPROC_CM4:
|
||||
|
@ -210,18 +208,16 @@ bool sam3x_probe(struct target_s *target)
|
|||
static int
|
||||
sam3x_flash_cmd(struct target_s *target, uint32_t base, uint8_t cmd, uint16_t arg)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n",
|
||||
__func__, base, cmd, arg);
|
||||
adiv5_ap_mem_write(ap, EEFC_FCR(base),
|
||||
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));
|
||||
target_mem_write32(target, EEFC_FCR(base),
|
||||
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));
|
||||
|
||||
while(!(adiv5_ap_mem_read(ap, EEFC_FSR(base)) & EEFC_FSR_FRDY))
|
||||
while (!(target_mem_read32(target, EEFC_FSR(base)) & EEFC_FSR_FRDY))
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
uint32_t sr = adiv5_ap_mem_read(ap, EEFC_FSR(base));
|
||||
uint32_t sr = target_mem_read32(target, EEFC_FSR(base));
|
||||
return sr & EEFC_FSR_ERROR;
|
||||
}
|
||||
|
||||
|
@ -394,11 +390,10 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest,
|
|||
|
||||
static bool sam3x_cmd_gpnvm_get(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
uint32_t base = sam3x_flash_base(t, 0, NULL);
|
||||
|
||||
sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0);
|
||||
gdb_outf("GPNVM: 0x%08X\n", adiv5_ap_mem_read(ap, EEFC_FRR(base)));
|
||||
gdb_outf("GPNVM: 0x%08X\n", target_mem_read32(t, EEFC_FRR(base)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
134
src/samd.c
134
src/samd.c
|
@ -167,13 +167,12 @@ static const char samd_xml_memory_map[] = "<?xml version=\"1.0\"?>"
|
|||
*/
|
||||
uint64_t samd_read_pid(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint64_t pid = 0;
|
||||
uint8_t i, j;
|
||||
|
||||
/* Five PID registers to read LSB first */
|
||||
for (i = 0, j = 0; i < 5; i++, j += 8)
|
||||
pid |= (adiv5_ap_mem_read(ap, SAMD_DSU_PID(i)) & 0xFF) << j;
|
||||
pid |= (target_mem_read32(target, SAMD_DSU_PID(i)) & 0xFF) << j;
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
@ -182,13 +181,12 @@ uint64_t samd_read_pid(struct target_s *target)
|
|||
*/
|
||||
uint32_t samd_read_cid(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint64_t cid = 0;
|
||||
uint8_t i, j;
|
||||
|
||||
/* Four CID registers to read LSB first */
|
||||
for (i = 0, j = 0; i < 4; i++, j += 8)
|
||||
cid |= (adiv5_ap_mem_read(ap, SAMD_DSU_CID(i)) & 0xFF) << j;
|
||||
cid |= (target_mem_read32(target, SAMD_DSU_CID(i)) & 0xFF) << j;
|
||||
|
||||
return cid;
|
||||
}
|
||||
|
@ -200,8 +198,6 @@ uint32_t samd_read_cid(struct target_s *target)
|
|||
static void
|
||||
samd_reset(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
/**
|
||||
* SRST is not asserted here as it appears to reset the adiv5
|
||||
* logic, meaning that subsequent adiv5_* calls PLATFORM_FATAL_ERROR.
|
||||
|
@ -219,28 +215,28 @@ samd_reset(struct target_s *target)
|
|||
*/
|
||||
|
||||
/* Read DHCSR here to clear S_RESET_ST bit before reset */
|
||||
adiv5_ap_mem_read(ap, CORTEXM_DHCSR);
|
||||
target_mem_read32(target, CORTEXM_DHCSR);
|
||||
|
||||
/* Request system reset from NVIC: SRST doesn't work correctly */
|
||||
/* This could be VECTRESET: 0x05FA0001 (reset only core)
|
||||
* or SYSRESETREQ: 0x05FA0004 (system reset)
|
||||
*/
|
||||
adiv5_ap_mem_write(ap, CORTEXM_AIRCR,
|
||||
target_mem_write32(target, CORTEXM_AIRCR,
|
||||
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
|
||||
|
||||
/* Exit extended reset */
|
||||
if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) &
|
||||
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
|
||||
SAMD_STATUSA_CRSTEXT) {
|
||||
/* Write bit to clear from extended reset */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT,
|
||||
target_mem_write32(target, SAMD_DSU_CTRLSTAT,
|
||||
SAMD_STATUSA_CRSTEXT);
|
||||
}
|
||||
|
||||
/* Poll for release from reset */
|
||||
while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST);
|
||||
while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST);
|
||||
|
||||
/* Reset DFSR flags */
|
||||
adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
|
||||
target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
|
||||
|
||||
/* Clear any target errors */
|
||||
target_check_error(target);
|
||||
|
@ -255,16 +251,15 @@ samd_reset(struct target_s *target)
|
|||
static void
|
||||
samd20_revB_detach(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
cortexm_detach(target);
|
||||
|
||||
/* ---- Additional ---- */
|
||||
/* Exit extended reset */
|
||||
if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) &
|
||||
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
|
||||
SAMD_STATUSA_CRSTEXT) {
|
||||
/* Write bit to clear from extended reset */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT,
|
||||
SAMD_STATUSA_CRSTEXT);
|
||||
target_mem_write32(target, SAMD_DSU_CTRLSTAT,
|
||||
SAMD_STATUSA_CRSTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,16 +272,15 @@ samd20_revB_detach(struct target_s *target)
|
|||
static void
|
||||
samd20_revB_halt_resume(struct target_s *target, bool step)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
cortexm_halt_resume(target, step);
|
||||
|
||||
/* ---- Additional ---- */
|
||||
/* Exit extended reset */
|
||||
if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) &
|
||||
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
|
||||
SAMD_STATUSA_CRSTEXT) {
|
||||
/* Write bit to clear from extended reset */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT,
|
||||
SAMD_STATUSA_CRSTEXT);
|
||||
target_mem_write32(target, SAMD_DSU_CTRLSTAT,
|
||||
SAMD_STATUSA_CRSTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +370,6 @@ struct samd_descr samd_parse_device_id(uint32_t did)
|
|||
char variant_string[40];
|
||||
bool samd_probe(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint32_t cid = samd_read_cid(target);
|
||||
uint32_t pid = samd_read_pid(target);
|
||||
|
||||
|
@ -385,12 +378,13 @@ bool samd_probe(struct target_s *target)
|
|||
(pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) {
|
||||
|
||||
/* Read the Device ID */
|
||||
uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID);
|
||||
uint32_t did = target_mem_read32(target, SAMD_DSU_DID);
|
||||
|
||||
/* If the Device ID matches */
|
||||
if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) {
|
||||
|
||||
uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT);
|
||||
uint32_t ctrlstat = target_mem_read32(target,
|
||||
SAMD_DSU_CTRLSTAT);
|
||||
struct samd_descr samd = samd_parse_device_id(did);
|
||||
|
||||
/* Protected? */
|
||||
|
@ -442,11 +436,11 @@ bool samd_probe(struct target_s *target)
|
|||
if (!connect_assert_srst) {
|
||||
/* We'll have to release the target from
|
||||
* extended reset to make attach possible */
|
||||
if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) &
|
||||
if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) &
|
||||
SAMD_STATUSA_CRSTEXT) {
|
||||
|
||||
/* Write bit to clear from extended reset */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT,
|
||||
target_mem_write32(target, SAMD_DSU_CTRLSTAT,
|
||||
SAMD_STATUSA_CRSTEXT);
|
||||
}
|
||||
}
|
||||
|
@ -463,17 +457,15 @@ bool samd_probe(struct target_s *target)
|
|||
*/
|
||||
static void samd_lock_current_address(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
/* Issue the unlock command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK);
|
||||
target_mem_write32(target, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK);
|
||||
}
|
||||
static void samd_unlock_current_address(struct target_s *target)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
/* Issue the unlock command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK);
|
||||
target_mem_write32(target, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -481,23 +473,22 @@ static void samd_unlock_current_address(struct target_s *target)
|
|||
*/
|
||||
static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
addr &= ~(SAMD_ROW_SIZE - 1);
|
||||
len &= ~(SAMD_ROW_SIZE - 1);
|
||||
|
||||
while (len) {
|
||||
/* Write address of first word in row to erase it */
|
||||
/* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, addr >> 1);
|
||||
target_mem_write32(target, SAMD_NVMC_ADDRESS, addr >> 1);
|
||||
|
||||
/* Unlock */
|
||||
samd_unlock_current_address(target);
|
||||
|
||||
/* Issue the erase command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW);
|
||||
target_mem_write32(target, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW);
|
||||
/* Poll for NVM Ready */
|
||||
while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -518,7 +509,6 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
|
|||
const uint8_t *src, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
|
||||
/* Find the size of our 32-bit data buffer */
|
||||
uint32_t offset = dest % 4;
|
||||
uint32_t words = (offset + len + 3) / 4;
|
||||
|
@ -560,11 +550,11 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
|
|||
samd_unlock_current_address(target);
|
||||
|
||||
/* Issue the write page command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA,
|
||||
target_mem_write32(target, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE);
|
||||
} else {
|
||||
/* Write first word to set address */
|
||||
adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++;
|
||||
target_mem_write32(target, addr, data[i]); addr += 4; i++;
|
||||
|
||||
/* Unlock */
|
||||
samd_unlock_current_address(target);
|
||||
|
@ -583,7 +573,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
|
|||
}
|
||||
|
||||
/* Poll for NVM Ready */
|
||||
while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -599,18 +589,16 @@ static int samd_flash_write(struct target_s *target, uint32_t dest,
|
|||
*/
|
||||
static bool samd_cmd_erase_all(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
/* Clear the DSU status bits */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT,
|
||||
target_mem_write32(t, SAMD_DSU_CTRLSTAT,
|
||||
(SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL));
|
||||
|
||||
/* Erase all */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE);
|
||||
target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE);
|
||||
|
||||
/* Poll for DSU Ready */
|
||||
uint32_t status;
|
||||
while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) &
|
||||
while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) &
|
||||
(SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
|
@ -641,20 +629,19 @@ static bool samd_cmd_erase_all(target *t)
|
|||
*/
|
||||
static bool samd_set_flashlock(target *t, uint16_t value)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
uint32_t high = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH);
|
||||
uint32_t low = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW);
|
||||
uint32_t high = target_mem_read32(t, SAMD_NVM_USER_ROW_HIGH);
|
||||
uint32_t low = target_mem_read32(t, SAMD_NVM_USER_ROW_LOW);
|
||||
|
||||
/* Write address of a word in the row to erase it */
|
||||
/* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1);
|
||||
target_mem_write32(t, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1);
|
||||
|
||||
/* Issue the erase command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW);
|
||||
target_mem_write32(t, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW);
|
||||
|
||||
/* Poll for NVM Ready */
|
||||
while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
if(target_check_error(t))
|
||||
return -1;
|
||||
|
||||
|
@ -662,12 +649,12 @@ static bool samd_set_flashlock(target *t, uint16_t value)
|
|||
high = (high & 0x0000FFFF) | ((value << 16) & 0xFFFF0000);
|
||||
|
||||
/* Write back */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_LOW, low);
|
||||
adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_HIGH, high);
|
||||
target_mem_write32(t, SAMD_NVM_USER_ROW_LOW, low);
|
||||
target_mem_write32(t, SAMD_NVM_USER_ROW_HIGH, high);
|
||||
|
||||
/* Issue the page write command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE);
|
||||
target_mem_write32(t, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -681,11 +668,9 @@ static bool samd_cmd_unlock_flash(target *t)
|
|||
}
|
||||
static bool samd_cmd_read_userrow(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
gdb_outf("User Row: 0x%08x%08x\n",
|
||||
adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH),
|
||||
adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW));
|
||||
target_mem_read32(t, SAMD_NVM_USER_ROW_HIGH),
|
||||
target_mem_read32(t, SAMD_NVM_USER_ROW_LOW));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -694,12 +679,10 @@ static bool samd_cmd_read_userrow(target *t)
|
|||
*/
|
||||
static bool samd_cmd_serial(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
gdb_outf("Serial Number: 0x");
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD_NVM_SERIAL(i)));
|
||||
gdb_outf("%08x", target_mem_read32(t, SAMD_NVM_SERIAL(i)));
|
||||
}
|
||||
|
||||
gdb_outf("\n");
|
||||
|
@ -711,10 +694,8 @@ static bool samd_cmd_serial(target *t)
|
|||
*/
|
||||
static uint32_t samd_flash_size(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
/* Read the Device ID */
|
||||
uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID);
|
||||
uint32_t did = target_mem_read32(t, SAMD_DSU_DID);
|
||||
|
||||
/* Mask off the device select bits */
|
||||
uint8_t devsel = did & SAMD_DID_DEVSEL_MASK;
|
||||
|
@ -727,21 +708,19 @@ static uint32_t samd_flash_size(target *t)
|
|||
*/
|
||||
static bool samd_cmd_mbist(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
/* Write the memory parameters to the DSU */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_ADDRESS, 0);
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_LENGTH, samd_flash_size(t));
|
||||
target_mem_write32(t, SAMD_DSU_ADDRESS, 0);
|
||||
target_mem_write32(t, SAMD_DSU_LENGTH, samd_flash_size(t));
|
||||
|
||||
/* Clear the fail bit */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL);
|
||||
target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL);
|
||||
|
||||
/* Write the MBIST command */
|
||||
adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST);
|
||||
target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST);
|
||||
|
||||
/* Poll for DSU Ready */
|
||||
uint32_t status;
|
||||
while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) &
|
||||
while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) &
|
||||
(SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
|
@ -755,7 +734,7 @@ static bool samd_cmd_mbist(target *t)
|
|||
/* Test the fail bit in Status A */
|
||||
if (status & SAMD_STATUSA_FAIL) {
|
||||
gdb_outf("MBIST Fail @ 0x%08x\n",
|
||||
adiv5_ap_mem_read(ap, SAMD_DSU_ADDRESS));
|
||||
target_mem_read32(t, SAMD_DSU_ADDRESS));
|
||||
} else {
|
||||
gdb_outf("MBIST Passed!\n");
|
||||
}
|
||||
|
@ -767,13 +746,12 @@ static bool samd_cmd_mbist(target *t)
|
|||
*/
|
||||
static bool samd_cmd_ssb(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
/* Issue the ssb command */
|
||||
adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB);
|
||||
target_mem_write32(t, SAMD_NVMC_CTRLA,
|
||||
SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB);
|
||||
|
||||
/* Poll for NVM Ready */
|
||||
while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0)
|
||||
if(target_check_error(t))
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -158,8 +158,7 @@ static const uint16_t stm32f1_flash_write_stub[] = {
|
|||
|
||||
bool stm32f1_probe(struct target_s *target)
|
||||
{
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE) & 0xfff;
|
||||
target->idcode = target_mem_read32(target, DBGMCU_IDCODE) & 0xfff;
|
||||
switch(target->idcode) {
|
||||
case 0x410: /* Medium density */
|
||||
case 0x412: /* Low denisty */
|
||||
|
@ -189,7 +188,7 @@ bool stm32f1_probe(struct target_s *target)
|
|||
return true;
|
||||
}
|
||||
|
||||
target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0) & 0xfff;
|
||||
target->idcode = target_mem_read32(target, DBGMCU_IDCODE_F0) & 0xfff;
|
||||
switch(target->idcode) {
|
||||
case 0x444: /* STM32F03 RM0091 Rev.7 */
|
||||
case 0x445: /* STM32F04 RM0091 Rev.7 */
|
||||
|
@ -223,33 +222,32 @@ bool stm32f1_probe(struct target_s *target)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void stm32f1_flash_unlock(ADIv5_AP_t *ap)
|
||||
static void stm32f1_flash_unlock(target *t)
|
||||
{
|
||||
adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1);
|
||||
adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2);
|
||||
target_mem_write32(t, FLASH_KEYR, KEY1);
|
||||
target_mem_write32(t, FLASH_KEYR, KEY2);
|
||||
}
|
||||
|
||||
static int stm32f1_flash_erase(struct target_s *target, uint32_t addr,
|
||||
size_t len, uint32_t pagesize)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint16_t sr;
|
||||
|
||||
addr &= ~(pagesize - 1);
|
||||
len = (len + pagesize - 1) & ~(pagesize - 1);
|
||||
|
||||
stm32f1_flash_unlock(ap);
|
||||
stm32f1_flash_unlock(target);
|
||||
|
||||
while(len) {
|
||||
/* Flash page erase instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_PER);
|
||||
target_mem_write32(target, FLASH_CR, FLASH_CR_PER);
|
||||
/* write address to FMA */
|
||||
adiv5_ap_mem_write(ap, FLASH_AR, addr);
|
||||
target_mem_write32(target, FLASH_AR, addr);
|
||||
/* Flash page erase start instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER);
|
||||
target_mem_write32(target, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while (target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -258,7 +256,7 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr,
|
|||
}
|
||||
|
||||
/* Check for error */
|
||||
sr = adiv5_ap_mem_read(ap, FLASH_SR);
|
||||
sr = target_mem_read32(target, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
|
||||
return -1;
|
||||
|
||||
|
@ -278,7 +276,6 @@ static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t le
|
|||
static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
|
||||
const uint8_t *src, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint32_t offset = dest % 4;
|
||||
uint32_t words = (offset + len + 3) / 4;
|
||||
if (words > 256)
|
||||
|
@ -304,7 +301,7 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
|
|||
while(!target_halt_wait(target));
|
||||
|
||||
/* Check for error */
|
||||
if (adiv5_ap_mem_read(ap, FLASH_SR) & SR_ERROR_MASK)
|
||||
if (target_mem_read32(target, FLASH_SR) & SR_ERROR_MASK)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
@ -312,21 +309,19 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest,
|
|||
|
||||
static bool stm32f1_cmd_erase_mass(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
stm32f1_flash_unlock(ap);
|
||||
stm32f1_flash_unlock(t);
|
||||
|
||||
/* Flash mass erase start instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER);
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_MER);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
|
||||
/* Check for error */
|
||||
uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR);
|
||||
uint16_t sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
|
||||
return false;
|
||||
|
||||
|
@ -335,14 +330,12 @@ static bool stm32f1_cmd_erase_mass(target *t)
|
|||
|
||||
static bool stm32f1_option_erase(target *t)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
/* Erase option bytes instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE);
|
||||
adiv5_ap_mem_write(ap, FLASH_CR,
|
||||
FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE);
|
||||
target_mem_write32(t, FLASH_CR,
|
||||
FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -350,15 +343,13 @@ static bool stm32f1_option_erase(target *t)
|
|||
|
||||
static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
if (value == 0xffff)
|
||||
return true;
|
||||
/* Erase option bytes instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE);
|
||||
adiv5_ap_mem_write_halfword(ap, addr, value);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE);
|
||||
target_mem_write16(t, addr, value);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -366,7 +357,6 @@ static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value
|
|||
|
||||
static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
uint16_t opt_val[8];
|
||||
int i, index;
|
||||
|
||||
|
@ -375,7 +365,7 @@ static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value)
|
|||
return false;
|
||||
/* Retrieve old values */
|
||||
for (i = 0; i < 16; i = i +4) {
|
||||
uint32_t val = adiv5_ap_mem_read(ap, FLASH_OBP_RDP + i);
|
||||
uint32_t val = target_mem_read32(t, FLASH_OBP_RDP + i);
|
||||
opt_val[i/2] = val & 0xffff;
|
||||
opt_val[i/2 +1] = val >> 16;
|
||||
}
|
||||
|
@ -398,7 +388,6 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
|
|||
{
|
||||
uint32_t addr, val;
|
||||
uint32_t flash_obp_rdp_key;
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
uint32_t rdprt;
|
||||
|
||||
switch(t->idcode) {
|
||||
|
@ -409,10 +398,10 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
|
|||
break;
|
||||
default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY;
|
||||
}
|
||||
rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT);
|
||||
stm32f1_flash_unlock(ap);
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1);
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2);
|
||||
rdprt = target_mem_read32(t, FLASH_OBR) & FLASH_OBR_RDPRT;
|
||||
stm32f1_flash_unlock(t);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, KEY1);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, KEY2);
|
||||
|
||||
if ((argc == 2) && !strcmp(argv[1], "erase")) {
|
||||
stm32f1_option_erase(t);
|
||||
|
@ -432,7 +421,7 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
|
|||
|
||||
if (0 && flash_obp_rdp_key == FLASH_OBP_RDP_KEY_F3) {
|
||||
/* Reload option bytes on F0 and F3*/
|
||||
val = adiv5_ap_mem_read(ap, FLASH_CR);
|
||||
val = target_mem_read32(t, FLASH_CR);
|
||||
val |= FLASH_CR_OBL_LAUNCH;
|
||||
stm32f1_option_write(t, FLASH_CR, val);
|
||||
val &= ~FLASH_CR_OBL_LAUNCH;
|
||||
|
@ -441,7 +430,7 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[])
|
|||
|
||||
for (int i = 0; i < 0xf; i += 4) {
|
||||
addr = 0x1ffff800 + i;
|
||||
val = adiv5_ap_mem_read(ap, addr);
|
||||
val = target_mem_read32(t, addr);
|
||||
gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF);
|
||||
gdb_outf("0x%08X: 0x%04X\n", addr + 2, val >> 16);
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ bool stm32f4_probe(struct target_s *target)
|
|||
{
|
||||
uint32_t idcode;
|
||||
|
||||
idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE);
|
||||
idcode = target_mem_read32(target, DBGMCU_IDCODE);
|
||||
switch(idcode & 0xFFF) {
|
||||
case 0x411: /* Documented to be 0x413! This is what I read... */
|
||||
case 0x413: /* F407VGT6 */
|
||||
|
@ -180,25 +180,24 @@ bool stm32f4_probe(struct target_s *target)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void stm32f4_flash_unlock(ADIv5_AP_t *ap)
|
||||
static void stm32f4_flash_unlock(target *t)
|
||||
{
|
||||
if (adiv5_ap_mem_read(ap, FLASH_CR) & FLASH_CR_LOCK) {
|
||||
if (target_mem_read32(t, FLASH_CR) & FLASH_CR_LOCK) {
|
||||
/* Enable FPEC controller access */
|
||||
adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1);
|
||||
adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2);
|
||||
target_mem_write32(t, FLASH_KEYR, KEY1);
|
||||
target_mem_write32(t, FLASH_KEYR, KEY2);
|
||||
}
|
||||
}
|
||||
|
||||
static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint16_t sr;
|
||||
uint32_t cr;
|
||||
uint32_t pagesize;
|
||||
|
||||
addr &= 0x07FFC000;
|
||||
|
||||
stm32f4_flash_unlock(ap);
|
||||
stm32f4_flash_unlock(target);
|
||||
|
||||
while(len) {
|
||||
if (addr < 0x10000) { /* Sector 0..3 */
|
||||
|
@ -215,12 +214,12 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le
|
|||
}
|
||||
cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER;
|
||||
/* Flash page erase instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, cr);
|
||||
target_mem_write32(target, FLASH_CR, cr);
|
||||
/* write address to FMA */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, cr | FLASH_CR_STRT);
|
||||
target_mem_write32(target, FLASH_CR, cr | FLASH_CR_STRT);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while(target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -229,7 +228,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le
|
|||
}
|
||||
|
||||
/* Check for error */
|
||||
sr = adiv5_ap_mem_read(ap, FLASH_SR);
|
||||
sr = target_mem_read32(target, FLASH_SR);
|
||||
if(sr & SR_ERROR_MASK)
|
||||
return -1;
|
||||
|
||||
|
@ -239,7 +238,6 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le
|
|||
static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
|
||||
const uint8_t *src, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint32_t offset = dest % 4;
|
||||
uint32_t words = (offset + len + 3) / 4;
|
||||
uint32_t data[2 + words];
|
||||
|
@ -264,7 +262,7 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest,
|
|||
while(!target_halt_wait(target));
|
||||
|
||||
/* Check for error */
|
||||
sr = adiv5_ap_mem_read(ap, FLASH_SR);
|
||||
sr = target_mem_read32(target, FLASH_SR);
|
||||
if(sr & SR_ERROR_MASK)
|
||||
return -1;
|
||||
|
||||
|
@ -276,17 +274,15 @@ static bool stm32f4_cmd_erase_mass(target *t)
|
|||
const char spinner[] = "|/-\\";
|
||||
int spinindex = 0;
|
||||
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
gdb_out("Erasing flash... This may take a few seconds. ");
|
||||
stm32f4_flash_unlock(ap);
|
||||
stm32f4_flash_unlock(t);
|
||||
|
||||
/* Flash mass erase start instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER);
|
||||
adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_MER);
|
||||
target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) {
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) {
|
||||
gdb_outf("\b%c", spinner[spinindex++ % 4]);
|
||||
if(target_check_error(t)) {
|
||||
gdb_out("\n");
|
||||
|
@ -296,7 +292,7 @@ static bool stm32f4_cmd_erase_mass(target *t)
|
|||
gdb_out("\n");
|
||||
|
||||
/* Check for error */
|
||||
uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR);
|
||||
uint16_t sr = target_mem_read32(t, FLASH_SR);
|
||||
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP))
|
||||
return false;
|
||||
|
||||
|
@ -305,23 +301,21 @@ static bool stm32f4_cmd_erase_mass(target *t)
|
|||
|
||||
static bool stm32f4_option_write(target *t, uint32_t value)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY1);
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY2);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1);
|
||||
target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2);
|
||||
value &= ~FLASH_OPTCR_RESERVED;
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return -1;
|
||||
|
||||
/* WRITE option bytes instruction */
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTCR, value);
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT);
|
||||
target_mem_write32(t, FLASH_OPTCR, value);
|
||||
target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT);
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY)
|
||||
while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
|
||||
if(target_check_error(t))
|
||||
return false;
|
||||
adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK);
|
||||
target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -329,8 +323,6 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
|
|||
{
|
||||
uint32_t addr, val;
|
||||
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(t);
|
||||
|
||||
if ((argc == 2) && !strcmp(argv[1], "erase")) {
|
||||
stm32f4_option_write(t, 0x0fffaaed);
|
||||
}
|
||||
|
@ -344,7 +336,7 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[])
|
|||
|
||||
for (int i = 0; i < 0xf; i += 8) {
|
||||
addr = 0x1fffC000 + i;
|
||||
val = adiv5_ap_mem_read(ap, addr);
|
||||
val = target_mem_read32(t, addr);
|
||||
gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF);
|
||||
}
|
||||
return true;
|
||||
|
|
138
src/stm32l0.c
138
src/stm32l0.c
|
@ -72,13 +72,13 @@
|
|||
to regain control of the target after the option byte reload.
|
||||
|
||||
stm32l0_option_write(t, 0x1ff80000, 0xffff0000);
|
||||
adiv5_ap_mem_write(ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH);
|
||||
target_mem_write32(target, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH);
|
||||
stm32l0_option_write(t, 0x1ff80000, 0xff5500aa);
|
||||
adiv5_ap_mem_write(ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH);
|
||||
target_mem_write32(target, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH);
|
||||
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = adiv5_ap_mem_read(ap, STM32L0_NVM_SR);
|
||||
sr = target_mem_read32(target, STM32L0_NVM_SR);
|
||||
} while (sr & STM32L0_NVM_SR_BSY);
|
||||
|
||||
o Errors. We probably should clear SR errors immediately after
|
||||
|
@ -288,7 +288,7 @@ bool stm32l0_probe(struct target_s* target)
|
|||
|
||||
#if defined(CONFIG_STM32L1)
|
||||
|
||||
idcode = adiv5_ap_mem_read(adiv5_target_ap(target),
|
||||
idcode = target_mem_read32(target,
|
||||
STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff;
|
||||
switch (idcode) {
|
||||
case 0x416: /* CAT. 1 device */
|
||||
|
@ -306,7 +306,7 @@ bool stm32l0_probe(struct target_s* target)
|
|||
}
|
||||
#endif
|
||||
|
||||
idcode = adiv5_ap_mem_read(adiv5_target_ap(target),
|
||||
idcode = target_mem_read32(target,
|
||||
STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff;
|
||||
switch (idcode) {
|
||||
default:
|
||||
|
@ -327,42 +327,42 @@ bool stm32l0_probe(struct target_s* target)
|
|||
|
||||
|
||||
/** Lock the NVM control registers preventing writes or erases. */
|
||||
static void stm32lx_nvm_lock(ADIv5_AP_t* ap, uint32_t nvm)
|
||||
static void stm32lx_nvm_lock(target *t, uint32_t nvm)
|
||||
{
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);
|
||||
}
|
||||
|
||||
|
||||
/** Unlock the NVM control registers for modifying program or
|
||||
data flash. Returns true if the unlock succeeds. */
|
||||
static bool stm32lx_nvm_prog_data_unlock(ADIv5_AP_t* ap, uint32_t nvm)
|
||||
static bool stm32lx_nvm_prog_data_unlock(target* t, uint32_t nvm)
|
||||
{
|
||||
/* Always lock first because that's the only way to know that the
|
||||
unlock can succeed on the STM32L0's. */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2);
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);
|
||||
target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1);
|
||||
target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2);
|
||||
target_mem_write32(t, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1);
|
||||
target_mem_write32(t, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2);
|
||||
|
||||
return !(adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm))
|
||||
return !(target_mem_read32(t, STM32Lx_NVM_PECR(nvm))
|
||||
& STM32Lx_NVM_PECR_PRGLOCK);
|
||||
}
|
||||
|
||||
|
||||
/** Unlock the NVM control registers for modifying option bytes.
|
||||
Returns true if the unlock succeeds. */
|
||||
static bool stm32lx_nvm_opt_unlock(ADIv5_AP_t* ap, uint32_t nvm)
|
||||
static bool stm32lx_nvm_opt_unlock(target *t, uint32_t nvm)
|
||||
{
|
||||
/* Always lock first because that's the only way to know that the
|
||||
unlock can succeed on the STM32L0's. */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1);
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2);
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);
|
||||
target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1);
|
||||
target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2);
|
||||
target_mem_write32(t, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1);
|
||||
target_mem_write32(t, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2);
|
||||
|
||||
return !(adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm))
|
||||
return !(target_mem_read32(t, STM32Lx_NVM_PECR(nvm))
|
||||
& STM32Lx_NVM_PECR_OPTLOCK);
|
||||
}
|
||||
|
||||
|
@ -400,8 +400,7 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target,
|
|||
while (!target_halt_wait(target))
|
||||
;
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(target);
|
||||
if (adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm))
|
||||
if (target_mem_read32(target, STM32Lx_NVM_SR(nvm))
|
||||
& STM32Lx_NVM_SR_ERR_M)
|
||||
return -1;
|
||||
}
|
||||
|
@ -477,8 +476,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target,
|
|||
while (!target_halt_wait(target))
|
||||
;
|
||||
|
||||
if (adiv5_ap_mem_read(adiv5_target_ap(target),
|
||||
STM32Lx_NVM_SR(nvm))
|
||||
if (target_mem_read32(target, STM32Lx_NVM_SR(nvm))
|
||||
& STM32Lx_NVM_SR_ERR_M)
|
||||
return -1;
|
||||
}
|
||||
|
@ -557,7 +555,6 @@ static int stm32lx_nvm_write(struct target_s* target,
|
|||
static int stm32lx_nvm_prog_erase(struct target_s* target,
|
||||
uint32_t addr, size_t len)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(target);
|
||||
const size_t page_size = stm32lx_nvm_prog_page_size(target);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(target);
|
||||
|
||||
|
@ -565,15 +562,15 @@ static int stm32lx_nvm_prog_erase(struct target_s* target,
|
|||
len += (addr & 3);
|
||||
addr &= ~3;
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(ap, nvm))
|
||||
if (!stm32lx_nvm_prog_data_unlock(target, nvm))
|
||||
return -1;
|
||||
|
||||
/* Flash page erase instruction */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(target, STM32Lx_NVM_PECR(nvm),
|
||||
STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG);
|
||||
|
||||
{
|
||||
uint32_t pecr = adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm));
|
||||
uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm));
|
||||
if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
!= (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE))
|
||||
return -1;
|
||||
|
@ -581,22 +578,22 @@ static int stm32lx_nvm_prog_erase(struct target_s* target,
|
|||
|
||||
/* Clear errors. Note that this only works when we wait for the NVM
|
||||
block to complete the last operation. */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M);
|
||||
target_mem_write32(target, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M);
|
||||
|
||||
while (len > 0) {
|
||||
/* Write first word of page to 0 */
|
||||
adiv5_ap_mem_write(ap, addr, 0);
|
||||
target_mem_write32(target, addr, 0);
|
||||
|
||||
len -= page_size;
|
||||
addr += page_size;
|
||||
}
|
||||
|
||||
/* Disable further programming by locking PECR */
|
||||
stm32lx_nvm_lock(ap, nvm);
|
||||
stm32lx_nvm_lock(target, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
while (1) {
|
||||
uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm));
|
||||
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm));
|
||||
if (target_check_error(target))
|
||||
return -1;
|
||||
if (sr & STM32Lx_NVM_SR_BSY)
|
||||
|
@ -618,7 +615,6 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
const uint8_t* source_8,
|
||||
size_t size)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(target);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(target);
|
||||
const bool is_stm32l1 = stm32lx_is_stm32l1(target);
|
||||
|
||||
|
@ -629,7 +625,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
if ((destination & 3) || (size & 3))
|
||||
return -1;
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(ap, nvm))
|
||||
if (!stm32lx_nvm_prog_data_unlock(target, nvm))
|
||||
return -1;
|
||||
|
||||
const size_t half_page_size = stm32lx_nvm_prog_page_size(target)/2;
|
||||
|
@ -639,7 +635,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
|
||||
/* Wait for BSY to clear because we cannot write the PECR until
|
||||
the previous operation completes on STM32Lxxx. */
|
||||
while (adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm))
|
||||
while (target_mem_read32(target, STM32Lx_NVM_SR(nvm))
|
||||
& STM32Lx_NVM_SR_BSY)
|
||||
if (target_check_error(target)) {
|
||||
return -1;
|
||||
|
@ -649,7 +645,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
// than a half page to write
|
||||
if (size < half_page_size
|
||||
|| (destination & (half_page_size - 1))) {
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(target, STM32Lx_NVM_PECR(nvm),
|
||||
is_stm32l1
|
||||
? 0
|
||||
: STM32Lx_NVM_PECR_PROG);
|
||||
|
@ -666,7 +662,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
}
|
||||
// Or we are writing a half-page(s)
|
||||
else {
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(target, STM32Lx_NVM_PECR(nvm),
|
||||
STM32Lx_NVM_PECR_PROG
|
||||
| STM32Lx_NVM_PECR_FPRG);
|
||||
|
||||
|
@ -679,11 +675,11 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
}
|
||||
|
||||
/* Disable further programming by locking PECR */
|
||||
stm32lx_nvm_lock(ap, nvm);
|
||||
stm32lx_nvm_lock(target, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
while (1) {
|
||||
uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm));
|
||||
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm));
|
||||
if (target_check_error(target)) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -706,7 +702,6 @@ static int stm32lx_nvm_prog_write(struct target_s* target,
|
|||
static int stm32lx_nvm_data_erase(struct target_s* target,
|
||||
uint32_t addr, size_t len)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(target);
|
||||
const size_t page_size = stm32lx_nvm_data_page_size(target);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(target);
|
||||
|
||||
|
@ -714,15 +709,15 @@ static int stm32lx_nvm_data_erase(struct target_s* target,
|
|||
len += (addr & 3);
|
||||
addr &= ~3;
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(ap, nvm))
|
||||
if (!stm32lx_nvm_prog_data_unlock(target, nvm))
|
||||
return -1;
|
||||
|
||||
/* Flash data erase instruction */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(target, STM32Lx_NVM_PECR(nvm),
|
||||
STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA);
|
||||
|
||||
{
|
||||
uint32_t pecr = adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm));
|
||||
uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm));
|
||||
if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA))
|
||||
!= (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA))
|
||||
return -1;
|
||||
|
@ -730,18 +725,18 @@ static int stm32lx_nvm_data_erase(struct target_s* target,
|
|||
|
||||
while (len > 0) {
|
||||
/* Write first word of page to 0 */
|
||||
adiv5_ap_mem_write(ap, addr, 0);
|
||||
target_mem_write32(target, addr, 0);
|
||||
|
||||
len -= page_size;
|
||||
addr += page_size;
|
||||
}
|
||||
|
||||
/* Disable further programming by locking PECR */
|
||||
stm32lx_nvm_lock(ap, nvm);
|
||||
stm32lx_nvm_lock(target, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
while (1) {
|
||||
uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm));
|
||||
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm));
|
||||
if (target_check_error(target))
|
||||
return -1;
|
||||
if (sr & STM32Lx_NVM_SR_BSY)
|
||||
|
@ -764,22 +759,21 @@ static int stm32lx_nvm_data_write(struct target_s* target,
|
|||
const uint8_t* source_8,
|
||||
size_t size)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(target);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(target);
|
||||
const bool is_stm32l1 = stm32lx_is_stm32l1(target);
|
||||
uint32_t* source = (uint32_t*) source_8;
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(ap, nvm))
|
||||
if (!stm32lx_nvm_prog_data_unlock(target, nvm))
|
||||
return -1;
|
||||
|
||||
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(target, STM32Lx_NVM_PECR(nvm),
|
||||
is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA);
|
||||
|
||||
while (size) {
|
||||
size -= 4;
|
||||
uint32_t v = *source++;
|
||||
adiv5_ap_mem_write(ap, destination, v);
|
||||
target_mem_write32(target, destination, v);
|
||||
destination += 4;
|
||||
|
||||
if (target_check_error(target))
|
||||
|
@ -787,11 +781,11 @@ static int stm32lx_nvm_data_write(struct target_s* target,
|
|||
}
|
||||
|
||||
/* Disable further programming by locking PECR */
|
||||
stm32lx_nvm_lock(ap, nvm);
|
||||
stm32lx_nvm_lock(target, nvm);
|
||||
|
||||
/* Wait for completion or an error */
|
||||
while (1) {
|
||||
uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm));
|
||||
uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm));
|
||||
if (target_check_error(target))
|
||||
return -1;
|
||||
if (sr & STM32Lx_NVM_SR_BSY)
|
||||
|
@ -813,16 +807,15 @@ static int stm32lx_nvm_data_write(struct target_s* target,
|
|||
The return value is true if the write succeeded. */
|
||||
static bool stm32lx_option_write(target *t, uint32_t address, uint32_t value)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(t);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
|
||||
/* Erase and program option in one go. */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX);
|
||||
adiv5_ap_mem_write(ap, address, value);
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX);
|
||||
target_mem_write32(t, address, value);
|
||||
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm));
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
return !(sr & STM32Lx_NVM_SR_ERR_M);
|
||||
|
@ -839,29 +832,28 @@ static bool stm32lx_option_write(target *t, uint32_t address, uint32_t value)
|
|||
static bool stm32lx_eeprom_write(target *t, uint32_t address,
|
||||
size_t cb, uint32_t value)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(t);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
const bool is_stm32l1 = stm32lx_is_stm32l1(t);
|
||||
|
||||
/* Clear errors. */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M);
|
||||
target_mem_write32(t, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M);
|
||||
|
||||
/* Erase and program option in one go. */
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
|
||||
(is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA)
|
||||
| STM32Lx_NVM_PECR_FIX);
|
||||
if (cb == 4)
|
||||
adiv5_ap_mem_write(ap, address, value);
|
||||
target_mem_write32(t, address, value);
|
||||
else if (cb == 2)
|
||||
adiv5_ap_mem_write_halfword(ap, address, value);
|
||||
target_mem_write16(t, address, value);
|
||||
else if (cb == 1)
|
||||
adiv5_ap_mem_write_byte(ap, address, value);
|
||||
target_mem_write8(t, address, value);
|
||||
else
|
||||
return false;
|
||||
|
||||
uint32_t sr;
|
||||
do {
|
||||
sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm));
|
||||
sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm));
|
||||
} while (sr & STM32Lx_NVM_SR_BSY);
|
||||
|
||||
return !(sr & STM32Lx_NVM_SR_ERR_M);
|
||||
|
@ -888,11 +880,10 @@ static bool stm32lx_cmd_stubs(target* t,
|
|||
|
||||
static bool stm32lx_cmd_option(target* t, int argc, char** argv)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(t);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
const size_t opt_size = stm32lx_nvm_option_size(t);
|
||||
|
||||
if (!stm32lx_nvm_opt_unlock(ap, nvm)) {
|
||||
if (!stm32lx_nvm_opt_unlock(t, nvm)) {
|
||||
gdb_out("unable to unlock NVM option bytes\n");
|
||||
return true;
|
||||
}
|
||||
|
@ -900,7 +891,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv)
|
|||
size_t cb = strlen(argv[1]);
|
||||
|
||||
if (argc == 2 && !strncasecmp(argv[1], "obl_launch", cb)) {
|
||||
adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm),
|
||||
target_mem_write32(t, STM32Lx_NVM_PECR(nvm),
|
||||
STM32Lx_NVM_PECR_OBL_LAUNCH);
|
||||
}
|
||||
else if (argc == 4 && !strncasecmp(argv[1], "raw", cb)) {
|
||||
|
@ -934,7 +925,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv)
|
|||
/* Report the current option values */
|
||||
for(unsigned i = 0; i < opt_size; i += sizeof(uint32_t)) {
|
||||
uint32_t addr = STM32Lx_NVM_OPT_PHYS + i;
|
||||
uint32_t val = adiv5_ap_mem_read(ap, addr);
|
||||
uint32_t val = target_mem_read32(t, addr);
|
||||
gdb_outf("0x%08x: 0x%04x 0x%04x %s\n",
|
||||
addr, val & 0xffff, (val >> 16) & 0xffff,
|
||||
((val & 0xffff) == ((~val >> 16) & 0xffff))
|
||||
|
@ -942,7 +933,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv)
|
|||
}
|
||||
|
||||
if (stm32lx_is_stm32l1(t)) {
|
||||
uint32_t optr = adiv5_ap_mem_read(ap, STM32Lx_NVM_OPTR(nvm));
|
||||
uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm));
|
||||
uint8_t rdprot = (optr >> STM32L1_NVM_OPTR_RDPROT_S)
|
||||
& STM32L1_NVM_OPTR_RDPROT_M;
|
||||
if (rdprot == STM32L1_NVM_OPTR_RDPROT_0)
|
||||
|
@ -964,7 +955,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv)
|
|||
(optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0);
|
||||
}
|
||||
else {
|
||||
uint32_t optr = adiv5_ap_mem_read(ap, STM32Lx_NVM_OPTR(nvm));
|
||||
uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm));
|
||||
uint8_t rdprot = (optr >> STM32L0_NVM_OPTR_RDPROT_S)
|
||||
& STM32L0_NVM_OPTR_RDPROT_M;
|
||||
if (rdprot == STM32L0_NVM_OPTR_RDPROT_0)
|
||||
|
@ -997,17 +988,16 @@ usage:
|
|||
STM32Lx_NVM_OPT_PHYS + opt_size - sizeof(uint32_t));
|
||||
|
||||
done:
|
||||
stm32lx_nvm_lock(ap, nvm);
|
||||
stm32lx_nvm_lock(t, nvm);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv)
|
||||
{
|
||||
ADIv5_AP_t* ap = adiv5_target_ap(t);
|
||||
const uint32_t nvm = stm32lx_nvm_phys(t);
|
||||
|
||||
if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) {
|
||||
if (!stm32lx_nvm_prog_data_unlock(t, nvm)) {
|
||||
gdb_out("unable to unlock EEPROM\n");
|
||||
return true;
|
||||
}
|
||||
|
@ -1061,6 +1051,6 @@ usage:
|
|||
+ stm32lx_nvm_eeprom_size(t));
|
||||
|
||||
done:
|
||||
stm32lx_nvm_lock(ap, nvm);
|
||||
stm32lx_nvm_lock(t, nvm);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ bool stm32l1_probe(struct target_s *target)
|
|||
{
|
||||
uint32_t idcode;
|
||||
|
||||
idcode = adiv5_ap_mem_read(adiv5_target_ap(target), STM32L1_DBGMCU_IDCODE);
|
||||
idcode = target_mem_read32(target, STM32L1_DBGMCU_IDCODE);
|
||||
switch(idcode & 0xFFF) {
|
||||
case 0x416: /* CAT. 1 device */
|
||||
case 0x429: /* CAT. 2 device */
|
||||
|
@ -105,45 +105,44 @@ bool stm32l1_probe(struct target_s *target)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void stm32l1_flash_unlock(ADIv5_AP_t *ap)
|
||||
static void stm32l1_flash_unlock(target *t)
|
||||
{
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1);
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2);
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1);
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2);
|
||||
target_mem_write32(t, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1);
|
||||
target_mem_write32(t, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2);
|
||||
target_mem_write32(t, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1);
|
||||
target_mem_write32(t, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2);
|
||||
}
|
||||
|
||||
static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint16_t sr;
|
||||
|
||||
addr &= ~255;
|
||||
len &= ~255;
|
||||
|
||||
stm32l1_flash_unlock(ap);
|
||||
stm32l1_flash_unlock(target);
|
||||
|
||||
/* Flash page erase instruction */
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG);
|
||||
target_mem_write32(target, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
|
||||
while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
while(len) {
|
||||
/* Write first word of page to 0 */
|
||||
adiv5_ap_mem_write(ap, addr, 0);
|
||||
target_mem_write32(target, addr, 0);
|
||||
|
||||
len -= 256;
|
||||
addr += 256;
|
||||
}
|
||||
|
||||
/* Disable programming mode */
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0);
|
||||
target_mem_write32(target, STM32L1_FLASH_PECR, 0);
|
||||
|
||||
/* Check for error */
|
||||
sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR);
|
||||
sr = target_mem_read32(target, STM32L1_FLASH_SR);
|
||||
if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP))
|
||||
return -1;
|
||||
|
||||
|
@ -153,7 +152,6 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, size_t le
|
|||
static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
|
||||
const uint8_t *src, size_t len)
|
||||
{
|
||||
ADIv5_AP_t *ap = adiv5_target_ap(target);
|
||||
uint16_t sr;
|
||||
|
||||
/* Handle non word-aligned start */
|
||||
|
@ -164,7 +162,7 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
|
|||
wlen = len;
|
||||
|
||||
memcpy((uint8_t *)&data + (dest & 3), src, wlen);
|
||||
adiv5_ap_mem_write(ap, dest & ~3, data);
|
||||
target_mem_write32(target, dest & ~3, data);
|
||||
src += wlen;
|
||||
dest += wlen;
|
||||
len -= wlen;
|
||||
|
@ -185,10 +183,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
|
|||
/* Write half-pages */
|
||||
if(len > 128) {
|
||||
/* Enable half page mode */
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG);
|
||||
target_mem_write32(target, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
|
||||
while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
|
||||
|
@ -198,10 +196,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
|
|||
len -= len & ~127;
|
||||
|
||||
/* Disable half page mode */
|
||||
adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0);
|
||||
target_mem_write32(target, STM32L1_FLASH_PECR, 0);
|
||||
|
||||
/* Read FLASH_SR to poll for BSY bit */
|
||||
while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
|
||||
while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY)
|
||||
if(target_check_error(target))
|
||||
return -1;
|
||||
}
|
||||
|
@ -219,11 +217,11 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest,
|
|||
uint32_t data = 0;
|
||||
|
||||
memcpy((uint8_t *)&data, src, len);
|
||||
adiv5_ap_mem_write(ap, dest, data);
|
||||
target_mem_write32(target, dest, data);
|
||||
}
|
||||
|
||||
/* Check for error */
|
||||
sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR);
|
||||
sr = target_mem_read32(target, STM32L1_FLASH_SR);
|
||||
if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP))
|
||||
return -1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue