cancel
Showing results for 
Search instead for 
Did you mean: 

Hard Fault on first SRAM access

robertroy9
Associate II
Posted on August 23, 2012 at 04:51

Hello,

STM32L152, Rowley CrossStudio 2.3, STM32L152DEMO pcb, Using CrossConnect debugger within CrossStudio.

I have seen this problem before, did not record/understand last time fixed.

What will cause a hard fault on first SRAM access in program (after startup_.s). I have a bunch of static structure global declarations before main, once in main execution hard faults at first SRAM access (usually is a push (R7, lr) ) and those values look reasonable.

Getting VCATCH, IMPRECISERR set, and drops to HardFault (CMSIS version). If I manually set CSB_SHCRS->BUSFAULTENA and rerun it will drop into bus fault handler.

The modified handler returns this:

[Hard fault handler - all numbers in hex]

R0 = 20001940

R1 = 0

R2 = 0

R3 = 0

R12 = 1fffe944

LR [R14] = 20001950  subroutine call return address

PC [R15] = 8000379  program counter

PSR = 80006a0

BFAR = e000ed38

CFSR = 400

HFSR = 40000000

DFSR = 8

AFSR = 0

SCB_SHCSR = 0

Tried making this the first thing in

uint32t *ACTLR = (uint32_t *)0xE000E008;

// *ACTLR |= 2; never executed this 

[Hard fault handler - all numbers in hex]

R0 = 20001940

R1 = 0

R2 = 0

R3 = 0

R12 = e008

LR [R14] = 20001950  subroutine call return address

PC [R15] = 8000177  program counter

PSR = 8000378

BFAR = e000ed38

CFSR = 400

HFSR = 40000000

DFSR = 8

AFSR = 0

SCB_SHCSR = 0

help or thoughtful guidance appreciated.

#stm32-hardfault-impreciserr
13 REPLIES 13
Posted on August 23, 2012 at 14:01

Presumably there is code in startup.s prior to main(), which gets executed and copys/clears out the statics?

Check the value of SP

The value for LR seems invalid, coming from RAM and EVEN.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
robertroy9
Associate II
Posted on August 23, 2012 at 19:00

Hi Clive,

Checked that static variablesa are intialized at debug entry to main. (what code initializes them is a mystery)

Code in debugger looks like this:

--- main.c -- 95 -------------------------------------------

static uint8_t bc5RxByte = (uint8_t) 0x5A;

static uint8_t lbtRxByte = (uint8_t) 0x5B;

int main(void)

{

    B580        push {r7, lr}

    B082        sub sp, sp, #8

    AF00        add r7, sp, #0

--- main.c -- 100 ------------------------------------------

{

    F5AD533E    sub.w r3, sp, #0x2F80

    F1A3037C    sub.w r3, r3, #0x7C

    F04F0200    mov.w r2, #0

    601A        str r2, [r3]

--- main.c -- 100 ------------------------------------------

bc5RxByte = 0x01;

    F240030C    movw r3, #12

    F2C20300    movt r3, #0x2000

    F04F0201    mov.w r2, #1

    701A        strb r2, [r3]

--- main.c -- 101 ------------------------------------------

lbtRxByte = 0x01;

    F240030D    movw r3, #13

    F2C20300    movt r3, #0x2000

    F04F0201    mov.w r2, #1

    701A        strb r2, [r3]

--

values of trace are as follows.

static uint8_t bc5RxByte = 0; //memloc = 0x20000149

static uint8_t lbtRxByte = 0;   //memloc = 0x2000014A

int main(void) 

{

push {r7, lr}, push {0x00000000, 0x08000177}      ... r7=0x00000000, lr=0x08000177

sub sp, sp, #8, sub 0x20001368, 0x20001950, #8    ... sp=0x20001360

add r7, sp, #0, 0x00000000, 0x20001360, #0        ... r7=0x20001360, sp=0x20001360

{

sub.w r3, sp, #0x2F80, 0x00000009, 0x20001360, #0x2F80      ... r3=0x1fffe3e0

sub.w r3, r3, #0x7C, 0x1fffe3e0, 0x1fffe3e0, #0x7C          ... r3=0x1fffe364

mov.w r2, #0, 0x08000361, #0                                ... r2=0x00000000

str r2, [r3], 0x00000000, 0x1fffe364                        ... r2=0x00000000 r3=0x1fffe364

** at this point the SCB_HFSR->FORCED, SCB_BFSR->IMPRECISERR, SCB_ICSR->ISPREEMPT, VECTPENDING=0x003 are set and of course I am then in the hard fault loop.

Looking in the project settings for preprocessor options of STM32_startup.s , I find

STM32L15x_HD

STARTUP_FROM_RESET

__NO_SYSTEM_INIT

INITIALIZE_STACK

I removed STARTUP_FROM_RESET & __NO_SYSTEM_INIT; but see not change in the behavior.

What is generating the code (before the bc5RxByte = 0x01;) that tries to write to memory is a mystery to me.

Enlightenment requested!

Posted on August 23, 2012 at 19:07

Guess you need to figure out why it's allocation 12 KB of auto/local variables.

R3 points into ROM, below RAM, need to make the stack bigger.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
robertroy9
Associate II
Posted on August 23, 2012 at 19:48

Changing the stack from 4k to 8k no change.

Memory Usage shows 6.6K free of 16K in idiot window.

So you are saying that R3 is determined somewhere in the compiler as a result of the auto/allocation of static variables?

I thought I could escape learning the startup.s and other particulars but it looks like I was wrong to think one could simply have the Crossworks figure out the bottom end stuff. Suggestions where to read? This is not covered that I see in Yiu's Definitive Guide to the M3 2nd edition.

Posted on August 23, 2012 at 20:37

I don't know what your source looks like, the compiler is generating epilogue code in anticipation of using data/pointers which are 12K below the current stack pointer. From the code presented so far I don't know why.

Does this work?

static uint8_t bc5RxByte = (uint8_t) 0x5A;
static uint8_t lbtRxByte = (uint8_t) 0x5B;
int main(void)
{
bc5RxByte = 0x01;
lbtRxByte = 0x01;
while(1);
}

You probably need to look at a microprocessor book that describes the concepts of stack frames, local variables and parameter passing. The concepts are the similar across x86, MIPS and ARM, with the RISC parts using registers to pass the first few parameters. I could probably cite a MIPS text that I though covered this well. Other than that, perhaps search on ABI (Application Binary Interface) methods. And compiler's use of epilogue/prologue code, interfacing between assembler and higher level languages.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 23, 2012 at 20:43

Introduction to RISC Assembly Language Programming, John Waldron

http://www.amazon.com/Introduction-RISC-Assembly-Language-Programming/dp/0201398281/

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on August 23, 2012 at 20:49

Changing the stack from 4k to 8k no change.

No doubt, it needs to be at least 12KB to make any difference.

F5AD533E    sub.w r3, sp, #0x2F80

    F1A3037C    sub.w r3, r3, #0x7C

0x2F80 + 0x7C = 0x2FFC = 12284 = 11.996 KB

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
robertroy9
Associate II
Posted on August 23, 2012 at 21:02

If I comment out the remainder of the program, the offending code is not there. So then there is no hardfault.

''generating epilogue'' , so I suppose that I should see a pointer or address in the memory map file that is in code space then? Or is there some other method of tracking this anticipatory action of the compiler...or is it the linker?

As to the book, I will likely get it <thank you for the pointer> but by God do I really need to understand that domain?

From: clive1

Posted: Thursday, August 23, 2012 8:44 PM

Subject: Hard Fault on first SRAM access

Introduction to RISC Assembly Language Programming, John Waldron

http://www.amazon.com/Introduction-RISC-Assembly-Language-Programming/dp/0201398281/

robertroy9
Associate II
Posted on August 23, 2012 at 21:08

Ok, stack to 12384 <I would have never thought of going so large> and no hard fault. Now to figure where this enormous allocation is taking place.

 But back to that little bit of code, where does it hark from?

int main(void)

{

    B580        push {r7, lr}

    B082        sub sp, sp, #8

    AF00        add r7, sp, #0

--- main.c -- 100 ------------------------------------------

{

    F5AD533E    sub.w r3, sp, #0x2F80

    F1A3037C    sub.w r3, r3, #0x7C

    F04F0200    mov.w r2, #0

    601A        str r2, [r3]