No description
  • C 65%
  • CMake 35%
Find a file
2026-11-02 22:56:46 +01:00
CMakeLists.txt version initiale 2026-10-23 17:20:01 +02:00
launch_in_renode.resc Modif pour fonctionnement dans renode (interruption 4 MemManage pour renode au lieu de 3 HardFault pour le pico) 2026-11-02 22:56:46 +01:00
main.c Modif pour fonctionnement dans renode (interruption 4 MemManage pour renode au lieu de 3 HardFault pour le pico) 2026-11-02 22:56:46 +01:00
pico_sdk_import.cmake version initiale 2026-10-23 17:20:01 +02:00
README.md version initiale 2026-10-23 17:20:01 +02:00

RP2040 MPU demo (Raspberry Pi Pico, Cortex-M0+)

Build & flash

export PICO_SDK_PATH=/path/to/pico-sdk
mkdir build && cd build
cmake -DPICO_BOARD=pico ..
make
# copy mpu_demo.uf2 to the RPI-RP2 drive (BOOTSEL), open the console (USB CDC or UART0 115200)

What the M0+ MPU offers (ARMv6-M PMSA)

Item RP2040
Regions 8 (MPU_TYPE.DREGION)
Region size power of 2, 256 B … 4 GB, base aligned on size
Sub-regions 8 per region (if size ≥ 256 B), disabled with SRD
Attributes AP (priv/unpriv RW/RO/none), XN, C/B/S
Overlap the highest region number wins
Fault HardFault only (no MemManage, no MMFAR/CFSR)
PRIVDEFENA privileged code uses the default map outside the regions

Registers: MPU_TYPE 0xE000ED90, CTRL ED94, RNR ED98, RBAR ED9C, RASR EDA0.

Experiments and expected output

# Shows Result
0 MPU off everything is allowed, ram_fn() returns 42
1 AP=RO on a RAM table read ok, write → FAULT, value unchanged
2 XN bit RAM code runs with XN=0 and faults with XN=1; data writes are still fine
3 SRD=0xFE guarded[0..127] → FAULT, guarded[128..] ok
4 CONTROL.nPRIV + PSP the task computes in its sandbox; 2 faults when it touches kernel_data

The HardFault handler records the fault and then resumes execution. On the M0+, every LDR/STR is 16-bit, so it skips the faulting instruction with PC += 2. If the fault was an instruction fetch from an XN region, it returns to the caller through the stacked LR instead. A real system would not resume like this. It would kill the task or reset.

Exercises for students

  1. Set MPU_CTRL_HFNMIENA and explain what happens on a fault, and why.
  2. Remove PRIVDEFENA: which regions must you add so that main() keeps working (SRAM, peripherals, ROM, PPB…)?
  3. Build a stack guard: place a 256 B no-access region at the bottom of the main stack (see __StackLimit in the linker script), then trigger it with deep recursion. Compare with PICO_USE_STACK_GUARDS=1 in the SDK.
  4. Use AP_PRIV_RW_USER_RO to let the unprivileged task read kernel_data but not write it.
  5. Add a printf to sandboxed_task(): why does it fault, and how could an SVC-based "syscall" solve this?
  6. Write a minimal two-task round-robin scheduler (SysTick + PendSV) that reprograms region 4 on every context switch.