MPU 栈对象

线程栈创建

线程栈使用 K_THREAD_STACK_DEFINE() 静态声明。

对于使用内存保护单元(MPU)硬件的架构,栈通过物理连续的内存分配实现。连续分配会影响栈在内存中的放置,以及栈保护、用户空间等其他功能的实现。对放置的影响直接源于 MPU 区域的对齐要求,下文的内存放置一节将对此进行讨论。

栈保护区

栈保护机制需要能够限制内存访问的硬件支持。内存保护单元可以提供这种支持。MPU 提供固定数量的区域,每个区域包含起始地址、结束地址、大小以及在该区域强制执行的访问属性等信息。

栈保护区使用一个 MPU 区域实现,并将该区域的属性设置为禁止写入。发生无效访问时会触发故障。栈保护区定义在栈的底部(最低地址处)。

内存放置

创建栈时,会对内存分配施加一组约束,包括确定栈的对齐方式和正确大小。链接二进制文件时,会使用这些约束来正确放置栈。

内存约束主要来源于 SoC 的 MPU 设计。MPU 设计可能对区域定义施加特定约束,包括起始地址和结束地址的对齐、分配大小,甚至重叠区域之间的相互影响。

有些 MPU 要求每个区域按 2 的幂对齐。这些 SoC 会定义 CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT。这意味着一个 1500 字节的栈应按 2kB 边界对齐,栈大小也应调整为 2kB,以确保该区域的剩余空间不会放置其他内容。包含未经修改的 ARM v7m MPU 的 SoC 就有这些约束。

有些 ARM MPU 使用起始地址和结束地址定义 MPU 区域,且两者都要求按 32 字节对齐。NXP FRDM K64F 中的 MPU 就属于这一类。

MPU 可能具有区域优先级机制,使用覆盖所访问内存的最高优先级区域来确定强制执行的策略。另一些 MPU 则可能对各区域进行逻辑或运算,以确定策略。

大小和对齐约束可能导致实际分配的栈大于请求大小。区域优先级机制可能增加栈保护区实现的复杂度。