代码之家  ›  专栏  ›  技术社区  ›  Andrea Biondo

Cortex-M4F惰性FPU堆叠

  •  4
  • Andrea Biondo  · 技术社区  · 9 年前

    我正在为Cortex M4F编写线程代码。一切正常,我现在正在研究通过延迟堆叠使FPU上下文切换更高效。

    我读过ARM的 AN298 我实施了基于禁用FPU和处理UsageFault的替代方法,但( S0-S15 )硬件未正确保存/恢复寄存器。我认为问题在于图11:

    Figure 11 Context switching

    据此,当PendSV运行时 FPCAR 应指向任务A堆栈中保留的空间。但在我看来,因为 CONTROL.FPCA 在任务C中处于高位, FPCAR公司 输入PendSV时,将更新为指向任务C的堆栈。如果是, 2015年4月 FPSCR 将保存到任务C的堆栈而不是任务A的堆栈,这当然是不正确的。

    我是在这里遗漏了什么,还是appnote错了?

    一个附带说明,我检查了一些开源RTOS。FreeRTOS和mbed RTOS总是堆叠 S16-S31 在上下文切换期间,导致自动 2015年4月 堆叠,也就是说,它们只使用延迟堆叠来减少中断延迟,但对任务进行完全状态保存(如appnote中概述的第一种方法)。M4F的TNKernel端口使用UsageFault方法,但可以完全保存/恢复 S0-S31 通过软件,有效地绕过 FPCAR公司 (以48个加载/存储(而不是32个)为代价,16个硬件在恢复时会被覆盖)。似乎没有人使用UsageFault方法,而只保留 S16-S31型 .

    (顺便说一下,这也张贴在 ARM Community

    1 回复  |  直到 9 年前
        1
  •  4
  •   Andrea Biondo    9 年前

    这花了一段时间,但最终我找到了如何尽可能有效地做到这一点。

    FPCAR 更新是正确的。请注意 FPCAR公司 即使FPU被禁用,也会更新。此外,通过测试,我确定 FPCAR公司 确实总是指向中断的堆栈。

    我的第一个方法是操纵 FPCAR公司 , LSPACT EXC_RETURN FPCAR公司 从延迟堆叠的角度来看,操作不算是FPU操作。当缺少文档时,我们只能从CPU中获取答案。。。

    LDR  R2, =0xE000EF38
    LDR  R3, =0xDEADBEEF
    STR  R3, [R2]
    VSTM R1, {S16-S31}
    UDF
    

    FPCAR公司 位于 0xE000EF38 . VSTM 是上下文保存例程的一部分。想法是,如果 FPCAR公司 操作是FPU操作,延迟堆叠将停止 FPCAR公司 FPCAR公司 仍然有效。这将在 UDF 。否则,上会发生延迟堆叠 车辆安全技术手册 带有已损坏的 FPCAR公司 ,导致总线故障。

    事实上,我有一个公共汽车故障。耶!我用一个有效的地址重复了测试:没有错误,工作正常。所以储蓄很简单。还原需要挂起PendSV并进行操作 FPCAR公司 , LSPACT公司 EXC_返回 在里面导致 S0-S15 用于在异常返回时还原当前线程。这里的问题是,您无法保持当前线程在其堆栈上的状态,因为它将被弹出。复制效率很低,所以最好的办法是指向 FPCAR公司 而不是保存CPU生成的TCB状态。

    我最终使用的方法完全在UsageFault中运行,绕过了硬件堆叠,而不会降低效率。启用FPU并确定需要FPU上下文开关后,I:

    1. 设置 LSPACT公司 归零;
    2. 保存/恢复完整 S0-S31 TCB的状态;
    3. 设置 LSPACT公司 回到一个。

    通过这样做,我可以整体工作 S0-S31号 状态没有延迟堆叠,因为CPU认为它已经堆叠了上下文 LSPACT公司 为零。当然,这依赖于UsageFault处理程序在保存/恢复之外不使用FPU操作,也不被FPU使用ISR抢占,这是非常简单的假设,因为它是手工编码的ASM,故障处理程序不能被ISR抢先。我还尝试通过禁用惰性堆叠 ASPEN / LSPEN 而不是工作 LSPACT公司 ,但似乎不起作用(它仍然会触发延迟堆叠,通过设置无效的 FPCAR公司 ).

    就效率而言,这与硬件堆叠一样有效。如果我想挑剔,它可以节省一个周期,因为我不需要写回递增的指针。

    顺便说一句,我包括了第一种方法,尽管我最终没有使用它,因为我认为它有一些有用的信息,如果其他人来找这个的话。