Portenta H7 LITE: SDRAM BUS FAULT / UNALIGNED ACCESS(USAGE FAULT)
Closed this issue · 5 comments
@KurtE - @facchinm
While testing SDRAM on the Portenta H7 Lite found that depending on sketch you will get one of the 2 faults mentioned in the tile depending on the sketch used.
If I run a simple sketch:
#include "SDRAM.h"
SDRAMClass ram;
void setup() {
Serial.begin(115200);
while (!Serial);
uint8_t *b;
ram.begin();
b = (uint8_t *)ram.malloc(320 * 240 * sizeof(uint8_t));
}
void loop() {
}
you will get the error message:
*** Booting Zephyr OS build v3.7.0-8126-g33bc8a018ecc ***
[00:00:03.158,000] <err> os: ***** BUS FAULT *****
[00:00:03.165,000] <err> os: Imprecise data bus error
[00:00:03.173,000] <err> os: r0/a1: 0xc0000000 r1/a2: 0x240256a0 r2/a3: 0x007ffff4
[00:00:03.184,000] <err> os: r3/a4: 0xc0000000 r12/ip: 0x00000008 r14/lr: 0x2402828d
[00:00:03.195,000] <err> os: xpsr: 0x21000000
[00:00:03.203,000] <err> os: s[ 0]: 0x00800000 s[ 1]: 0xc0000000 s[ 2]: 0x00000008 s[ 3]: 0xc0000000
[00:00:03.215,000] <err> os: s[ 4]: 0x00000000 s[ 5]: 0x240282fb s[ 6]: 0x240282e9 s[ 7]: 0x240282c3
[00:00:03.228,000] <err> os: s[ 8]: 0x240288a9 s[ 9]: 0x24028299 s[10]: 0x00000000 s[11]: 0x24028479
[00:00:03.240,000] <err> os: s[12]: 0x00000000 s[13]: 0x2402554c s[14]: 0x2402845d s[15]: 0x0804ab79
[00:00:03.253,000] <err> os: fpscr: 0x2402554c
[00:00:03.260,000] <err> os: Faulting instruction address (r15/pc): 0x24028030
[00:00:03.270,000] <err> os: >>> ZEPHYR FATAL ERROR 26: Unknown error on CPU 0
[00:00:03.280,000] <err> os: Current thread: 0x24003200 (main)
[00:00:03.289,000] <err> os: Halting system
This also occurs with the portenta H7 example sketch used for Mbed.
If I run the current example that tests memory in current zephy_sdram library you get the usuage fault:
*** Booting Zephyr OS build v3.7.0-8126-g33bc8a018ecc ***
[00:00:04.695,000] <err> os: ***** USAGE FAULT *****
[00:00:04.703,000] <err> os: Unaligned memory access
[00:00:04.711,000] <err> os: r0/a1: 0xd9c519ba r1/a2: 0x00000017 r2/a3: 0x0 006f71f
[00:00:04.722,000] <err> os: r3/a4: 0x2402d88c r12/ip: 0x00000008 r14/lr: 0x2 40283a7
[00:00:04.733,000] <err> os: xpsr: 0x01000200
[00:00:04.740,000] <err> os: s[ 0]: 0x24029a20 s[ 1]: 0x24029a05 s[ 2]: 0x2 402f010 s[ 3]: 0x00000000
[00:00:04.753,000] <err> os: s[ 4]: 0x24028391 s[ 5]: 0x2402a041 s[ 6]: 0x2 4028361 s[ 7]: 0x24029b3d
[00:00:04.765,000] <err> os: s[ 8]: 0x00000000 s[ 9]: 0x2402554c s[10]: 0x2 4029b21 s[11]: 0x0804ab79
[00:00:04.778,000] <err> os: s[12]: 0x2402554c s[13]: 0x24029b21 s[14]: 0x0 0000000 s[15]: 0x00000000
[00:00:04.791,000] <err> os: fpscr: 0x00000000
[00:00:04.798,000] <err> os: Faulting instruction address (r15/pc): 0x24029c24
[00:00:04.808,000] <err> os: >>> ZEPHYR FATAL ERROR 31: Unknown error on CPU 0
[00:00:04.818,000] <err> os: Current thread: 0x24003200 (main)
[00:00:04.827,000] <err> os: Halting system
Comparing the config files for the giga and the h7 the only real difference that would apply is:
CONFIG_MPU=y
Note in the prj.conf it is set as:
CONFIG_MPU=n
If I comment it out it in the H7 it fails to rebuild:
warning: NOCACHE_MEMORY (defined at arch/Kconfig:408) has direct dependencies ARCH_HAS_NOCACHE_MEMORY_SUPPORT with value n, but is currently being y-selected by the following symbols:
- ETH_STM32_HAL (defined at drivers/ethernet/Kconfig.stm32_hal:7), with value y, direct dependencies DT_HAS_ST_STM32_ETHERNET_ENABLED && ETH_DRIVER (value: y), and select condition SOC_SERIES_STM32H7X && CPU_CORTEX_M7 && DT_HAS_ST_STM32_ETHERNET_ENABLED && ETH_DRIVER (value: y)
Parsing /home/my_new_zephyr_folder/zephyr/Kconfig
Loaded configuration '/home/my_new_zephyr_folder/zephyr/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_defconfig'
Merged configuration '/home/my_new_zephyr_folder/ArduinoCore-zephyr/loader/prj.conf'
Merged configuration '/home/my_new_zephyr_folder/ArduinoCore-zephyr/loader/boards/arduino_portenta_h7_m7.conf'
error: Aborting due to Kconfig warnings
CMake Error at /home/my_new_zephyr_folder/zephyr/cmake/modules/kconfig.cmake:396 (message):
command failed with return code: 1
Call Stack (most recent call first):
/home/my_new_zephyr_folder/zephyr/cmake/modules/zephyr_default.cmake:133 (include)
/home/my_new_zephyr_folder/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:66 (include)
/home/my_new_zephyr_folder/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:92 (include_boilerplate)
CMakeLists.txt:7 (find_package)
-- Configuring incomplete, errors occurred!
FATAL ERROR: command exited with status 1: /usr/bin/cmake -DWEST_PYTHON=/home/my_new_zephyr_folder/ArduinoCore-zephyr/venv/bin/python3.12 -B/home/my_new_zephyr_folder/ArduinoCore-zephyr/build -GNinja -DBOARD=arduino_portenta_h7//m7 -S/home/my_new_zephyr_folder/ArduinoCore-zephyr/loader
In the Portenta H7 SDRAM library it configures the MPU to address unaligned region:
int SDRAMClass::begin(uint32_t start_address) {
if (FMC_SDRAM_DEVICE->SDCMR == 0x00000000U) {
bool ret = sdram_init();
if (ret == false) {
return 0;
}
/* Enable MPU for the SDRAM Memory Region to allow non-aligned
accesses (hard-fault otherwise)
Initially disable all access for the entire SDRAM memory space,
then enable access/caching for the size used
*/
if (SDRAM_START_ADDRESS == 0x60000000) {
HAL_SetFMCMemorySwappingConfig(FMC_SWAPBMAP_SDRAM_SRAM);
}
#ifdef CORE_CM4
MPU_Config();
#endif
}
if (start_address) {
malloc_addblock((void*)start_address, SDRAM_END_ADDRESS - start_address);
}
return 1;
}
so do not know how to handle this under Zephyr. PS there is more they do to configure the region.
Under zephyr did see the config option to
CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT
not sure enabling this will cause other issues
Probably have to address via:
https://docs.zephyrproject.org/apidoc/latest/arm__mpu__v8_8h.html
actually probably
https://docs.zephyrproject.org/apidoc/latest/arm__mpu__v7m_8h.html
or maybe address it through memory regions:
https://docs.zephyrproject.org/latest/services/mem_mgmt/index.html
https://docs.zephyrproject.org/apidoc/latest/group__mm__drv__apis.html
@mjs513 I verified your sketch gives the same results on my H7.
I also tried updating your sketch to see if anything would print out:
#include "SDRAM.h"
SDRAMClass ram;
void setup() {
Serial.begin(115200);
while (!Serial);
uint8_t *b;
Serial.println("Before Ram begin"); Serial.flush();
ram.begin();
Serial.println("After Ram begin"); Serial.flush();
b = (uint8_t *)ram.malloc(320 * 240 * sizeof(uint8_t));
Serial.println("After malloc begin"); Serial.flush();
}
void loop() {
}
No output in the Serial monitor;
Same fault:
uart:~$
*** Booting Zephyr OS build v3.7.0-8126-g33bc8a018ecc ***
[00:00:30.728,000] <err> os: ***** BUS FAULT *****
[00:00:30.736,000] <err> os: Imprecise data bus error
[00:00:30.744,000] <err> os: r0/a1: 0xc0000000 r1/a2: 0x24030ea0 r2/a3: 0x007ffff4
[00:00:30.755,000] <err> os: r3/a4: 0xc0000000 r12/ip: 0x00000002 r14/lr: 0x2403328d
[00:00:30.766,000] <err> os: xpsr: 0x21000000
[00:00:30.773,000] <err> os: s[ 0]: 0x00000002 s[ 1]: 0x240337c1 s[ 2]: 0x08068298 s[ 3]: 0x61000000
[00:00:30.786,000] <err> os: s[ 4]: 0x00000000 s[ 5]: 0x00000000 s[ 6]: 0x00000000 s[ 7]: 0x00000000
[00:00:30.798,000] <err> os: s[ 8]: 0x00000000 s[ 9]: 0x00000000 s[10]: 0x00000000 s[11]: 0x00000000
[00:00:30.811,000] <err> os: s[12]: 0x00000000 s[13]: 0x00000000 s[14]: 0x00000000 s[15]: 0x00000000
[00:00:30.823,000] <err> os: fpscr: 0x4bbebc20
[00:00:30.831,000] <err> os: Faulting instruction address (r15/pc): 0x24033030
[00:00:30.841,000] <err> os: >>> ZEPHYR FATAL ERROR 26: Unknown error on CPU 0
[00:00:30.851,000] <err> os: Current thread: 0x240031f8 (main)
[00:00:30.860,000] <err> os: Halting system
If I add printk calls like:
#include "SDRAM.h"
SDRAMClass ram;
void setup() {
printk("Setup called\n");
Serial.begin(115200);
while (!Serial)
;
uint8_t *b;
Serial.println("Before Ram begin");
Serial.flush();
printk("before Ram begin\n");
ram.begin();
printk("after Ram begin\n");
Serial.println("After Ram begin");
Serial.flush();
b = (uint8_t *)ram.malloc(320 * 240 * sizeof(uint8_t));
Serial.println("After malloc begin");
Serial.flush();
}
I see...
uart:~$
*** Booting Zephyr OS build v3.7.0-8126-g33bc8a018ecc ***
Setup called
before Ram begin
[00:00:04.747,000] <err> os: ***** BUS FAULT *****
and the Ram begin also prints in the USB port...
Quick update: I was curious if the IO pins associated with SDRam were updated to the proper Altenate Function mode.
S I added some code to dump out some of the GPIO states just before we called the SDRam:
Whole sketch again:
#include "SDRAM.h"
SDRAMClass ram;
void print_gpio_regs(const char *name, GPIO_TypeDef* port) {
printk("GPIO%s(%p) %08X %08X %08x\n", name, port, port->MODER, port->AFR[0], port->AFR[1]);
Serial.print("GPIO"); Serial.print(name);
Serial.print(" "); Serial.print(port->MODER, HEX);
Serial.print(" "); Serial.print(port->AFR[0], HEX);
Serial.print(" "); Serial.println(port->AFR[1], HEX);
}
void setup() {
printk("Setup called\n");
Serial.begin(115200);
while (!Serial)
;
uint8_t *b;
Serial.println("Before Ram begin");
Serial.flush();
printk("before Ram begin\n");
print_gpio_regs("A", GPIOA);
print_gpio_regs("B", GPIOB);
print_gpio_regs("C", GPIOC);
print_gpio_regs("D", GPIOD);
print_gpio_regs("E", GPIOE);
print_gpio_regs("F", GPIOF);
print_gpio_regs("G", GPIOG);
print_gpio_regs("H", GPIOH);
print_gpio_regs("I", GPIOI);
print_gpio_regs("J", GPIOJ);
print_gpio_regs("K", GPIOK);
ram.begin();
printk("after Ram begin\n");
Serial.println("After Ram begin");
Serial.flush();
b = (uint8_t *)ram.malloc(320 * 240 * sizeof(uint8_t));
Serial.println("After malloc begin");
Serial.flush();
}
void loop() {
}
On the Portenta H7: that crashes with this sketh I see:
*** Booting Zephyr OS build v3.7.0-8126-g33bc8a018ecc ***
Setup called
before Ram begin
GPIOA(0x58020000) ABEBBBAA B0A0ABB8 00000770
GPIOB(0x58020400) FAAFAABA 44A000AA 00aaaa00
GPIOC(0x58020800) FFFFFAAA 00BB55BA 00000000
GPIOD(0x58020c00) FABFFFFF 00000000 00999000
GPIOE(0x58021000) FFFFFFFF 00000000 00000000
GPIOF(0x58021400) FFEFBFFF 90000000 00000900
GPIOG(0x58021800) EABBEFFF 0A000000 07bbb070
GPIOH(0x58021c00) FEBEBEF7 400A0000 00044004
GPIOI(0x58022000) FFB8FFFB 00000050 0000a080
GPIOJ(0x58022400) 7FFFFD5F 00000000 00000000
GPIOK(0x58022800) FFFF5FFC 00000000 00000000
[00:00:01.303,000] <err> os: ***** BUS FAULT *****
[00:00:01.311,000] <err> os: Imprecise data bus error
[00:00:01.319,000] <err> os: r0/a1: 0xc0000000 r1/a2: 0x24030ea0 r2/a3: 0x007ffff4
[00:00:01.330,000] <err> os: r3/a4: 0xc0000000 r12/ip: 0x00000000 r14/lr: 0x2403328d
[00:00:01.341,000] <err> os: xpsr: 0x21000000
[00:00:01.348,000] <err> os: s[ 0]: 0x0806b4af s[ 1]: 0x24033885 s[ 2]: 0x240335cd s[ 3]: 0x00000000
[00:00:01.361,000] <err> os: s[ 4]: 0x00000010 s[ 5]: 0x00000000 s[ 6]: 0x00000000 s[ 7]: 0x0806ba85
[00:00:01.373,000] <err> os: s[ 8]: 0x00000000 s[ 9]: 0x00000000 s[10]: 0x24032200 s[11]: 0x2403057c
[00:00:01.386,000] <err> os: s[12]: 0x0806b4af s[13]: 0x0806b4bf s[14]: 0x24032200 s[15]: 0x2403057c
[00:00:01.398,000] <err> os: fpscr: 0x58022800
[00:00:01.406,000] <err> os: Faulting instruction address (r15/pc): 0x24033030
[00:00:01.416,000] <err> os: >>> ZEPHYR FATAL ERROR 26: Unknown error on CPU 0
[00:00:01.426,000] <err> os: Current thread: 0x240031f8 (main)
[00:00:01.435,000] <err> os: Halting system
I know that the SDRam is under the FMC, And for example I know it includes these pins:
<style> </style>| PF_00 | SDRAM_A0 | PF0 | - | - | - | - | I2C2_SDA | - | - | - | - | - | - | - | FMC_A0 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PF_01 | SDRAM_A1 | PF1 | - | - | - | - | I2C2_SCL | - | - | - | - | - | - | - | FMC_A1 | |
| PF_02 | SDRAM_A2 | PF2 | - | - | - | - | I2C2_SMBA | - | - | - | - | - | - | - | FMC_A2 | |
| PF_03 | SDRAM_A3 | PF3 | - | - | - | - | - | - | - | - | - | - | - | - | FMC_A3 | |
| PF_04 | SDRAM_A4 | PF4 | - | - | - | - | - | - | - | - | - | - | - | - | FMC_A4 | |
| PF_05 | SDRAM_A5 | PF5 | - | - | - | - | - | - | - | - | - | - | - | - | FMC_A5 |
Now if I run the same sketch on GIGA I see:
Before Ram begin
GPIOA AABAAFA7 2D001100 AA07B
GPIOB FFBAAEBF 76025000 4022
GPIOC FFFFBFFF 70000000 0
GPIOD AAAAA9FA 577000CC CC299CCC
GPIOE AAAABF6A C00009CC CCCCCCCC
GPIOF AAAAAAAA 79CCCCCC CCCCC977
GPIOG AFBAEAEA ACC0CCC C700D05C
GPIOH EAAAEAAF 2C4CC00 D84DDDD
GPIOI FDFBAAFF DDDD0000 80
GPIOJ F7AAFFFF 0 1313
GPIOK FFFFFFFB 10 0
After Ram begin
After malloc begin
Again same pins used on GIGA for FMC. and if we again look at GPIOF: MODER
We have: GPIOF AAAAAAAA So The last 3 nibbles: A 1010 so these 6 pins are mode 2: which is Alternate function.
If we Look ath the print for AFR[0], bottom 6 nibbles: 79CCCCCC They are all C (12), which matches the FMC AF12
I am still trying to figure out where in the code, is something called that initializes the SDRAM FMC/SDRam hardware:
(SDRAM1).
Wondering if/where there might be an SYS_INIT(...) function that initializes it.
The one place I see a sys init that mentiones SDRAM1 is in our loader\fixups.c
But that is onlye if: CONFIG_SHARED_MULTI_HEAP
int smh_init(void)
{
int ret = 0;
ret = shared_multi_heap_pool_init();
if (ret != 0) {
return ret;
}
const struct memory_region_t regions[] = {
DT_FOREACH_STATUS_OKAY(zephyr_memory_region, _BUILD_MEM_REGION)
};
for (size_t i=0; i<ARRAY_SIZE(regions); i++) {
if (!strncmp("SDRAM", regions[i].dt_name, 5)) {
struct shared_multi_heap_region smh_sdram = {
.addr = regions[i].dt_addr,
.size = regions[i].dt_size,
.attr = SMH_REG_ATTR_EXTERNAL,
};
ret = shared_multi_heap_add(&smh_sdram, NULL);
if (ret != 0) {
return ret;
}
}
}
return 0;
}
SYS_INIT(smh_init, POST_KERNEL, CONFIG_CLOCK_CONTROL_PWM_INIT_PRIORITY);
But it looks like it excludes doing anything with the region name starts with SDRAM.
Question is, what is different here versus GIGA.
Don't know if this is related or not, think probably not, but there are Warning messages for Quadspi, as part of this
build:
-- Found BOARD.dts: /home/kurte/git/zephyr/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7.dts
-- Found devicetree overlay: /home/kurte/git/zephyr/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_1_0_0.overlay
-- Found devicetree overlay: /home/kurte/git/ArduinoCore-zephyr/loader/boards/arduino_portenta_h7_m7.overlay
unit address and first address in 'reg' (0xe0000) don't match for /soc/flash-controller@52002000/flash@8000000/partitions/partition@0
-- Generated zephyr.dts: /home/kurte/git/ArduinoCore-zephyr/build/zephyr/zephyr.dts
-- Generated pickled edt: /home/kurte/git/ArduinoCore-zephyr/build/zephyr/edt.pickle
-- Generated zephyr.dts: /home/kurte/git/ArduinoCore-zephyr/build/zephyr/zephyr.dts
-- Generated devicetree_generated.h: /home/kurte/git/ArduinoCore-zephyr/build/zephyr/include/generated/zephyr/devicetree_generated.h
-- Including generated dts.cmake file: /home/kurte/git/ArduinoCore-zephyr/build/zephyr/dts.cmake
CMake Warning at /home/kurte/git/zephyr/cmake/modules/dts.cmake:426 (message):
dtc raised one or more warnings:
/home/kurte/git/ArduinoCore-zephyr/build/zephyr/zephyr.dts:1435.29-1467.5:
Warning (spi_bus_bridge): /soc/quadspi@52005000: node name for SPI buses
should be 'spi'
<stdout>: Warning (spi_bus_reg): Failed prerequisite 'spi_bus_bridge'
Call Stack (most recent call first):
/home/kurte/git/zephyr/cmake/modules/zephyr_default.cmake:133 (include)
/home/kurte/git/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:66 (include)
/home/kurte/git/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:92 (include_boilerplate)
CMakeLists.txt:7 (find_package)
But maybe that flash message about not matching?
Resolved down to needing:
CONFIG_DMA=y
CONFIG_MEMC=y
In the Portenta .conf file
Pushed it up into the changes in my PR: #71
PR closed so going to close this - if problem persists will create new