Electronic – MCU RAM – Why accessing RAM across the boundary causes Bus Fault

armmicrocontroller

My question is best explained by an example. There's an evaluation kit from Infineon that uses ARM Cortex-M4 and has a total of 80 kB of RAM. There is also 512 kB of Flash memory. [However, it seems that due to large areas within RAM being "reserved" (as per board's reference manual), the maximum RAM size is below 20 kB. What could be the cause of such behaviour?] After further investigation, the problem appears to be that the RAM allocated for program data passes the boundary between the two regions, and does so in a misaligned fashion. This may cause problems even if code size is well below RAM size.

To give a little context to the problem, here is the output of arm-none-eabi-size with SysV option enabled:

section               size        addr
.text                 5628   134217728
Stack                 2048   536854528
.data                  116   536856576
.bss                 16386   536856692
USB_RAM                  2   536873078
.no_init                32   536936384
.debug_aranges        2208           0
.debug_info          43565           0
.debug_abbrev         3389           0
.debug_line          11094           0
.debug_frame          9968           0
.debug_str           30489           0
.debug_loc           21316           0
.debug_ranges         2064           0
.build_attributes      472           0
Total               148777

Unless I am mistaking, the only parts that go into RAM are .bss, .data(as it goes both into RAM and Flash). The relevant linker map section is as follows (i.e. shows exactly the point where the .bss section goes out of its bounds):

.bss            0x1fffc874     0x4009 load address 0x0c0016a8
                0x1fffc874                . = ALIGN (0x4)
                0x1fffc874                __bss_start = .
 *(.bss)
 *(.bss*)
 .bss.resultsArray
                0x1fffc874     0x4000 ./main.o
                0x1fffc874                resultsArray
 .bss.resultsArrayIndex
                0x20000874        0x2 ./main.o
                0x20000874                resultsArrayIndex
 *fill*         0x20000876        0x2 
 .bss.oversamplingResult
                0x20000878        0x4 ./main.o
                0x20000878                oversamplingResult
 .bss.numberOfOversamplingSamplesCollected
                0x2000087c        0x1 ./main.o
                0x2000087c                numberOfOversamplingSamplesCollected

Note that per user manual, PSRAM ends at 0x1FFFFFFF and DSRAM begins at 0x20000000. Running this program generates a Bus Fault when the startup sequence reaches 0x1FFFFFFD. Reducing the size so that it fits in PSRAM makes the program compile and run without any Faults. The question is not as much about this particular program; instead, I am genuinely curious as to why so little RAM is available for the actual program variables and uninitialized data and everything else that goes into RAM?

Below is the screen capture from the reference manual outlining the memory organization at the boundary.

enter image description here

Best Answer

Running this program generates a Bus Fault when the startup sequence reaches 0x1FFFFFFD

Usual startup routines write 4-byte words, but your address is not 4-byte aligned. Your linker script probably misses one ALIGN(4) statement (or similar if not LD).

Now the Cortex M4 should in theory split the unaligned write into two, but yours would wrap over two memory segments at different memory busses. It is possible that this particular case is not handled correctly in hardware, causing the address to flip over 0x00000000 instead of 0x20000000. Thus you try to write to flash at 0x00 => Bus fault. Correctly aligning your data should fix this problem.