这花了一段时间,但最终我找到了如何尽可能有效地做到这一点。
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:
-
设置
LSPACT公司
归零;
-
保存/恢复完整
S0-S31
TCB的状态;
-
设置
LSPACT公司
回到一个。
通过这样做,我可以整体工作
S0-S31号
状态没有延迟堆叠,因为CPU认为它已经堆叠了上下文
LSPACT公司
为零。当然,这依赖于UsageFault处理程序在保存/恢复之外不使用FPU操作,也不被FPU使用ISR抢占,这是非常简单的假设,因为它是手工编码的ASM,故障处理程序不能被ISR抢先。我还尝试通过禁用惰性堆叠
ASPEN
/
LSPEN
而不是工作
LSPACT公司
,但似乎不起作用(它仍然会触发延迟堆叠,通过设置无效的
FPCAR公司
).
就效率而言,这与硬件堆叠一样有效。如果我想挑剔,它可以节省一个周期,因为我不需要写回递增的指针。
顺便说一句,我包括了第一种方法,尽管我最终没有使用它,因为我认为它有一些有用的信息,如果其他人来找这个的话。