【AUTOSAR】时间保护(Timing Protection)概念、应用与实现源代码解析(下篇)
本文主要接续上一文章的内容,通过一个开源的autosar cp的具体实现,来详细介绍一下实现的原理。感谢开源小满项目的共享,小满的开源代码可以在网上上获取到。具体的代码见代码文件:RTOS/kernel/Os_Tprot.c。
首先摘录具体相关的代码函数实现,而后将具体的对每一个函数进行分析总结。
Part 1:相关函数实现源代码
Os_TmProtMainProc 工作过程详解
首先,观察Os_TmProtMainProc函数的代码结构:
FUNC(void, OS_CODE) Os_TmProtMainProc(void)
{VAR(uint16, OS_VAR) i;/* 1: Timing Protection for task. */Os_TmProtTaskProc();/* 2: Timing Protection for Resource lock. */
#if (CFG_STD_RESOURCE_MAX > 0)for (i = 0u; i < Os_CfgResourceMax; i++){Os_TmProtResCounter((ResourceType)i);}
#endif/* 3: Timing Protection for Isr2. */
#if (CFG_ISR2_MAX > 0)Os_TmProtIsrProc();
#endifreturn;
}
该函数分为三个主要部分:任务的时间保护、资源锁定的时间保护以及中断(ISR2)的时间保护。每个部分都通过条件编译控制是否启用。接下来需要深入每个子函数,分析它们的具体实现。
**一:分析Os_TmProtTaskProc()**
Os_TmProtTaskProc()负责处理所有任务的时间保护检查。其代码如下:
static FUNC(void, OS_CODE) Os_TmProtTaskProc(void)
{VAR(uint16, OS_VAR) i;VAR(Os_TaskStateType, OS_VAR) osTaskState;#if (CFG_TASK_MAX > 0)for (i = 0U; i < Os_SCB.sysTaskMax; i++){/* Implementation-dependent: IDLE task should not be protected. */if (OS_TASK_IDLE != (Os_TaskType)i){osTaskState = Os_TCB[i].taskState;if (TASK_STATE_RUNNING == osTaskState){/* Exe_budget only checked in running state. */Os_TmProtTaskCounter((Os_TaskType)i, TP_TASK_EXE);Os_TmProtTaskCounter((Os_TaskType)i, TP_TASK_ARRIVAL);Os_TmProtTaskCounter((Os_TaskType)i, TP_TASK_SUS_OS_INT);Os_TmProtTaskCounter((Os_TaskType)i, TP_TASK_SUS_ALL_INT);Os_TmProtTaskCounter((Os_TaskType)i, TP_TASK_DIS_ALL_INT);}else{/* Time-frame is checked in running and ready states. */Os_TmProtTaskCounter((Os_TaskType)i, TP_TASK_ARRIVAL);}}}
#endifreturn;
}
该函数遍历所有任务(除空闲任务外),根据任务状态执行不同的时间保护检查。对于正在运行的任务(TASK_STATE_RUNNING),会检查执行时间(TP_TASK_EXE)、到达间隔(TP_TASK_ARRIVAL)、中断锁定时间(如TP_TASK_SUS_OS_INT等)。对于非运行状态的任务(如就绪状态),仅检查到达间隔。
接下来需要理解Os_TmProtTaskCounter函数的具体实现,该函数是执行具体时间检查的核心。
二:分析Os_TmProtTaskCounter
该函数处理特定任务的某一类时间保护检查。例如,当osOptType为TP_TASK_EXE时,检查执行时间是否超限。关键代码如下:
static FUNC(void, OS_CODE) Os_TmProtTaskCounter(Os_TaskType osTaskId, Os_TmProtOptTaskType osOptType)
{VAR(StatusType, OS_VAR) osErrType;P2VAR(Os_TCBType, AUTOMATIC, OS_VAR) pTcb;P2VAR(Os_TmProtCbDataDef, AUTOMATIC, OS_VAR) pCbData;if (TP_TASK_ARRIVAL == osOptType){Os_TmProtTaskFrameCounter(osTaskId, osOptType);}else{pTcb = &Os_TCB[osTaskId];pCbData = &(pTcb->osTpTask[osOptType]);if (TRUE == pCbData->osIsTpStart){if (OS_TMPROT_TARGET_ISR_OFFSET <= Os_IntNestISR2){/* 中断嵌套时不处理 */}else{pCbData->osTpTime += 1U;
#if ((OS_SC4 == CFG_SC) && (CFG_TRUSTED_SYSTEM_SERVICE_MAX > 0U))if (FALSE == Os_TrustedFuncTportDelayCall)
#endif{if (pCbData->osTpTime >= pCbData->osTpBudget){pCbData->osTpTime = 0u;pCbData->osIsTpStart = FALSE;if (TP_TASK_EXE == osOptType){osErrType = E_OS_PROTECTION_TIME;}else{osErrType = E_OS_PROTECTION_LOCKED;}(void)Os_CallProtectionHook(osErrType, OS_TMPROT_HOOK_TASK);}}}}}
}
该函数首先判断是否是到达间隔检查(TP_TASK_ARRIVAL),如果是,调用Os_TmProtTaskFrameCounter处理时间帧检查。否则,针对其他类型的时间保护(如执行时间、中断锁定时间),检查计时器是否已启动(osIsTpStart),并在非中断嵌套的情况下累加时间。如果时间超过预算(osTpBudget),则调用保护钩子函数报告错误。
三:分析Os_TmProtResCounter
资源锁定的时间保护在Os_TmProtResCounter中处理:
static FUNC(void, OS_CODE) Os_TmProtResCounter(ResourceType osResId)
{P2VAR(Os_RCBType, AUTOMATIC, OS_VAR) pRcb;P2VAR(Os_TCBType const, AUTOMATIC, OS_VAR) pTcb;P2VAR(Os_TmProtCbDataDef, AUTOMATIC, OS_VAR) pCbData;P2VAR(Os_SCBType const, AUTOMATIC, OS_VAR) pScb;VAR(boolean, OS_VAR) Status = TRUE;pRcb = &Os_RCB[osResId];pCbData = &(pRcb->osResTpData);pScb = &Os_SCB;/* 检查资源是否被任务或中断有效占用 */if (pRcb->osWhichTaskOccupy < Os_SCB.sysTaskMax){pTcb = &Os_TCB[pRcb->osWhichTaskOccupy];if (TASK_STATE_RUNNING != pTcb->taskState){Status = FALSE;}}else if (Os_IntNestISR2 >= OS_TMPROT_TARGET_ISR_OFFSET){if (pScb->sysIsrNestQueue[Os_IntNestISR2 - OS_TMPROT_TARGET_ISR_OFFSET] != pRcb->osWhichIsrOccupy){Status = FALSE;}}else{Status = FALSE;}if (Status){if (pCbData->osIsTpStart){pCbData->osTpTime += 1U;if (pCbData->osTpTime >= pCbData->osTpBudget){pCbData->osTpTime = 0u;pCbData->osTpBudget = 0u;pCbData->osIsTpStart = FALSE;(void)Os_CallProtectionHook(E_OS_PROTECTION_LOCKED, (uint32)pCbData->osWhoHook);}}}
}
该函数检查资源是否被有效占用(任务在运行或中断在嵌套队列中),如果计时器已启动,则累加时间并检查是否超限。超限时报告E_OS_PROTECTION_LOCKED错误。
四:分析Os_TmProtIsrProc
中断的时间保护由Os_TmProtIsrProc处理:
static FUNC(void, OS_CODE) Os_TmProtIsrProc(void)
{VAR(uint16, OS_VAR) i;VAR(Os_IsrType, OS_VAR) osIsrC2Id;P2CONST(Os_IsrCfgType, AUTOMATIC, OS_VAR) pIsrCfg;P2VAR(Os_SCBType const, AUTOMATIC, OS_VAR) pScb;pScb = &Os_SCB;if (Os_IntNestISR2 >= OS_TMPROT_TARGET_ISR_OFFSET){osIsrC2Id = pScb->sysIsrNestQueue[Os_IntNestISR2 - OS_TMPROT_TARGET_ISR_OFFSET];if (osIsrC2Id < CFG_ISR_MAX){pIsrCfg = &Os_IsrCfg[osIsrC2Id];if (OS_ISR_CATEGORY2 == pIsrCfg->OsIsrCatType){Os_TmProtIsrCounter(osIsrC2Id, TP_ISR_CAT2_EXE);Os_TmProtIsrCounter(osIsrC2Id, TP_ISR_CAT2_SUS_OS_INT);Os_TmProtIsrCounter(osIsrC2Id, TP_ISR_CAT2_SUS_ALL_INT);Os_TmProtIsrCounter(osIsrC2Id, TP_ISR_CAT2_DIS_ALL_INT);}}}#if (CFG_ISR2_MAX > 0U)for (i = (Os_CfgIsrMax - Os_CfgIsr2Max); i < Os_CfgIsr2Max; i++){if (i != pScb->sysRunningIsrCat2Id){Os_TmProtIsrCounter(i, TP_ISR_CAT2_ARRIVAL);}}
#endifreturn;
}
该函数首先处理当前嵌套中断的执行时间,然后遍历所有ISR2检查其到达间隔。Os_TmProtIsrCounter与任务的计数器类似,处理中断的执行时间和锁定时间。
Part 2:相关函数实现总结
1. 任务时间保护(Os_TmProtTaskProc)
-
遍历所有任务(除空闲任务):
- 运行状态任务:
- 执行时间检查(TP_TASK_EXE):累加
osTpTime
,若超过osTpBudget
,触发E_OS_PROTECTION_TIME
错误。 - 到达间隔检查(TP_TASK_ARRIVAL):验证任务激活间隔是否符合时间帧(
OsTaskTimeFrame
)。 - 中断锁定检查(如
TP_TASK_SUS_OS_INT
):监控任务禁用中断的时间。
- 执行时间检查(TP_TASK_EXE):累加
- 非运行状态任务(如就绪状态):
- 仅检查到达间隔,防止频繁激活。
- 运行状态任务:
-
示例:
任务A配置执行预算为100 ticks(10ms)。每次系统节拍中断(1ms)时,osTpTime
递增。若任务A连续运行超过10ms,第10次中断时触发超限错误。
2. 资源锁定时间保护(Os_TmProtResCounter)
-
遍历所有资源:
- 检查资源占用者状态:
- 任务占用:验证任务是否仍在运行。
- 中断占用:确认中断位于当前嵌套队列中。
- 计时器处理:
- 若资源被有效占用,累加
osTpTime
。 - 超限时触发
E_OS_PROTECTION_LOCKED
错误,标识占用者类型(任务/中断)。
- 若资源被有效占用,累加
- 检查资源占用者状态:
-
示例:
资源R的锁定预算为50 ticks(5ms)。任务B获取R后执行耗时操作,若6ms未释放,触发锁定超限错误。
3. 中断时间保护(Os_TmProtIsrProc)
-
处理当前嵌套中断:
- 执行时间检查(TP_ISR_CAT2_EXE):累加中断执行时间,超限时上报错误。
- 中断锁定检查(如
TP_ISR_CAT2_SUS_OS_INT
):监控中断禁用其他中断的时间。
-
检查所有ISR2的到达间隔:
- 排除当前运行中断:避免自检干扰。
- 验证中断激活间隔,防止高频触发。
-
示例:
中断ISR1配置时间帧为200 ticks(20ms)。若ISR1在15ms内被触发两次,第二次激活时触发到达间隔错误。
4. 错误处理与钩子调用
- 统一错误上报:
- 通过
Os_CallProtectionHook
传递错误类型(如E_OS_PROTECTION_TIME
)和触发实体(任务/中断)。 - 应用层可自定义钩子函数,执行恢复策略(如终止任务、系统复位)。
- 通过
5. 条件编译与配置适配
- 资源保护:通过
CFG_STD_RESOURCE_MAX
控制是否启用。 - 中断保护:由
CFG_ISR2_MAX
决定是否包含ISR2检查。 - 安全扩展:如
CFG_TRUSTED_SYSTEM_SERVICE_MAX
支持可信功能延迟处理。
时序与硬件依赖
- 触发周期:由系统节拍中断驱动,通常在1-10ms之间。
- 硬件支持:依赖高精度定时器(如TPT)实现精确计时,确保计数器独立于软件延迟。
- 中断嵌套处理:通过
Os_IntNestISR2
跟踪嵌套深度,避免在深层中断中误判时间。
总结
Os_TmProtMainProc
作为时间保护的总控函数,通过周期性检查任务、资源和中断的时间属性,确保系统行为符合AUTOSAR OS的安全约束。其设计紧密结合硬件特性与实时性要求,是功能安全(如ISO 26262 ASIL-D)的关键实现。