文章目录
- 1. Event 是什么
- 1.1 核心特征
- 1.2 基本任务 vs 扩展任务
- 1.3 Event的4个核心API
- 1.4 两个核心位掩码
- 2. SetEvent
- 2.1 SetEvent流程图
- 2.2 SetEvent调用层级
- 2.3 SetEvent状态切换(扩展任务)
- 2.4 SetEvent调用栈
- 2.5 SetEvent
- 2.5.1 Os_Event_SetEvent
- 2.5.1.1 Os_Event_SetEventSimp
- 2.5.1.2 Os_Task_SetEvent
- 3. WaitEvent
- 3.1 WaitEvent流程图
- 3.2 WaitEvent调用层级
- 3.3 WaitEvent状态切换
- 3.4 WaitEvent 完整时序图
- 3.5 WaitEvent
- 3.5.1 Os_Event_WaitEvent
- 3.5.2 Os_Task_WaitEvent
- 4. ClearEvent
- 4.1 ClearEvent流程图
- 4.2 ClearEvent调用层级
- 4.3 ClearEvent状态切换
- 4.4 ClearEvent完整时序图
- 4.5 Os_Event_ClearEvent
- 5. GetEvent
- 5.1 GetEvent流程图
- 5.2 GetEvent调用层级
- 5.3 GetEvent状态切换
- 5.4 GetEvent完整时序图
- 5.5 Os_Event_GetEvent
- 5.5.1 Os_Event_GetEventSimp
- 6. 完整同步闭环时序图
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个核心API
| API | 作用 | 调用者 |
| SetEvent(taskId, mask) | 设置目标任务的事件触发位 | 任意 Task/ISR2 |
| WaitEvent(mask) | 等待事件触发(可能阻塞) | 仅扩展任务 |
| ClearEvent(mask) | 清除自己的事件触发位 | 仅扩展任务自己 |
| GetEvent(taskId, &mask) | 查询目标任务的事件状态 | 任意 Task/ISR2 |
1.4 两个核心位掩码
每个扩展任务的 TCB 中有两个关键字段:
structOs_TaskDynType{...EventMaskType eventWait;// 等待掩码:WaitEvent 时设置EventMaskType eventTrigger;// 触发掩码:SetEvent 时设置...};2. SetEvent
2.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()│ │ │ ├─ eventWaiting=GETEVENTWAIT(A)│ ← 先读旧值 │ │ ├─Os_Event_SetEventSimp(A,MASK_X)│ │ │ │ └─ A.eventTrigger|=MASK_X │ ← 设置触发位 │ │ ├─ 判断:A.state==WAITING 且(eventWaiting&MASK_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.prio<currentPrio?│ │ │ ├─ Yes → Schedle+TaskSwitch(B,A)│ │ │ │ ├─SVLCX(保存 B)│ │ │ │ ├─ PCXI=A.runCSA │ │ │ │ ├─RSLCX(恢复 A)│ │ │ │ └─RFE(跳到 A)│ │ │ └─ No → B 继续运行 │ │ └────────────────────────────────────────────────────┘ │ ▼(若 A 优先级更高,A 恢复运行;否则 B 继续)2.5 SetEvent
SetEvent(TaskType TaskID,EventMaskType Mask){#if(OS_MEMORY_PROTECTION==STD_ON)Os_SysCallParamType sysCallParam;sysCallParam.Os_SetEvent.taskId=TaskID;sysCallParam.Os_SetEvent.mask=Mask;Os_SysCall(Os_Syscall_SetEvent_ID,&sysCallParam);// 走 SysCall trapret=sysCallParam.Os_SetEvent.retVal;#elseret=Os_Event_SetEvent(TaskID,Mask);// 直接调用#endif}2.5.1 Os_Event_SetEvent
Os_Event_SetEvent(TaskType taskId,EventMaskType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_SetEvent);coreId=Os_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;// ③ 调用上下文taskCfg=OS_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,¶meter);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 阶段:设置事件触发位 ============ */eventWaiting=OS_TASK_GETEVENTWAIT(taskCfg);// 先读旧值(防 race)ret=Os_Event_SetEventSimp(taskCfg,mask);// 设置 trigger/* ============ 第 6 阶段:唤醒判断 ============ */if(E_OS_OK==ret){if((WAITING==OS_TASK_GETTASKSTATE(taskCfg))&&(OS_ZERO_VALUE!=(eventWaiting&mask))){ret=Os_Task_SetEvent(taskCfg);// 唤醒+可能切换}}Os_Arch_IntEnable(intState);returnOs_Hook_CallErrorHook(OSServiceId_SetEvent,ret);}2.5.1.1 Os_Event_SetEventSimp
Os_Event_SetEventSimp(task,mask){if(OS_APP_STATEOFF(task->ownerAppId))returnE_OS_ACCESS;eventTrigger=OS_TASK_GETEVENTTRIGGER(task);eventTrigger|=mask;// 按位或OS_TASK_SETEVENTTRIGGER(task,eventTrigger);// 写回returnE_OS_OK;}2.5.1.2 Os_Task_SetEvent
Os_Task_SetEvent(taskCfg){if(taskCfg!=NULL_PTR){currentCoreId=taskCfg->coreId;/* ============ 1. 状态转换 + 入队 ============ */if(WAITING==taskCfg->taskDyn->state){taskCfg->taskDyn->state=READY;// WAITING → READYret=Os_Schedler_InsertTask(scheduler,taskCfg->taskDyn);// ↑ 入队 + 位图置位}/* ============ 2. 判断是否切换 ============ */if(OS_CORE_GETALLOWSCH(currentCoreId)// 调度允许&&OS_CORE_CHECKCURRENTINTASK(currentCoreId))// 在任务上下文{if(Os_Schedler_NeedSchedle(scheduler)){// 唤醒的优先级更高?nextDyn=Os_Schedler_Schedle(scheduler);ret=Os_Task_TaskSwitch(currentTaskCfg,nextTaskCfg);}}}}3. WaitEvent
3.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.eventWait=MASK_X(设置等待掩码)│ │ │ ├─ waitTrigger=(eventWait&eventTrigger)│ │ │ ├─ 判断: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.state=WAITING │ │ │ │ ├─SetNextTaskData(next)│ │ │ │ │ ├─ next.state=RUNNING │ │ │ │ │ └─PreTaskHook(next)│ │ │ │ └─ Os_Arch_Context_Switch │ │ │ │ ├─SVLCX(保存 A)│ │ │ │ ├─ PCXI=next.runCSA │ │ │ │ ├─RSLCX(恢复 next)│ │ │ │ └─RFE(跳到 next)│ │ │ └─Os_Arch_IntEnable()│ │ └────────────────────────────────────────────────────┘ │ ▼(若事件未触发,A 阻塞,nextTask 运行)(若事件已触发,A 继续运行)3.5 WaitEvent
WaitEvent(EventMaskType Mask){#if(OS_MEMORY_PROTECTION==STD_ON)Os_SysCallParamType sysCallParam;sysCallParam.Os_WaitEvent.mask=Mask;Os_SysCall(Os_Syscall_WaitEvent_ID,&sysCallParam);// 走 SysCall trapret=sysCallParam.Os_WaitEvent.retVal;#elseret=Os_Event_WaitEvent(Mask);// 直接调用#endif}3.5.1 Os_Event_WaitEvent
Os_Event_WaitEvent(EventMaskType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_WaitEvent);coreId=Os_Core_GetLogicId();/* ============ 第 1 阶段:参数和上下文检查 ============ */if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ① 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_WAITEVENT_ACCESS))returnE_OS_CALLEVEL;// ② 调用上下文taskCfg=OS_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 = maskwait=OS_TASK_GETEVENTWAIT(taskCfg);trigger=OS_TASK_GETEVENTTRIGGER(taskCfg);waitTrigger=(wait&trigger);// 关键判断/* ============ 第 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// ② 事件未触发(慢路径){ret=Os_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_WaitEvent
Os_Task_WaitEvent(taskCfg){if(taskCfg!=NULL_PTR){/* ============ 1. 从就绪队列移除(出队+清位图) ============ */Os_Schedler_DeleteTask(scheduler,taskCfg->taskDyn);// 时序保护:重置 budgetOs_Tp_ResetCurrentBudget(taskCfg->tpCfg,coreId);/* ============ 2. 选下一个任务 ============ */nextDyn=Os_Schedler_Schedle(scheduler);/* ============ 3. 切换 ============ */ret=Os_Task_TaskSwitch(taskCfg,OS_TASK_GETCFG(nextDyn->taskId));}}4. ClearEvent
4.1 ClearEvent流程图
4.2 ClearEvent调用层级
4.3 ClearEvent状态切换
NA.
4.4 ClearEvent完整时序图
NA.
4.5 Os_Event_ClearEvent
Os_Event_ClearEvent(EventMaskType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_ClearEvent);coreId=Os_Core_GetLogicId();/* ============ 第 1 阶段:上下文检查(只有 2 道) ============ */if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ① 中断禁用if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_CLEAREVENT_ACCESS))returnE_OS_CALLEVEL;// ② 调用上下文taskCfg=OS_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. GetEvent
5.1 GetEvent流程图
5.2 GetEvent调用层级
5.3 GetEvent状态切换
NA.
5.4 GetEvent完整时序图
NA.
5.5 Os_Event_GetEvent
Os_Event_GetEvent(TaskType taskId,EventMaskRefType mask){OS_ORTI_API_MONITOR_ENTRY(OSServiceId_GetEvent);coreId=Os_Core_GetLogicId();/* ============ 第 1 阶段:参数和上下文检查(6 道) ============ */if(OS_TASK_ISINVAILD(taskId))returnE_OS_ID;// ① ID 范围if(OS_CORE_MASK_INTERRUPT(coreId))returnE_OS_DISABLEDINT;// ② 中断禁用if(NULL_PTR==mask)returnE_OS_PARAM_POINTER;// ③ 空指针if(OS_CORE_PROCESSTYPEMATCH(coreId,OS_GETEVENT_ACCESS))returnE_OS_CALLEVEL;// ④ 调用上下文taskCfg=OS_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_GetEventSimp
Os_Event_GetEventSimp(task,mask){(*mask)=OS_TASK_GETEVENTTRIGGER(task);// 直接读取 eventTrigger}6. 完整同步闭环时序图
任务A(扩展,prio=5)任务B(prio=3,更高)│ │ │1.WaitEvent(MASK_X)│ │ eventWait=MASK_X │ │ waitTrigger=0(未触发)│ │ A.state=WAITING │ │DeleteTask(A)(出队+清位图)│ │ Schedle → B │ │TaskSwitch(A,B)│ │ SVLCX │ │ PCXI=B.runCSA │ │ RSLCX │ │ RFE → B │ │ ▼ 任务B 运行 │(A 阻塞,不消耗 CPU)│ │ │ │ │2.SetEvent(TaskA,MASK_X)│ │ eventTrigger|=MASK_X │ │ A.state==WAITING 且 │ │(A.eventWait&MASK_X)!=0│ │ →Os_Task_SetEvent(A)│ │ A.state=READY │ │InsertTask(A)(入队+置位图)│ │ NeedSchedle?A.prio(5)>B.prio(3)│ │ → 不切换!B 继续运行 │ ▼ │ │ │ │3.B 运行结束/调用Schedule()│ │ Schedle →A(最高优先级)│ │TaskSwitch(B,A)│ │ SVLCX │ │ PCXI=A.runCSA │ │ RSLCX │ │ RFE → A │ ◄──────────────────────────────────┘ ▼ 任务A 恢复运行 │ │4.WaitEvent 返回 E_OS_OK │(A 从上次挂起点继续执行)│ ▼