UCOSIII操作系统API使用方法
(1) UCOSIII的启动和初始化(主函数中的内容):
OS_ERR err; //定义一个变量
CPU_SR_ALLOC();
Cpu_Init(); //CPU外设初始化
OSInit(&err);//初始化 UCOSIII
OS_CRITICAL_ENTER();//进入临界区
//创建开始任务
OSTaskCreate((OS_TCB* )&StartTaskTCB, //任务控制块
(CPU_CHAR* )"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void* )0, //传递给任务函数的参数
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK* )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE )START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE )START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收
//的最大消息数目,为 0 时禁止
//接收消息
(OS_TICK )0, //当使能时间片轮转时的时间
//片长度,为 0 时为默认长度
(void* )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR* )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT();//退出临界区
OSStart(&err);//开启UCOSIII
while(1);
即在主函数中先初始化CPU的外设,然后初始化UCOSIII,并且让其进入临界状态,再创建一个开始任务,之后退出临界状态,再开启UCOSIII,最后一个死循环。我们一般的策略就是在主函数中创建一个开始任务,然后在开始任务函数中闯将其它函数并且再挂起开始任务。
(2)任务的创建与删除:
1、创建任务:
//宏定义
define START_TASK_PRIO 3//start_task 任务优先级
#define START_STK_SIZE 128 //start_task 任务堆栈大小
OS_TCB StartTaskTCB; // start_task 任务控制块
CPU_STKSTART_TASK_STK[START_STK_SIZE]; // start_task 任务堆栈
void start_task(void *p_arg); //start_task 任务函数
//在主函数或者Start函数中创建新任务需要用到上面的宏定义,而且在创建一个新任务之前必须先让系统进入临界区,创建完之后退出临界区。
OS_CRITICAL_ENTER();//进入临界区
OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块
(CPU_CHAR *)"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void * )0, //传递给任务函数的参数
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度,
(void *)0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,//任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
2、删除任务:删除任务只需调用函数:
void OSTaskDel (OS_TCB*p_tcb,OS_ERR *p_err) 即可
(3)任务挂起与解挂:
1、挂起即暂停运行程序,需调用void OSTaskSuspend (OS_TCB *p_tcb,OS_ERR *p_err)函数
2、解挂即恢复被挂起的程序:void OSTaskResume (OS_TCB *p_tcb,OS_ERR *p_err)
(4)时间片轮换调度:UCOSIII 是支持多个任务拥有同一个优先级的,这些任务采用时间片轮转调度方法进行任务调度。
设置步骤:
1、设置宏OS_CFG_SCHED_ROUND_ROBIN_EN为1,
2、调用函数OSSchedRoundRobinCfg()开启时间片轮转调度功能,并且在创建任务的函数里设置时间片长度。
我们一般采取的策略是在strat起始任务中通过宏定义判断OS_CFG_SCHED_ROUND_ROBIN_EN的值来决定是否调用OSSchedRoundRobinCfg()函数。
(5)钩子函数:钩子函数一般主要是用来扩展其他函数(任务)功能的。
如果要使用钩子函数,则需要以下配置步骤:
1、 将 钩子对应任务的宏OS_CFG_APP_HOOKS_EN 置 1
2、 调用App_OS_SetAllHooks();
3、 在os_app_hooks.c中完成钩子函数的功能。
策略还是在strat起始任务中通过宏定义判断。
(6)UCOSIII中断:
中断函数函数体如下:
void XXX_Handler(void) (1)
{
OSIntEnter(); //进入中断(2)
用户自行编写的中断服务程序; //这部分就是我们的中断服务程序(3)
OSIntExit(); //触发任务切换软中断 (4)
}
和非rtos下的中断函数一样,只不过是在中断服务程序执行之前加上OSIntEnter(); 以进入中断,在中断服务程序之后加上OSIntExit(); 以触发任务切换软中断。中断中只能用delay_ms()之类的延时,即在这段延时时间之内不能进行任务的切换。
(7)临界段代码保护:有一些代码我们需要保证其完成运行,不能被打断,这些不能被打断的代码就是临界段代码,也叫临界区。我们在进入临界段代码的时候使用宏OS_CRITICAL_ENTER(),退出临界区的时候使用宏 OS_CRITICAL_EXIT()或者 OS_CRITICAL_EXIT_NO_SCHED()
(8)时间管理:
1、任务延时:,UCOSIII中除空闲任务外的所有任务必须在合适的位置调用系统提供的延时函数,让当前的任务暂停运行一段时间并进行一个任务切换。
延时函数有两种,OSTimeDly()和OSTimeDlyHMSM(),而OSTimeDlyResume()可以取消延时而进入就绪状态。
2、获取和设置系统时间:
UCOSIII定义了一个CPU_INT32U类型的全局变量OSTickCtr来记录系统时钟节拍数,在调用OSInit()时被初始化为0,以后每发生1个时钟节拍,OSTickCtr加1。
OSTimeSet()允许用户改变当前时钟节拍计数器的值,慎用!!!!!
OSTimeGet()用来获取动迁时钟节拍计数器的值。
(9)UCOSIII软件定时器:
1、软件定时器原理:定时器其实就是一个递减计数器, 当计数器递减到 0 的时候就会触发一个动作,这个动作就是回调函数,当定时器计时完成时就会自动的调用这个回调函数。
2、软件定时器的分辨率有OS_CFG_TMR_TASK_RATE_HZ这个宏决定,这 个 值 绝 对 不 能 大 于OS_CFG_TICK_RATE_HZ
3、定时器初始化步骤:
①将宏 OS_CFG_TMR_DEL_EN 定义为 1
②根据所需分辨率给宏OS_CFG_TMR_TASK_RATE_HZ赋值
③定义结构体OS_TMR tmr1;//定义定时器
④void Tmr1_Callback (OS_TMR *p_tmr, void *p_arg);//声明回调函数
⑤OSTmrCreate ((OS_TMR*)&tmr1, //指向定时器的指针
(CPU_CHAR*) "tmr1",//定时器名称
(OS_TICK) 20,//初始化定时器的延迟值
(OS_TICK) 100,//重复周期
(OS_OPT) OS_OPT_TMR_PERIODIC,//定时器运行选项
(OS_TMR_CALLBACK_PTR) Tmr1_Callback,//指向回调函数的名字
(void*) 0,//回调函数的参数
(OS_ERR*) &err);//调用此函数以后返回的错误码
⑥OSTmrStart()函数可以打开软件定时器
OSTmrStop()函数可以关闭软件定时器