Tricore的上下文堆栈管理

背景说明:
最近在移植HSM的算法后,在产线做27服务的标定处理发现①极高的概率出现第一次标定过的情况;②100%第二次标定不过。

分析:
Ⅰ
因为样本数据不多,检查发现第二次标定有两次都卡在2702的地方,怀疑是上位机诊断仪没有发送报文又或者是流控帧的3E 00 05这个5ms上位机无法满足。

Ⅱ
产线的日志缺少关键信息,于是实车使用Canoe和ZLG去抓取关键报文。

Ⅲ
和网络的同事分析报文的时候发现,HAD出现了规律的重启。通过某些HAD的特殊帧的counter得到确认(数值突然变为0)。

Ⅳ
检查HAD的重启原因,在Mcu_PerformReset函数处断点抓到复位原因。证明是软件逻辑引起的软件复位,而非看门狗等引起的复位。

img_v3_0215v_acc3d963-bf73-4df7-94be-6cad3c55484g

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

img_v3_02168_bfaa8948-e9f8-4194-bceb-676edcaec46g

Ⅵ
增大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 链表指针)
posted @ 2026-10-07 14:37  日暮_途远  阅读(7)  评论(0)    收藏  举报