学习Qt有点无聊,春节期间就开始看看uCOS-III操作系统吧
①配置文件,通过定义这些文件里宏的值可以轻易地裁剪 uC/OS-III 的功能。
②用户应用文件,定义和声明应用任务。
③内核服务文件,其代码与 CPU 无关,可以不做任何修改移植到任何 CPU。主要用到的都是这部分内容。
④底层函数库,比如字符串的常规操作,常用的数学计算,等等。
⑤CPU 移植文件,用户如果想要移植 uC/OS-III 到不同平台上,需要修改这部分代码。
⑥CPU 配置文件,主要是 CPU 的一些工作模式和服务函数。
⑦其他 CPU 相关文件。
uC/OS-III 中的内核对象大多都是以结构体的形式存在的,在结构体中,可以看到很多宏,通过定义这些宏,就可以轻易地裁剪任务控制块具有的属性(任务的功能)。
在 uC/OS-III 中,对内核对象的管理大多采用线性链表的数据结构,包括单向链表和双向链表。链表就是将要管理的对象按照方便管理的规则一个接一个串联在一起,提高管理效率。比如节拍列表就是一个双向链表,其中每个 OSCfgTickWheel 数组元素代表着一
个时间点的节拍列表,相邻 OSCfgTickWheel 元素代表的时间点的对 OSCfgTickWheel 数组长度的余数相差一个时钟节拍。对于那些延时或有期限等待的任务的任务控制块 OS_TCB,会先根据其延时或等待的节拍对 OSCfgTickWheel 数组长度的余数插入到哪个节拍列表,然后
再把该节拍列表里的任务控制块 OS_TCB 按照其延时或等待的节拍的大小顺序串联成双向链表。
在 uC/OS-III 中,可以创建无数多个任务,让这些任务并发运行,就好像有多个主函数在运行一样。在 uC/OS-III 初始化的时候,至少会创建空闲任务 OS_IdleTask()和时基任务OS_TickTask() 这 两 个 任 务 , 另 外 还 有 三 个 可 选 择 的 内 部 任 务 , 软 件 定 时 器 任 务
OS_TmrTaks() 、中断延迟提交任务 OS_IntQTask()和统计任务 OS_StatTask()。
从用户的角度来看,uC/OS-III 中的任务可以分为 5 种状态,分别是休眠态、就绪态、运行态、挂起态和中断态,如下表所示
从 uC/OS-III 任务管理的角度来看,uC/OS-III 中的任务 9 种状态,如下表所示。分别是休眠态、就绪态、运行态、挂起态和中断态,如下表所示。
uC/OS-III 常用程序段
临界段 :
临界段主要是为了某段代码在执行时避免被其它任务或中断打断。临界段根据是否是使能了中断延迟提交(OS_CFG_ISR_POST_DEFERRED_EN)大体可以分为两种,如下面代码所示。当使能中断延迟提交时,中断级任务会转换成任务级任务,这种情况下进入和退出临界段主要分别是锁调度器和解锁调度器。当禁用中断延迟提交时,进入和退出临界段的方式分别是关中断和开中断。
#define OS_CRITICAL_ENTER() /*加锁调度器*/ do { CPU_CRITICAL_ENTER(); /*关中断*/ OSSchedLockNestingCtr++; /*给调度器加锁*/ if (OSSchedLockNestingCtr == 1u) { /*如果调度器刚被上(第一把)锁*/ OS_SCHED_LOCK_TIME_MEAS_START(); /*开始测试调度器被锁时间*/ } CPU_CRITICAL_EXIT(); /*开中断*/ } while (0) #define OS_CRITICAL_ENTER_CPU_EXIT() /*加锁调度器,并开中断*/ do { OSSchedLockNestingCtr++; /*给调度器加锁*/ if (OSSchedLockNestingCtr == 1u) { /*如果调度器刚被上(第一把)锁*/ OS_SCHED_LOCK_TIME_MEAS_START(); /*开始测试调度器被锁时间*/ } CPU_CRITICAL_EXIT(); /*开中断*/ } while (0) #define OS_CRITICAL_EXIT() /*减锁调度器,如果有中断消息发布,调度中断消息*/ do { /*队列任务 OS_IntQTask 。 */ CPU_CRITICAL_ENTER(); /*关中断*/ OSSchedLockNestingCtr--; /*给调度器减锁*/ if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {/*如果调度器被开启了*/ OS_SCHED_LOCK_TIME_MEAS_STOP(); /*测试调度器被锁时间完毕,更新调度器被锁最大时间*/ if (OSIntQNbrEntries > (OS_OBJ_QTY)0) { /*如果中断消息队列非空*/ CPU_CRITICAL_EXIT(); /*开中断*/ OS_Sched0(); /*强制调度优先级为0的任务( OS_IntQTask 任务优先级为0)*/ } else { /*如果中断消息队列为空*/ CPU_CRITICAL_EXIT(); /*开中断*/ } } else { /*如果调度器尚未被开启*/ CPU_CRITICAL_EXIT(); /*开中断*/ } } while (0) #define OS_CRITICAL_EXIT_NO_SCHED() /*减锁调度器,不附带调度操作*/ do { CPU_CRITICAL_ENTER(); /*关中断*/ OSSchedLockNestingCtr--; /*给调度器减锁*/ if (OSSchedLockNestingCtr == (OS_NESTING_CTR)0) {/*如果调度器被开启了*/ OS_SCHED_LOCK_TIME_MEAS_STOP(); /*测试调度器被锁时间完毕,更新调度器被锁最大时间*/ } CPU_CRITICAL_EXIT(); /*开中断*/ } while (0) #else //如果禁用(默认使能了)中断延迟发布 #define OS_CRITICAL_ENTER() CPU_CRITICAL_ENTER() //关中断 #define OS_CRITICAL_ENTER_CPU_EXIT() //没操作 #define OS_CRITICAL_EXIT() CPU_CRITICAL_EXIT() //开中断 #define OS_CRITICAL_EXIT_NO_SCHED() CPU_CRITICAL_EXIT() //开中断 #endif
其中, OS_CRITICAL_ENTER()和 OS_CRITICAL_ENTER_CPU_EXIT() 为进入临界段,OS_CRITICAL_EXIT() 和 OS_CRITICAL_EXIT_NO_SCHED() 为 退 出 临 界 段 ,CPU_CRITICAL_ENTER()为关中断,CPU_CRITICAL_EXIT()为开中断。
中断嵌套管理
为方便 uC/OS对中断的管理,在进入中断服务函数时需要调用 OSIntEnter() 函数将中断嵌套计数OSIntNestingCtr 加 1,并且在退出中断服务函数时需要调用 OSIntExit() 函数将中断嵌套计数 OSIntNestingCtr 减 1。
void OSIntEnter (void) { if (OSRunning != OS_STATE_OS_RUNNING) { /* Is OS running? */ return; /* No */ } if (OSIntNestingCtr >= (OS_NESTING_CTR)250u) { /* Have we nested past 250 levels? */ return; /* Yes */ } OSIntNestingCtr++; /* Increment ISR nesting level */ }
void OSIntExit (void) { CPU_SR_ALLOC(); if (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) { /* ISRs still nested? */ CPU_INT_EN(); /* Yes */ return; } if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Scheduler still locked? */ CPU_INT_EN(); /* Yes */ return; } OSPrioHighRdy = OS_PrioGetHighest(); /* Find highest priority */ OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr; /* Get highest priority task ready-to-run */ if (OSTCBHighRdyPtr == OSTCBCurPtr) { /* Current task still the highest priority? */ CPU_INT_EN(); /* Yes */ return; } #if OS_CFG_TASK_PROFILE_EN > 0u OSTCBHighRdyPtr->CtxSwCtr++; /* Inc. # of context switches for this new task */ #endif OSTaskCtxSwCtr++; /* 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(); }