1
votes

I am trying to configure the MPU of SAMD51 (Cortex-M4) to protect one 1k of FLASH from any access, and 1k of SRAM from write access that would contains sensitive information that should never be access or corrupted (from a SW bug or any other way).

I wish to protect those sections, even in privileged (software has no RTOS and will always be in privileged mode).

As code will be running in privileged mode, I use MPU_CTRL_PRIVDEFENA_Msk flag, and wish to only overwrite access for my two regions.

I have checked the alignment requirements of those sections:

  • Region 0 (in FLASH) @ 0x0001d400 (1k aligned)
  • Region 1 (in SRAM) @ 0x20000000 (1k aligned)

Find below my code to configure the MPU:

__disable_irq();

//
// Region0
//
__DSB();
__ISB();
MPU->RNR = 0;
MPU->RBAR = (0x0001d400 << MPU_RBAR_ADDR_Pos);
// 1k size - log2(1k) = 10
MPU->RASR  = ((10 - 1) << MPU_RASR_SIZE_Pos); 
// Normal; Not shareable; Cacheable; Inner Write back; no write allocate
MPU->RASR |= ((0x4 << MPU_RASR_TEX_Pos) | (1 << MPU_RASR_C_Pos) | (1 << MPU_RASR_B_Pos)); 
// No priviledged or unpriviledge access
MPU->RASR |= (0UL << MPU_RASR_AP_Pos);
// Enable
MPU->RASR |= 1UL;

//
// Section 1
//
__DSB();
__ISB();
MPU->RNR = 1;
MPU->RBAR = (0x20000000 << MPU_RBAR_ADDR_Pos);
// 1k size - log2(1k) = 10
MPU->RASR  = ((10 - 1) << MPU_RASR_SIZE_Pos); 
// Normal; Not shareable; Cacheable; Inner Write back; no write allocate
MPU->RASR |= ((0x4 << MPU_RASR_TEX_Pos) | (1 << MPU_RASR_C_Pos) | (1 << MPU_RASR_B_Pos)); 
// Read-Only Priviledged or unpriviledge access
MPU->RASR |= (6UL << MPU_RASR_AP_Pos);
// Enable
MPU->RASR |= 1UL;

// Enable MPU
MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_HFNMIENA_Msk | MPU_CTRL_PRIVDEFENA_Msk;
// Enable MemFault handler
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
__DSB();
__ISB();
__enable_irq();

It appears the configuration is ignored and it never generates a fault when accessing the configured region.

I have read the ARM documentation many times and cannot see what is wrong...

  • Is there a mistake in my code?
  • Is the cache/memory configuration wrong for SAMD51?
  • Is what I want to do not achievable by staying in privileged mode?

Thanks for you help!

1

1 Answers

0
votes

Well there are some clear problems in your code. Please refer this for bit fields: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337e/BIHHGADD.html

From the start: 1: Why are you shifting the base address here

MPU->RBAR = (0x0001d400 << MPU_RBAR_ADDR_Pos);

it needs to be like this. Refer for bit fields of this register.

MPU->RBAR = (0x0001d400);

2: This line has no effect. As this field has been already set to zero while setting the size and it is also incorrect. To clear the bit we use & operation not |.

MPU->RASR |= (0UL << MPU_RASR_AP_Pos);

3: For the testing purpose try with caches off. i-e tex=1, b=0, c=0, s=0. Also set instruction fetches bit XN to disable instruction fetches access.