cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F207 / skips instructions when jumping from FLASH to mapped SRAM...

RRIDDICC
Associate III

Hi!

My STM32F207 behave funny when i "blx r3" from 0x800'0344 (FLASH) to 0x870 (lower 112KiB SRAM mapped to 0x0):

It seems to ignore the first 4 bytes of instructions... When i insert 4 nops at 0x870 (or "DSB();ISB();"), then everything works as expected:

int main() {
   { dbgb[0]=0xAFFE0000; asm("nop\n nop\n nop\n nop"); }
   { dbgb[19]=__SP(); for (u32 i=0; i<16; i++) dbgb[i]=0xABBA0000|i; }
   { dbgb[8]=__get_MSP(); dbgb[10]=__get_PSP(); dbgb[12]=__SP(); }
   { dbgb[0]=0xAFFEABBA; bla(); dbgb[1]=0xAFFEBEEB; }
   { dbgb[9]=__get_MSP(); dbgb[11]=__get_PSP(); dbgb[13]=__SP(); reset(); return 0; }
   init();
   if (!mainrptver(0)) reset();
   SET_BIT(SCB->SCR,SCB_SCR_SLEEPONEXIT_Msk);
   __WFI();
}
void Reset_Handler() { dbgb[16]=__get_MSP(); main(); }

the code in the flash is this (P is a u32* to 0x2000'0000):

SYSCFG->MEMRMP = (0b11 << SYSCFG_MEMRMP_MEM_MODE_Pos); __DSB(); __ISB(); // map first 112KiB of SRAM to 0x0
__set_MSP(P[0]); __DSB(); __ISB(); // set stack pointer from app's ((u32*)g_pfnVectors)[0]
void (*app)() = (void(*)()) P[1]; // get address of app's reset ISR from app's ((u32*)g_pfnVectors)[1]
SCB->VTOR = (u32)0x0; __DSB(); __ISB(); // app's &g_pfnVectors is always @ 0x0
app(); // jump into the freshly mapped code segment in order to use ICode bus by leaving slow System bus
for (;;) { __DSB(); __ISB(); __WFI(); }

 

the disassembly:

 8000326:       f383 8808       msr     MSP, r3
 800032a:       f3bf 8f4f       dsb     sy
 800032e:       f3bf 8f6f       isb     sy
 8000332:       2100            movs    r1, #0
 8000334:       4a1e            ldr     r2, [pc, #120]  ; (80003b0 <main+0xf0>)
 8000336:       4b1f            ldr     r3, [pc, #124]  ; (80003b4 <main+0xf4>)
 8000338:       681b            ldr     r3, [r3, #0]
 800033a:       6091            str     r1, [r2, #8]
 800033c:       f3bf 8f4f       dsb     sy
 8000340:       f3bf 8f6f       isb     sy
 8000344:       4798            blx     r3
00000870 <Reset_Handler>:
     870:       f3ef 8208       mrs     r2, MSP
     874:       4b01            ldr     r3, [pc, #4]    ; (87c <Reset_Handler+0xc>)
     876:       641a            str     r2, [r3, #64]   ; 0x40
     878:       f7ff bfa2       b.w     7c0 <main>
     87c:       2001c000        andcs   ip, r1, r0

 After the "reset();" dbg[16..19] is:

2001C040: E000ED00 00000000 00000000 2001BFE8 00000000 00000000 00000000 00000000

Why is that? Are there similar traps with executing from SRAM?

Thx.

Bye

8 REPLIES 8
waclawek.jan
Super User

I have honestly no idea how do the snippets you've presented above match together.

Maybe try to post a minimal but complete example exhibiting the problem, posting the result explaining how does it differ from the expectation.

JW

TDK
Super User

I also could not figure out how the presented code shows there is a problem.

You can single step in assembly to see what it's executing. Going to be easier investigating by doing that than writing to a debug array.

If you feel a post has answered your question, please click "Accept as Solution".

This is hard to follow, perhaps make a cleaner example.

I will note

a) You need to clear the write buffers with some sort of fencing instruction, this can be a read of the memory via an LDR, to force in-order execution. The MCU doesn't have a cache.

b) That the R3 address needs to be ODD, ie 0x00000871, whilst the words need to be written too 0x00000870, and 0x00000874, etc

If the address is Not ODD you'll get a Hard Fault

Make a word, or half-word, array of opcodes, and memcpy() those to your RAM address. use DSB or an LDR to fence the operation.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

since dbgb[16] is the SCB base address, i do not get a hard fault...

and P[1] is taken from what gcc produced...

plus i do a lot of dsb&isb...

i still wonder, why the "mrs r2, MSP" at 0x870 is not executed... that is why r2 has still that old value from 0x800'0334...

any ideas?

the problem is that dbgb[16] is the SCB base address, although i expect the value of SP...

and i cant single step... i dont have that fancy board... just that huge chip, that i hand-soldered on my own little board... :face_savoring_food:

the "app()" happens in 0x800'0344 (blx r3)...

P[1] == app == 0x871 is the Reset_Handler at 0x870...

it is a quite minimal example, that shows how i map SRAM to 0x0 and then jump from flash to SRAM using the ICode bus...

ChatGPT thinks, that the pipeline is disturbed, when reading switches from Flash to SRAM... if i understood him correctly... 

waclawek.jan
Super User

> it is a quite minimal example

It's not complete. I can't compile it.

JW

> It's not complete. I can't compile it.

ok... u would need the ld-files and several other files to make it "work"...

i attached boot.bin (goes to 0x800'0000) and kevin.bin (goes to 0x2000'C000; only the first 64KiB of kevin.bin...) and then u start at 0x800'0000 and after the reset u can see the result in 0x2001'C000... or u set a breakpoint in 0x800'0344 and watch what it does... :face_savoring_food: