ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【TriCore-OS】SetRelAlarm

【TriCore-OS】SetRelAlarm 文章目录1. SetRelAlarm流程图2. SetRelAlarm整体调用链3. SetRelAlarm状态切换4. SetRelAlarm调用栈5. SetRelAlarm代码逻辑5.1 SetRelAlarm5.2 Os_Alarm_SetRelAlarm5.2.1 Os_Alarm_IntSetRelAlarm5.2.1.1 Os_Counter_InsertExpPoint5.2.1.1.1 Os_Counter_SetExpPoint5.3 Os_Arch_Mach_HrtTimerSetCompareValue6. CancelAlarm整体调用链7. CancelAlarm调用栈8. CancelAlarm代码逻辑8.1 CancelAlarm8.2 Os_Alarm_CancelAlarm8.2.1 Os_Alarm_IntCancel8.2.1.1 Os_Counter_ExpPointDel1. SetRelAlarm流程图2. SetRelAlarm整体调用链3. SetRelAlarm状态切换Alarm 状态机 4. SetRelAlarm调用栈5. SetRelAlarm代码逻辑5.1 SetRelAlarmStatusTypeSetRelAlarm(AlarmType AlarmID,TickType Increment,TickType Cycle){StatusType ret;#if(OS_MEMORY_PROTECTIONSTD_ON)Os_SysCallParamType sysCallParam;sysCallParam.Os_SetRelAlarm.alarmIdAlarmID;sysCallParam.Os_SetRelAlarm.incrementIncrement;sysCallParam.Os_SetRelAlarm.cycleCycle;Os_SysCall(Os_Syscall_SetRelAlarm_ID,sysCallParam);/* 走 SysCall trap. */retsysCallParam.Os_SetRelAlarm.retVal;#elseretOs_Alarm_SetRelAlarm(AlarmID,Increment,Cycle);/* 直接调用*/#endifreturnret;}5.2 Os_Alarm_SetRelAlarmOs_StatusTypeOs_Alarm_SetRelAlarm(alarmId,increment,cycle){/* 第 1 阶段参数和上下文检查 */coreIdOs_Core_GetLogicId();if(alarmIdOS_ALARMID_COUNT)returnE_OS_ID;// ① ID 范围if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ② 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_SETRELALARM_ACCESS))returnE_OS_CALLEVEL;// ③ 调用上下文alarmCfgOS_ALARM_GETCFG(alarmId);if(OS_APPMATCH(alarmCfg-accessingApps,OS_CORE_GETAPPID(coreId)))returnE_OS_ACCESS;// ④ Permission/* 第 2 阶段多核路由 */#ifMULTI_COREif(coreId!OS_ALARM_GETCOREID(alarmCfg)){// 跨核消息转发到目标核Os_MultiCore_Trigger(TRUE,coreId,OS_ALARM_GETCOREID(alarmCfg),Os_MCServe_SetRelAlarm_ID,parameter);return;}#endif/* 第 3 阶段状态和参数检查 */if(OS_APP_STATEOFF(alarmCfg-ownerAppId))returnE_OS_ACCESS;// ⑤ Accessibilityif(OS_ALARM_SETalarmDyn-state)returnE_OS_STATE;// ⑥ 已设置if(OS_ZERO_VALUEincrement)returnE_OS_VALUE;// ⑦ increment0if(OS_COUNTER_CHECKINVALIDVALUE(alarmCfg-counter,increment,cycle))returnE_OS_VALUE;// ⑧ 范围检查/* 第 4 阶段禁中断临界区 */Os_Arch_IntDisable(intState);/* 第 5 阶段激活 Alarm核心 */retOs_Alarm_IntSetRelAlarm(alarmDyn,increment,cycle);/* 第 6 阶段开中断 */Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_SetRelAlarm,ret);}5.2.1 Os_Alarm_IntSetRelAlarmOs_Alarm_IntSetRelAlarm(alarmDyn,increment,cycle){if(alarmDyn!NULL_PTR){alarmDyn-stateOS_ALARM_SET;// ① 状态机OFF → SETalarmDyn-cyclecycle;// ② 保存周期值供到期后重插入retOs_Counter_InsertExpPoint(alarmDyn-counter,alarmDyn-expNode,increment);// ③ 插入过期点到 Counter}}5.2.1.1 Os_Counter_InsertExpPointOs_Counter_InsertExpPoint(counterBase,expListNode,increment){if(counterBase!NULL_PTR){valueOs_Counter_GetCntValue(counterBase);// ① 读当前 Counter 值Os_Counter_SetExpPoint(counterBase,value,increment,expListNode);// ② 计算时间戳 入队}}与 SetAbsAlarm 的差异 SetRelAlarm diff increment 相对值SetAbsAlarm diff start - value 绝对值转相对值5.2.1.1.1 Os_Counter_SetExpPointOs_Counter_SetExpPoint(counterBase,start,offset,expListNode){cntExpListHeadcounterBase-Os_CntExpList;/* 双队列选择处理 Counter 回绕 */if((counterBase-maxAllowValue-start)offset){// 不回绕过期点在当前周期内cntExpListCntcntExpListHead-cntExplistMux;// 用当前队列setExpTimebase(startoffset);// 时间戳 当前值 偏移ifCheakTRUE;}else{// 回绕过期点在下一周期cntExpListCnt(cntExpListHead-cntExplistMux1)OS_COUNTER_EXPLISTMAX;setExpTimebaseoffset-(counterBase-maxAllowValue-start1);ifCheakFALSE;}/* 设置过期点时间戳 */expListNode-expTimestamp.timebasesetExpTimebase;/* 入优先队列 */Os_PriQueue_PUSH(cntExpListHead-cntExpList[cntExpListCnt],(Os_PriQueueNodeType*)expListNode);/* 若是 HRT更新 STM 比较值 */if(OS_COUNTER_HRTcounterBase-counterType){cntDynOS_COUNTER_GETDYN(counterBase);if(OS_COUNTER_INITcntDyn-value){// 情况 ACMP0 未设置第一次设置retOs_Counter_GetQueueData(cntExpListHead,expTimebase);if(ret!E_OS_BUFFEMPTY){cntDyn-valueexpTimebase;// 取队头时间戳setCmpTRUE;}}elseif(ifCheakcntDyn-valuesetExpTimebase){// 情况 B新过期点比当前 CMP0 更早cntDyn-valuesetExpTimebase;// 更新为更早的时间戳setCmpTRUE;}if(TRUEsetCmp){Os_Counter_HrtSetCompareValue(counterBase,cntDyn-value);// ← 写 STM CMP0 寄存器}}}双队列环绕机制当Counter maxAllowValue 100不回绕offset 在当前周期内当前 Counter 30, offset 50maxAllowValue(100) - 30 70 50cntExpListCnt mux (当前队列)setExpTimebase 30 50 80回绕offset 超出当前周期当前 Counter 80, offset 50maxAllowValue(100) - 80 20 50cntExpListCnt (mux 1) 0x1 (下一队列)setExpTimebase 50 - (100 - 80 1) 50 - 21 29(下一周期的 29)5.3 Os_Arch_Mach_HrtTimerSetCompareValueOs_Arch_Mach_HrtTimerSetCompareValue(hrtCfg,value){*(volatileuint32*)(hrtCfg-ModulelCmpRegAddr)value;// 写 STM CMP0 寄存器}6. CancelAlarm整体调用链7. CancelAlarm调用栈8. CancelAlarm代码逻辑8.1 CancelAlarmOs_StatusTypeCancelAlarm(AlarmType AlarmID){#if(OS_MEMORY_PROTECTIONSTD_ON)Os_SysCallParamType sysCallParam;sysCallParam.Os_CancelAlarm.alarmIdAlarmID;Os_SysCall(Os_Syscall_CancelAlarm_ID,sysCallParam);// 走 SysCall trapretsysCallParam.Os_CancelAlarm.retVal;#elseretOs_Alarm_CancelAlarm(AlarmID);// 直接调用#endif}8.2 Os_Alarm_CancelAlarmOs_StatusTypeOs_Alarm_CancelAlarm(AlarmType alarmId){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_CancelAlarm);coreIdOs_Core_GetLogicId();/* 第 1 阶段参数和上下文检查 */if(alarmIdOS_ALARMID_COUNT)returnE_OS_ID;// ① ID 范围if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ② 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_CANCELALARM_ACCESS))returnE_OS_CALLEVEL;// ③ 调用上下文alarmCfgOS_ALARM_GETCFG(alarmId);if(OS_APPMATCH(alarmCfg-accessingApps,OS_CORE_GETAPPID(coreId)))returnE_OS_ACCESS;// ④ Permission/* 第 2 阶段多核路由 */#ifMULTI_COREif(coreId!OS_ALARM_GETCOREID(alarmCfg)){// 跨核消息转发到目标核Os_MultiCore_Trigger(TRUE,coreId,OS_ALARM_GETCOREID(alarmCfg),Os_MCServe_CancelAlarm_ID,parameter);return;}#endif/* 第 3 阶段状态检查 */if(OS_APP_STATEOFF(alarmCfg-ownerAppId))returnE_OS_ACCESS;// ⑤ Accessibilityif(OS_ALARM_SET!alarmDyn-state)returnE_OS_NOFUNC;// ⑥ 必须是 SET 状态/* 第 4 阶段禁中断临界区 */Os_Arch_IntDisable(intState);/* 第 5 阶段取消 Alarm核心 */Os_Alarm_IntCancel(alarmDyn);/* 第 6 阶段开中断 */Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_CancelAlarm,ret);}8.2.1 Os_Alarm_IntCancelOs_Alarm_IntCancel(alarmDyn){if(alarmDyn!NULL_PTR){alarmDyn-stateOS_ALARM_OFF;// ① 状态机SET → OFFalarmDyn-cycleOS_ALARM_INIT;// ② 清除周期值防止下次误重插入(void)Os_Counter_ExpPointDel(alarmDyn-counter,alarmDyn-expNode);// ③ 从优先队列删除过期点}}8.2.1.1 Os_Counter_ExpPointDelOs_Counter_ExpPointDel(counterBase,expListNode){cntExpListHeadcounterBase-Os_CntExpList;cntExpListCntcntExpListHead-cntExplistMux;// ① 先查当前队列retOs_PriQueue_Del(cntExpListHead-cntExpList[cntExpListCnt],(Os_PriQueueNodeType*)expListNode);// ② 尝试删除if((E_OS_NODATAret)||(E_OS_BUFFEMPTYret)){// ③ 当前队列没找到查另一队列回绕情况cntExpListCnt(cntExpListHead-cntExplistMux1)OS_COUNTER_EXPLISTMAX;if(E_OS_NODATAOs_PriQueue_Del(cntExpListHead-cntExpList[cntExpListCnt],(Os_PriQueueNodeType*)expListNode)){retE_OS_NODATA;// ④ 两个队列都没有}}returnret;}双队列删除逻辑Counter 双队列结构:cntExpList[0] 当前周期队列 (mux0)cntExpList[1] 下一周期队列 (mux1)删除过期点时:先在 cntExpList[mux] 查找并删除若没找到 (NODATA/EMPTY)在 cntExpList[(mux1)0x1] 查找若都没找到返回 E_OS_NODATACancelAlarm 不更新 CMP0 的原因取消的过期点不是队头CMP0 对应的过期点CMP0 仍指向队头过期点不需要更新Counter 到期时 OS_HRT ISR 正常触发取消的过期点恰好是队头CMP0 对应的过期点CMP0 已经过时指向已删除的节点但 Counter 继续计数当 TIM0 CMP0 时仍会触发中断OS_HRT ISR 中弹出过期点时发现队列空或节点已删除会调用 Os_Counter_SetNextPoint 重新设置下一个过期点双队列删除的潜在问题取消过期点时Alarm1 的过期点在队头CMP0 仍指向 Alarm1 的时间戳Counter 继续计数…Counter 到达 CMP0 触发 OS_HRT ISRISR 弹出过期点 发现是已删除的 Alarm1队列可能空了调用 Os_Counter_SetNextPoint 取下一个过期点若无过期点CMP0 保持可能等到下次 SetRelAlarm 时重设。
返回列表