
文章目录1. Event 是什么1.1 核心特征1.2 基本任务 vs 扩展任务1.3 Event的4个核心API1.4 两个核心位掩码2. SetEvent2.1 SetEvent流程图2.2 SetEvent调用层级2.3 SetEvent状态切换扩展任务2.4 SetEvent调用栈2.5 SetEvent2.5.1 Os_Event_SetEvent2.5.1.1 Os_Event_SetEventSimp2.5.1.2 Os_Task_SetEvent3. WaitEvent3.1 WaitEvent流程图3.2 WaitEvent调用层级3.3 WaitEvent状态切换3.4 WaitEvent 完整时序图3.5 WaitEvent3.5.1 Os_Event_WaitEvent3.5.2 Os_Task_WaitEvent4. ClearEvent4.1 ClearEvent流程图4.2 ClearEvent调用层级4.3 ClearEvent状态切换4.4 ClearEvent完整时序图4.5 Os_Event_ClearEvent5. GetEvent5.1 GetEvent流程图5.2 GetEvent调用层级5.3 GetEvent状态切换5.4 GetEvent完整时序图5.5 Os_Event_GetEvent5.5.1 Os_Event_GetEventSimp6. 完整同步闭环时序图1. Event 是什么Event事件是 AUTOSAR OS 提供的轻量级任务间同步机制用于一个任务等待某个条件成立另一个任务通知该条件已成立。1.1 核心特征特征说明本质位掩码EventMaskType通常为 uint32归属只能绑定到扩展任务Extended Task方向单向SetEvent 通知WaitEvent 等待容量每个任务最多 32 个独立事件bit0~bit31持久性触发后保持直到 ClearEvent 清除不计数多次 SetEvent 同一事件等同于一次1.2 基本任务 vs 扩展任务维度基础任务(Basic Task)扩展任务(Extended Task)WaitEvent不能调用可以调用TCB字段无 eventWait/eventTrigger有 eventWait/eventTrigger状态机RUNNING-READY/SUSPENDED多了WAITING状态使用场景周期性工作、无阻塞事件驱动、需等待外部条件1.3 Event的4个核心APIAPI作用调用者SetEvent(taskId, mask)设置目标任务的事件触发位任意 Task/ISR2WaitEvent(mask)等待事件触发可能阻塞仅扩展任务ClearEvent(mask)清除自己的事件触发位仅扩展任务自己GetEvent(taskId, mask)查询目标任务的事件状态任意 Task/ISR21.4 两个核心位掩码每个扩展任务的 TCB 中有两个关键字段structOs_TaskDynType{...EventMaskType eventWait;// 等待掩码WaitEvent 时设置EventMaskType eventTrigger;// 触发掩码SetEvent 时设置...};2. SetEvent2.1 SetEvent流程图2.2 SetEvent调用层级2.3 SetEvent状态切换扩展任务2.4 SetEvent调用栈任务 B 运行中,任务 A 在WAITING(等待 MASK_X)│ │SetEvent(TaskA,MASK_X)│ ┌────────────────────────────────────────────────────┐ │ │ Os_Event_SetEvent │ │ │ ├─ ① taskId 范围检查 │ │ │ ├─ ② 中断禁用检查 │ │ │ ├─ ③ 调用上下文检查 │ │ │ ├─ ④ Permission 检查accessingApps 位掩码 │ │ │ ├─ ⑤ 必须是扩展任务检查 │ │ │ ├─ ⑥ Accessibility 检查App 状态 │ │ │ ├─ ⑦ 目标任务非 SUSPENDED 检查 │ │ │ ├─Os_Arch_IntDisable()│ │ │ ├─ eventWaitingGETEVENTWAIT(A)│ ← 先读旧值 │ │ ├─Os_Event_SetEventSimp(A,MASK_X)│ │ │ │ └─ A.eventTrigger|MASK_X │ ← 设置触发位 │ │ ├─ 判断:A.stateWAITING 且(eventWaitingMASK_X)!0│ │ │ → 命中唤醒条件 │ │ │ └─Os_Task_SetEvent(A)│ │ │ ├─ A.state:WAITING → READY │ │ │ ├─Os_Schedler_InsertTask(A)│ │ │ │ ├─TaskQue_Push(queues[A.prio],A)│ ← 入队尾 │ │ │ └─BitMap_Set(A.prio)│ ← 位图置位 │ │ └─ NeedSchedle?A.priocurrentPrio?│ │ │ ├─ Yes → SchedleTaskSwitch(B,A)│ │ │ │ ├─SVLCX(保存 B)│ │ │ │ ├─ PCXIA.runCSA │ │ │ │ ├─RSLCX(恢复 A)│ │ │ │ └─RFE(跳到 A)│ │ │ └─ No → B 继续运行 │ │ └────────────────────────────────────────────────────┘ │ ▼(若 A 优先级更高,A 恢复运行;否则 B 继续)2.5 SetEventSetEvent(TaskType TaskID,EventMaskType Mask){#if(OS_MEMORY_PROTECTIONSTD_ON)Os_SysCallParamType sysCallParam;sysCallParam.Os_SetEvent.taskIdTaskID;sysCallParam.Os_SetEvent.maskMask;Os_SysCall(Os_Syscall_SetEvent_ID,sysCallParam);// 走 SysCall trapretsysCallParam.Os_SetEvent.retVal;#elseretOs_Event_SetEvent(TaskID,Mask);// 直接调用#endif}2.5.1 Os_Event_SetEventOs_Event_SetEvent(TaskType taskId,EventMaskType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_SetEvent);coreIdOs_Core_GetLogicId();/* 第 1 阶段参数和上下文检查 */if(OS_TASK_ISINVAILD(taskId))returnE_OS_ID;// ① ID 范围if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ② 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_SETEVENT_ACCESS))returnE_OS_CALLEVEL;// ③ 调用上下文taskCfgOS_TASK_GETCFG(taskId);if(OS_APPMATCH(taskCfg-accessingApps,OS_CORE_GETAPPID(coreId)))returnE_OS_ACCESS;// ④ Permission/* 第 2 阶段多核路由 */#ifMULTI_COREif(coreId!OS_TASK_GETCOREID(taskCfg)){// 跨核消息转发到目标核Os_MultiCore_Trigger(TRUE,coreId,OS_TASK_GETCOREID(taskCfg),Os_MCServe_SetEvent_ID,parameter);return;}#endif/* 第 3 阶段状态检查 */if(OS_TASK_ISBASIC(taskCfg))returnE_OS_ACCESS;// ⑤ 必须是扩展任务if(OS_APP_STATEOFF(taskCfg-ownerAppId))returnE_OS_ACCESS;// ⑥ Accessibilityif(OS_TASK_CHECKISSUSPENDED(taskCfg))returnE_OS_STATE;// ⑦ 目标不能 SUSPENDED/* 第 4 阶段禁中断临界区 */Os_Arch_IntDisable(intState);/* 第 5 阶段设置事件触发位 */eventWaitingOS_TASK_GETEVENTWAIT(taskCfg);// 先读旧值防 raceretOs_Event_SetEventSimp(taskCfg,mask);// 设置 trigger/* 第 6 阶段唤醒判断 */if(E_OS_OKret){if((WAITINGOS_TASK_GETTASKSTATE(taskCfg))(OS_ZERO_VALUE!(eventWaitingmask))){retOs_Task_SetEvent(taskCfg);// 唤醒可能切换}}Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_SetEvent,ret);}2.5.1.1 Os_Event_SetEventSimpOs_Event_SetEventSimp(task,mask){if(OS_APP_STATEOFF(task-ownerAppId))returnE_OS_ACCESS;eventTriggerOS_TASK_GETEVENTTRIGGER(task);eventTrigger|mask;// 按位或OS_TASK_SETEVENTTRIGGER(task,eventTrigger);// 写回returnE_OS_OK;}2.5.1.2 Os_Task_SetEventOs_Task_SetEvent(taskCfg){if(taskCfg!NULL_PTR){currentCoreIdtaskCfg-coreId;/* 1. 状态转换 入队 */if(WAITINGtaskCfg-taskDyn-state){taskCfg-taskDyn-stateREADY;// WAITING → READYretOs_Schedler_InsertTask(scheduler,taskCfg-taskDyn);// ↑ 入队 位图置位}/* 2. 判断是否切换 */if(OS_CORE_GETALLOWSCH(currentCoreId)// 调度允许OS_CORE_CHECKCURRENTINTASK(currentCoreId))// 在任务上下文{if(Os_Schedler_NeedSchedle(scheduler)){// 唤醒的优先级更高nextDynOs_Schedler_Schedle(scheduler);retOs_Task_TaskSwitch(currentTaskCfg,nextTaskCfg);}}}}3. WaitEvent3.1 WaitEvent流程图3.2 WaitEvent调用层级3.3 WaitEvent状态切换NA.3.4 WaitEvent 完整时序图任务A(扩展任务)运行中(RUNNING)│ │WaitEvent(MASK_X)│ ┌────────────────────────────────────────────────────┐ │ │ Os_Event_WaitEvent │ │ │ ├─ ① 中断禁用检查 │ │ │ ├─ ② 调用上下文检查 │ │ │ ├─ ③ Permission 检查 │ │ │ ├─ ④ Resource 占用检查不能持有 │ │ │ ├─ ⑤ Spinlock 占用检查不能持有 │ │ │ ├─ ⑥ 必须是扩展任务检查 │ │ │ ├─Os_Arch_IntDisable()│ │ │ ├─ A.eventWaitMASK_X(设置等待掩码)│ │ │ ├─ waitTrigger(eventWaiteventTrigger)│ │ │ ├─ 判断:waitTrigger!0?│ │ │ │ ├─Yes(事件已触发):│ │ │ │ │ └─ 快路径:时序保护检查,直接返回 │ │ │ │ │(不阻塞,任务继续运行)│ │ │ │ └─No(事件未触发):│ │ │ │ └─ 慢路径:Os_Task_WaitEvent(A)│ │ │ │ ├─Os_Schedler_DeleteTask(A)│ │ │ │ │ ├─ TaskQue_Pop/Del(A)│ ← 出队 │ │ │ │ └─BitMap_Clear(A.prio)│ ← 清位图 │ │ │ ├─Os_Schedler_Schedle()│ │ │ │ │ ├─BitMap_CountLeadZeros()│ │ │ │ │ └─TaskQue_Get()→ nextTask │ │ │ │ └─Os_Task_TaskSwitch(A,next)│ │ │ │ ├─PostTaskHook(A)│ │ │ │ ├─ A.stateWAITING │ │ │ │ ├─SetNextTaskData(next)│ │ │ │ │ ├─ next.stateRUNNING │ │ │ │ │ └─PreTaskHook(next)│ │ │ │ └─ Os_Arch_Context_Switch │ │ │ │ ├─SVLCX(保存 A)│ │ │ │ ├─ PCXInext.runCSA │ │ │ │ ├─RSLCX(恢复 next)│ │ │ │ └─RFE(跳到 next)│ │ │ └─Os_Arch_IntEnable()│ │ └────────────────────────────────────────────────────┘ │ ▼(若事件未触发,A 阻塞,nextTask 运行)(若事件已触发,A 继续运行)3.5 WaitEventWaitEvent(EventMaskType Mask){#if(OS_MEMORY_PROTECTIONSTD_ON)Os_SysCallParamType sysCallParam;sysCallParam.Os_WaitEvent.maskMask;Os_SysCall(Os_Syscall_WaitEvent_ID,sysCallParam);// 走 SysCall trapretsysCallParam.Os_WaitEvent.retVal;#elseretOs_Event_WaitEvent(Mask);// 直接调用#endif}3.5.1 Os_Event_WaitEventOs_Event_WaitEvent(EventMaskType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_WaitEvent);coreIdOs_Core_GetLogicId();/* 第 1 阶段参数和上下文检查 */if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ① 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_WAITEVENT_ACCESS))returnE_OS_CALLEVEL;// ② 调用上下文taskCfgOS_TASK_GETCFG(OS_CORE_GETCURRENTTASKID(coreId));// 操作自己if(OS_APPMATCH(taskCfg-accessingApps,OS_CORE_GETAPPID(coreId)))returnE_OS_ACCESS;// ③ Permissionif(OS_TASK_MASK_RESOURCE(taskCfg))returnE_OS_RESOURCE;// ④ 不能持有 Resourceif(OS_TASK_MASK_SPINLOCK(taskCfg))returnE_OS_SPINLOCK;// ⑤ 不能持有 Spinlockif(OS_TASK_ISBASIC(taskCfg))returnE_OS_ACCESS;// ⑥ 必须是扩展任务/* 第 2 阶段禁中断临界区 */Os_Arch_IntDisable(intState);/* 第 3 阶段设置等待掩码 */OS_TASK_SETEVENTWAIT(taskCfg,mask);// eventWait maskwaitOS_TASK_GETEVENTWAIT(taskCfg);triggerOS_TASK_GETEVENTTRIGGER(taskCfg);waitTrigger(waittrigger);// 关键判断/* 第 4 阶段快慢路径分支 */if(OS_EVENT_TRIGGER_INIT!waitTrigger)// ① 事件已触发快路径{// 不阻塞直接返回// 时序保护检查 frame interval 重置 budgetOs_Tp_CheckFrameInterval(taskCfg-tpCfg);Os_Tp_ResetCurrentBudget(taskCfg-tpCfg,coreId);Os_Tp_StartNextBudget(taskCfg-tpCfg,coreId);}else// ② 事件未触发慢路径{retOs_Task_WaitEvent(taskCfg);// 真正的挂起切换}Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_WaitEvent,ret);}Note.1快慢路径设计WaitEvent 特有如果事件已经触发先 SetEvent 后 WaitEvent任务不会被挂起避免无谓的上下文切换。Note.2为什么 WaitEvent 要检查 Resource/Spinlock防止死锁.任务A:GetResource(R1)→WaitEvent(MASK_X)(A 持锁阻塞)任务B:想要SetEvent(A,MASK_X)但需要 R1 → 死锁持锁任务阻塞后无法释放资源其他等资源的任务也全部阻塞 → 死锁。3.5.2 Os_Task_WaitEventOs_Task_WaitEvent(taskCfg){if(taskCfg!NULL_PTR){/* 1. 从就绪队列移除出队清位图 */Os_Schedler_DeleteTask(scheduler,taskCfg-taskDyn);// 时序保护重置 budgetOs_Tp_ResetCurrentBudget(taskCfg-tpCfg,coreId);/* 2. 选下一个任务 */nextDynOs_Schedler_Schedle(scheduler);/* 3. 切换 */retOs_Task_TaskSwitch(taskCfg,OS_TASK_GETCFG(nextDyn-taskId));}}4. ClearEvent4.1 ClearEvent流程图4.2 ClearEvent调用层级4.3 ClearEvent状态切换NA.4.4 ClearEvent完整时序图NA.4.5 Os_Event_ClearEventOs_Event_ClearEvent(EventMaskType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_ClearEvent);coreIdOs_Core_GetLogicId();/* 第 1 阶段上下文检查只有 2 道 */if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ① 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_CLEAREVENT_ACCESS))returnE_OS_CALLEVEL;// ② 调用上下文taskCfgOS_TASK_GETCFG(OS_CORE_GETCURRENTTASKID(coreId));// 操作自己if(OS_TASK_ISBASIC(taskCfg))returnE_OS_ACCESS;// ③ 必须是扩展任务/* 第 2 阶段禁中断临界区 */Os_Arch_IntDisable(intState);/* 第 3 阶段清除事件触发位 */OS_TASK_GETEVENTTRIGGER(taskCfg)(~mask);// 核心操作/* 第 4 阶段开中断 */Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_ClearEvent,ret);}5. GetEvent5.1 GetEvent流程图5.2 GetEvent调用层级5.3 GetEvent状态切换NA.5.4 GetEvent完整时序图NA.5.5 Os_Event_GetEventOs_Event_GetEvent(TaskType taskId,EventMaskRefType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_GetEvent);coreIdOs_Core_GetLogicId();/* 第 1 阶段参数和上下文检查6 道 */if(OS_TASK_ISINVAILD(taskId))returnE_OS_ID;// ① ID 范围if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ② 中断禁用if(NULL_PTRmask)returnE_OS_PARAM_POINTER;// ③ 空指针if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_GETEVENT_ACCESS))returnE_OS_CALLEVEL;// ④ 调用上下文taskCfgOS_TASK_GETCFG(taskId);if(OS_APPMATCH(taskCfg-accessingApps,OS_CORE_GETAPPID(coreId)))returnE_OS_ACCESS;// ⑤ Permissionif(OS_TASK_ISBASIC(taskCfg))returnE_OS_ACCESS;// ⑥ 目标必须是扩展任务if(OS_APP_STATEOFF(taskCfg-ownerAppId))returnE_OS_ACCESS;// ⑦ Accessibilityif(OS_TASK_CHECKISSUSPENDED(taskCfg))returnE_OS_STATE;// ⑧ 目标不能 SUSPENDED/* 第 2 阶段禁中断临界区 */Os_Arch_IntDisable(intState);/* 第 3 阶段读取事件触发位 */Os_Event_GetEventSimp(taskCfg,mask);// 核心操作/* 第 4 阶段开中断 */Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_GetEvent,ret);}5.5.1 Os_Event_GetEventSimpOs_Event_GetEventSimp(task,mask){(*mask)OS_TASK_GETEVENTTRIGGER(task);// 直接读取 eventTrigger}6. 完整同步闭环时序图任务A(扩展,prio5)任务B(prio3,更高)│ │ │1.WaitEvent(MASK_X)│ │ eventWaitMASK_X │ │ waitTrigger0(未触发)│ │ A.stateWAITING │ │DeleteTask(A)(出队清位图)│ │ Schedle → B │ │TaskSwitch(A,B)│ │ SVLCX │ │ PCXIB.runCSA │ │ RSLCX │ │ RFE → B │ │ ▼ 任务B 运行 │(A 阻塞,不消耗 CPU)│ │ │ │ │2.SetEvent(TaskA,MASK_X)│ │ eventTrigger|MASK_X │ │ A.stateWAITING 且 │ │(A.eventWaitMASK_X)!0│ │ →Os_Task_SetEvent(A)│ │ A.stateREADY │ │InsertTask(A)(入队置位图)│ │ NeedSchedle?A.prio(5)B.prio(3)│ │ → 不切换B 继续运行 │ ▼ │ │ │ │3.B 运行结束/调用Schedule()│ │ Schedle →A(最高优先级)│ │TaskSwitch(B,A)│ │ SVLCX │ │ PCXIA.runCSA │ │ RSLCX │ │ RFE → A │ ◄──────────────────────────────────┘ ▼ 任务A 恢复运行 │ │4.WaitEvent 返回 E_OS_OK │(A 从上次挂起点继续执行)│ ▼