UCOS—III 常用资料整理
ucosiii操作系统工作原理
ucosiii操作系统工作原理ucosiii是一种常用的嵌入式实时操作系统,它具有高度可靠性和高实时性的特点。
本文将介绍ucosiii操作系统的工作原理。
ucosiii操作系统是由美国Micrium公司开发的一种实时操作系统,它是用C语言编写的,可以运行在各种嵌入式系统中。
ucosiii采用了一种基于内核对象的任务管理机制,可以有效地管理系统中的各个任务,并提供了丰富的服务功能,如任务间通信、时间管理、内存管理等。
在ucosiii中,任务是操作系统的基本执行单元,每个任务都有自己的优先级和堆栈空间。
ucosiii使用了一种优先级抢占式的调度算法,即优先级高的任务可以抢占优先级低的任务的执行权。
这种调度算法可以保证高优先级任务的及时响应,并提高系统的实时性。
ucosiii的任务管理机制是通过任务控制块(TCB)来实现的。
每个任务都有一个对应的TCB,其中包含了任务的状态、优先级、堆栈指针等信息。
ucosiii通过不同的系统调用函数来管理任务的创建、删除、挂起、恢复等操作。
任务的切换是通过ucosiii的任务调度器来完成的,任务调度器会按照任务的优先级进行任务切换。
ucosiii提供了丰富的服务功能,其中包括任务间通信、时间管理、内存管理等。
任务间通信是通过信号量、邮箱、消息队列等机制来实现的,可以实现任务之间的数据共享和同步。
时间管理功能可以实现任务的定时执行和延时操作,可以满足实时系统对时间要求的需要。
内存管理功能可以对系统的内存进行分配和释放,提高系统的资源利用率。
ucosiii的内核对象是操作系统提供的一种资源管理机制,包括信号量、邮箱、消息队列等。
这些内核对象可以用于任务间的同步和通信,可以有效地避免资源竞争和数据冲突的问题。
ucosiii的工作原理可以总结为以下几个步骤:1. 初始化ucosiii操作系统,包括初始化任务控制块、任务堆栈等。
2. 创建任务,包括创建任务控制块、任务堆栈等。
UCOS-II和UCOS-III的性能对比(中文)
否
是
是
是
否
是
uC/OS-III 中文资料
任务级的时基定时 否
器处理
提供的服务
~20
MISRA-C:1998
否
MISRA-C:2004
否
DO178B
否
EUROCAE ED-12B
FDA 认证
否
SIL3/SIL4 IEC
否
IEC-61508
否
否
是
~90
~70
是(除了 10 个规 N/A
则)
否
是(除了 7 个规则)
是
申请中
是
申请中
是
ห้องสมุดไป่ตู้
uCOSIII使用心得(持续更新中)
uCOSIII使⽤⼼得(持续更新中)1.时间管理的作⽤?时间管理函数实质上是各任务进⼊调度的⼊⼝,表现为各任务按照设定的时钟节拍循环执⾏。
设定不同的延迟时间对任务切换有很⼤影响:设定延迟时间合理,则程序运⾏流畅;若设定延迟时间不合理,则各任务调度可能会存在堵塞,程序不能按照设定的功能进⾏。
2.信号量的理解?信号量主要⽤于共享资源(如硬件外设)的管理和标志事件发⽣(cnt参数设为0)。
信号量是⼀个数值,对于多值信号量,可以取⼀定范围内的整数,计数形式;⽽对于互斥信号量来说,只能取0和1两个数。
如果任务接收到⼀个信号量,则该信号量的数值会⾃动减1。
对于互斥信号量,被⼀个任务接收后,会减为0。
此时若不重新发布(释放),则其他需要相同互斥量的任务不能执⾏。
建⽴信号量的⼯作必须在任务级代码中或者多任务启动之前完成。
想得到信号量的任务,必须执⾏等待操作(pend)。
3.互斥信号量的理解及使⽤?互斥信号量形象的解释:⼀间屋⼦,只能⼀个⼈进去。
门⼝箱⼦⾥放着⼀把钥匙。
当有钥匙时箱⼦显⽰1,⽆钥匙时显⽰0。
来⼈看见1就打开箱⼦取出钥匙进屋,同时显⽰减1为0,再来⼈时看见0,就知道有⼈在屋⼦⾥,于是在外等待。
屋⾥⼈出来时,把钥匙放回箱中,显⽰加1。
后⾯的⼈看见1⼜可以进⼊。
这⾥钥匙就相当于互斥信号量,根据钥匙有⽆取0/1两个值;屋⼦相当于公共资源,同⼀时间只能由⼀⼈使⽤。
对于与硬件设计相关的公共资源,如SPI/I2C/UART接⼝,都是独占类型的,也就是⼀个任务在使⽤这些资源的时候,其余的申请使⽤该资源的任务只能处于等待状态。
这就需要互斥型信号。
4.信号量的删除?删除信号量是⽤信号量删除函数,但前提是删除操作该信号量的所有任务,否则删除⽆效。
4.临界段的作⽤?临界段的作⽤是保证临界段内的程序执⾏不受中断的⼲扰,能持续运⾏直⾄跳出临界段。
所以,对⼀些需要持续运⾏的操作,可以放在临界段中执⾏,特别是⼀些关键任务。
UCOSIII
UCOSIII代码临界区CPU_SR_ALLOC()OS_CRITICAL_ENTER()OS_CRITICAL_EXIT()延时OSTimeDly()OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&er r)OSTimeDlyResume()钩子函数void App_OS_IdleT askHook (void)在空闲任务的钩子函数 OSIdleTaskHook()中不能出现可以让空闲任务进入等待态的代码!创建删除函数OSTaskCreate()OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err)挂起恢复任务OSTaskSuspend()OSTaskResume()时间片轮转调度OSSchedRoundRobinCfg(DEF_ENABLED,1,&err) 时间片轮转调度初始化void OSSchedRoundRobinYield (OS_ERR *p_err) 放弃时间片中断函数OSIntEnter() 进入中断时放在最前面OSIntExit() 放在中断函数最下面,用于退出中断时做一次任务切换定时器OSTmrCreate()OSTmrStart()OSTmrStop()在定时器的回调函数里面一定要注意避免使用任何可以阻塞或者删除掉定时器任务的函数!信号量OSSemCreate() 创建一个信号量OSSemDel() 删除一个信号量OSSemPend() 等待一个信号量OSSemPost() 释放一个信号量OSSemPendAbort() 取消等待OSSemSet() 强制设置一个信号量的值互斥信号量(解决优先级反转)OSMutexCreate() 创建一个互斥信号量OSMutexDel() 删除一个互斥型信号量OSMutexPend() 等待一个互斥型信号量OSMutexPost() 释放一个互斥型信号量OSMutexPendAbort() 取消等待只有任务才能使用互斥信号量(中断服务程序则不可以)任务内建信号量OSTaskSemPend() 等待任务信号量OSTaskSemPost() 发布任务信号量OSTaskSemPendAbort() 取消等待任务信号量OSTaskSemSet() 强行设置任务信号量计数消息队列OSQCreate() 创建一个消息队列OSQDel() 删除一个消息队列OSQFlush() 清空一个消息队列OSQPend() 等待消息队列OSQPendAbort() 取消等待消息队列OSQPost() 向消息队列发送一条消息中断服务程序只能使用 OSQPost()函数!内建消息队列OSTaskQPend() 等待消息OSTaskQPost() 向任务发送一条消息OSTaskQPendAbort() 取消等待消息OSTaskQFlush() 清空任务的消息队列ISR只能OSTaskQPost()!同时请求多个内建对象UCOSIII 中只支持同时等待多个信号量和消息队列,不支持同时等待多个事件标志组和互斥信号量OSPendMulti()。
UCOSIII任务管理III
UCOSIII任务管理III重点在于第三部分代码讲解•UCOSIII可剥夺型内核调度一、任务级调度器OS_Sched(),在OSTimeDlyHMSM中调用了该函数二、中断级调度器OSInitExit(),在退出中断的时候,启动任务调度。
1、释放信号量或者发送消息,也可通过配置相应的参数不发生任务调度。
2、使用延时函数OSTimeDly()或者OSTimeDlyHMSM()。
Dly()是时间延迟,DlyHMSM()是按节拍延迟delay_ms()封装了TimeDly3、任务等待的事情还没发生(等待信号量,消息队列等)。
4、任务取消等待。
5、创建任务。
6、删除任务。
7、删除一个内核对象。
8、任务改变自身的优先级或者其他任务的优先级。
9、任务通过调用OSTaskSuspend()将自身挂起。
10、任务解挂某个挂起的任务。
11、退出所有的嵌套中断。
12、通过OSSchedUnlock()给调度器解锁。
13、任务调用OSSchedRoundRobinYield()放弃其执行时间片。
14、用户调用OSSched()。
OSSchedLock()上锁OSSchedUnlock()解锁•时间片轮转调度器为:OS_SchedRoundRobin()•任务可以主动放弃时间片任务切换是任务调度的一部分任务切换分为两种:任务级切换和中断级切换。
任务级切换函数为:OSCtxSw()。
中断级切换函数为:OSIntCtxSw()。
OS_ERR err;...OSInit(&err); //OSInit(&err)必须先于其他所有函数执行OS_CRITICAL_ENTER(); //进入临界区OSTaskCreate();OS_CRITICAL_EXIT(); //退出临界区...OSStart(&err);•临界区是用于保护代码不被打断的代码讲解在于理清该函数的思路。
部分代码会省略中文备注的是讲解部分void OSInit (OS_ERR *p_err){CPU_STK *p_stk;CPU_STK_SIZE size;/*检查参数是否合格*/#ifdef OS_SAFETY_CRITICALif (p_err == (OS_ERR *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return;}#endifOSInitHook(); /* Call port specific initialization code */OSIntNestingCtr = (OS_NESTING_CTR)0; /* Clear the interrupt nesting counter *//*标识操作系统是否在运行*/OSRunning = OS_STATE_OS_STOPPED; /* Indicate that multitasking not started */OSSchedLockNestingCtr = (OS_NESTING_CTR)0; /* Clear the scheduling lock counter */OSTCBCurPtr = (OS_TCB *)0; /* Initialize OS_TCB pointers to a known state */OSTCBHighRdyPtr = (OS_TCB *)0;/*=============此处省略部分初始化,暂时不讲解==============================*//*优先级位映射表初始化,在任务管理(中)中进行了讲解*/OS_PrioInit(); /* Initialize the priority bitmap table *//*任务就绪队列,在任务管理(中)中进行了讲解*/OS_RdyListInit(); /* Initialize the Ready List *//*内存管理初始化*/#if OS_CFG_MEM_EN > 0u /* Initialize the Memory Manager module */OS_MemInit(p_err);if (*p_err != OS_ERR_NONE) {return;}#endif/*消息池初始化*/#if (OS_MSG_EN) > 0u /* Initialize the free list of OS_MSGs */OS_MsgPoolInit(p_err);if (*p_err != OS_ERR_NONE) {return;}#endif/*互斥量初始化*/#if OS_CFG_MUTEX_EN > 0u /* Initialize the Mutex Manager module */OS_MutexInit(p_err);if (*p_err != OS_ERR_NONE) {return;#endif/*消息队列初始化*/#if OS_CFG_Q_EN > 0uOS_QInit(p_err); /* Initialize the Message Queue Manager module */if (*p_err != OS_ERR_NONE) {return;}#endif/*信号量初始化*/#if OS_CFG_SEM_EN > 0u /* Initialize the Semaphore Manager module */OS_SemInit(p_err);if (*p_err != OS_ERR_NONE) {return;}#endif/*=============省略了task一些初始化,暂时不讲解==============================*//*空闲任务初始化,优先级MAX-1*/OS_IdleTaskInit(p_err); /* Initialize the Idle Task */if (*p_err != OS_ERR_NONE) {return;}/*时钟节拍任务初始化*/OS_TickTaskInit(p_err); /* Initialize the Tick Task */if (*p_err != OS_ERR_NONE) {return;}/*=============省略了一些初始化,暂时不讲解==============================*/OSCfg_Init();}通过如上OSInit对操作系统运行所需要的资源进行了准备•本质是开始运行就绪队列中最高优先级的任务void OSStart (OS_ERR *p_err){/*检查参数合法性*/#ifdef OS_SAFETY_CRITICALif (p_err == (OS_ERR *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return;}#endifif (OSRunning == OS_STATE_OS_STOPPED) {/*找到就绪队列中最高优先级任务*/OSPrioHighRdy = OS_PrioGetHighest(); /* Find the highest priority */OSPrioCur = OSPrioHighRdy;OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;OSTCBCurPtr = OSTCBHighRdyPtr;OSRunning = OS_STATE_OS_RUNNING;/*开始执行*/OSStartHighRdy(); /* Execute target specific code to start task */*p_err = OS_ERR_FATAL_RETURN; /* OSStart() is not supposed to return */} else {*p_err = OS_ERR_OS_RUNNING; /* OS is already running */}}。
UCOSIII任务管理I
UCOSIII任务管理I基于stm32代码讲解本文第一部分:涉及移植后stm32工程中delay.c,usart.c,sys.c 3个源文件中重要的函数说明第二部分:讲解ucos任务管理的基本概念和相关代码帮助理解,包括-1.任务的组成部分2.系统任务3.任务状态4.任务状态的切换第三部分:进行总结归纳和反思1-delay.c在m3,m4中代码完全一样。
在m4权威指南中NVIC和中断一章中Systick有详细讲解滴答定时器void SysTick_Handler(void){if(delay_osrunning==1) //操作系统正常运行后执行{OSIntEnter(); //进入中断OSTimeTick(); //调用ucos中断服务函数OSIntExit(); //触发任务切换软中断(进入就绪态)}}•delay_init,初始化了ucos的时钟节拍•delay_ms在<=最小周期的时候使用原本的函数-不会引起任务调度,在大于的时候使用ucos自带的函数-会引起任务调度•delay_us不会引起任务调度2-usart.c•在中断中要使用ucos特定的中断进入和退出函数void USART1_IRQHandler(void){u8 Res;#if SYSTEM_SUPPORT_OSOSIntEnter(); //使用ucos操作系统#endif....................//自定义的中断处理#if SYSTEM_SUPPORT_OSOSIntExit(); //退出中断(调度优先级最高的任务)#endif}3-sys.c 完全不变1-任务的组成•任务堆栈:上下文切换用于保存任务当前环境。
也就是stm32内部寄存器的值。
•任务控制块:保存任务的各个属性•任务函数:完成指定功能1-1三大组成使用部分代码讲解//任务优先级#define TASK1_TASK_PRIO 4//任务堆栈大小#define TASK1_STK_SIZE 128//任务控制块OS_TCB Task1_TaskTCB;//任务函数CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];void task1_task(void *p_arg);void XXX_task(void *p_arg){while(1){...//任务处理过程OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&er r); //延时一秒}}//创建task1任务OSTaskCreate((OS_TCB * )&Task1_TaskTCB, //任务控制块(CPU_CHAR * )"Task1 task",(OS_TASK_PTR )task1_task, //使用任务函数(void * )0,(OS_PRIO )TASK1_TASK_PRIO, //任务优先级(CPU_STK * )&TASK1_TASK_STK[0],//任务堆栈(CPU_STK_SIZE)TASK1_STK_SIZE/10,(CPU_STK_SIZE)TASK1_STK_SIZE,(OS_MSG_QTY )0,(OS_TICK )0,(void * )0,(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CL R,(OS_ERR * )&err);2-系统任务1、空闲任务:UCOSIII创建的第一个任务,UCOSIII必须创建的任务,此任务有UCOSIII自动创建,不需要用户手动创建。
【ucos-III教程】第11章
【ucos-III教程】第11章 uCOS-III内核函数分析(上)第11章 uCOS-III内核函数分析(上)本期教程开始分析µCOS-III的内核函数,源码的分析采⽤先对源码进⾏注释,然后讲解函数实现的功能和相关的原理分析,最后是举⼀个例⼦(如果这个函数是供外部函数调⽤的)。
内核函数很重要,是学习任务管理,任务间通信机制的基础。
希望初学的同学认真学习,这部分应该算是µCOS-III的核⼼代码。
11.1系统配置⽂件11.2源码⽂件11.3µCOS-III初始化11.4µCOS-III启动11.5获取系统版本11.6空闲任务11.7临界段11.8安全关键IEC6150811.9任务切换11.10调度锁11.11 Round-Robin调度11.12总结11.1 系统配置⽂件下⾯先简单说明下µCOS-III中⼏个配置⽂件的作⽤,⽅便分析源码的时候查看,配置⽂件主要有以下⼏个:11.1.1 lib_cfg.h配置⽂件lib_cfg.h⽂件内容如下:#ifndef LIB_CFG_MODULE_PRESENT#define LIB_CFG_MODULE_PRESENT#define LIB_MEM_CFG_ARG_CHK_EXT_EN DEF_ENABLED#define LIB_MEM_CFG_OPTIMIZE_ASM_EN DEF_ENABLED#define LIB_MEM_CFG_ALLOC_EN DEF_ENABLED#define LIB_MEM_CFG_HEAP_SIZE 23u * 1024u#endiflib_cfg.h是⽤于给uC/LIB做配置的头⽂件。
如果程序中使⽤uC/LIB的话,需要调⽤函数Mem_Init()进⾏初始化。
11.1.2 os_cfg.h配置⽂件os_cfg.h⽂件中的内容如下:#ifndef OS_CFG_H#define OS_CFG_H#define OS_CFG_APP_HOOKS_EN 1u#define OS_CFG_ARG_CHK_EN 1u#define OS_CFG_CALLED_FROM_ISR_CHK_EN 1u#define OS_CFG_DBG_EN 1u#define OS_CFG_ISR_POST_DEFERRED_EN 0u#define OS_CFG_OBJ_TYPE_CHK_EN 1u#define OS_CFG_TS_EN 1u#define OS_CFG_PEND_MULTI_EN 1u#define OS_CFG_PRIO_MAX 64u#define OS_CFG_SCHED_LOCK_TIME_MEAS_EN 0u#define OS_CFG_SCHED_ROUND_ROBIN_EN 0u#define OS_CFG_STK_SIZE_MIN 64u#define OS_CFG_FLAG_EN 1u#define OS_CFG_FLAG_DEL_EN 1u#define OS_CFG_FLAG_MODE_CLR_EN 1u#define OS_CFG_FLAG_PEND_ABORT_EN 1u#define OS_CFG_MEM_EN 1u#define OS_CFG_MUTEX_EN 1u#define OS_CFG_MUTEX_DEL_EN 1u#define OS_CFG_MUTEX_PEND_ABORT_EN 1u#define OS_CFG_Q_EN 1u#define OS_CFG_Q_DEL_EN 1u#define OS_CFG_Q_FLUSH_EN 1u#define OS_CFG_Q_PEND_ABORT_EN 1u#define OS_CFG_SEM_EN 1u#define OS_CFG_SEM_DEL_EN 1u#define OS_CFG_SEM_PEND_ABORT_EN 1u#define OS_CFG_SEM_SET_EN 1u#define OS_CFG_STAT_TASK_EN 1u#define OS_CFG_STAT_TASK_STK_CHK_EN 1u#define OS_CFG_TASK_CHANGE_PRIO_EN 1u#define OS_CFG_TASK_DEL_EN 1u#define OS_CFG_TASK_Q_EN 1u#define OS_CFG_TASK_Q_PEND_ABORT_EN 1u#define OS_CFG_TASK_PROFILE_EN 1u#define OS_CFG_TASK_REG_TBL_SIZE 1u#define OS_CFG_TASK_SEM_PEND_ABORT_EN 1u#define OS_CFG_TASK_SUSPEND_EN 1u#define OS_CFG_TIME_DLY_HMSM_EN 1u#define OS_CFG_TIME_DLY_RESUME_EN 1u#define OS_CFG_TMR_EN 1u#define OS_CFG_TMR_DEL_EN 1u#endif这个配置⽂件⽐较的重要,主要⽤于µCOS-III源码中相关函数的配置。
ucosIII中断、临界区与时间管理
ucosIII中断、临界区与时间管理中断:应内部或外部异步事件的请求中止当前任务,而去处理异步事件所要求的任务的过程叫做中断。
void USART1_IRQHandler(void){OSIntEnter();//中断服务程序OSIntExit();}•1•2•3•4•5•6void OSIntEnter (void){if (OSRunning != OS_STATE_OS_RUNNING) {//用于确定系统是否正常运行return}if (OSIntNestingCtr >= (OS_NESTING_CTR)250u) {return;}OSIntNestingCtr++;//中断嵌套的层数}•1•2•3•4•5•6•7•8•9•10OSIntNestingCtr来记录中断嵌套次数,UCOSIII最多支持250级的中断嵌套。
退出中断服务函数时要调用函数OSIntExit()。
退出函数内部步骤如下:1.系统是否运行。
不符合则退出2.关闭全局中断3.中断嵌套次数和任务切换次数记录4.进行中断级任务切换void OSIntExit (void){CPU_SR_ALLOC();//宏定义的CPU_SRif (OSRunning != OS_STATE_OS_RUNNING) { /* Has the OS started? */return; /* No */ }/*关闭全局中断,包括关闭滴答定时器中断*/CPU_INT_DIS();if (OSIntNestingCtr == (OS_NESTING_CTR)0) { /*Prevent OSIntNestingCtr from wrapping */CPU_INT_EN();return;}OSIntNestingCtr--;//中断嵌套次数if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* ISRsstill nested? */CPU_INT_EN(); /* Yes */return;}/*OSSchedLockNestingCtr 调度器是否加锁的标志*/if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Scheduler still locked? */CPU_INT_EN(); /* Yes */return;}/*获得最高优先级的任务*/OSPrioHighRdy = OS_PrioGetHighest(); /* Findhighest priority */OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;/* Get highest priority task ready-to-run */if (OSTCBHighRdyPtr == OSTCBCurPtr) { /* Currenttask still the highest priority? */CPU_INT_EN(); /* Yes */return;}#if OS_CFG_TASK_PROFILE_EN > 0uOSTCBHighRdyPtr->CtxSwCtr++; /* Inc. # of context switches for this new task */#endifOSTaskCtxSwCtr++; //任务切换的次数 /* Keep track of the total number of ctx switches */#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)OS_TLS_TaskSw();#endif/*中断级任务调度*/OSIntCtxSw(); /* Perform interrupt level ctx switch */CPU_INT_EN();}•1•2•3•4•5•6•7•8•9•10•11•12•13•14 •15 •16 •17 •18 •19 •20 •21 •22 •23 •24 •25 •26 •27 •28 •29 •30 •31 •32 •33 •34 •35 •36 •37 •38 •39 •40 •41 •421.临界段代码也叫做临界区,是指那些必须完整连续运行,不可被打断的代码段。
UCOS—III-常用资料整理
UC/OS—III的常用资料整理任务堆栈:存储任务中的调用的函数、局部变量、中断服务程序和CPU寄存器的值。
全局变量的保护:1.如果只在一个任务中写(或只有一个数据),而在其他任务中只是读取,则可以不用互斥型信号量,最多会造成读取的数据未被完全写完。
2.如果全局变量在多个任务中写,则需要用互斥型信号量保护,这样当有任务申请到互斥型信号量(保护不可重入的程序段)写数据时,其他任务的同一个互斥型信号量必须等待上一个任务的释放才可进行写。
3.如果全局变量在中断中写,则在其他任务中的全局变量的写操作要用临界段(禁止中断和禁止调度:保护不可被分割的程序段)保护。
(因为如果不关中断相当于中断的优先级最高,而且不能被像其他任务那样挂起。
)OS_CFG_ISR_POST_DEFERRED_EN为1临界段使用锁调度器方式;为0临界段使用禁中断方式(CPU_SR_ALLOC();存放中断的变量OS_CRITICAL_ENTER();OS_CRITICAL_EXIT();OS_CRITICAL_EXIT_NO_SCHED();OSSchedLockNestingCtr记录调度器被锁的次数)。
检测任务堆栈的使用情况:OS_CFG_STAT_TASK_STK_CHK_EN使能OS_ERRerr;CPU_STK_SIZE stk_free;CPU_STK_SIZE stk_used;OSTaskStkChk(&TaskBStkTCB,&stk_free,&stk_used,&err);中断中使用OSIntEnter(); 和OSIntExit();是为了退出中断后执行中断调度操作,如果中断中并未用到OSSemPost();等系统函数,则退出中断服务程序后不需要进行任务调度,就可以不在中断服务程序中使用OSIntEnter(); 和OSIntExit();。
(有时候用:CPU_CRITICAL_ENTER();OSIntNestingCtr++;CPU_CRITICAL_EXIT();替代OSIntEnter();)一、变量类型在cpu.h中是有关cpu变量的重新定义,还包括CPU_STK(CPU堆栈类型),和CPU_STK_SIZE(CPU堆栈类型的大小)的定义,CPU_SR(CPU状态寄存器的定义)。
ucos学习_知识点笔记
Chapter 1 实时系统实时系统的特点是,如果逻辑和时序出现偏差将会引起严重后果的系统.代码的临界段代码的临界段也称为临界区,指处理时不可分割的代码。
一旦这部分代码开始执行,则不允许任何中断打入。
为确保临界段代码的执行,在进入临界段之前要关中断,而临界段代码执行完以后要立即开中断。
任务都处在以下5种状态就绪态、运行态、挂起态(等待某一事件发生)和被中断态(参见下图),休眠态相当于该任务驻留在内存中,但并不被多任务内核所调度。
任务切换(Context Switch or Task Switch当多任务内核决定运行另外的任务时,它保存正在运行任务的当前状态(Context),即CPU寄存器中的全部内容。
这些内容保存在任务的当前状况保存区(Task’s Context Storage area),也就是任务自己的栈区之中。
(见下图)。
入栈工作完成以后,就是把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU 的寄存器,并开始下一个任务的运行。
这个过程叫做任务切换。
任务切换过程增加了应用程序的额外负荷。
CPU的内部寄存器越多,额外负荷就越重。
做任务切换所需要的时间取决于CPU有多少寄存器要入栈。
实时内核的性能不应该以每秒钟能做多少次任务切换来评价。
不可剥夺内核运行示意图:可剥夺型内核当系统响应时间很重要时,要使用可剥夺型内核。
(运行示意图如下)可重入性(Reentrancy)可重入型函数可以被一个以上的任务调用,而不必担心数据的破坏。
可重入型函数任何时候都可以被中断,一段时间以后又可以运行,而相应数据不会丢失。
可重入型函数或者只使用局部变量,即变量保存在CPU寄存器中或堆栈中。
如果使用全局变量,则要对全局变量予以保护。
可重入Example:void strcpy(char *dest, char *src){while (*dest++ = *src++){*dest = NUL;; }不可重入函数举例:int Temp;void swap(int *x, int *y){Temp = *x;*x = *y;*y = Temp;}此不可重入函数被分别调用后的后果:使用以下技术之一即可使Swap()函数具有可重入性:把Temp定义为局部变量调用Swap()函数之前关中断,调动后再开中断用信号量禁止该函数在使用过程中被再次调用互斥条件与共享资源打交道时,使之满足互斥条件最一般的方法有:关中断使用测试并置位指令禁止做任务切换利用信号量信号量信号量是60年代中期 Edgser Dijkstra 发明的。
uCosIII学习
uCosIII 学习本人前言:很久没有练习英语了,本想发点时间在工作之余,翻译一下μC/OS III用户手册,发现还是有点吃力,于是乎,参见网络上的嘉兴学院的屈环宇同学的译本,谢谢!前言做为Micrium公司推出的第三代操作系统,μC/OS III 支持现代的实时内核所期待的大部分功能;μC/OS III是一个可裁剪、可固化、基于优先级的实时内核,支持例如资源管理、同步、任务间的通信等等。
同时μC/OS III也具备一些很有特色的功能,是很多的其他的实时内核所不具备的,比如完备的实际测量性能、直接发送信号或消息到任务、任何可同时等待多个内核对象等。
与第二代μC/OS II相比,μC/OS III更加优秀,μC/OS III中删除或更新了μC/OS II中很少使用的一些功能;添加了更高效的功能和服务,比如时间片轮转调度(round robin)等,μC/OS II最多支持64个任务,而μC/OS III在理论上任务数量没有限第一章介绍实时系统软实时系统和硬实时系统的区别在于一旦没有在规定的时间内完成任务所导致后果的严重性。
超过时限后所得到的结果即使正确也可能是毫无作用的。
硬实时系统中,运算超时是不允许发生的。
在很多情况下,超时会导致巨大的灾难,会威胁人们的生命安全。
但是在软实时系统中,超时不会导致严重后果。
前后台系统简单的小型系统设计一般是基于前后台的或者无限循环的系统。
包含一个无限循环的模块实现需要的操作(后台)。
中断处理程序实现异步事件(前台)。
前台也叫做中断级,后台也叫作任务级。
多数高产量低成本微控制器的应用软件(例如微波炉,电话玩具等)都是基于前后台系统的。
实时内核实时内核是一个能管理MPU、MCU、DSP时间和资源的软件。
实时内核的应用包括迅速地响应,可靠地完成工作的各个部分。
uC OS III函数
uCOS-III常用函数参考手册陈俊辉OSInit(), 用于初始化uC/OS-III 。
OSInit ()初始化内部变量和数据结构,同时产生2 个到 5 个内部任务。
最低程度,uC/OS-III******************5 个内部任务**********************OS_IdleTask ()空闲任务;(OSIdleTaskHook() 并进入低功耗模式。
然后,进入OS_IdleTask()并循环)。
OS_TickTask()时基任务(通过配置OS_CFG_APP.H 中的OS_CFG_TICK_TASK_PRIO 。
通常设置其优先级较高。
事实上,它的优先级应该设置比重要任务的优先级稍低)。
OS_StatTask() 统计任务。
OS_TmrTask() 定时器任务。
OS_IntQTask() 中断队列处理任务(它的优先级通常被设为0 )。
(大多数的uC/OS-III 函数会通过一个指向OS_ERR 变量的指针返回一个错误代号。
如果OSInit() 初始化函数运行成功,错误代号被设为OS_ERR_NONE 。
如果在初始化不成功,uC/OS-III 会根据执行的结果返回对应的错误代号。
参照OS.H 中的错误代号。
3 个可选择的任务OS_CFG.H 中的配置决定)OSTaskCreate(),通过调用创建任务。
OSTaskCreate ()需要13 个参数。
第一个参数是任务堆栈的地址。
{ 该任务堆栈的开始地址} 详见第 5 章。
OSTaskDel (),如果任务的使命完成了,就要调用删除该任务。
实际上不是删除任务的代码,只是让任务不再具有使用;CPU 的资格而已。
OSTaskSuspend () 停止任务(暂停中的任务只能通过调用OSTaskResume() 被恢复)。
OSTaskResume () 恢复任务)。
(提交信号量到其它任务、发送消息到其它任务、提供共享资源等。
换句话说,任务不是只被限制于“等待事件”。
uCOS-III中文翻译
uC/OS-III 是一个可扩展的,可固化的,抢占式的实时内核,它管 理的任务个数不受限制。它是第三代内核,提供了现代实时内核所期 望的所有功能包括资源管理、同步、内部任务交流等。uC/OS-III 也 提供了很多特性是在其他实时内核中所没有的。比如能在运行时测量 运行性能,直接得发送信号或消息给任务,任务能同时等待多个信号 量和消息队列。 以下列出 uC/OS-III 的特点:
临界操作应该在任务级中被执行,不可避免地必须在中断处理程 序中执行也要确保是在很短的时间内完成。因为这会导致 ISR 占用更 长的时间。通常的,ISR 中使能相关的信息而在后台程序中执行相应 的操作。这叫做任务级响应。任务级响应的时间依赖于后台循环一次 所需的时间,通常这不是一个固定常量。另外,如果其中的代码稍有 改动,那么循环一次所用的时间也将有所变化。
:屈环宇 :嘉兴学院 :2011 年 11 月 3 日晚
uC/OS-III 中文资料
序言
什么是 uC/OS-III? uC/OS-III(Micro C OS Three 微型的 C 语言编写的操作系统第 3
版)是一个可升级的,可固化的,基于优先级的实时内核。它对任务 的个数无限制。uC/OS-III 是一个第 3 代的系统内核,支持现代的实 时内核所期待的大部分功能。例如资源管理,同步,任务间的通信等 等。然而,uC/OS-III 提供的特色功能在其它的实时内核中是找不到 的,比如说完备的运行时间测量性能,直接地发送信号或者消息到任 务,任务可以同时等待多个内核对象等。
在此,我要感谢: 1、我的导师:乐光学教授。是您经常带我去公司拓展视野, 并让我坚定不移地往嵌入式方面发展。 2、我的师傅:张雪强博士。是您无偿提供给我一些开发板, 作为回报,帮您的店铺宣传一下 / 3、还有我的亲朋好友们。 特 别 是 今 天 上 午 , 用 了 3 小 时 终 于 在 MDK4.0 编 译 器 上 将 uC/OS-III 移植到 stm32f103rb 处理器上,并成功运行。移植的步骤, 我也会发布到网上的,谢谢大家。 我的 QQ 号码是 522430192,我的邮箱是 522430192@,希 望大家多多联系我,共同学习,共同进步。
嵌入式实时操作系统uCOS-III
目录第一部分:μC/OS-III 实时内核μC/OS-III的演变—Jack Ganssle前言第1章概述1-1前后台系统1-2实时内核1-3RTOS(实时操作系统)1-4μC/OS-III1-5μC/OS,μC/OS-II,μC/OS-III特性比较1-6关于本书1-7μC/Probe 调试软件工具1-8本书的常用约定1-9各章内容第2章目录和文件2-1 应用代码2-2 CPU2-3 板级支持包(BSP)2-4 μC/OS-III,与CPU无关的源代码2-5 μC/OS-III,与CPU相关的源代码2-6 μC/CPU,与CPU相关的源代码2-7 μC/LIB,可移植的库函数2-8 小结第3章初识μC/OS-III3-1 单任务应用程序3-2 有内核对象参与的多任务应用程序第4章临界段代码4-1 关中断4-1-1 测量中断关闭时间4-2 给调度器上锁4-2-1 测量调度器锁定时间4-3 μC/OS-III的某些功能会导致临界段代码长度增加4-4 小结第5章任务管理5-1 任务优先级的分配5-2 栈空间大小的确定5-3 任务栈溢出检测5-4 任务管理函数5-5 任务管理的内部原理5-5-1 任务状态5-5-2 任务控制块TCB5-6 系统内部任务5-6-1 空闲任务(OS_IdleTask(),os_core.c)5-6-2 时钟节拍任务(OS_TickTask(), os_tick.c)5-6-3 统计任务(OS_StatTask(),os_stat.c)5-6-4 定时任务(OS_TmrTask(),os_tmr.c)5-6-5 中断服务管理任务(OS_IntQTask(),os_int.c)5-7小结第6章任务就绪表6-1 优先级6-2 就绪任务列表6-3 向就绪任务列表中增加任务6-4小结第7章任务调度7-1 可剥夺型调度7-2 调度点7-3 时间片轮转调度7-4 调度的实现细节7-4-1 OSSched()7-4-2 OSIntExit()7-4-3 OS_SchedRoundRobin()7-5 小结第8章任务切换8-1 OSCtxSw()8-2 OSIntCtxSw()8-3小结第9章中断管理9-1 CPU的中断处理9-2 典型的μC/OS-III中断服务程序9-3 无需内核参与的中断服务程序9-4 多中断优先级的处理器9-5 所有中断源共用中断服务程序9-6 每个中断源都有专用中断服务程序9-7 直接发布和延时发布9-7-1 直接发布9-7-2 延迟发布9-8 直接发布模式和延迟发布模式的对比9-9 时钟节拍(也称为系统节拍)9-10小结第10章任务挂起表10-1 小结第11章时间管理11-1 OSTimeDly()11-2 OSTimeDlyHMSM()11-3 OSTimeDlyResume()11-4 OSTimeSet() 和OSTimeGet()11-5 OSTimeTick()11-6 小结第12章定时器管理12-1 单次定时器12-2 周期定时器(无初始延迟)12-3 周期定时器(有初始延迟)12-4 定时器管理内部机制12-4-1 定时器管理内部机制——定时器状态12-4-2 定时器管理内部机制——OS_TMR12-4-3 定时器管理内部机制——定时器任务12-4-4 定时器管理内部机制——定时器列表12-5 总结第13章资源管理13-1 关中断/开中断13-2 给调度器上锁/开锁13-3 信号量13-3-1 二进制信号量13-3-2 计数型信号量13-3-3 使用信号量的注意事项13-3-4 (用来共享资源的)信号量内部结构13-3-5 优先级反转13-4 互斥型信号量(MUTEX)13-4-1 互斥型信号量内部结构13-5 何时可以用普通信号量替代互斥型信号量13-6 死锁(或称抱死)13-7 小结第14章任务同步14-1 信号量14-1-1 单向同步14-1-2 信用记录14-1-3 多个任务等待同一个信号量14-1-4 信号量的内部结构(以同步为目的)14-2 任务信号量14-2-1 等待任务信号量14-2-2 发布任务信号量14-2-3 双向同步14-3 事件标志组14-3-1 使用事件标志14-3-2 事件标志的内部结构14-4 与多任务同步14-5 小结第15章消息传递15-1 消息15-2 消息队列15-3 任务内建的消息队列15-4 双向同步15-5 流量控制(flow control)15-6 保持数据的可见性15-7 使用消息队列15-8 客户端和服务器15-9 消息队列内部的细节15-10 小结第16 章同时等待多个内核对象16-1 小结第17章存储管理17-1 创建存储分区17-2 从分区中获得存储块17-3 将存储块归还到分区中17-4 使用存储分区17-5 小结第18章移植µC/OS-Ⅲ18-1 约定18-2 μC/CPU18-2-1 CPU_BSP.H18-2-2 CPU_DEF.H18-2-3 CPU_CFG.H18-2-4 CPU_CORE.C18-2-5 CPU_CORE.H18-2-6 CPU.H18-2-7 CPU_C.C18-2-8 CPU_A.ASM18-3 μC/OS-III移植18-3-1 OS_CPU.H18-3-2 OS_CPU_C.C18-3-3 OS_CPU_A.ASM18-3-4 OS_CPU_A.INC18-4 板级支持包(BSP)18-4-1 BSP.C和BSP.H18-4-2 BSP_INT.C和BSP_INT.H18-5 移植的测试18-5-1 创建一个简单的测试工程18-5-2 验证任务级任务切换18-5-3 验证中断级任务切换18-6 小结第19章程序运行时的各类统计信息19-1程序运行时的总体统计19-2 任务运行时的统计19-3 程序运行时和内核对象相关的统计信息19-4 OS_DBG.C –统计19-5 OS_CFG_APP. C –统计19-6 小结附录A μC/OS-III API参考手册A-1 任务管理A-2 时间管理A-3 互斥型信号量——资源管理A-4 事件标志组——同步A-5 信号量——同步A-6 任务信号量——同步A-7 消息队列——消息传递A-8 任务消息队列——消息传递A-9 等待多个对象A-10 定时器A-11 固定大小的存储分区——存储管理A-12 OSCtxSw()A-13 OSFlagCreate()A-14 OSFlagDel()A-15 OSFlagPend()A-16 OSFlagPendAbort()A-17 OSFlagPendGetFlagsRdy()A-18 OSFlagPost()A-19 OSIdleTaskHook()A-20 OSInit()A-21 OSInitHook()A-22 OSIntCtxSw()A-23 OSIntEnter()A-24 OSIntExit()A-25 OSMemCreate()A-26 OSMemGet()A-27 OSMemPut()A-28 OSMutexCreate()A-29 OSMutexDel()A-30 OSMutexPend()A-31 OSMutexPendAbort()A-32 OSMutexPost()A-33 OSPendMulti()A-34 OSQCreate()A-35 OSQDel()A-36 OSQFlush()A-36 OSQPend()A-38 OSQPendAbort()A-32 OSQPost()A-41 OSSched()A-42 OSSchedLock()A-43 OSSchedRoundRobinCfg() A-44 OSSchedRoundRobinYield() A-45 OSSchedUnlock()A-46 OSSemCreate()A-47 OSSemDel()A-48 OSSemPend()A-49 OSSemPendAbort()A-50 OSSemPost()A-51 OSSemSet()A-52 OSStart()A-53 OSStartHighRdy()A-54 OSStatReset()A-55 OSStatTaskCPUUsageInit() A-56 OSStatTaskHook()A-57 OSTaskChangePrio()A-58 OSTaskCreate()A-59 OSTaskCreateHook()A-60 OSTaskDel()A-61 OSTaskDelHook()A-62 OSTaskQFlush()A-63 OSTaskQPend()A-64 OSTaskQPendAbort()A-65 OSTaskQPost()A-66 OSTaskRegGet()A-67 OSTaskRegSet()A-68 OSTaskReturnHook()A-69 OSTaskResume()A-70 OSTaskSemPend()A-71 OSTaskSemPendAbort()A-72 OSTaskSemPost()A-73 OSTaskSemSet()74 OSStatTaskHook()A-75 OSTaskStkChk()A-76 OSTaskStkInit()A-77 OSTaskSuspend()A-78 OSTaskSwHook()A-79 OSTaskTimeQuantaSet()A-80 OSTickISR()A-81 OSTimeDly()A-82 OSTimeDlyHMSM()A-83 OSTimeDlyResume()A-84 OSTimeGet()A-85 OSTimeSet()A-86 OSTimeTick()A-87 OSTimeTickHook()A-88 OSTmrCreate()A-89 OSTmrDel()A-90 OSTmrRemainGet()A-91 OSTmrStart()A-92 OSTmrStateGet()A-93 OSTmrStop()A-94 OSVersion()附录B μC/OS-III配置手册B-1 μC/OS-III的功能(os_cfg.h)B-2μC/OS-III的数据类型(os_type.h)B-3 μC/OS-III的堆栈、池和其他数据类型(os_cfg_app.h)附录C从μC/OS-II 迁移到μC/OS-IIIC-1源文件名称和内容的差异C-2编程约定的变化C-3变量名称的变化C-4 API的变化C-4-1事件标志C-4-2消息邮箱C-4-3存储管理C-4-4互斥型信号量C-4-5消息队列C-4-6信号量C-4-7任务管理C-4-8时间管理C-4-9定时器管理C-4-10其他C-4-11介入函数与系统移植附录D MISRA-C:2004和μC/OS-III D-1 MISRA-C:2004,规则8.5 (强制)D-2 MISRA-C:2004,规则8.12(强制)D-3 MISRA-C:2004,规则14.7 (强制)D-4 MISRA-C:2004,规则15.2 (强制)D-5 MISRA-C:2004,规则17.4 (强制)附录E 参考文献附录F μC /OS-III许可政策致中国读者这本书是很多人多年辛勤劳动的结晶,讲述的是一个最早于1992年发布的实时内核的第三代。
ucosiii常用函数(1)
任务堆栈:存储任务中的调用的函数、局部变量、中断服务程序和CPU寄存器的值。
全局变量的保护:1.如果只在一个任务中写(或只有一个数据),而在其他任务中只是读取,则可以不用互斥型信号量,最多会造成读取的数据未被完全写完。
2.如果全局变量在多个任务中写,则需要用互斥型信号量保护,这样当有任务申请到互斥型信号量(保护不可重入的程序段)写数据时,其他任务的同一个互斥型信号量必须等待上一个任务的释放才可进行写。
3.如果全局变量在中断中写,则在其他任务中的全局变量的写操作要用临界段(禁止中断和禁止调度:保护不可被分割的程序段)保护。
(因为如果不关中断相当于中断的优先级最高,而且不能被像其他任务那样挂起。
)OS_CFG_ISR_POST_DEFERRED_EN为1临界段使用锁调度器方式;为0临界段使用禁中断方式(CPU_SR_ALLOC();OS_CRITICAL_ENTER();OS_CRITICAL_EXIT();OS_CRITICAL_EXIT_NO_SCHED();OSSchedLockNestingCtr记录调度器被锁的次数)。
检测任务堆栈的使用情况:OS_CFG_STAT_TASK_STK_CHK_EN使能OS_ERRerr;CPU_STK_SIZE stk_free;CPU_STK_SIZE stk_used;OSTaskStkChk(&TaskBStkTCB,&stk_free,&stk_use d,&err);中断中使用OSIntEnter();和OSIntExit();是为了退出中断后执行中断调度操作,如果中断中并未用到OSSemPost();等系统函数,则退出中断服务程序后不需要进行任务调度,就可以不在中断服务程序中使用OSIntEnter(); 和OSIntExit();。
(有时候用:CPU_CRITICAL_ENTER();OSIntNestingCtr++;CPU_CRITICAL_EXIT();替代OSIntEnter();)一、变量类型在中是有关cpu变量的重新定义,还包括CPU_STK (CPU堆栈类型),和CPU_STK_SIZE(CPU堆栈类型的大小)的定义,CPU_SR(CPU状态寄存器的定义)。
以UCOSIII为例-嵌入式实时操作系统概述
单向同步例子
单向同步例子
多值信号量计数值
多值信号量计数值中保存了它还能被分配多少次 。换句话说,当ISR 提交该信号量n 次,那么该信 号量计数值就会增加n。
多个任务等待一个信号量
多个任务可以同时等待同样的信号量,假设每个 任务都被设置了定时期限。
事件标志组
当任务要与多个事件同步时可以使用事件标志。 若其中的任意一个事件发生时任务被就绪,叫做 逻辑或(OR)。 若所有的事件都发生时任务被就绪,叫做逻辑与 (AND)。 用户可以创建任意个事件标志组(限制于RAM) 。
恢复处于延时状态的任务
获得当前的时基计数值 设置当前的时基计数值
系统时基
uC/OS-III 需要一个能提供周期性时间的时基源 ,叫做系统时基。硬件定时器可以被设置为每秒产 生10 到1000Hz 的中断提供系统时基。 时基可以看做是系统的心跳。它的速率决定于时 基源。然而,时基速率越快,系统的额外支出就越 大。
实时内核
一.任务及其状态
什么是任务
任务(也叫做线程)是简单的程序。单CPU 中 ,在任何时刻只能是一个任务被执行。 任务看起来像C 函数。在大多数嵌入式系统中, 任务通常是无限循环的。任务不能像C 函数那样, 它是不能return 的。
任务的基本样子
任务的创建
一个简单的任务例子
任务状态
五.中断管理
什么是中断
中断是硬件机制,用于通知CPU 有异步事件发 生。当中断被响应时,CPU 保存部分(或全部)寄 存器值并跳转到中断服务程序(ISR)。ISR 响应 这个事件,当ISR 处理完成后,程序会返回中断前 的任务或更高优先级的任务。 在实时系统中,关中断的时间越短越好。长时间 关中断可能会导致中断来不及响应而重叠。
uCOS-III学习笔记
UCOS-III学习笔记一.知识要点1.用户代码不允许调用任务函数,任务一旦创建只能由UCOS-III调用2.每个任务都必须创建创建自己的堆栈,可以静态分配或由malloc()动态分配,但类型只能为CPU_STK3.任务优先级数越小越高,设置范围1~OS_CFG_PRIO_MAX-2,OS_CFG_PRIO_M AX在OS_CFG。
h中定义,系统默认的最大优先级为10,统计任务的优先级在os _CFG_app。
h中定义。
系统默认的一些优先级:统计任务:11OS_CFG_TICK_TASK_PRIO :104.分配堆栈大小时:1K=2565.OSTaskCreate()里面有些指针没有意义。
6.推荐在调用OSStart()函数之前只创建一个任务,因为此时UCOS—III 可以统计CPU的使用率7.每个任务都是一个无限循环,通过调用延时函数OSTimeDly()或OSTimeD lyHMSM()等待一个事件而被挂起。
8.任务不像C函数,没有return的。
9.只运行一次的任务结束时必须调用OSTaskDel()删除自己。
10.任务在等待事件时不会占用CPU11.一旦堆栈被动态分配就不能再回收,对于不需要删除的任务,建议动态分配堆栈12.uC/OS-III 允许用户在调用 OSStart() 之前创建任意个任务,但当用到统计任务统计 CPU 的使用率时,调用 OSStart()之前只允许创建1个任务,给这个任务一个相当高的优先级。
统计任务本身也有优先级OS_CFG_STAT_TASK_ PRIO,在os_CFG_app。
h中定义。
,此优先级排倒数第二,第一是空闲任务.13.任务要获得共享资源使用权就必须先获得互斥信号量(mutex),使用完后要释放mutex。
14.消息队列是任务与任务间的通信,未接受到消息队列的任务会被暂时挂起,处于等待接受的状态。
15.OSTimeDly(),任务调用这个函数后就会被挂起直到期满.二.单任务应用程序二.多任务管理程序主任务主任务中创建多个子任务四.统计任务这部分可以参考UCOS—ii的http://jingyan.baidu。
ucosIII_时间片轮转调度
ucosIII_时间⽚轮转调度1.什么是时间⽚,他的作⽤是什么在UCOSII下,同⼀优先级下只能有⼀个任务。
在UCOSIII下,同⼀优先级下可以有多个任务。
所以在UCOSIII下引⼊时间⽚轮转调度解决相同优先级任务都可以执⾏的问题。
还需要注意的事,我们只需要配置时间⽚功能,系统即可⾃动完成调度,不需要⽤户⼿动调⽤函数。
配置过程在下⾯。
2.基本配置过程。
⽂件os_core.cvoid OSSchedRoundRobinCfg (CPU_BOOLEAN en,OS_TICK dflt_time_quanta,OS_ERR *p_err)这个是配置时间⽚的函数,第⼀个参数打开or关闭,第⼆个参数是分配给每个任务的时间⽚时间,第三个参数是保存返回值,记录了错误类型。
这个函数在程序中⼀般都在⼀个宏定义中:#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使⽤时间⽚轮转的时候//使能时间⽚轮转调度功能,时间⽚长度为1个系统时钟节拍,既1*5=5msOSSchedRoundRobinCfg(DEF_ENABLED,1,&err);#endifOS_CFG_SCHED_ROUND_ROBIN_EN 这个宏在os_cfg.h中#define OS_CFG_SCHED_ROUND_ROBIN_EN 1u /* Include code for Round-Robin scheduling当我们在os_cfg.h⽂件中把这个宏定义为1时,UCOSIII会⾃动把所有和时间⽚有关的代码包括到所需要的地⽅去。
这个也符合系统可裁剪的规则,其他模块也是这样做的。
需要哪个模块则把该模块的宏定义打开。
看⼀下其他模块的宏定义:#define OS_CFG_APP_HOOKS_EN 1u /* Enable (1) or Disable (0) application specific hooks */#define OS_CFG_ARG_CHK_EN 1u /* Enable (1) or Disable (0) argument checking */#define OS_CFG_CALLED_FROM_ISR_CHK_EN 1u /* Enable (1) or Disable (0) check for called from ISR */#define OS_CFG_DBG_EN 1u /* Enable (1) debug code/variables */#define OS_CFG_ISR_POST_DEFERRED_EN 1u /* Enable (1) or Disable (0) Deferred ISR posts 通过调度器上锁来访问临界段*/#define OS_CFG_OBJ_TYPE_CHK_EN 1u /* Enable (1) or Disable (0) object type checking */#define OS_CFG_TS_EN 1u /* Enable (1) or Disable (0) time stamping */到⽬前为⽌,时间⽚已经打开了。
uCOS-III时间管理(二)
uCOS-III时间管理(⼆)时间管理就是⼀种建⽴在时钟节拍上,对操作系统任务的运⾏实现时间上管理的⼀种系统内核机制。
常⽤以下五个函数:OSTimeDly()OSTimeDlyHMSM()OSTimeDlyResume()OSTimeGet ()OSTimeSet ()下⾯来介绍各个函数的作⽤。
OSTimeDly()OSTimeDly() 函数⽤于停⽌当前任务进⾏的运⾏,延时⼀段时间后再运⾏(和定时器中断有些类似)。
OSTimeDly()函数的信息如下表所⽰。
OSTimeDly() 函数中,如果函数的实参和调⽤场合均合法,就会调⽤OS_TickListInsert()函数将当前任务插⼊到节拍列表进⾏管理,如果OS_TickListInsert() 函数将当前任务插⼊节拍列表成功的话,就会调⽤OS_RdyListRemove() 函数将当前任务从任务就绪列表中移除,并将系统切换⾄其他任务,等到延时的时间到来,再根据优先级决定是否将CPU使⽤权分配给该任务。
这就是OSTimeDly() 函数实现任务延时的⼤致过程。
OSTimeDlyHMSM()OSTimeDlyHMSM() 函数与OSTimeDly() 函数的功能类似,也是⽤于停⽌当前任务进⾏的运⾏,延时⼀段时间后再运⾏,只是OSTimeDlyHMSM()函数⽐较于OSTimeDly()的定时格式不⼀样⽽已。
但是,⽤户若要使⽤OSTimeDlyHMSM() 函数,得事先将宏OS_CFG_TIME_DLY_HMSM_EN(位于“os_cfg.h”)设为1。
OSTimeDlyHMSM () 函数的信息如下表所⽰。
OSTimeDlyHMSM() 函数中,如果函数的实参和调⽤场合均合法,就会调⽤OS_TickListInsert() 函数将当前任务插⼊到节拍列表进⾏管理。
如果OSTimeDlyHMSM() 函数调⽤OS_TickListInsert() 函数将当前任务插⼊节拍列表成功的话,就会调⽤OS_RdyListRemove() 函数将当前任务从任务就绪列表中移除,并将系统切换⾄其他任务。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
UC/OS—III的常用资料整理作者:~风中的叶~ QQ:654705188任务堆栈:存储任务中的调用的函数、局部变量、中断服务程序和CPU寄存器的值。
全局变量的保护:1.如果只在一个任务中写(或只有一个数据),而在其他任务中只是读取,则可以不用互斥型信号量,最多会造成读取的数据未被完全写完。
2.如果全局变量在多个任务中写,则需要用互斥型信号量保护,这样当有任务申请到互斥型信号量(保护不可重入的程序段)写数据时,其他任务的同一个互斥型信号量必须等待上一个任务的释放才可进行写。
3.如果全局变量在中断中写,则在其他任务中的全局变量的写操作要用临界段(禁止中断和禁止调度:保护不可被分割的程序段)保护。
(因为如果不关中断相当于中断的优先级最高,而且不能被像其他任务那样挂起。
)OS_CFG_ISR_POST_DEFERRED_EN为1临界段使用锁调度器方式;为0临界段使用禁中断方式(CPU_SR_ALLOC();存放中断的变量OS_CRITICAL_ENTER();OS_CRITICAL_EXIT();OS_CRITICAL_EXIT_NO_SCHED();OSSchedLockNestingCtr记录调度器被锁的次数)。
检测任务堆栈的使用情况:OS_CFG_STAT_TASK_STK_CHK_EN使能OS_ERRerr;CPU_STK_SIZE stk_free;CPU_STK_SIZE stk_used;OSTaskStkChk(&TaskBStkTCB,&stk_free,&stk_used,&err);中断中使用OSIntEnter(); 和OSIntExit();是为了退出中断后执行中断调度操作,如果中断中并未用到OSSemPost();等系统函数,则退出中断服务程序后不需要进行任务调度,就可以不在中断服务程序中使用OSIntEnter(); 和OSIntExit();。
(有时候用:CPU_CRITICAL_ENTER();OSIntNestingCtr++;CPU_CRITICAL_EXIT();替代OSIntEnter();)一、变量类型在cpu.h中是有关cpu变量的重新定义,还包括CPU_STK(CPU堆栈类型),和CPU_STK_SIZE(CPU堆栈类型的大小)的定义,CPU_SR(CPU状态寄存器的定义)。
在os.h中是有关os类型的定义如OS_TCB(任务控制块)、OS_SEM(信号量)、OS_MUTEX (互斥型信号量)、OS_MSG(消息)、OS_Q(消息队列)、OS_ERR(系统错误)等。
在cpu_core.h中是有关cpu的定义,如CPU_ERR、CPU_TS、CPU_TS_TMR等。
CPU_STK:typedef unsigned int堆栈的类型定义OS_TCB:structos_tcb任务控制块的类型定义OS_ERR:enumos_err错误信息定义CPU_TS:typedef unsigned int时间戳变量CPU_TS_TMR:typedef unsigned int定时器变量二、全局变量(OS_CFG_STAT_TASK_EN使能且调用了OSStatTaskCPUUsageInit(&err);则开启了统计任务的功能:可以统计CPU使用率等。
)OSStatTaskCPUUsage:CPU的使用率(0—10000= 0.00-100.00%)OSStatTaskCPUUsageMax:CPU的使用率最大值(0—10000= 0.00-100.00%)OSTaskCtxSwCtr:任务切换次数的记录变量OSStatTaskCtr:已经建立了的任务数三、常用函数一、OS_CORE.C(1)void OSInit() //系统初始化(2)void OSIntEnter() //发生了一次中断(中断嵌套的逐层进入)(3)void OSIntExit() //退出了一次中断(中断嵌套的逐层退出)(4)void OSSched() //系统进行调度(5)void OSSchedLock() //给调度器上锁(6)void OSSchedUnlock() //给调度器解锁,成对使用(7)void OSStart() //启动多任务过程,在启动之前必须调用OSInit(),并已建立一个任务。
其中OSStartHighRdy()必须调用OSTaskSwHook(),并令OSRunning = TRUE.(8)void OS_Pend() //挂起任务(9)void OS_Post() //解挂任务(10)void OS_PendAbort() //取消挂起任务(11)INT16UOSVersion () //返回uc/os的版本号*10000(12)void OS_IdleTaskInit() //空闲任务初始化(13)void OS_IdleTask() //空闲任务二、OS_TASK.C(1)void OSTaskCreate(OS_TCB *p_tcb,//任务控制块CPU_CHAR *p_name,//任务名OS_TASK_PTR p_task,//任务函数指针void *p_arg,//任务函数参数OS_PRIO prio,//任务优先级CPU_STK *p_stk_base,//堆栈指针CPU_STK_SIZE stk_limit,//任务的堆栈剩余警戒线CPU_STK_SIZE stk_size,//任务的空间大小OS_MSG_QTY q_size, //能接收的信息队列最大值OS_TICK time_quanta,//时间片轮转时间void *p_ext,// 任务控制块的扩展信息OS_OPT opt, //任务的选项OS_ERR *p_err) //任务的错误信息(2)void OSTaskChangePrio() //任务优先级别的改变(3)void OSTaskDel() //任务的删除(4)void OSTaskSuspend() //任务的暂停(5)void OSTaskResume() //任务的恢复(6)void OSTaskStkChk() //校核空余内存的数量(7)OS_MSG_QTY OSTaskQFlush() //清空任务级消息队列中的消息(8)void *OSTaskQPend() //挂起任务级消息队列(9)CPU_BOOLEAN OSTaskQPendAbort()//取消任务级消息队列的挂起状态(10)void OSTaskQPost() //向任务级消息队列中发送消息(11)OS_REG OSTaskRegGet() //获取任务寄存器的当前值(12)void OSTaskRegSet() //设置任务寄存器的当前值(13)OS_SEM_CTR OSTaskSemPend() //任务信号量等待信号(14)CPU_BOOLEAN OSTaskSemPendAbort()//任务信号量取消挂起状态(15)OS_SEM_CTR OSTaskSemPost() //任务信号量发送消息(16)OS_SEM_CTR OSTaskSemSet() //设置任务信号量的计数值(17)void OSTaskTimeQuantaSet() //改变任务的时间片voidTaskMain(void *pdata); //任务声明static OS_TCB TaskMainTCB; //任务控制块#define TASK_MAIN_PRIO 3 //任务优先级#define TASK_MAIN_STK_SIZE 256 //任务堆栈大小256*4=1024Bstatic CPU_STK TaskMainStk[TASK_MAIN_STK_SIZE];//任务堆栈定义OSTaskCreate((OS_TCB *)&TaskMainTCB, //任务的控制块(CPU_CHAR *)"Task Main Start", //任务的名称(OS_TASK_PTR )TaskMain, //任务的函数指针(void *)0, //任务的函数初值(OS_PRIO )TASK_MAIN_PRIO, //任务的优先级(CPU_STK *)&TaskMainStk[0], //任务的堆栈(CPU_STK_SIZE)TASK_MAIN_STK_SIZE/10,//任务的堆栈剩余警戒线(CPU_STK_SIZE)TASK_MAIN_STK_SIZE,//任务的空间大小(OS_MSG_QTY )0, //所能接收的信息队列最大值(OS_TICK )0, //任务的时间片轮转时间(void *)0, //任务的任务控制块的扩展信息(OS_OPT )(OS_OPT_TASK_STK_CHK| OS_OPT_TASK_STK_CLR), //任务的选项 (OS_ERR *)&err); //任务的错误信息三、OS_TIME.C(1)void OSTimeDly() //以时钟节拍数为单位延时(2)void OSTimeDlyHMSM() //用时、分、秒、毫秒为单位延时(3)void OSTimeDlyResume() //取消任务中的延时,引发一次调度(4)OS_TICKOSTimeGet() //获取OSTime 值(5)void OSTimeSet() //设置 OSTime 值四、OS_SEM.C(1)void OSSemCreate() //创建信号量(2)OS_OBJ_QTY OSSemDel() //删除信号量(3)OS_SEM_CTR OSSemPend() //请求信号量(4)OS_SEM_CTR OSSemPost() //发送(释放)信号量(5)void OSSemSet() //设置信号量的计数值(6)OS_OBJ_QTYOSSemPendAbort() //取消信号量static OS_SEM AppSem; //定义一个信号量变量CPU_TS ts=0;//存放发送消息时的时间戳OS_TS_GET();(获取当前时间戳)OS_ERR err; //返回的错误信息OSSemCreate(&AppSem,"Test Sem", 0, &err);//要在使用之前创建(如果在两个任务中都用到,则最好在两个任务创建前建立,也可在优先级高的任务中建立)OSSemPend(&AppSem,0,OS_OPT_PEND_BLOCKING,&ts,&err);//等待信号量(ts为发送信号量的时间戳)OSSemPost(&AppSem, OS_OPT_POST_1,&err);//发送信号量五、OS_FLAG.C(1)void OSFlagCreate() //信号标志组的创建函数(2)OS_OBJ_QTY OSFlagDel() //删除信号标志组(3)OS_FLAGS OSFlagPend() //挂起信号标志组(4)OS_FLAGS OSFlagPost() //向信号标志组发送信号(5)OS_OBJ_QTYOSFlagPendAbort() //取消挂起信号标志组staticOS_FLAG_GRPAppFlag; //定义一个信号标志组变量CPU_TSts=0; //存放发送消息时的时间戳OS_TS_GET();(获取当前时间戳)OS_ERRerr; //返回的错误信息OSFlagCreate(&AppFlag,"TestFlag",0x00,&err);//创建信号标志组且设置初值为0x00 OSFlagPend(&AppFlag,0x03,0,OS_OPT_PEND_FLAG_SET_ALL,&ts,&err);//等待信号标志组的bit0和bit1都为1OSFlagPost(&AppFlag,0x01,OS_OPT_POST_FLAG_SET,&err);//把信号标志组的bit0设置为1六、OS_MUTEX.C(1)void OSMutexCreate() //创建互斥型信号量(2)OS_OBJ_QTY OSMutexDel() //删除互斥型信号量(3)void OSMutexPend() //请求互斥型信号量(4)void OSMutexPost() //发送(释放)互斥型信号量(5)OS_OBJ_QTYOSMutexPendAbort() //取消互斥型信号量static OS_MUTEX AppMutex; //定义一个互斥型信号量变量CPU_TS ts=0;//存放发送消息时的时间戳OS_TS_GET();(获取当前时间戳)OS_ERR err; //返回的错误信息OSMutexCreate(&AppMutex,"Test Mutex", &err);//创建互斥型信号量OSMutexPend(&AppMutex, 0, OS_OPT_PEND_BLOCKING,&ts,&err);//互斥型信号量申请(阻塞方式)OSMutexPost(&AppMutex, OS_OPT_POST_NONE,&err);//互斥型信号量释放七、OS_Q.C(1)void OSQCreate() //创建一个消息队列(2)OS_OBJ_QTY OSQDel() //删除消息队列(3)OS_MSG_QTY OSQFlush() //清空消息队列(4)void *OSQPend() //请求一个消息队列(6)void OSQPost() //向消息队列发送消息(6)OS_OBJ_QTYOSQPendAbort() //取消消息队列的等待状态以指针和长度的形式向其他任务发送消息,如果是阻塞方式则接收到的数据的次数等于发送的次数才会被阻塞。