From 49bd64347a21f5e12b33c256171b3035126d1260 Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Mon, 27 Aug 2018 10:50:46 -0400 Subject: [PATCH 1/1] 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 Change-Id: I4dc3427ab195d06c3fd780ea768027fefccc4c28 Reviewed-on: http://openocd.zylin.com/4658 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/target/armv7m.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 7d3bd73674..a1962fefc8 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -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) { -- 2.30.2