针对官网给的uc/os-IIIfor stm32 arm Cortex-M3书籍的学习笔记。
第三章 开始使用ucos-III
1.文件介绍:与其他的C程序一样,在使用前必须包含应用程序所需要的头文件。对应Ucosiii来说,我们可以将需要的头文件放入“includes.h”的文件中,并在拥有主函数的文件中(如app.c)中将它包含进来。
根据书上的历程,其中包含有“app_cfg.h”,“bsp.h”,“os.h”.
- “app_cfg.h”文件:可以用来定义任务优先级(APP_TASK_START_PRIO),
任务堆栈大小(APP_TASK_START_STK_SIZE)
其他应用程序的细节。 - “bsp.h”文件:用来定义应用程序需要使用的外设的函数原型,如
“BSP_Init()”“LED_set_high()”"OS_TS_GET()"等应用程序需要的功能即可以将使用的外设引进此文件中,并在其定义如外设初始化,外设相关功能等函数,并通过
include“bsp.h”将其引入app.c中供应用程序调用。 - “os.h”文件:为UcosIII的主头文件,其包含以下头文件“os_cfg.h”,“cpu.h”,“cpu_core.h”,“lib_bef.h”,“os_type.h”,“os_cpu.h”.
2.创建应用程序任务,必要的操作是为任务分配任务控制模块(OS_TCB),声明任务堆栈,声明任务函数的原型。并在主函数中创建开始任务
/*在app_cfg.h文件中声明*/
#define APP_TASK_START_PRIO 2 //任务的优先级
#define APP_TASK_START_STK_SIZE 128 //任务堆栈的大小
/*在app.c文件主函数前*/
static OS_TCB AppTaskStartTCB; //定义任务模块
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; //定义任务堆栈大小
static void AppTaskCreate (void); //声明任务函数原型
其中任务优先级是数字约小级别约高,其值必须设置在1到OS_CFG_PRIO_MAX-2之间,其中0与OS_CFG_PRIO_MAX-2优先级用于UcosIII自己保留,OS_CFG_PRIO_MAX其在os_cfg.h文件中定义。
对于任务堆栈的大小定义需要根据所使用MCU的大小去做决定,假如你想分配1KB的空间,而CPU_STK为32为,则可以设置堆栈大小为256.
主函数如下:
int main(void)
{
OS_ERR err;
bsp_Init();
OSInit(&err);
OSTaskCreate((OS_TCB *)&AppTaskStartTCB, //指向任务的任务控制块
(CPU_CHAR *)"App Task Start", //任务名
(OS_TASK_PTR ) AppTaskStart, //任务函数名
(void *) 0, //传递给任务的参数
(OS_PRIO ) APP_TASK_START_PRIO, //任务优先级
(CPU_STK *)&AppStartTaskStk[0], //任务堆栈基地址
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10, //任务堆栈深度限位
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY ) 0u, //任务内部消息队列能够接收的最大消息数,为0禁止接收消息
(OS_TICK ) 0u, //当使能时间片轮时的时间片长度,为0时为默认长度
(void *) 0, //用户补充的存储区
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),//任务选项
(OS_ERR *)&err); //存放该函数错误时的返回值
OSStart(&err);
}
其中OS_ERR err;
声明一个存在错误标志的变量。
第二行bsp_Init();
初始化所有外设,可根据自己使用的外设和单片机去做处理。
第三行OSInit(&err);
是os系统的初始化,初始化内部变量和数据结构,并且创建2到5个内部任务,至少会创建OS_IdleTask()任务用于在无其他任务就绪时执行,创建tick task用于记录时钟的允许。此外还会根据宏定义去创建统计任务(OS_StatTask()),计时器任务(OS_tmrTask()),和中断处理程序队列管理任务(OS_IntQTask()).如果os初始化成功则err为OS_ERR_NONE.否则返回相应错误标志,其错误标志以OS_ERR开头可在os.h文件中查询。需要保证OSInit(&err);
最优先调用。
第四行任务创建函数OSTaskCreate()
:它有13个参数。
其中第一个参数时任务控制模块地址。即在主函数前声明的;
第二个是任务名,用于为每个任务分配名称,系统并没有限制其字符的数量;
第三是任务函数名,用于确定所执行的任务函数;
第四是传递给任务的参数,在例程中为0即空指针。可以是任何的指针,给任务函数使用;
第五是任务的优先级,假如你有B,C两个任务在A函数中创建时,当B函数优先级高于A时,任务创建完毕后会立即执行任务B,反之则继续执行任务A创建任务C;
第六是分配给任务的堆栈的基地址;
第七是任务堆栈深度,用于确定任务允许的堆栈增长,在本例中当堆栈剩余10%时达到极限。
第八任务堆栈的大小;
第九是任务内部消息队列接收的最大消息量,
第十是使能时间片轮时时间片长度,
第十一是用户补充的存储区,
第十二是在启用统计任务情况下检查堆栈并创建任务时清除堆栈的内容;
最后一个是任务创建失败时的错误标志返回值。
在创建任务后可以对err变量进行判断,并执行当任务创建失败时所需要执行的操作。
最后一个函数是OSStart(&err);
即启动os多任务处理过程。
注意事项:在调用OSStart()函数之前,可以创建任意数量的任务,但是建议只创建 一个任务,因为在单个应用程序任务时允许UcosIII确定CPU的相对速度,允许UcosIII去决定CPU在运行时的使用量的比例,此外如果应用程序需要其他的内核对象如消息队列和信号量那么建议在调用OSStart()之前创建。最后检查中断是否使能。
所有先创建一个开始任务(AppTaskStart),之后在开始任务中创建应用程序所需要执行的任务。
代码如下
/* start task */
static void AppTaskStart(void *p_arg)
{
CPU_INT32U cnts;
OS_ERR err;
CPU_SR_ALLOC();
cnts = SystemCoreClock / (CPU_INT32U)OSCfg_TickRate_Hz; /* Determine nbr SysTick increments */
OS_CPU_SysTickInit(cnts);
OS_CRITICAL_ENTER();
/* LED1任务创建 */
OSTaskCreate((OS_TCB *)&AppTaskLED1TCB, //任务控制块
(CPU_CHAR *)"App Task LED1", //任务名
(OS_TASK_PTR)AppTaskLED1, //任务函数名
(void *)0, //传输给任务的参数
(OS_PRIO )APP_TASK_LED1_PRIO, //任务优先级
(CPU_STK *)&AppLED1TaskStk[0], //任务堆栈地址
(CPU_STK_SIZE)APP_TASK_LED1_STK_SIZE/10, //任务堆栈深度
(CPU_STK_SIZE)APP_TASK_LED1_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0u, //任务内部消息队列接收的最大消息量
(OS_TICK )0u, //使能时间片轮时的时间片长度,默认0
(void *)0, //用户补充的存储区
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),//任务选项
(OS_ERR *)&err); //存放函数错误时的返回值
/* LED2任务创建 */
OSTaskCreate((OS_TCB *)&AppTaskLED2TCB,
(CPU_CHAR *)"App Task LED2",
(OS_TASK_PTR)AppTaskLED2,
(void *)0,
(OS_PRIO )APP_TASK_LED2_PRIO,
(CPU_STK *)&APPLED2TaskStk[0],
(CPU_STK_SIZE)APP_TASK_LED2_STK_SIZE/10,
(CPU_STK_SIZE)APP_TASK_LED2_STK_SIZE,
(OS_MSG_QTY )0u,
(OS_TICK )0u,
(void *)0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
(OS_ERR *)&err);
OS_CRITICAL_EXIT();//退出临界区
OSTaskDel((OS_TCB*)&AppTaskStartTCB,&err);//删除任务自身
}
/* App Task LED1 */
static void AppTaskLED1(void *p_arg)
{
OS_ERR err;
while(1){
GPIO_SetBits(GPIOB,GPIO_Pin_5);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
}
}
/* App Task LED2 */
static void AppTaskLED2(void *p_arg)
{
OS_ERR err;
while(1){
GPIO_SetBits(GPIOE,GPIO_Pin_5);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s
}
}