Cortex-M: fix stale DHCSR cache values
In cortex_m_assert_reset, in two locations, DHCSR is written directly using mem_ap_write_u32. This means that the cached version, target_to_cm(target)->dcb_dhcsr, is not updated when these writes are performed, so subsequent writes to DHCSR that use cortex_m_write_debug_halt_mask will change those bits back to their old values which, unless modified in that particular invocation, come from the cache. This causes an actual, observable bug on an STM32F7 in which running “reset run” immediately after “program” can in some cases result in execution proceeding with C_MASKINTS set (it is cleared on line 1021 but is then set immediately afterward in cortex_m_clear_halt), causing failure of the application. Replace these mem_ap_write_u32 calls with cortex_m_write_debug_halt_mask calls to do the same jobs. Change-Id: Id35ca7f6057c2df2ba9cd67c53a73b50816d0b71 Signed-off-by: Christopher Head <chead@zaber.com> Reviewed-on: http://openocd.zylin.com/4239 Tested-by: jenkins Reviewed-by: Tomas Vanek <vanekt@fbl.cz>fence_i_fix_for_release
parent
079d78f7de
commit
02df0abb54
|
@ -242,7 +242,7 @@ static int cortex_m_endreset_event(struct target *target)
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
|
if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
|
||||||
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
|
retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP | C_MASKINTS);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1005,12 +1005,12 @@ static int cortex_m_assert_reset(struct target *target)
|
||||||
/* Store important errors instead of failing and proceed to reset assert */
|
/* Store important errors instead of failing and proceed to reset assert */
|
||||||
|
|
||||||
if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN))
|
if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN))
|
||||||
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN);
|
retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP | C_MASKINTS);
|
||||||
|
|
||||||
/* If the processor is sleeping in a WFI or WFE instruction, the
|
/* If the processor is sleeping in a WFI or WFE instruction, the
|
||||||
* C_HALT bit must be asserted to regain control */
|
* C_HALT bit must be asserted to regain control */
|
||||||
if (retval == ERROR_OK && (cortex_m->dcb_dhcsr & S_SLEEP))
|
if (retval == ERROR_OK && (cortex_m->dcb_dhcsr & S_SLEEP))
|
||||||
retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN);
|
retval = cortex_m_write_debug_halt_mask(target, C_HALT, 0);
|
||||||
|
|
||||||
mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0);
|
mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0);
|
||||||
/* Ignore less important errors */
|
/* Ignore less important errors */
|
||||||
|
@ -1018,8 +1018,7 @@ static int cortex_m_assert_reset(struct target *target)
|
||||||
if (!target->reset_halt) {
|
if (!target->reset_halt) {
|
||||||
/* Set/Clear C_MASKINTS in a separate operation */
|
/* Set/Clear C_MASKINTS in a separate operation */
|
||||||
if (cortex_m->dcb_dhcsr & C_MASKINTS)
|
if (cortex_m->dcb_dhcsr & C_MASKINTS)
|
||||||
mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
|
cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS);
|
||||||
DBGKEY | C_DEBUGEN | C_HALT);
|
|
||||||
|
|
||||||
/* clear any debug flags before resuming */
|
/* clear any debug flags before resuming */
|
||||||
cortex_m_clear_halt(target);
|
cortex_m_clear_halt(target);
|
||||||
|
|
Loading…
Reference in New Issue