Harden cortexm_reset() and remove double reset(#601)

Thanks to Dave Marples <dave@marples.net> for input.
- Issue only one reset. Start with SRST. Only if not seen, use SYSRESETREQ
- Wait for release of DHCSR_S_RESET_ST before issuing more commands
- Add timeout to catch reset line stuck low
- Remove AP errors
This commit is contained in:
Uwe Bonnes 2020-03-06 19:44:13 +01:00 committed by UweBonnes
parent bc84d803ea
commit effd43ce38
1 changed files with 27 additions and 20 deletions

View File

@ -598,36 +598,43 @@ static void cortexm_pc_write(target *t, const uint32_t val)
* using the core debug registers in the NVIC. */ * using the core debug registers in the NVIC. */
static void cortexm_reset(target *t) static void cortexm_reset(target *t)
{ {
/* Read DHCSR here to clear S_RESET_ST bit before reset */
target_mem_read32(t, CORTEXM_DHCSR);
platform_timeout to;
if ((t->target_options & CORTEXM_TOPT_INHIBIT_SRST) == 0) { if ((t->target_options & CORTEXM_TOPT_INHIBIT_SRST) == 0) {
platform_srst_set_val(true); platform_srst_set_val(true);
platform_srst_set_val(false); platform_srst_set_val(false);
/* Some NRF52840 users saw invalid SWD transaction with
* native/firmware without this delay.*/
platform_delay(10);
}
uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR);
if ((dhcsr & CORTEXM_DHCSR_S_RESET_ST) == 0) {
/* No reset seen yet, maybe as SRST is not connected, or device has
* CORTEXM_TOPT_INHIBIT_SRST set.
* Trigger reset by AIRCR.*/
target_mem_write32(t, CORTEXM_AIRCR,
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
} }
/* Read DHCSR here to clear S_RESET_ST bit before reset */
target_mem_read32(t, CORTEXM_DHCSR);
/* Request system reset from NVIC: SRST doesn't work correctly */
/* This could be VECTRESET: 0x05FA0001 (reset only core)
* or SYSRESETREQ: 0x05FA0004 (system reset)
*/
target_mem_write32(t, CORTEXM_AIRCR,
CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ);
/* If target needs to do something extra (see Atmel SAM4L for example) */ /* If target needs to do something extra (see Atmel SAM4L for example) */
if (t->extended_reset != NULL) { if (t->extended_reset != NULL) {
t->extended_reset(t); t->extended_reset(t);
} }
/* Wait for CORTEXM_DHCSR_S_RESET_ST to read 0, meaning reset released.*/
/* Poll for release from reset */ platform_timeout_set(&to, 1000);
while (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); while ((target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST) &&
!platform_timeout_is_expired(&to));
#if defined(PLATFORM_HAS_DEBUG)
if (platform_timeout_is_expired(&to))
DEBUG("Reset seem to be stuck low!\n");
#endif
/* 10 ms delay to ensure that things such as the STM32 HSI clock
* have started up fully. */
platform_delay(10);
/* Reset DFSR flags */ /* Reset DFSR flags */
target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL);
/* Make sure we ignore any initial DAP error */
/* 1ms delay to ensure that things such as the stm32f1 HSI clock have started target_check_error(t);
* up fully.
*/
platform_delay(1);
} }
static void cortexm_halt_request(target *t) static void cortexm_halt_request(target *t)