【AUTOSAR OS】资源以及资源管理原理与实现解析

文章目录

        • 一、Resource定义与作用
        • 二、核心数据结构
          • 1. 资源控制块(RCB,Resource Control Block)
          • 2. 任务/中断控制块关联字段
          • 3. 配置数据结构
        • 三、关键函数实现原理
          • 1. 资源初始化:`Os_InitResource()`
          • 2. 获取资源:`GetResource(ResourceType ResID)`
          • 3. 释放资源:`ReleaseResource(ResourceType ResID)`
          • 4. 时间保护机制
        • 四、使用示例:任务间资源互斥
          • 1. 资源配置
          • 2. 任务实现
          • 3. 执行流程
        • 五、总结

一、Resource定义与作用

在AUTOSAR经典平台中,**Resource(资源)**指多个任务或中断共享的临界资源(如全局变量、外设寄存器等),通过资源管理器实现互斥访问,防止竞态条件。其核心作用包括:

  1. 互斥控制:确保同一时刻仅有一个任务/中断访问资源。
  2. 优先级管理:通过天花板优先级(Ceiling Priority)机制避免优先级反转。
  3. 访问权限验证:基于任务/中断的访问掩码(Access Mask)限制非法访问。
  4. 时间保护:监控资源占用时间,防止超时导致的功能安全风险。
二、核心数据结构
1. 资源控制块(RCB,Resource Control Block)
typedef struct {
    uint16 saveCount;          // 当前资源占用计数(嵌套获取次数)
    Os_PriorityType savePrio;  // 占用前的任务优先级
    Os_LevelType saveLevel;    // 占用时的OS级别(任务/中断)
    // 时间保护相关字段
    Os_TaskType osWhichTaskOccupy;
    Os_IsrType osWhichIsrOccupy;
    Os_TickType* osTmProtResBgtTask;
    Os_TickType* osTmProtResBgtIsr;
    TmProtResData osResTpData;
} Os_RCBType;
  • 作用:记录资源状态,如当前占用者、优先级上下文、时间保护预算等。
  • 关联数组:通过Os_RCB数组管理所有资源,索引为ResID
2. 任务/中断控制块关联字段
  • 任务控制块(TCB)
    typedef struct {
        uint16 taskResCount;           // 已获取资源计数
        ResourceType taskResourceStack[CFG_RESOURCE_MAX]; // 资源栈(LIFO顺序)
        // 临界区相关字段(与资源释放顺序同步)
        uint16 taskCriticalZoneCount;
        ObjectType taskCriticalZoneType[CFG_SPINLOCK_MAX];
        uint16 taskCriticalZoneStack[CFG_SPINLOCK_MAX];
    } Os_TCBType;
    
  • 中断控制块(ICB)
    typedef struct {
        uint16 IsrC2ResCount;          // Cat2中断已获取资源计数
        ResourceType IsrC2ResourceStack[CFG_RESOURCE_MAX]; // 资源栈
        // 临界区相关字段
        uint16 isr2CriticalZoneCount;
        ObjectType isr2CriticalZoneType[CFG_SPINLOCK_MAX];
        uint16 isr2CriticalZoneStack[CFG_SPINLOCK_MAX];
    } Os_ICBType;
    
  • 作用:通过栈结构记录资源获取顺序,确保释放时按LIFO原则匹配,避免非法释放。
3. 配置数据结构
  • 资源配置数组Os_ResourceCfg存储每个资源的类型(resourceOccupyType)和天花板优先级(ceiling)。
  • 访问掩码(扩展状态下):
    P2CONST(uint16*, OS_VAR, OS_CONST) Os_TaskResourceAccessMask; // 任务资源访问掩码
    P2CONST(uint16*, OS_VAR, OS_CONST) Os_IsrResourceAccessMask; // 中断资源访问掩码
    
    • 每个任务/中断通过掩码位(如ResID & 0x0Fu)验证是否有权限访问资源。
三、关键函数实现原理
1. 资源初始化:Os_InitResource()
FUNC(void, OS_CODE) Os_InitResource(void) {
    // 初始化RCB数组
    for (resId = 0; resId < Os_CfgStdResourceMax; resId++) {
        Os_RCB[resId].saveCount = 0U;
        Os_RCB[resId].savePrio = OS_PRIORITY_INVALID;
        // 时间保护初始化
        #if (TRUE == CFG_TIMING_PROTECTION_ENABLE)
            Os_RCB[resId].osWhichTaskOccupy = OS_TASK_INVALID;
            for (i = 0U; i < Os_SCB.sysTaskMax; i++) {
                Os_RCB[resId].osTmProtResBgtTask[i] = OS_TICK_INVALID;
            }
        #endif
    }
    // 多核场景下初始化核心相关配置
    vCoreId = Os_SCB.sysCore;
    Os_ResourceCfg = Os_ResourceCfg_Inf[vCoreId];
    Os_RCB = Os_RCB_Inf[vCoreId];
}
  • 作用
    • 重置所有资源的RCB状态,确保初始为未占用。
    • 加载核心相关的资源配置(如多核场景下的独立配置)。
    • 初始化时间保护相关字段(如预算数组指针)。
2. 获取资源:GetResource(ResourceType ResID)
FUNC(StatusType, OS_CODE) GetResource(ResourceType ResID) {
    OS_ENTER_KERNEL();
    // 核心ID验证、资源ID有效性检查
    if (Os_SCB.sysCore != Os_GetObjCoreId(ResID)) return E_OS_CORE;
    ResID = Os_GetObjLocalId(ResID); // 转换为本地索引
    // 扩展状态下的访问权限检查
    #if (OS_STATUS_EXTENDED == CFG_STATUS)
        if (Os_RCB[ResID].saveCount > 0U) return E_OS_ACCESS; // 资源已被占用
        if (任务/中断无访问权限) return E_OS_ACCESS;
    #endif
    // 根据资源类型调用具体获取逻辑
    return Os_GetResource(ResID);
}

static FUNC(void, OS_CODE) Os_GetResourceByTask(Os_TCBType* pTCB, ResourceType ResID) {
    Os_PriorityType prio = Os_ResourceCfg[ResID].ceiling;
    // 保存当前优先级并提升至天花板优先级
    pTCB->taskRunPrio = (prio > pTCB->taskRunPrio) ? prio : pTCB->taskRunPrio;
    // 更新系统最高优先级
    if (prio > Os_SCB.sysHighPrio) {
        Os_SCB.sysHighPrio = prio;
        Os_SCB.sysHighTaskID = Os_SCB.sysRunningTaskID;
    }
    // 记录资源获取顺序
    Os_SaveResourceByTaskOrder(pTCB, ResID);
    // 时间保护启动
    #if (TRUE == CFG_TIMING_PROTECTION_ENABLE)
        Os_TmProtResStart(ResID, TP_RES_OCCUPY_TASK);
    #endif
}
  • 核心逻辑
    1. 权限与状态检查:验证资源是否可用、调用者是否有权限。
    2. 优先级提升:根据资源类型(OCCUPIED_BY_TASK等)提升任务优先级至天花板优先级,避免优先级反转。
    3. 中断处理:对于OCCUPIED_BY_TASK_OR_INTERRUPT类型,通过Os_ArchSetIpl()屏蔽中断至对应优先级。
    4. 栈记录:将资源ID压入任务/中断的资源栈,确保释放顺序正确。
3. 释放资源:ReleaseResource(ResourceType ResID)
FUNC(StatusType, OS_CODE) ReleaseResource(ResourceType ResID) {
    OS_ENTER_KERNEL();
    // 有效性检查(如核心ID、资源ID、调用上下文)
    // 转换为本地索引并调用具体释放逻辑
    return Os_ReleaseResource(ResID);
}

static FUNC(StatusType, OS_CODE) Os_ReleaseResourceByTask(Os_TCBType* pTCB, ResourceType ResID) {
    // 验证释放顺序(栈顶匹配)
    #if (CFG_SPINLOCK_MAX > 0U)
        if (资源栈顶 != ResID) return E_OS_NOFUNC;
    #endif
    // 恢复任务优先级
    Os_PriorityType savePrio = Os_RCB[ResID].savePrio;
    pTCB->taskRunPrio = savePrio;
    // 从就绪队列移除当前任务的天花板优先级
    Os_ReadyQueueRemove(OS_LEVEL_STANDARD_RESOURCE, prio);
    // 弹出资源栈
    Os_ResumeResourceByTaskOrder(pTCB, ResID);
    // 时间保护结束
    #if (TRUE == CFG_TIMING_PROTECTION_ENABLE)
        Os_TmProtResEnd(ResID);
    #endif
    // 重新计算系统最高优先级并触发调度
    Os_SCB.sysHighPrio = Os_GetHighPrio();
    if (需要调度) Os_Dispatch();
    return E_OK;
}
  • 核心逻辑
    1. 合法性验证:确保释放顺序与获取顺序一致(LIFO),避免非法释放。
    2. 优先级恢复:将任务优先级降回获取资源前的优先级,并更新系统最高优先级。
    3. 中断恢复:对于OCCUPIED_BY_TASK_OR_INTERRUPT类型,恢复中断屏蔽级别。
    4. 调度触发:若释放资源后存在更高优先级就绪任务,触发任务切换。
4. 时间保护机制
// 启动资源占用计时
#if (TRUE == CFG_TIMING_PROTECTION_ENABLE)
    if (任务/中断配置了时间保护) {
        Os_TmProtResStart(ResID, TP_RES_OCCUPY_TASK);
    }
// 结束计时并检查超时
    Os_TmProtResEnd(ResID);
#endif
  • 通过Os_TmProtResStartOs_TmProtResEnd监控资源占用时间,若超过配置的预算(osTmProtResBgtTask),触发时间保护错误处理。
四、使用示例:任务间资源互斥

假设存在两个任务TaskATaskB,共享资源ResID=0(类型为OCCUPIED_BY_TASK,天花板优先级为5)。

1. 资源配置
// Os_ResourceCfg[0] 配置
{
    .resourceOccupyType = OCCUPIED_BY_TASK,
    .ceiling = 5, // 天花板优先级
    // 其他配置...
}
// 任务访问掩码:允许TaskA和TaskB访问
Os_TaskResourceAccessMask[TaskA_ID][0 >> 4] |= (1u << (0 & 0x0F));
Os_TaskResourceAccessMask[TaskB_ID][0 >> 4] |= (1u << (0 & 0x0F));
2. 任务实现
TASK(TaskA) {
    StatusType err;
    // 获取资源
    err = GetResource(ResID);
    if (err == E_OK) {
        // 临界区代码
        SharedData = 42;
        // 释放资源
        ReleaseResource(ResID);
    }
    TerminateTask();
}

TASK(TaskB) {
    StatusType err;
    err = GetResource(ResID);
    if (err == E_OK) {
        // 临界区代码
        uint32 temp = SharedData;
        ReleaseResource(ResID);
    }
    TerminateTask();
}
3. 执行流程
  1. TaskA调用GetResource,优先级提升至5,获取资源成功。
  2. 若此时TaskB(优先级4)就绪,因TaskA优先级更高,继续运行。
  3. TaskA释放资源后,优先级恢复为原优先级,系统重新调度,TaskB获取资源并执行。
五、总结

该资源管理器实现遵循AUTOSAR标准,通过天花板优先级机制解决优先级反转,利用栈结构保证资源获取/释放顺序正确性,并集成时间保护功能满足功能安全需求。核心设计要点包括:

  • 配置灵活性:通过宏开关(如CFG_RESOURCE_MAXOS_STATUS_EXTENDED)支持不同硬件和安全等级配置。
  • 多核支持:通过核心ID隔离资源配置(如Os_RCB_Inf[vCoreId]),避免跨核心资源冲突。
  • 错误处理:通过E_OS_ACCESSE_OS_NOFUNC等错误码及Os_TraceErrorHook提供调试和故障诊断能力。

实际应用中,需根据系统需求配置资源类型、天花板优先级及访问掩码,确保临界资源的安全互斥访问。

你可能感兴趣的:(autosar,c++)