ARM Cortex-M3 — Why might I (appear to) receive a UsageFault on a PUSH instruction?

0

I'm having some trouble diagnosing the cause of an INVSTATE UsageFault that appears to be occurring on a push instruction in a particular circumstance.

Here's what I know:

  1. If this segment of code runs from a 'fresh' boot, it runs as expected.
  2. If this segment of code runs after a software RESET, I drop in to forced hard fault which (unless I'm reading it wrong) suggests itself to be an INVSTATE UsageFault.

Here are the registers just before the instruction runs on fresh boot:

(gdb) info registers
r0             0x8001000    134221824
r1             0x8020000    134348800
r2             0x8020000    134348800
r3             0x40022014   1073881108
r4             0x0  0
r5             0x0  0
r6             0x0  0
r7             0x20009fc0   536911808
r8             0x0  0
r9             0x0  0
r10            0x0  0
r11            0x0  0
r12            0x0  0
sp             0x20009fc0   0x20009fc0
lr             0x8000259    134218329
pc             0x8000178    0x8000178 <wait_for_busy>
xPSR           0x81000000   -2130706432

... and here they are just before the instruction after software reset:

(gdb) info registers
r0             0x8001000    134221824
r1             0x8020000    134348800
r2             0x8020000    134348800
r3             0x40022014   1073881108
r4             0x4028   16424
r5             0x0  0
r6             0x20009a90   536910480
r7             0x20009fc0   536911808
r8             0x4028   16424
r9             0x0  0
r10            0x0  0
r11            0x0  0
r12            0x0  0
sp             0x20009fc0   0x20009fc0
lr             0x8000259    134218329
pc             0x8000178    0x8000178 <wait_for_busy>
xPSR           0x81000000   -2130706432

Some more facts:

  • Stack high address is 0x2000A000.
  • lr contains the expected value (instruction after branch to this func).

The instructions at and just after pc are:

(gdb) disassemble 0x08000178
Dump of assembler code for function wait_for_busy:
   0x08000178 <+0>: push    {r7}
   0x0800017a <+2>: sub sp, #12
   0x0800017c <+4>: add r7, sp, #0
   0x0800017e <+6>: ldr r3, [pc, #28]   ; (0x800019c <wait_for_busy+36>)
   0x08000180 <+8>: str r3, [r7, #4]
   0x08000182 <+10>:    nop

If I break at 0x08000178, then nexti, I drop in to an exception handler. Registers are now:

(gdb) info register
r0             0x8001000    134221824
r1             0x8020000    134348800
r2             0x8020000    134348800
r3             0xe000ed04   -536810236
r4             0x4028   16424
r5             0x0  0
r6             0x20009a90   536910480
r7             0x20009fc0   536911808
r8             0x4028   16424
r9             0x0  0
r10            0x0  0
r11            0x0  0
r12            0x0  0
sp             0x20009f78   0x20009f78
lr             0xfffffff1   -15
pc             0x8000368    0x8000368 <Stub_Handler+2>
xPSR           0x81000003   -2130706429

A frame up is:

0x20009f98: 0x08001000  0x08020000  0x08020000  0x40022014
0x20009fa8: 0x00000000  0x08000259  0x08000178  0x81000200

The value of the HFSR is (below), suggesting a forced hard fault:

(gdb) x/1wx 0xE000ED2C
0xe000ed2c: 0x40000000

The value of the CSFR is (below), suggesting an INVSTATE UsageFault:

(gdb) x/1wx 0xE000ED28
0xe000ed28: 0x00020000

The description for INVSTATE is:

When this bit is set to 1, the PC value stacked for the exception return points to the instruction that attempted the illegal use of the EPSR.

And this is where I'm stuck. What might be different after a software reset that could cause this? Is this even the real problem?

Any direction on where to go from here would be great!

assembly
cortex-m3
asked on Stack Overflow May 10, 2016 by jstephenson

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0