【简介】
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 的属性配置过程都是一致只是属性配置不同,在此就不再赘述了。