IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> NXP S32系列MCU官方AUTOSAR OS分析(一) -> 正文阅读

[嵌入式]NXP S32系列MCU官方AUTOSAR OS分析(一)

1. 概述

我之前介绍过如何用Keil编译NXP官方提供的AUTOSAR OS,想要了解的朋友可以去翻一下之前的文章,本文来简要介绍下AUTOSAR OS的代码实现。

我使用的单片机时S32K144,AUTOSAR的版本是4.0.3

2. 源码分析

(1)StartOS

StartOS()函数是AUTOSAR OS的入口,在main函数中做一些硬件和应用层的初始化,之后进入StartOS。

在这个函数中,会对各种对象(Object)进行初始化,如Application、Task、Alarm、ISR、Timer、Stack、Loc、ScheduleTable、Counter等。

初始化完成后,OS会启动AutoStart的任务,系统开始运行。

(2)对象初始化

上文所述的初始化,每种对象会对应一个配置结构体和一个控制结构体(下文称控制块),配置结构体由EB生成,固化在MCU的Flash中,控制块位于RAM中,在程序运行过程中实时记录和控制该对象的状态。在对象的初始化函数中,会把配置结构体中的对象属性赋给控制块,作为初始化状态。

在AUTOSAR OS 中,所有的对象都是程序编译时定义好了的,不支持动态创建任务等对象。

以Task为例,EB中定义了如下几个Task(官方测试例程):

在这里插入图片描述
EB生成的Task配置结构体如下:

/* Task Configuration table */
const    OSTSK   OsTaskCfgTable[OSNTSKS] = 
{
    {
        3U, /* Application identification mask value */
        (OSTASKENTRY) &FuncTASKRCV1, /* entry point of task */
        OSTASKRCV1STKTOS, /* top of task stack */
        0U | OSTSKEXTENDED | OSTSKACTIVATE, /* properties of task OSTSKACTIVATE, OSTSKEXTENDED, OSTSKNONPREMPT, OSTSKFLOATINGPOINT */
        0U, /* task id (task number in the task table) */
        0U, /* application identification value */
    }, /* TASKRCV1 */
    {
        3U, /* Application identification mask value */
        (OSTASKENTRY) &FuncTASKRCV2, /* entry point of task */
        0U, /* top of task stack */
        0U, /* properties of task OSTSKACTIVATE, OSTSKEXTENDED, OSTSKNONPREMPT, OSTSKFLOATINGPOINT */
        1U, /* task id (task number in the task table) */
        0U, /* application identification value */
    }, /* TASKRCV2 */
    {
        2U, /* Application identification mask value */
        (OSTASKENTRY) &FuncTASKSND1, /* entry point of task */
        0U, /* top of task stack */
        0U, /* properties of task OSTSKACTIVATE, OSTSKEXTENDED, OSTSKNONPREMPT, OSTSKFLOATINGPOINT */
        2U, /* task id (task number in the task table) */
        1U, /* application identification value */
    }, /* TASKSND1 */
    {
        2U, /* Application identification mask value */
        (OSTASKENTRY) &FuncTASKSND2, /* entry point of task */
        0U, /* top of task stack */
        0U, /* properties of task OSTSKACTIVATE, OSTSKEXTENDED, OSTSKNONPREMPT, OSTSKFLOATINGPOINT */
        3U, /* task id (task number in the task table) */
        1U, /* application identification value */
    }, /* TASKSND2 */
    {
        2U, /* Application identification mask value */
        (OSTASKENTRY) &FuncTASKCNT, /* entry point of task */
        0U, /* top of task stack */
        0U | OSTSKNONPREEMPT, /* properties of task OSTSKACTIVATE, OSTSKEXTENDED, OSTSKNONPREMPT, OSTSKFLOATINGPOINT */
        4U, /* task id (task number in the task table) */
        1U, /* application identification value */
    }, /* TASKCNT */
    {
        4U, /* Application identification mask value */
        (OSTASKENTRY) &FuncTASKSTOP, /* entry point of task */
        0U, /* top of task stack */
        0U | OSTSKNONPREEMPT, /* properties of task OSTSKACTIVATE, OSTSKEXTENDED, OSTSKNONPREMPT, OSTSKFLOATINGPOINT */
        5U, /* task id (task number in the task table) */
        2U, /* application identification value */
    }, /* TASKSTOP */
};

在初始化代码中,定义了配置结构体指针task_cfg和控制块指针task_cb,截取的部分代码如下:

    OSTSKCBPTR task_cb;
    const OSTSK *task_cfg;

	for (i = 0U; i < OSNTSKS; i++)
    {
        task_cb = &(OsTaskTable[i]);
        task_cfg = &(OsTaskCfgTable[i]);



        #if defined(OSAPPLICATION)
        task_cb->appMask = task_cfg->appMask;   /* copy application identification mask value */
        task_cb->appId = task_cfg->appId;       /* copy application identification value */
        #endif

        task_cb->entry = task_cfg->entry;       /* entry point of task */
        task_cb->taskId = task_cfg->taskId;

        #if defined(OSINRES)
        task_cb->runprio = (OSBYTE)task_cfg->runprio;
        #endif

        #if defined(OSRESOURCE) || defined(OSINRES)
        /*
        * @violates @ref Os_task_c_REF_17_4_1 MISRA 2004 Required Rule 17.4, pointer arithmetic other than array indexing used
        */
        OsPrioLink[task_cfg->taskId] = task_cb;
        #endif

    }

(3)任务调度

所涉及的变量:

OsRunning:任务控制块指针,指向当前运行的任务的控制块。
OsSchedulerVector1:就绪任务向量
OsSchedulerVectorMask1:就绪任务向量掩码
OsPrioLink:按优先级排序的Task表,成员是任务控制块指针,数量是Task数量+1
OsTaskTable:存储所有任务的任务控制块的表,成员是任务控制块,数量是Task数量+1
OsTaskCfgTable:存储所有任务配置信息的表

关于任务的初始化我们上面简单说了一下,总的来说就是把任务配置表中的初始化配置赋给任务控制块,同时会初始化OsPrioLink,按优先级将任务排序,以便于之后根据优先级来查找任务。

EB生成的任务配置表中,每个任务的配置按任务优先级数值从大到小排序,并从0开始为每个任务按顺序分配TaskID,因此优先级和TaskID在数值上的顺序是相反的,也就是说优先级越高的任务,优先级数值越大,排在配置表的前面,TaskID数值越小

在OS运行过程中,TaskID起优先级的作用,无论是任务配置表还是控制块中,都没有任务优先级了,所以EB中的任务优先级只是为配置表中的排序提供依据,是仅用来比较大小关系的相对的数值,因此也不允许配置为相同的优先级。后文提到的代码中的优先级的概念,都指TaskID。

任务就绪:

当一个任务转为就绪态时,调用以下接口函数:

OSTask2Ready:该函数设置相应的Task状态为Ready,例如Task优先级(TaskID)为3,那么就把OsSchedulerVector1的左数第4位设置为1,代码如下:

#define OSSETBITNUM2MASK(taskprio)  ( OsSchedulerVector1 |=  (OSDWORD)( OSDWORDMSB >> (taskprio) ) )

优先级判断:

OS在计算最高优先级的时候,会计算OsSchedulerVector1最左侧的0的个数(clz汇编指令),例如上面说的第4位为1,则前面有3个0,即最高的优先级为3。用该优先级去OsPrioLink链表中调取相应的任务控制块。

如果有一个优先级为2的Task就绪,则会先查找到优先级为2的Task,因此TaskID越小,优先级越高。

查找最高优先级的函数接口为 OSGETMAXPRIOTASK

任务调度接口:

OS内部的任务调度接口函数是OSDISPATCH,该函数内部又调用OSTaskForceDispatch函数,真正执行优先级查找和上下文切换。

OS中在以下函数中会执行任务调度:
在这里插入图片描述
此外还有中断任务调度函数:OSInterruptDispatcher()

开放给用户的任务调度接口函数是Schedule()

(4)上下文切换

上下文切换发生在OSTaskForceDispatch()和OSInterruptDispatcher()等会执行任务调度的函数中,执行保存环境的函数是OSSetJmp(context),恢复环境的函数是OSLongJmp (OsRunning->pcontext),当然这只是两个主要的上下文切换函数,还有一些寄存器控制函数就不展开讲了。

这些函数与MCU底层架构强相关,而且对效率要求很高,所以都是用汇编编写的,这些函数基本都在Os_hw_core.c中。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:50:31  更:2021-12-16 17:51:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 16:36:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码