Skip to main content
Graduate II
September 15, 2025
Question

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

  • September 15, 2025
  • 4 replies
  • 400 views

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

    This topic has been closed for replies.

    4 replies

    Super User
    September 15, 2025

    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

    RRIDDICCAuthor
    Graduate II
    September 16, 2025

    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... 

    Super User
    September 15, 2025

    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.

    RRIDDICCAuthor
    Graduate II
    September 16, 2025

    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:

    Graduate II
    September 15, 2025

    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.

    RRIDDICCAuthor
    Graduate II
    September 16, 2025

    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?

    Super User
    September 16, 2025

    > it is a quite minimal example

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

    JW

    RRIDDICCAuthor
    Graduate II
    September 16, 2025

    > 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: