【简介】
S32K3 系列芯片的Memory 的访问权限是通过Memory Protection Unit (MPU)来配置,MPU 可以配置Memory 的访问权限是否特权级访问(privileged access only or full access)及内存的访问属性(bufferable, cacheable)。在Cortex M架构中对 Memory Map 做了划分,在设计时已经把4G的地址空间划分为不同的Region 不同的Region 访问可以配置成特定的属性来提高安全性。

MPU 的保护也是基于Region 来进行配置,MPU 的Region 的属性配置主要涉及以下几个寄存器

以下框图为通过MPU 来访问Memory 的说明

配置的流程按照如下的流程图有介绍

上述配置流程也比较清晰,首先通过MPU_CTRL 寄存器来关闭MPU,然后通过 MPU_RNR 寄存选择需要配置的Region,通过 MPU_RBAR 、MPU_RASR 寄存器配置Region 的地址 size 访问属性配置,配置完成后最后通过控制寄存器开启MPU 从而完成MPU 的配置。
上述的理论知识介绍完了,我们看下S32K3 的MPU 初始化配置代码如下:
#ifdef MPU_ENABLE
/**************************************************************************/
/* DEFAULT MEMORY ENABLE*/
/**************************************************************************/
/* Init MPU table for memory layout*/
/* Cover all memory on device as background set all memory as strong-order and no access*/
rbar[0]=0x00000000UL;
rasr[0]=0x1004003FUL;
/* Note: For code portability to other Arm processors or systems, Arm recommends that TCM regions are always defined as Normal, Non-shared memory in the MPU. */
/* This is consistent with the default ARMv7E-M memory map attributes that apply when the MPU is either disabled or not implemented.*/
/* ITCM for cortex M7 if no set it as zero */
rbar[1]=(uint32)__INT_ITCM_START;
rasr[1]=0x0308001FUL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
rbar[2]=(uint32)__ROM_CODE_START;
#if defined(S32K311) || defined(S32K341) || defined(S32M276) || defined(S32K310) || defined(S32M274)
rasr[2]=0x070B0027UL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: No, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
#elif defined(S32K342) || defined(S32K312) || defined(S32K322)
rasr[2]=0x070B0029UL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: No, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
#else
rasr[2]=0x070B002BUL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: No, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
#endif
/*Data flash which would extract from linker symbol*/
rbar[3]=(uint32)__ROM_DATA_START;
rasr[3]=0x160B0023UL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: Yes, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
/*UTEST*/
rbar[4]=0x1B000000UL;
/* Size: 8KB, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: Yes, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
rasr[4]=0x160B0019UL;
/*DTCM for cortex m7 if no set it as zero*/
rbar[5]=(uint32)__INT_DTCM_START;
rasr[5]=0x03080021UL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
/*Ram unified section*/
#if defined(S32K396) || defined(S32K394) || defined(S32K344) || defined(S32K324) || defined(S32K314) || defined(S32K374)|| defined(S32K376)
rbar[6]=(uint32)__INT_SRAM_START;
/* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back, write and read allocate, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
/* Disable subregion 7 & 8*/
rasr[6]=((uint32)0x030B0001UL)|(((uint32)__RAM_CACHEABLE_SIZE - 1) << 1)|(1<<15)|(1<<14);
#else
rbar[6]=(uint32)__INT_SRAM_START;
/* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back, write and read allocate, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
rasr[6]=((uint32)0x030B0001UL)|(((uint32)__RAM_CACHEABLE_SIZE - 1) << 1);
#endif
/* Limitation : TCM is not cacheable memory, the purpose is to expand the RAM size for low RAM derivatives. Used for cases like ccov testing,... */
#ifdef EXTEND_LOWRAM_DERIVATIVES
#if defined(S32K310) || defined(S32K311) || defined(S32M274) || defined(S32M276)
rbar[6]=(uint32)__INT_DTCM_START;
/* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back, write and read allocate, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
rasr[6]=((uint32)0x030B0001UL)|(((uint32)__RAM_CACHEABLE_SIZE - 1) << 1);
#endif
#endif
/*Ram non-cache section plus int result which is using for test report*/
rbar[7]=(uint32)__RAM_NO_CACHEABLE_START;
/* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[7]= ((uint32)0x130C0001UL)|(((uint32)__RAM_NO_CACHEABLE_SIZE - 1) << 1);
#ifdef EXTEND_LOWRAM_DERIVATIVES
#if defined(S32K310) || defined(S32K311) || defined(S32M274) || defined(S32M276)
/*Ram non-cache section plus int result which is using for test report*/
rbar[7]=(uint32)__INT_SRAM_START;
/* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[7]= ((uint32)0x130C0001UL)|(((uint32)__RAM_NO_CACHEABLE_SIZE - 1) << 1);
#endif
#endif
/*Ram shareable section*/
rbar[8]=(uint32)__RAM_SHAREABLE_START;
/* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[8]=((uint32)0x130C0001UL)|(((uint32)__RAM_SHAREABLE_SIZE - 1) << 1);
/* Additional configuration for peripheral device*/
/*AIPS_0, AIPS_1, AIPS_2*/
rbar[9]=0x40000000UL;
/* Size: 6MB, Type: Strongly-ordered, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
/* Disable subregion 7 & 8*/
rasr[9]=((uint32)0x1304002DUL)|(1<<15)|(1<<14);
/*AIPS_3*/
rbar[10]=0x40600000UL;
#if defined(S32K396) || defined(S32K394) || defined(S32K374) || defined(S32K376)
/* Size: 2MB, Type: Strongly-ordered, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[10]=0x13040029UL;
#else
rasr[10]=0x0UL;
#endif /* S32K39x */
/*QSPI Rx*/
rbar[11]=0x67000000UL;
/* Size: 128MB, Type: Strongly-ordered, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[11]=0x13040013UL;
/*QSPI AHB*/
rbar[12]=0x68000000UL;
/* Size: 128MB, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back, write and read allocate, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
rasr[12]=0x030B0035UL;
/*Private Peripheral Bus*/
rbar[13]=0xE0000000UL;
/* Size: Normal, Type: Strongly-ordered, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[13]=0x13040027UL;
/* Program flash */
/* Note: Do not merge with MPU region 2 because of alignment with the size */
rbar[14]=(uint32)((uint32)__ROM_CODE_START + 0x400000UL);
#if defined(S32K396) || defined(S32K376)
rasr[14]=0x070B0029UL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: No, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
#elif defined(S32K358) || defined(S32K388) || defined(S32K328) || defined(S32K338) || defined(S32K348)
rasr[14]=0x070B002BUL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: Inner write-back, write and read allocate, Outer Cache Policy: Outer write-back. write and read allocate, Shareable: No, Privileged Access: Read-Only, Unprivileged Access: Read-Only */
#else
rasr[14]=0UL;
#endif
/*ACE region*/
rbar[15]=0x44000000UL;
#if defined(S32K388)
/* Size: 1KB, Type: Strongly-ordered, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: Yes, Privileged Access:RW, Unprivileged Access:RW */
rasr[15]=0x13040013UL;
#else
rasr[15]=0UL;
#endif
MCAL_DATA_SYNC_BARRIER();
MCAL_INSTRUCTION_SYNC_BARRIER();
/*Checking if cache is enable before*/
if (((((uint32)1U << (uint32)17U) & S32_SCB->CCR) != (uint32)0) || ((((uint32)1U << (uint32)16U) & S32_SCB->CCR) != (uint32)0))
{
/*synchronize cache before update mpu */
sys_m7_cache_clean();
sys_m7_cache_disable();
}
/* Set default memory regions */
for (index = 0U; index < CPU_MPU_MEMORY_COUNT; index++)
{
if ((rasr[index]&(uint32)0x1) == (uint32)0x1)
{
S32_MPU->RNR = regionNum;
S32_MPU->RBAR = rbar[index];
S32_MPU->RASR = rasr[index];
regionNum++;
}
}
/* Enable MPU, enables the MPU during the HardFault handler */
S32_MPU->CTRL |= (S32_MPU_CTRL_ENABLE_MASK | S32_MPU_CTRL_HFNMIENA_MASK);
MCAL_DATA_SYNC_BARRIER();
MCAL_INSTRUCTION_SYNC_BARRIER();
#endif /* MPU_ENABLE */上述代码主要是对16个region 配置属性最后通过MPU 的寄存器完成配置,跟上述的流程图也是一致。

我们找其中一段ITCM 的配置代码来分析对应的属性配置。
/* ITCM for cortex M7 if no set it as zero */ rbar[1]=(uint32)__INT_ITCM_START; rasr[1]=0x0308001FUL; /* Size: import information from linker symbol, Type: Normal, Inner Cache Policy: None, Outer Cache Policy: None, Shareable: No, Privileged Access:RW, Unprivileged Access:RW */
上述配置代码通过配置 MPU_RBAR 配置TCM 的起始地址为 0,配置MPU_RASR 数值为 0x0308001FUL
对应MPU_RASR 的寄存器定义如下:

解析配置的0x0308001FUL 可知 AP 配置为011 为Full Acess 特权和非特权 均可读写访问。

XN = 0 该区域可以执行代码

SIZE 为b0111 对应的大小为64KB

TEX C B S 为 001 0 0 0 对应的属性为no cache no share

其它Region 的属性配置过程都是一致只是属性配置不同,在此就不再赘述了。
25

