RTOS系统

硬实时

规定时间内必须完成操作,不允许超时

软实时

不如硬实时严格

可剥夺性内核

可以剥夺其他任务的CPU使用权,总是在运行就绪任务中的优先级最高的那个任务

UCOS在F103上的移植

源码获取

源码我是通过正点原子提供的源码直接复制过来的,也可以通过mirium官网进行下载。

官网地址:https://www.silabs.com/developers/micrium

源码移植

文件移植

将ucos路径下的三个文件夹复制到工程路径下

新建两个文件夹UCOS_BSP,UCOS_CONFIG

向UCOS_CONFIG文件夹中添加\Micrium\Software\EvalBoards\Micrium\uC-Eval-STM32F107\uCOS-III路径下的程序文件

向UCOS_BSP文件夹中添加Micrium\Software\EvalBoards\Micrium\uC-Eval-STM32F107\BSP路径下的程序文件

移植到工程

在工程中新建分组

移植工程内的文件

添加完毕后将文件的只读属性取消,随后将所有文件的头文件路径添加到工程中。

修改文件

直接将修改好的bsp文件和os_cpu_a.asm文件进行替换

修改完成后将void PendSV_Handler(void)函数注释掉

修改os_cpu_c.c,添加#include”includes.h”, 并将该文件内的#include <stm32f10x_lib.h>注释掉

修改os_cfg_app.h文件,直接复制粘贴修改好的工程 文件

修改sys.h文件

将SYSTEM_SUPPORT_OS宏定义更改为1

任务管理

滴答定时器

SysTick->CTRL:控制及状态寄存器

SysTick->LOAD:重装载值寄存器

SysTick->VAL:当前数值寄存器

SysTick->CALIB:校准数值寄存器

默认系统任务

空闲任务

时钟节拍任务

统计任务

定时任务

中断服务管理任务

任务状态

休眠态

存在于flash中,但不受ucos管理

就绪态

任务准备就绪,具备了运行的条件

运行态

获得CPU的使用权,正在运行

等待态

阻塞状态,等待条件达成后进入就绪态加入就绪队列

中断服务态

系统运行过程中发生中断,当前正在运行的任务被挂起,系统转去执行中断处理函数,此时任务的状态为为中断服务态

任务堆栈

任务堆栈的功能是为了满足任务切换和响应中断时保存CPU寄存器中的内容以及任务调用其他函数时的需要

任务堆栈初始化函数:OSTaskStkInit();该函数由创建任务函数自动调用。

任务控制块

用于记录与任务相关信息的数据结构,每个任务都有自己的任务控制块,任务创建时自动完成任务控制块的初始化。

任务就绪表

优先级

数值越小,优先级越高

就绪表

优先级位映射表OSPriodTbl[]:用来记录哪个优先级下有任务就绪。

就绪任务列表OSRdyList[]:用来记录每一个优先级下所有就绪的任务。

就绪任务列表存有首个就绪任务的地址和最后一个就绪任务的地址,就绪任务之间使用链表进行连接。

任务调度

可剥夺性任务调度

高优先级任务可以抢占低优先级任务的CPU使用权

任务调度器

任务级调度器

OSSched();任务级调度器可以在其他的osAPI函数中进行自动调用

中断级调度器

OSInExit();当退出外部中断服务函数时使用中断级任务调度。

任务调度点

释放信号或发送消息

使用延时函数

任务等待的事情还没发生

任务取消等待

创建任务

删除任务

删除一个内核对象

任务改变自身的优先级或其他任务的优先级

任务通过调用函数将自己挂起

结束挂起

用户调用OSSched();

任务切换时切换到当前就绪队列中优先级最高的任务。

调度器的上锁和解锁

不希望发生任务调度时使用对应函数对调度器进行上锁。

时间片轮转调度

每个任务可以执行指定的时间。

初始化流程

首先调用OSInit()函数,随后调用OSStart()函数开启ucos。找到当前优先级最高的任务后开始执行该任务

任务基础API函数

任务创建函数

OSTaskCreate();

参数

OS_TCB:任务控制块

CPU_CHAR:任务名

OS_TASK_PTR:任务名

p_arg:任务参数

OS_PRIO:任务优先级

CPU_STK:栈基地址

CPU_STK_SIZE:栈容量和深度

OS_MSG_QTY:内置消息队列长度

OS_TICK:时间片轮转调度的情况下为时间片的长度

p_ext:用户补充的参数区

OS_OPT:用户选项

OS_ERR:保存任务创建不成功的错误码

任务删除函数

OSTaskDel

参数

OS_TCB

OS_ERR

任务的挂起与恢复

挂起函数OSTaskSuspend(),参数为任务控制块和错误码

恢复函数OSTaskResume(), 参数与挂起函数一致

时间片轮转调度

适用于同一优先级下的多个任务调度

函数OSSchedRoundRobinCfg(使能,时间片长度,传入错误码);

OSScheRoundRobinYield放弃本次时间片函数

开启时间片轮转调度步骤

设置宏OS_CFG_SCHED_ROUND_ROBIN_EN为1

调用函数OSSchedRoundRobinCfg来开启时间片轮转调度功能,并且设置时间片长度

在创建任务时对OS_TICK进行赋值即可,单位为时间片个数

系统内部任务

空闲任务

空闲任务是ucos创建的第一个任务

空闲任务时ucos必须创建的

时钟节拍任务

时钟节拍任务用来跟踪任务延时和任务等待超时

任务函数为OS_TickTask,是ucos必须创建的一个任务

统计任务

用来统计CPU的使用率

将OS_CFG_STAT_TASK_EN置一

调用函数OSStatTaskCPUUsageInit来使用

定时任务

调用OS_TmrInit来创建定时任务

中断服务管理任务

OS_CFG_IS_POST_DEFERREND_EN置一使能中断服务函数

中断服务管理任务优先级永远为0

钩子函数

当使能空闲任务的钩子函数之后每次进入空闲任务就会调用指针所指向的钩子函数

使能钩子函数需要将对应宏定义置一

UCOS的中断和时间管理

中断管理

进入中断函数时先调用OSInTEnter()函数,退出时调用OSIntExit()函数

OSInTEnter()函数内部使用全局变量OSIntNestingCtr来记录中断嵌套次数,最多支持250级中断嵌套

任务延时

除空闲任务外的所有任务必须在合适的位置调用系统提供的延时函数,让当前的任务暂停运行一段时间并进行一个任务切换

软件定时器

OS_CFG_TMR_EN宏置一

回调函数再特定的事件或条件发生时由另外的一方调用,用于对该事件或条件进行响应

单次定时器

只执行一次,可以调用定时器启动函数再次启动

周期模式

定时结束触发定时回调函数

无初始延迟
有初始延迟

第一次定时根据dly来确定第一个周期,之后每个周期被重置为period

优先级反转

获取信号量的任务被抢占CPU使用权后,高优先级的任务由于没有信号量,无法执行,只能等待获取信号量的低优先级任务执行完成才能继续运行

互斥信号量

可用于解决优先级反转问题,在低优先级任务获得信号量时被抢占CPU使用权后高优先级任务由于没有信号量无法访问共享资源,会将低优先级任务的优先级暂时提高,使其执行完毕并释放信号量,随后执行高优先级任务

内嵌信号量

ucos任务自带的信号量

消息传递

任务间通信

在使用全局变量进行任务间通信时必须保证其对全局变量的独占式访问

也可以通过消息队列作为中介发布给任务

消息类型

指向数据的指针,数据的长度,记录消息发布时刻的时间戳

消息队列

消息队列时ucos中的一个内核对象,为OS_Q

结构体为OS_MSG_Q

成员变量InPtr指向要插入的数据的位置

成员变量OutPtr指向输出数据的位置

消息队列使用链式存储存储数据

API函数

OSQCreate()创建一个消息队列

OSQPend()等待消息

OSQPost()向消息队列中发布一条消息

事件标志组