CH04-01-02-操作系统原理与实践.pptx
嵌入式系统设计原理嵌入式操作系统原理与实践主讲人:赖树明东莞理工学院05C/OS-III任务管理01嵌入式操作系统基础02初识C/OS-III操作系统03C/OS-III任务使用04C/OS-III时间管理06C/OS-III通信机制07C/OS-III操作系统作业 0101嵌入式操作系统基础常见嵌入式操作系统操作系统系统分类裸机和操作系统比较嵌入式操作系统基础常见嵌入式操作系统01嵌入式操作系统基础常见嵌入式操作系统01QNX是一种商用的遵从POSIX规范的类Unix硬实时操作系统,主要是面向嵌入式系统。高可靠性、低风险高级安全机制能耗更低可扩展及标准合规广泛的板卡支持GPU 加速图形支持高效的产品开发嵌入式操作系统基础常见嵌入式操作系统01安卓是一种基于Linux内核的自由及开放源代码的操作系统。Android 操作系统最初由 Andy Rubin 开发,主要支持手机。2005年8月由Google收购注资,由Google公司和开放手机联盟领导及开发。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。Google以Apache开源许可证的授权方式,发布了Android的源代码。嵌入式操作系统基础常见嵌入式操作系统01Linux,全称GNU/Linux,是一套免费使用和自由传播的类UNIX操作系统。广泛的硬件支持开放源码,软件丰富高效、灵活性高良好的可移植性具有多任务、多用户的能力强大的网络功能能在PC计算机上实现全部的 Unix特性。提供完善的进程通信、线程同步等服务,网络功能超级强大,支持动态链接,文件系统完善嵌入式操作系统基础常见嵌入式操作系统01Embedded Configurable Operating System(eCos)是一个开源、免费的实时操作系统,适合实时处理需求和内存有限的嵌入式应用。开源,免费小巧,功能可裁剪移植性强支持POSIX标准接口,比较完善的线程同步服务集成network、file system等各种模块嵌入式操作系统基础常见嵌入式操作系统01源码开放,商用收费系统小巧,功能可裁剪可移植性强稳定性、可靠性强同优先级级任务支持时间片轮转调度嵌入式操作系统基础常见嵌入式操作系统01RT-Thread 是一款来自中国的开源嵌入式实时操作系统体积小,成本低,功耗低、启动快速、实时性高、占用资源小完全开源,商用免费集成一系列应用组件和驱动框架,如TCP/IP协议栈,虚拟文件系统,POSIX接口,图形用户界面,FreeModbus主从协议栈,CAN框架,动态模块等嵌入式操作系统基础常见嵌入式操作系统01 FreeRTOS(读作free-arr-toss)是一个嵌入式系统使用的开源实时操作系统。设计小巧,简单易用源码开放,商用免费可移植性强,支持多种硬件平台支持抢占式多任务和协作式多任务嵌入式操作系统基础常见嵌入式操作系统01采用基于微内核的体系结构,整个系统由四百多个相对独立、短小精练的目标模块组成,用户可以根据自己的需要选择适当的模块,进行裁减和配置。采用GNU类型的编译和调试器,支持x86、Motorola MC68xxx、PowerPC、MIPS、ARM、i960等主流的32位处理器超强可靠性卓越的实时性嵌入式领域应用最广泛、市场占有率最高的商业系统之一嵌入式操作系统基础操作系统分类01分时操作系统以时间片为基本调度原则的操作系统。对于分时操作系统,软件的执行在时间上的要求,并不严格,时间上的错误,一般不会造成灾难性的后果。典型代表 Windows 操作系统分时操作系统实时操作系统(Real Time Operating System)以优先级为基本调度原则的操作系统实时操作系统与一般的操作系统相比,最大的特色就是“实时性”.如果有高优先级任务需要执行,实时操作系统会尽可能快的执行该任务,延时较短。这个特性保证了各个任务的及时执行。典型代表:VxWork、eCos、FreeRTOS、RT-Thread、uCOS-II/III实时操作系统嵌入式操作系统基础裸机和操作系统比较01裸机代码结构嵌入式操作系统基础裸机和操作系统比较01实时操作系统程序代码结构任务代码结构任务代码结构main函数中不再有无限循环;代码结构更清晰,易于维护和移植 把复杂的程序划分为一个个小任务;提供任务管理、通信、内存管理等机制;RTOS程序特点0202初识C/OS-III操作系统系统简介源码结构系统裁剪任务优先级任务调度法则程序模板-虚席以待-初识C/OS-III操作系统系统简介02C/OS 是一个老牌嵌入式实时操作系统编程语言,到目前已经发展了三代版本:C/OS-I:1992 -目前几乎没有在使用了C/OS-II:1998 -目前还有很多产器在使用C/OS-III:2009-市场上目前正在逐步取代C/OS-II概述初识C/OS-III操作系统系统简介02可裁剪、可剥夺型抢占式多任务实时内核。可剥夺型内核:总是执行当前优先级最高的就绪任务。高可扩展性:无限数量的任务,优先级和内核对象。极短的关中断时间:采用锁定内核调度方式而不是关中断方式来保护内部数据结构和变量的临界段。同优先级时间片轮转:当多个优先级相同的任务同时就绪,并且这些任务的优先级是当前最高优先级时,系统会轮转调度这些任务。丰富的系统服务:任务管理、时间管理、信号量、时间标志组、互斥型信号量、消息列队、软件定时器、存储块管理等。内核对象:任务、信号量、互斥信号量、事件标记、消息列队、定时器、存储块 等。独有功能:内嵌的实时性能测试、向任务直接发送信号量和消息、同时等待多个内核对象等。C/OS-III亮点初识C/OS-III操作系统系统简介02可剥夺型(preemptive):当一个事件发生,使得更高优先级的任务就绪时,C/OS-III就会立即将CPU的控制权剥夺,转交给更高优先级的任务使用,这个过程看起来好像是高优先级任务“抢占”了CPU。判断CPU如何执行程序,始终根据“可剥夺型”特性为依据。可剥夺型概念初识C/OS-III操作系统源码结构02系统源码可以在官网上下载到https:/ UCOSIII任务创建和删除-sim初识C/OS-III操作系统系统裁剪02uCOS_CONFIG 文件夹中存放了系统各个配置文件,通过定义这些文件里宏的值可以轻易地裁剪 C/OS-III的功能。os_cfg.h:系统相关代码配置,这部分是拓展性的,比如配置是否裁剪定时器等内核对象的宏。os_cfg_app.h:系统相关代码配置,这部分是必须设置的,如任务堆栈、时钟节拍频率、消息缓冲池、软件定时器等;cpu_cfg.h:定义CPU相关指令(计算前导0)存在与否、CPU_NAME、时间戳、关中断时间测量等CPU相关配置;lib_cfg.h:配置C/LIB目录库文件代码相关选项。配置文件初识C/OS-III操作系统任务优先级02C/OS每个任务都有一个优先级设置,数字越小,优先级越高。C/OS每个任务都根据其重要程度来分配优先级。C/OS高优先级任务就绪可以抢占低优先级任务的CPU。C/O取值范围:C/OS-I:64;C/OS-II:255;C/OS-III:无限C/OS-I、II每个任务具有惟一的优先级,不同任务不允许相同。C/OS-III支持不同任务设置相同的优先级,相同优先级的任务采用时间片轮转法进行调度,该功能是C/OS-III独有功能。优先级说明初识C/OS-III操作系统任务优先级02C/OS-III中部分优先级是系统使用了,不建议用户再去使用这些优先等,将这些优先级分配给C/OS-III的5个系统内部任务:优先级0:中断服务服务管理任务 OS_IntQTask()优先级1:时钟节拍任务 OS_TickTask()优先级2:定时任务 OS_TmrTask()优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask()优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask()C/OS-III中优先级数字最大取值在cpu.h 中定义,用户可根据需要修改,以下是默认定义:#define OS_CFG_PRIO_MAX 64uC/OS-III系统中使用 OS_PRIO 表示任务优先级数据类型,这个类型是可以根据需要配置的,默认是定义为 unsigned char 类型,即范围0255,数值越小优先级越高。优先级说明初识C/OS-III操作系统任务调度法则02任务调度器,又叫调度程序,负责确定下一个要执行的任务。C/OS-III任务调度器支持优先级调度法则和时间片轮转调度法则。当存在相同优先级任务就绪时,采用时间片调度法则,否则使用优先级调度法则。C/OS-III 任务调度器有2种:任务级调度器和中断级调度器。任务调度器任何操作系统都需要时钟节拍发生器来驱动系统运行,如用于系统定时、延时、超时判断、任务调度等。时钟节拍发生器通常由硬件定时器实现,C/OS-III移植到ARM Cortex-M系列芯片上时,使用滴答定时器(SysTickTimer)实现。时钟节拍发生器周期的设置:在uC/OS-III配置文件 uCOS_CONFIGos_cfg_app.h 中用宏定义方式设置。#define OS_CFG_TICK_RATE_HZ 1000u /*(10 to 1000 Hz)*/滴答定时器的中断服务程序 SysTick_Handler 函数通过调用 OSTimeTick()函数,完成每个操作系统节拍的系统工作。节拍发生器初识C/OS-III操作系统任务调度法则02任务级调度初识C/OS-III操作系统任务调度法则02中断级调度初识C/OS-III操作系统任务调度法则02当具有相同优先级的多个任务就绪时,采用时间片轮转调度算法(Round Bobin Scheduling),系统会根据分配给它们的时间片轮流调度各个任务运行。使用时间片轮转调度功能:使能 OS_CFG_SCHED_ROUND_ROBIN_EN(位于“os_cfg.h”);#define OS_CFG_SCHED_ROUND_ROBIN_EN 1初始化时调用 OSSchedRoundRobinCfg()函数使能时间片轮转调度和配置相关指标。允许用户为每个任务指定不同的时间片,1个时间片就是1个时钟节拍时长。时间片长度是在任务建立时指定的,也可以调用OSTaskTimeQuantaSet()来改变。任务可以调用 OSSchedRoundRobinYield 函数主动放弃时间片,提前放弃CPU。时间片轮转调度初识C/OS-III操作系统任务调度法则02时间片轮转调度分析初识C/OS-III操作系统程序模板02C/OS-III系统main程序代码结构初识C/OS-III操作系统程序模板02实时操作系统程序代码结构start_task 是开始任务,用于创建其他更多的用户任务,创建完成后,这个开始任务就没有作用,需要把它删除。这里的删除并不是把代码删除,而是把 start_task 任务函数从调度队列中移除,后面不再会被CPU执行。一个被删除的任务函数,除非你重新创建它,否则永远不可能再被CPU执行。uCOS-III任务1代码模板uCOS-III任务2代码模板初识C/OS-III操作系统程序模板020303C/OS-III任务使用任务基本概念定义任务控制块定义任务栈定义优先级定义任务函数创建任务C/OS-III中的任务是复杂问题“分而治之”的问题解题思路。C/OS-III的两种任务:系统任务(如空闲任务,统计任务)、用户任务(用户自己创建的任务)。任务的组成任务控制块:C/OS-III 进行任务管理用的数据结构,记录了任务的特征信息。任务名称:C/OS-III每个任务都可自定义设置一个名称。任务函数:实现程序目标功能的核心代码。任务函数参数:当任务函数被调用时,传递给任务函数的实参。任务优先级:每个任务都有一个运行级别,C/OS-III 根据优先级进行调度。任务堆栈:任务切换时保存当前的程序状态、数据信息(类似于函数调用的使用的栈)。C/OS-III任务使用任务基本概念03任务概述概述C/OS-III系统中使用 CPU_STK 表示任务栈数据类型,对于32位处理器,被定义为 unsigned int 类型,任务栈本质上就是一片连续的内存。一般定义为全局数组,栈大小不容易精确计算得到,因此,在RAM资源允许情况下,可以尽量分配大一些。如果任务栈分配过小,会导致任务切换时,无法保存全部任务数据,CPU状态信息,导致任务栈溢出,引发程序运行异常。任务栈定义#define START_STK_SIZE 128 /start_task任务栈大小 CPU_STK START_TASK_STKSTART_STK_SIZE;/start_task任务栈#define TASK1_STK_SIZE 256 /task1_task任务栈大小 CPU_STK TASK1_TASK_STKTASK1_STK_SIZE;/task1_task任务栈#define TASK2_STK_SIZE 256 /task2_task任务堆栈大小CPU_STK TASK2_TASK_STKTASK2_STK_SIZE;/task2_task任务栈C/OS-III任务使用定义任务栈03概述C/OS-III系统中使用 OS_PRIO 表示任务优先级数据类型,这个类型是可以根据需要配置的,默认是定义为unsigned char类型,即范围是0255,数值越小优先级越高。在定义优先级时,不建议用户使用0,1,2 以及最小2个优先级数值(这5个优先级在第2节中优先级小节中已经有讲述)。在C/OS-III 中支持不同任务使用相同优先级,如相同优先级任务都就绪了,则采用时间片轮转调度方式调度这些任务。优先级定义#define START_TASK_PRIO 3 /start_task 任务优先级#define TASK1_TASK_PRIO 4 /task1_task 任务优先级#define TASK2_TASK_PRIO 5 /task2_task 任务优先级C/OS-III任务使用定义优先级03概述任 务 控 制 块 TCB(Task Control Block)是 内 核 使 用 的 一 种 数 据 结 构(类型名为OS_TCB),用来维护任务相关的信息。在C/OS-III中,每个任务都要有自己的TCB,创建任务前需要开发者定义。当调用任务相关函数(即OSTask*()这类函数)时,要把任务TCB的地址传递给所调用的函数。控制块定义/定义全局任务控制块变量OS_TCB StartTaskTCB;/start_task 任务控制块OS_TCB Task1_TaskTCB;/task1_task 任务控制块OS_TCB Task2_TaskTCB;/task2_task 任务控制块C/OS-III任务使用定义任务控制块03任务函数模板C/OS-III任务使用定义任务函数03任务1函数/t a sk 1任 务 函 数 vo i d t as k 1 _ t a s k(vo i d *p _ arg)O S_ E RR e r r;C P U _ S R _ A LLO C();u 8 ta s k 1_ n u m =0;p _ a rg =p _ arg;w h i l e(1)t a s k1 _ n u m+;/任 务 执 1行 次 数 加 1 L E D 0 =L E D 0;/取 反 L E D 0 状 态 p r i n tf(任 务 1已 经 执 行:%d 次 r n,t a sk 1 _ n u m);i f(t as k 1_ n u m =5)/任 务 1执 行 5此 后 删 除 掉 任 务 2 O S Tas k D e l(OS _TC B*)&Ta s k 2 _ Ta s k TC B,&e r r);p ri n t f(任 务 1删 除 了 任 务 2!r n);/延 时 1 s,放 弃 C P U,C P U去 执 行 其 他 任 务 代 码 O S T i m e D l y H MS M(0,0,1,0,O S _ O P T _ T I ME _ H MSM _ S T R IC T,&e r r);C/OS-III任务使用定义任务函数03任务2函数/task2任务函数 void task2_task(void*p_arg)OS_ERR err;CPU_SR_ALLOC();u8 task2_num=0;p_arg=p_arg;while(1)task2_num+;/任务执2行次数加1,到255会清0 LED1=LED1;/取反 LED1 状态 printf(任务2已经执行:%d次rn,task2_num);/延时1s,放弃CPU,CPU去执行其他任务代码 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err);C/OS-III任务使用定义任务函数03OSTaskCreate(OS_TCB *)&Task1_TaskTCB,/任务控制块 (CPU_CHAR *)Task1 task,/任务名字 (OS_TASK_PTR)task1_task,/任务函数 (void *)0,/传递给任务函数的参数 (OS_PRIO )TASK1_TASK_PRIO,/任务优先级 (CPU_STK *)&TASK1_TASK_STK0,/任务堆栈基地址 (CPU_STK_SIZE)TASK1_STK_SIZE/10,/任务堆栈深度限位 (CPU_STK_SIZE)TASK1_STK_SIZE,/任务堆栈大小 (OS_MSG_QT Y )0,/任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 (OS_TICK )0,/当使能时间片轮转时的时间片长度,为0时为默认长度,(void *)0,/用户补充的存储区 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,/任务选项 (OS_ERR *)&err);/存放该函数错误时的返回值C/OS-III任务使用创建任务03task1_task任务创建OSTaskCreate(OS_TCB *)&Task2_TaskTCB,/任务控制块 (CPU_CHAR *)Task2 task,/任务名字 (OS_TASK_PTR)task2_task,/任务函数 (void *)0,/传递给任务函数的参数 (OS_PRIO )TASK2_TASK_PRIO,/任务优先级 (CPU_STK *)&TASK2_TASK_STK0,/任务堆栈基地址 (CPU_STK_SIZE)TASK2_STK_SIZE/10,/任务堆栈深度限位 (CPU_STK_SIZE)TASK2_STK_SIZE,/任务堆栈大小 (OS_MSG_QT Y )0,/任务内部消息队列接收的最大消息数,为0时禁止接收消息 (OS_TICK )0,/当使能时间片轮转时的时间片长度,为0时为默认长度,(void *)0,/用户补充的存储区 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,/任务选项 (OS_ERR *)&err);/存放该函数错误时的返回值C/OS-III任务使用创建任务03task2_task任务创建完整示例见配套代码:例6-1 UCOSIII任务创建和删除-sim0404C/OS-III时间管理OSTimeDlyOSTimeDlyHMSMOSTimeDlyResumeOSTimeGet/Set原型:void OSTimeDly(OS_TICK dly,OS_OPT opt,OS_ERR*p_err)功能:对一个任务进行延时操作,当前任务调用后进入等待状态,放弃指定长时长的CPU。参数:dly:指定延时的时间长度,这里单位为时间节拍数。opt:指定延迟使用的选项,有四种选项。OS_OPT_TIME_DLY :相对模式OS_OPT_TIME_TIMEOUT:和 OS_OPT_TIME_DLY 一样OS_OPT_TIME_MATCH :绝对模式OS_OPT_TIME_PERIODIC:周期模式p_err:指向存放函数返回的错误码说明:相对模式:从当前延时时刻开始,延时指定长时间。绝对模式:从上电开始计算到某个时间点定延时到。C/OS-III时间管理OSTimeDly04OSTimeDly函数说明原型:void OSTimeDlyHMSM(CPU_INT16U hours,/需要延时的小时数 CPU_INT16U minutes,/需要延时的分钟数 CPU_INT16U seconds,/需要延时的秒钟数 CPU_INT32U milli,/需要延时的毫秒数 OS_OPT opt,/延时选项 OS_ERR *p_err)/指向存放函数返回的错误码功能:对任务进行延时操作,调用后当前任务放弃指定长时长的CPU。参数:opt:比 OSTimeDly()函数多了两个选项:OS_OPT_TIME_HMSM_STRICT 和 OS_OPT_TIME_HMSM_NON_STRICT;OS_OPT_TIME_HMSM_STRICT:选项的话将会检查延时参数,hours 的范围应该是 099;minutes 的范围应该是 059seconds 的范围为 059;milli 的范围为 0999OS_OPT_TIME_HMSM_NON_STRICT:hours 的范围为 0999;minutes 的范围为 09999 seconds 的范围为 065535;milli 的范围为 04294967259C/OS-III时间管理OSTimeDlyHMSM04OSTimeDlyHMSM函数说明 原型:void OSTimeDlyResume(OS_TCB *p_tcb,OS_ERR *p_err)功能:恢复使用OSTimeDly或 OSTimeDlyHMSM 延时挂起的任务(即提前结束延时)。参数:p_tcb:需要恢复的任务的任务控制块。p_err:指向存放函数返回的错误码C/OS-III时间管理OSTimeDlyResume04OSTimeDlyResume函数说明原型:OS_TICK OSTimeGet(OS_ERR *p_err)功能:获取当前时钟节拍计数器的值。参数:p_err:指向存放函数返回的错误码C/OS-III时间管理OSTimeGet/Set04OSTimeGet 函数说明原型:void OSTimeSet(OS_TICK ticks,OS_ERR *p_err)功能:设置时钟节拍计数器的值,用户很少使用该函数,不建议开发者使用。参数:ticks:要设置的时钟节拍器数值 p_err:指向存放函数返回的错误码OSTimeSet 函数说明0505C/OS-III任务管理任务状态迁移任务管理服务C/OS-III系统每个任务都有多种工作作态,在不同的情况下会进行状态的切换,任务状态分别为休眠态,就绪态,等待态,运行态,中断服务态。休眠态(dormantstate):是指任务已经存在于存储器中,但还不受C/OS-III的管理。就绪态(Ready):当一个任务准备运行时,它就进人就绪态。在同一时刻可以有任意个任务处于就绪态,任务就绪表记录这些就绪的任务。等待态(Pending):把任务会放入等待表(pend-list或wait-list)等待某特定事件发生,任务进入到等待态。任务在等待某个事件发生的时候并不消耗任何CPU时间。运行态(Runing):就绪态任务在调度条件满足时进入运行态(running state)。对于单核CPU,在任何时刻只有一个任务能够运行。中断服务态:发生中断时,当前正在运行的任务会被挂起,CPU开始执行中断服务子程序ISR,此时任务处于中断服务态。C/OS-III任务管理任务状态迁移05详细状态转换图见:ucosiii-manual-5-5-1 TASK STATES.pdfC/OS-III任务管理任务管理服务05任务管理服务任务创建函数p_arg:传递给任务的参数,很少使用,一般设置为NULL,任务函数原型:void start_task(void*p_arg);q_size:C/OS-III中每个任务都有一个可裁剪的内部消息队列,我们要定义宏OS_CFG_TASK_Q_EN0,这是才会使用这个内部消息队列;opt:包含任务的特定选项,常用设置:OS_OPT_TASK_NONE:表示没有任何选项;OS_OPT_TASK_STK_CHK:指定是否允许检测该任务的堆栈;OS_OPT_TASK_STK_CLR:指定是否清除该任务的堆栈:OS_OPT_TASK_SAVE_FP:指定是否存储浮点寄存器;C/OS-III任务管理任务相关操作05注意:不能在中断服务程序中调用OSTaskCreat()函数来创建任务。用来删除一个任务,当一个任务不需要运行的话,我们就可以将其删除掉,删除任务不是说删除任务代码,而是C/OS-III不再管理这个任务。C/OS-III任务管理任务相关操作05任务删除函数暂停任务运行,后面可以使用OSTaskResume()函数恢复这个任务运行。多次调用OSTaskSuspend()函数来挂起一个任务,因此我们需要调用同样次数的OSTaskResume()函数才可以恢复被挂起的任务,这一点非常重要。任务挂起函数C/OS-III任务管理任务相关操作05OSTaskResume()函数用来恢复被OSTaskSuspend()函数挂起的任务,OSTaskResume()函数是唯一能恢复被挂起任务的函数。任务恢复函数0505C/OS-III操作系统作业 作业概述作业任务描述C/OS-III操作系统作业 05作业概述根据本章内容讲解,编写代码,练习C/OS-III任务使用,代码功能划分功能。作业任务1.作业:基于C/OS-III,编写一个任务,实现跑马灯。06致谢ACKNOWLEDGEMENTS感谢聆听,如有不足之处敬请指出,欢迎提出您的宝贵建议!致谢