LDMIA instruction not working correctly on external SRAM in cortex M4

2

I am using STM32L486ZG board in thumb mode. I am running a simple bare-metal application without any RTOS. I have external SRAM connected to the board using FSM. The external SRAM is located at address 0x60000000. The system is initialized and running at 72MHz (i have tried this issue with frequency from 18-80 MHz) now in my main function i have following code:

int main(){
    asm volatile (
            "push {r0}\n"
            "mov r0, #0x60000000\n"
            "add r0, #0x400\n"
            "stmdb r0!, {r1-r12}\n"
            "ldmia r0!, {r1-r12}\n"
            "pop {r0}\n"
            );
}

According to this code no register should be changed after this main function has executed, but that's not the case after the following instruction

ldmia r0!, {r1-r12}

i.e. r9 is not correct after execution. stmdb instruction is working correctly but ldmia is not loading the data correctly. I have verified this by viewing the contents from memory.

This issue is persistent with any arguments in the ldmia instruction: the 9th register is always affected.

Explanation: Lets say I am debugging this code and the next instruction to execute is this:

stmdb r0!, {r1-r12}

after stepping up all these registers have been saved in the memory and value of r0 is 0x600003d0

the contents of memory:

0x600003D0  00000000 40021008 0000000C  .......@....
0x600003DC  40000000 00000000 00000000  ...@........
0x600003E8  20017FEC 00000000 00000000  ì.. ........
0x600003F4  00000000 00000000 00000000  ............

content of the registers:

r0  0x600003d0
r1  0x00000000
r2  0x40021008
r3  0x0000000c
r4  0x40000000
r5  0x00000000
r6  0x00000000
r7  0x20017fec
r8  0x00000000
r9  0x00000000
r10 0x00000000
r11 0x00000000  
r12 0x00000000

this shows that all the registers are successfully saved in the memory. Now i step the next instruction

ldmia r0!, {r1-r12}

after this these are the contents of registers:

r0  0x60000400
r1  0x00000000
r2  0x40021008
r3  0x0000000c
r4  0x40000000
r5  0x00000000
r6  0x00000000
r7  0x20017fec
r8  0x00000000
r9  0x555555d5
r10 0x00000000
r11 0x00000000
r12 0x00000000

as you can see all the registers are restored except r9 which oddly has its value "pop"ed from 0x60000000 instead of 0x600003F0.

Any idea what could be causing this issue. I am using Jlink to write into flash.

P.S. This issue doesn't occur when the registers are saved to onchip SRAM as opposed to external SRAM;

edit if the instruction

ldmia r0!, {r1-r12}

is split into two parts like:

ldmia r0!, {r1-r6}
ldmia r0!, {r7-r12}

then all the registers are restored successfully

gcc
memory
arm
ram
cortex-m
asked on Stack Overflow Dec 21, 2016 by ALK007 • edited Dec 21, 2016 by ALK007

1 Answer

6

You need to read the STM32L4xx6xx Silicon Limitations. Section 2.2.4 Read burst access of nine words or more is not supported by FMC. ( DocID026121 Rev 4 ) available from ST.

"CPU read burst access equal to or more than 9 registers to FMC returns corrupted data starting from the 9th read word. These bursts can only be generated by Cortex®-M4 CPU and not by the other masters (i.e not by DMA). This issue occurs when the stack is remapped on the external memory on the FMC and POP operations are performed with 9 or more registers. This also occurs when LDM/VLDM operations are used with 9 or more registers."

answered on Stack Overflow Dec 21, 2016 by Realtime Rik

User contributions licensed under CC BY-SA 3.0