armv7m: always set xPSR.T=1 when starting an algorithm
xPSR.T sets the processor to Thumb mode when set to 1. ARMv7-M only supports execution of Thumb instructions, so it must always be set to 1. If xPSR.T is set to 0 on armv7m, a usage fault is generated when a instruction execution is attempted. On armv7m, issuing a reset causes the vector table to be examined. PC and xPSR.T are loaded from the vector table at byte offset 4. xPSR.T is taken from the least significant bit this value, PC from the remaining bits. This occurs even with `reset halt`, as the reset itself causes this load to occur without the execution of any instructions. As a result of this, following a reset with a "bad" value programmed in the vector table, openocd would be unable to run algorithms on the target, as running them would immediately result in a usage fault due to xPSR.T being unset (0). Allow algorithms to run regardless of the content of the vector table by explicitly setting xPSR so that xPSR.T=1 prior to executing an algorithm. One can think of this as openocd more closely emulating a reset or branch instruction in executing it's algorithms. Ticket: https://sourceforge.net/p/openocd/tickets/203/ Signed-off-by: Cody P Schafer <openocd@codyps.com> Change-Id: I4dc3427ab195d06c3fd780ea768027fefccc4c28 Reviewed-on: http://openocd.zylin.com/4658 Tested-by: jenkins Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
parent
5fd1cb0e5b
commit
49bd64347a
|
@ -407,6 +407,23 @@ int armv7m_start_algorithm(struct target *target,
|
|||
armv7m_set_core_reg(reg, reg_params[i].value);
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
* Ensure xPSR.T is set to avoid trying to run things in arm
|
||||
* (non-thumb) mode, which armv7m does not support.
|
||||
*
|
||||
* We do this by setting the entirety of xPSR, which should
|
||||
* remove all the unknowns about xPSR state.
|
||||
*
|
||||
* Because xPSR.T is populated on reset from the vector table,
|
||||
* it might be 0 if the vector table has "bad" data in it.
|
||||
*/
|
||||
struct reg *reg = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR];
|
||||
buf_set_u32(reg->value, 0, 32, 0x01000000);
|
||||
reg->valid = 1;
|
||||
reg->dirty = 1;
|
||||
}
|
||||
|
||||
if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
|
||||
armv7m_algorithm_info->core_mode != core_mode) {
|
||||
|
||||
|
|
Loading…
Reference in New Issue