helium / cortex-mpu

Cortex-M MPU library
Apache License 2.0
6 stars 5 forks source link

Problems getting it working #3

Open ctron opened 3 years ago

ctron commented 3 years ago

I have some problems getting it working, but maybe I am just using it wrong.

I have a STM32F411 Nucleo board, so MPU should be supported to my understanding.

I set it up like this:

#[exception]
fn MemoryManagement() -> ! {
    rprintln!("Memory management error");
    loop {
        cortex_m::asm::nop();
    }
}

#[entry]
fn main() -> ! {
    let mut regions = ArrayVec::new();
    let base = cortex_m_rt::heap_start() as usize;
    regions.push(Region {
        base_addr: base,
        size: Size::S32B,
        subregions: Subregions::ALL,
        executable: false,
        permissions: AccessPermission::NoAccess,
        attributes: MemoryAttributes::Normal {
            shareable: false,
            cache_policy: CachePolicy::NonCacheable,
        },
    });

    rprintln!("Configure MPU - base: 0x{:08x}", base);
    let mut mpu = unsafe { Mpu::new(core.MPU) };
    mpu.configure_unprivileged(&regions);

    rprintln!("Try access");
    unsafe {
        ptr::write_volatile(base as *mut i32, 0);
    }

    rprintln!("Whoopsie");

    loop {
        cortex_m::asm::nop();
    }
}

My expectation would be, that the point of "Whoopsie" is never reached. And it calls into the fn MemoryManagement instead.

However, the code just runs past that point.

lthiery commented 3 years ago

Hi @ctron

It's been a while since I looked at this code, but I think your understanding of the intent is correct. But we never tested any of this beyond and M0 (stm32l0 to be precise) so there could easily be nuances per platform that were neglected.

Perhaps you could try other regions/boundaries? I forget what the rules were for the ARM MPU and if they change much per M0-M4, but it could hopefully be just a memory boundary nuance? Perhaps your current base is not at a good place for enabling MPU?

--Louis

samcrow commented 3 years ago

After doing some tests on an STM32F4, I think I can explain this.

The access permissions (when using the configure_unprivileged function) do not apply to privileged code. This example is all privileged code because it never switches to unprivileged mode. Therefore, the MPU configuration code in this example does not block any memory reads or writes.

I have a pull request that adds some functions to restrict reads and writes from privileged code.