Tricore的上下文堆栈管理
背景说明:
最近在移植HSM的算法后,在产线做27服务的标定处理发现①极高的概率出现第一次标定过的情况;②100%第二次标定不过。
分析:
Ⅰ
因为样本数据不多,检查发现第二次标定有两次都卡在2702的地方,怀疑是上位机诊断仪没有发送报文又或者是流控帧的3E 00 05这个5ms上位机无法满足。
Ⅱ
产线的日志缺少关键信息,于是实车使用Canoe和ZLG去抓取关键报文。
Ⅲ
和网络的同事分析报文的时候发现,HAD出现了规律的重启。通过某些HAD的特殊帧的counter得到确认(数值突然变为0)。
Ⅳ
检查HAD的重启原因,在Mcu_PerformReset函数处断点抓到复位原因。证明是软件逻辑引起的软件复位,而非看门狗等引起的复位。

Ⅴ
检查出现报错时的栈区发现Error = 13,这说明软件发生了栈溢出并且溢出发生在ctx部分。

Ⅵ
增大ctx后产线测试通过。
总结:
1.英飞凌TriCore(AURIX TC39x)与普通ARM/x86芯片最大的不同在于:它有硬件级双堆栈!
①sp(普通数据栈):放函数局部变量和数组,配置是2048B,实际使用208B
②ctx(上下文栈/CSA-Context Save Area):在TriCore芯片上,函数的返回地址(PC)和通用寄存器根本不压在SP栈上,而是由硬件自动分配专门的CSA(每个CSA固定64字节)
2.一共18个ctx超过了设置的1024B
Os_Dispatch0() → 任务切换调度(消耗 1 个)
Os_Entry_Bsw_Task_10ms() → 任务入口(消耗 1 个)
Dcm_MainFunction() → 诊断主函数(消耗 1 个)
Dcm_Prv_DsdStateMachine() → 状态机(消耗 1 个)
Dcm_DcmSecurityAccess() → 27服务入口(消耗 1 个)
Dcm_Prv_ProcessKeyApplication() → 秘钥处理(消耗 1 个)
DEME_SecurityLevel_1_CompareKey() → 秘钥比对(消耗 1 个)
Board_AES_CMAC_Verify() → CMAC校验(消耗 1 个)
Board_AES_CMAC_ComputeKey() → 计算Key(消耗 1 个)
CryptoHSM_UpdateMacGenerate_AES_CMAC() → HSM接口(消耗 1 个)
ecy_hsm_Csai_MacGenerateUpdate() → CSAI接口(消耗 1 个)
Applet_Function() → Applet调度(消耗 1 个)
ecy_hsm_OpRequest_NoJobHandle() → 异步请求(消耗 1 个)
LoadOp() → 加载操作(消耗 1 个)
PrvGetElapsedCounterValue() → 定时器读取(消耗 1 个)
__ll_div64(asm) → 64位除法汇编(消耗 1 个)到这里,静态函数调用链已经整整占了16个CSA!
-> exception:此时恰好CAN接收中断或定时器中断打断(硬件再分配 1 个 Lower CSA)
Os_ISRWrapper0:中断处理程序入口(再分配 1 个 Upper CSA)
3.第一次一般能过是因为第一次调用HSM,里面的熵值无需要做更新,时间较快,中断不易于最深处DIV处发生。第二次则因为硬件熵值更新需要的时间较多更易触发底层的中断。当然没有实际测量时间的差异,这个更多的是一个推论。
| 对比项 | Lower CSA(低位上下文) | Upper CSA(高位上下文) |
|---|---|---|
| 大小 | 64 字节 | 64 字节 |
| 保存的数据寄存器 | D0 ~ D7(8 个,32 字节) | D8 ~ D15(8 个,32 字节) |
| 保存的地址寄存器 | A2 ~ A7(6 个,24 字节) | A12 ~ A15(4 个,16 字节) |
| 保存的关键状态寄存器 | • A11(中断断点返回地址 PC)• PCXI(前一个 CSA 链表指针) | • A10(当前堆栈指针 SP!)• A11(函数返回地址 RA)• PSW(CPU 状态与标志位)• PCXI(前一个 CSA 链表指针) |

浙公网安备 33010602011771号