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