在该配置下,要求同一个 section 的 code / data 放在连续的地址空间;
若实际硬件上有多块不连续的 flash 或 sram,则需要控制链接文件让相同 section 的数据位于连续空间;
若实在无法满足上述约束,则需要改造 FreeRTOS 的 MPU 配置(可能需要减少用户自定义 Region 数量)。
系统调用方式
在 MPU 开启后,kernel api 处于 privileged section, unprivilege task 会被MPU屏蔽而无权直接访问;
FreeRTOS 提供了 wrapper 层,用于间接调用 kernel api,其命名为 MPU_xxx(xxx 是 kernel api 名称)。
为了确保兼容性,减少用户调用的复杂性,FreeRTOS 还通过 mpu_wrapper.h 将 xxx 映射为 MPU_xxx。
系统调用目前有2个版本,分为 mpu_v1 和 mpu_v2。
1、MPU V1
mpu_v1 的工作流程如下:
可以看到,task 需要先调用 wrapper 层的接口 MPU_xxx,再由 wrapper 层调用 kernel api;
在 mpu_wrapper 中,会对 task 的权限做检查:
2、MPU V2
mpu_v2 的工作流程如下:
与 mpu_v1 相比,mpu_v2 有如下改动:
根据讨论,这么做的主要目的是为了防止泄露信息给 unprivileged task.
四、MPU 对 FreeRTOS 的其他影响pxTopOfStack 的变化
pxTopOfStack 是 TCB 中的首个成员,主要用于任务切换时记录栈的位置。
在未开启 MPU 时,pxTopOfStack 直接指向任务栈,cpu 上下文信息存储在任务栈上;
在开启 MPU 后,pxTopOfStack 指向 TCB 中的 ulContent 区域,cpu 上下文信息存储在 ulContent 中,而任务的栈指针则存储在 ulContent 中。