RIOT-OS / RIOT

RIOT - The friendly OS for IoT
https://riot-os.org
GNU Lesser General Public License v2.1
4.94k stars 1.99k forks source link

MPU doesn't work on cortex-m0+ #14822

Open aabadie opened 4 years ago

aabadie commented 4 years ago

Description

MPU doesn't work on cortex-m0+.

Initially it was enabled for stm32g0 and was resulting in the following problems:

Context switching is broken in master on stm32g0 CPUs (cortex-m0+). Every switch to the idle thread triggers an hard fault:

examples/hello_world ``` 2020-08-21 14:20:23,397 # main(): This is RIOT! (Version: 2020.10-devel-888-g0b639) 2020-08-21 14:20:23,398 # Hello World! 2020-08-21 14:20:23,402 # You are running RIOT on a(n) nucleo-g070rb board. 2020-08-21 14:20:23,405 # This board features a(n) stm32 MCU. 2020-08-21 14:20:23,406 # 2020-08-21 14:20:23,408 # Context before hardfault: ```
examples/default ``` 2020-08-21 14:22:40,262 # main(): This is RIOT! (Version: 2020.10-devel-888-g0b639) 2020-08-21 14:22:40,263 # Welcome to RIOT! > 2020-08-21 14:22:40,263 # 2020-08-21 14:22:40,266 # Context before hardfault: ```
tests/thread_flags ``` 2020-08-21 14:23:47,476 # Help: Press s to start test, r to print it is ready 2020-08-21 14:23:47,477 # 2020-08-21 14:23:47,479 # Context before hardfault: ```

All these applications were working when the support was introduced in #14163.

Bisecting shows that the commit introducing the regression is 43d6c4147a8034a1a115a061a1b8ca0705c86222 from #14355. So it seems that it's rather an issue with MPU although the STM32G0 family provides that feature.

@bergzand @kaspar030, any idea what could be the problem ?

Steps to reproduce the issue

Just build and flash examples/hello-world and you'll get the following output:

make BOARD=nucleo-g070rb -C examples/hello-world flash term --no-print-directory 
Building application "hello-world" for "nucleo-g070rb" with MCU "stm32".

"make" -C /work/riot/RIOT/pkg/stm32cmsis
"make" -C /work/riot/RIOT/boards/nucleo-g070rb
"make" -C /work/riot/RIOT/boards/common/nucleo
"make" -C /work/riot/RIOT/core
"make" -C /work/riot/RIOT/cpu/stm32
"make" -C /work/riot/RIOT/cpu/cortexm_common
"make" -C /work/riot/RIOT/cpu/cortexm_common/periph
"make" -C /work/riot/RIOT/cpu/stm32/bootloader
"make" -C /work/riot/RIOT/cpu/stm32/periph
"make" -C /work/riot/RIOT/cpu/stm32/stmclk
"make" -C /work/riot/RIOT/cpu/stm32/vectors
"make" -C /work/riot/RIOT/drivers
"make" -C /work/riot/RIOT/drivers/periph_common
"make" -C /work/riot/RIOT/sys
"make" -C /work/riot/RIOT/sys/auto_init
"make" -C /work/riot/RIOT/sys/newlib_syscalls_default
"make" -C /work/riot/RIOT/sys/pm_layered
"make" -C /work/riot/RIOT/sys/stdio_uart
   text    data     bss     dec     hex filename
   8484     112    2568   11164    2b9c /work/riot/RIOT/examples/hello-world/bin/nucleo-g070rb/hello-world.elf
/work/riot/RIOT/dist/tools/openocd/openocd.sh flash /work/riot/RIOT/examples/hello-world/bin/nucleo-g070rb/hello-world.elf
### Flashing Target ###
Open On-Chip Debugger 0.10.0+dev-01383-gd46f28c2e-dirty (2020-08-20-10:53)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
WARNING: interface/stlink-v2-1.cfg is deprecated, please switch to interface/stlink.cfg
hla_swd
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
srst_only separate srst_nogate srst_open_drain connect_assert_srst

Info : clock speed 2000 kHz
Info : STLINK V2J31M21 (API v2) VID:PID 0483:374B
Info : Target voltage: 3.226076
Info : stm32g0x.cpu: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for stm32g0x.cpu on 0
Info : Listening on port 42317 for gdb connections
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* stm32g0x.cpu       hla_target little stm32g0x.cpu       reset

Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0xf1000000 pc: 0x08000494 msp: 0x20000200
Info : device idcode = 0x20006460 (STM32G07/G08xx - Rev: B)
Info : flash size = 128kbytes
Info : flash mode : single-bank
Info : Padding image section 1 at 0x08002194 with 4 bytes (bank write end alignment)
Warn : Adding extra erase range, 0x08002198 .. 0x080027ff
auto erase enabled
wrote 8600 bytes from file /work/riot/RIOT/examples/hello-world/bin/nucleo-g070rb/hello-world.elf in 0.274143s (30.635 KiB/s)

verified 8596 bytes in 0.070788s (118.587 KiB/s)

Info : Unable to match requested speed 2000 kHz, using 1800 kHz
Info : Unable to match requested speed 2000 kHz, using 1800 kHz
shutdown command invoked
Done flashing
/work/riot/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "115200"  
Twisted not available, please install it if you want to use pyterm's JSON capabilities
2020-08-21 14:20:20,915 # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2020-08-21 14:20:23,397 # main(): This is RIOT! (Version: 2020.10-devel-888-g0b639)
2020-08-21 14:20:23,398 # Hello World!
2020-08-21 14:20:23,402 # You are running RIOT on a(n) nucleo-g070rb board.
2020-08-21 14:20:23,405 # This board features a(n) stm32 MCU.
2020-08-21 14:20:23,406 # 
2020-08-21 14:20:23,408 # Context before hardfault:
2020-08-21 14:20:24,488 # Exiting Pyterm

Expected results

Applications work

Actual results

All applications trigger an hard fault

Versions

make print-versions ``` Operating System Environment ---------------------------- Operating System: "Ubuntu" "20.04.1 LTS (Focal Fossa)" Kernel: Linux 5.4.0-42-generic x86_64 x86_64 System shell: /usr/bin/dash (probably dash) make's shell: /usr/bin/dash (probably dash) Installed compiler toolchains ----------------------------- native gcc: gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0 arm-none-eabi-gcc: arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 9-2019-q4-major) 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] avr-gcc: avr-gcc (AVR_8_bit_GNU_Toolchain_3.6.2_1759) 5.4.0 mips-mti-elf-gcc: mips-mti-elf-gcc (Codescape GNU Tools 2016.05-03 for MIPS MTI Bare Metal) 4.9.2 msp430-elf-gcc: missing riscv-none-embed-gcc: riscv-none-embed-gcc (GNU MCU Eclipse RISC-V Embedded GCC, 64-bit) 8.2.0 xtensa-esp32-elf-gcc: missing xtensa-esp8266-elf-gcc: missing clang: clang version 10.0.0-4ubuntu1 Installed compiler libs ----------------------- arm-none-eabi-newlib: "3.1.0" mips-mti-elf-newlib: "2.1.0" msp430-elf-newlib: missing riscv-none-embed-newlib: "3.0.0" xtensa-esp32-elf-newlib: missing xtensa-esp8266-elf-newlib: missing avr-libc: "2.0.0" ("20150208") Installed development tools --------------------------- ccache: ccache version 3.7.7 cmake: cmake version 3.16.3 cppcheck: Cppcheck 1.90 doxygen: 1.8.17 git: git version 2.25.1 make: GNU Make 4.2.1 openocd: Open On-Chip Debugger 0.10.0+dev-01383-gd46f28c2e-dirty (2020-08-20-10:53) python: Python 3.8.2 python2: Python 2.7.18rc1 python3: Python 3.8.2 flake8: 3.7.9 (mccabe: 0.6.1, pycodestyle: 2.5.0, pyflakes: 2.1.1) CPython 3.8.2 on Linux coccinelle: missing ```
bergzand commented 4 years ago

Second attempt at guessing at this solution:

https://github.com/RIOT-OS/RIOT/pull/14355#issuecomment-677558815

There is a difference between the cortex-m0+ and the cortex-m4(and higher) MPU. The cortex-m0+ minimum MPU region size is 256 bytes, whereas the cortex-m4 MPU minimum region size is 32 bytes.

What could be happening here is that on the cortex-m0+, the region is automatically increased to 256B, covering a larger area than initially expected.

aabadie commented 4 years ago

A quick fix could be to disable mpu on stm32g0 but if it's possible to really fix it, then I would prefer that.

bergzand commented 4 years ago

Also note that the cortex-m0+ doesn't have a separate mem_manage_handler and triggers a hard fault when the MPU denies access.