UCOS
序章
延时函数
1 |
|
任务管理
1 |
|
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
一般设定小于10%即可(OS_TCB * )&StartTaskTCB, //任务控制块
不要访问和更改其中的成员变量
优先级
数值越小优先级越高
os_cfg.h line48 OS_CFG_PRIO_MAX 最大优先级数
就绪表
- 优先级位映射表**OSPrioTbl[]**:用来记录哪个优先级下有任务就绪
- 就绪任务列表**OSRdyList[]**:用来记录每一个优先级下所有就绪的任务
前导零
- 硬件计算 能计算一个值前面有多少零
任务调度
任务调度
- 任务调度器 进入中断 OSIntEnter();
- 任务调度器 退出中断 OSIntExit();
发生任务调度的调度点
- 延时函数OSTimeDly()(按时间延时)或者OSTimeDlyHMSM()(按节拍延时)
- 创建、删除任务
- 改变优先级
- 通过调用OSTaskSuspend()将自身挂起、或解除某个挂起的任务
- OSSched() 用户自行请求调度
调度器上锁解锁
- OSSchedLock()加锁
- OSSchedUnlock()解锁
时间片轮转调度
- 待补充
UCOS系统初始化
1 |
|
- OSInit()必须先于其他的UCOS函数调用包括OSStart()
任务创建与管理
任务的创建
1 |
|
OS_ERR 错误代码
任务的删除
1 |
|
不建议在系统运行时删除任务
尽管UCOSIII允许在系统运行中删除任务,但是应该尽量避免这种操作,如果这个任务可能占有与其他任务共享的资源,在删除此任务之前这个被占有的资源没有被释放就有可能导致奇怪的结果。
任务的挂起与恢复
挂起
1 |
|
挂起错误
- 任务被加锁
- 任务空闲
恢复
1 |
|
恢复错误
- 任务状态无效(错误的状态)、任务不是已经挂起的
- 不能恢复自己
时间片轮转调度
1 |
|
初始化
- 设置宏 OS_CFG_SCHED_ROUND_ROBIN_EN 为1
- 调用函数 OSSchedRoundRobinCfg() 开启时间片轮转调度功能
时间片的放弃
OSSchedRoundRobinYield(&err);
注:
时间片如果不够执行可能会产生奇怪的效果请注意
系统内部任务
中断服务管理任务
时钟节拍任务
定时任务(可选)
统计任务(可选)
空闲任务
中断服务管理任务
- 默认优先级最高,第一,不可更改。
时钟节拍任务
- 优先级较高,第二。
定时任务(可选)
默认优先级,第三。
提供软件定时功能
将宏OS_CFG_TMR_EN设置为1就会使能定时任务,在OSInit()中将会调用函数OS_TmrInit()来创建定时任务。
统计任务(可选)
- 一般优先级,倒数第二。
- 统计CPU使用率,堆栈使用率
- 可选创建(将宏OS_CFG_STAT_TASK_EN置1)
- 必须在main函数创建的以一个任务也是唯一的一个应用任务里面调用函数**OSStatTaskCPUUsageInit()**查询使用情况
空闲任务
- 优先级最低,倒数第一。
- 不能调用会使空闲任务进入等待态的函数。
- 可统计CPU使用率(用处)
钩子函数
共有8个
- OSIdleTaskHook(), 空闲任务 调用这个函数,可以用来让CPU进入低功耗模式
- OSInitHook(), 系统初始化 函数OSInit()调用此函数
- OSStatTaskHook(), 统计任务每秒 中都会调用这个函数,此函数允许你向统计任务中添加自己的应用函数。
- OSTaskCreateHook(), 任务创建 的钩子函数。
- OSTaskDelHook(), 任务删除 的钩子函数。
- OSTaskReturnHook(), 任务意外返回 时调用的钩子函数,比如删除某个任务
- OSTaskSwHook(), 任务切换 时候调用的钩子函数。
- OSTimeTickHook(), 滴答定时器 调用的钩子函数。
中断时间管理
1 |
|
- 最大250级中断嵌套
临界区代码保护
临界区:不可被打断的代码段
OS_CFG_ISR_POST_DEFERRED_EN 的值与临界段代码保护方式
0 | 关中断 |
---|---|
1 | 调度器上锁(可能会被其它中断打断) |
进入临界段
- 一个进入函数
退出临界段
退出后产生调度——-OS_CRITICAL_EXIT()
退出后不产生调度—-OS_CRITICAL_EXIT_NO_SCHED()
CPU_SR_ALLOC()
- 函数CPU_SR_ALLOC()是为CPU_CRITICAL_ENTER()和CPU_CRITICAL_EXIT()申请一个变量:
#define CPU_SR_ALLOC() CPU_SR cpu_sr = (CPU_SR)0
这个是临界代码段,在下面一个小节有详细讲解。
- 这样做是为了防止编译器警告。
任务延时
- 开始延时
OSTimeDly() | 相对延时 | 基于时钟节拍 |
---|---|---|
绝对延时 | ||
周期延时 | ||
OSTimeDlyHMSM() | 相对延时 | 基于时间 |
取消延时
延时任务任务可通过在其他任务中调用函数OSTimeDlyResume()取消延时而进入就绪状态,此函数最后会引发一次任务调度。
获取系统时间
UCOSIII定义了一个 CPU_INT32U 类型的全局变量 OSTickCtr 来记录系统时钟节拍数,在调用 OSInit() 时被初始化为 0,以后每发生1个时钟节拍,OSTickCtr加1。
- OSTimeSet()允许用户改变当前时钟节拍计数器的值
- OSTimeGet()用来获取动迁时钟节拍计数器的值
软件定时器
定时器本质是递减计数器,当计数器减到零时可以执行回调函数。应用程序可以有任意数量的定时器,UCOSIII中定时器的时间分辨率由一个宏 OS_CFG_TMR_TASK_RATE_HZ 确定,单位为HZ,默认为100Hz。
- 避免在回调函数使用 阻塞,删除 定时器任务的函数。
软件定时器的API
OSTmrCreate() | 创建定时器并制定运行模式 |
---|---|
OSTmrDel() | 删除定时器 |
OSTmrRemainGet() | 获取定时器的剩余时间 |
OSTmrStart() | 启动定时器计数 |
OSTmrStateGet() | 获取当前定时器状态 |
OSTmrStop() | 停止计数器倒计时 |
OSTmrCreate()有三种模式
- 单次模式(通过OSTmrStart()触发)
- 周期无延迟模式
- 周期有延迟模式
信号量、互斥信号量、内嵌信号量
信号量
信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行。
- 信号量用于控制对共享资源的保护,但是现在基本用来做任务同步用。
信号量API
OSSemCreate() | 建立一个信号量 |
---|---|
OSSemDel() | 删除一个信号量 |
OSSemPend() | 等待一个信号量 |
OSSemPendAbrot() | 取消等待 |
OSSemPost() | 释放或者发出一个信号量 |
OSSemSet() | 强制设置一个信号量的值 |
1 |
|
- OS_SEM_CTR cnt,
- 如果设置成计数型信号量 此处设置成对应数字即可
- 如果设置成二进制信号量 此处设置成0,指示事件的发生(同步)
1 |
|
- OS_OPT opt,
- OS_OPT_PEND_BLOCKING —————-> 阻塞式
- OS_OPT_PEND_NON_BLOCKING ——-> 非阻塞式
1 |
|
- OS_OPT opt,
- OS_OPT_POST_1 —–>只使能等待信号量的最高优先级任务 (如果任务正在等待)。
- OS_OPT_POST_ALL ——>发送到所有等待信号量的任务
- OS_OPT_POST_NO_SCHED ———>不调用调度程序 可以与其他选项之一一起添加。
互斥信号量
互斥信号量API
OSMutexCreate() | 建立一个互斥信号量 |
---|---|
OSMutexDel() | 删除一个互斥信号量 |
OSMutexPend() | 等待一个互斥信号量 |
OSMutexPendAbrot() | 取消等待 |
OSMutexPost() | 释放或者发布一个互斥信号量 |
内嵌信号量
OSTaskSemPend() | 等待一个任务信号量 |
---|---|
OSTaskSemPendAbort() | 取消等待任务信号量 |
OSTaskSemPost() | 发布任务信号量 |
OSTaskSemSet() | 强行设置任务信号量计数 |
消息队列
消息队列
函数名 | 作用 |
---|---|
OSQCreate() | 创建一个消息 队列 |
OSQDel() | 删除一个消息队列 |
OSQFlush() | 清空消息队列 |
OSQPend() | 等待消息 |
OSQPendAbort() | 取消等待消息 |
OSQPost() | 向消息队列发布一则消息 |
1 |
|
1 |
|
1 |
|
任务内建消息队列
函数名 | 作用 |
---|---|
OSTaskQPend() | 等待消息 |
OSTaskQPendAbort() | 取消等待消息 |
OSTaskQPost() | 向任务发布一则消息 |
OSTaskQFlush() | 清空任务的消息队列 |
1 |
|
- 注意看 OS_MSG_QTY 正常时其设置为0 使用内建消息队列将之设置成对应的数量即可
事件标志组
在UCOSIII中事件标志组为OS_FLAG_GRP,如果需要使用事件标志组的时候需要将宏OS_CFG_FLAG_EN置1,
函数名 | 作用 |
---|---|
OSFlagCreate() | 创建事件标志组 |
OSFlagDel() | 删除事件标志组 |
OSFlagPend() | 等待事件标志组 |
OSFlagPendAbort() | 取消等待事件标志 |
OSFlagPendGetFlagsRdy() | 获取使任务就绪的事件标志 |
OSFlagPost() | 向事件标志组发布标志 |
同时等待多个内核对象
在UCOSIII中允许任务同时等待多个信号量和多个消息队列,也就是说,UCOSIII不支持同时等待多个事件标志组或互斥信号量。
一个任务可以等待任意数量的信号量和消息队列,第一个信号量或消息队列的发布会导致该任务进入就绪态。
1 |
|
1 |
|