main函数中通过OSTaskcreate()创建了一个名字为start_task的任务。在start_task任务进入临界区之后创建了一个名字为led1 task的任务。在该任务中实现了led的闪烁。
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "includes.h"
//任务优先级
#define START_TASK_PRIO 3
//任务堆栈大小
#define START_TASK_SIZE 512
//任务控制模块
OS_TCB StartTaskTCB;
//任务堆栈
CPU_STK START_TASK_STK[START_TASK_SIZE];
//任务函数
void start_task(void *p_arg);
//任务优先级
#define LED1_TASK_PRIO 4
//任务堆栈大小
#define LED1_TASK_SIZE 128
//任务控制模块
OS_TCB LED1TaskTCB;
//任务堆栈
CPU_STK LED1_TASK_STK[START_TASK_SIZE];
//任务函数
void LED1_task(void *p_arg);
int main()
{
OS_ERR err;
SysTick_Init(72);
LED_Init();
OSInit(&err); //初始化UCOSIII
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_TASK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_TASK_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); //存放该函数错误时返回值
OSStart(&err); //开启UCOSIII
while(1);
}
//开始任务函数
void start_task(void *p_arg)
{
OS_ERR err;
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
CPU_SR_ALLOC();
p_arg=p_arg;
CPU_Init();
cpu_clk_freq = BSP_CPU_ClkFreq();
//Determine SysTick reference freq.
cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;
//Determine nbr SysTick increments
OS_CPU_SysTickInit(cnts);
Mem_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err);
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
OSTaskCreate((OS_TCB*)&LED1TaskTCB,
(CPU_CHAR*)"led1 task",
(OS_TASK_PTR)LED1_task,
(void*)0,
(OS_PRIO)LED1_TASK_PRIO,
(CPU_STK*)&LED1_TASK_STK[0],
(CPU_STK_SIZE)LED1_TASK_SIZE/10,
(CPU_STK_SIZE)LED1_TASK_SIZE,
(OS_MSG_QTY)0,
(OS_TICK)0,
(void*)0,
(OS_OPT)OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR*)&err);
OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务
OS_CRITICAL_EXIT(); //进入临界区
}
void LED1_task(void *p_arg)
{
OS_ERR err;
p_arg=p_arg;
while(1){
led1=!led1;
OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_NON_STRICT,&err);
}
}
程序说明:
OS_ERR
该类型在os.h文件中被定义为一个结构体。该结构体定义了错误相关代号。例如OSInit()初始化函数运行成功,错误代号被设为OS_ERR_NONE。如果在初始化不成功,UCOSIII会根据执行结果返回相应的错误代号。
部分代码:
OS_Init()
必须在UCOSIII的其他函数之前调用,用于对操作系统的各项初始化。如清除中断嵌套计数器,清除调度锁计数器,OS_TCB指针初始化,优先级变量初始化等
OSTaskCreate()
该函数用于任务的创建,OsTaskCreate()需要13个参数。
第一个参数:指向任务的TCB指针。
第二个参数:ASCII字符串类型,用于任务名字
第三个参数:执行任务代码的指针,任务函数名字。
第四个参数:传递给任务函数的参数,和任务函数的形参数据类型相对应。
第五个参数:任务优先级,数字越小,优先级越高
第六个参数:指向任务堆栈基地址的指针
第七个参数:是设置为堆栈“水印”限制的堆栈元素数量。这个值表示栈满前剩余的 CPU_STK 条目数。例如,指定 ‘stk_size’ 值的 10% 表示将达到堆栈限制当堆栈达到 90% 满时。
第八个参数:是元素数量的堆栈大小。如果 CPU_STK 设置为 CPU_INT08U,‘stk_size’ 对应于可用的字节数。如果 CPU_STK 设置为
CPU_INT16U, ‘stk_size’ 包含可用的 16 位条目数。最后,如果CPU_STK 设置为CPU_INT32U,‘stk_size’ 包含 32 位条目的数量
在堆栈上可用。
第九个参数:可以发送任务消息最大数目,为零表示默认长度
第十个参数:任务之间循环时间片。的时间量(以滴答为单位)指定0表示默认
第十一个参数:用户补充的存储区。是指向用户提供的内存位置的指针,用作 TCB 扩展。例如,这个用户内存可以保存浮点寄存器的内容在上下文切换期间,每个任务执行所需的时间,执行次数任务已切入等
第十二个参数:任务选项。包含有关任务行为的附加信息(或选项)。参见 OS.H 中的OS_OPT_TASK_xxx。目前的选择是:
*OS_OPT_TASK_NONE 未选择任何选项
*OS_OPT_TASK_STK_CHK 允许任务的堆栈检查
*OS_OPT_TASK_STK_CLR 创建任务时清空堆栈
*OS_OPT_TASK_SAVE_FP 如果CPU有浮点寄存器,保存
在上下文切换期间。
OS_OPT_TASK_NO_TLS 如果调用者不想要或不需要 TLS (Thread Local存储)支持任务。如果你不包括这个选项,默认情况下将支持 TLS。
第十三个参数:存放该函数错误时的返回值。p_err 是指向将在此调用期间设置的错误代码的指针。值指针
*OS_ERR_NONE 如果函数成功。
*OS_ERR_ILLEGAL_CREATE_RUN_TIME 如果您在调用后尝试创建任务
*OSSafetyCriticalStart()。
*OS_ERR_NAME 如果 ‘p_name’ 是一个 NULL 指针
*OS_ERR_PRIO_INVALID 如果您指定的优先级高于最大值
允许(即 >= OS_CFG_PRIO_MAX-1)或,如果 OS_CFG_ISR_POST_DEFERRED_EN 设置为 1 并且您尝试过使用保留的优先级 0。
*OS_ERR_STK_INVALID 如果你为“p_stk_base”指定了一个空指针
*OS_ERR_STK_SIZE_INVALID 如果您为 ‘stk_size’ 指定了零
*OS_ERR_STK_LIMIT_INVALID 如果您指定了大于或等于的 ‘stk_limit’
*‘stk_size’
*OS_ERR_TASK_CREATE_ISR 如果您尝试从 ISR 创建任务。
*OS_ERR_TASK_INVALID 如果你为“p_task”指定了一个空指针
*OS_ERR_TCB_INVALID 如果你为 ‘p_tcb’ 指定了一个 NULL 指针
返回值:指向所创建任务的 TCB 的指针。该指针必须用作任务的 ID(即句柄)。
OSStart()
开始多任务处理。在OSStart()调用之前UCOSIII会选择最高优先级任务。
所有的UCOSIII任务需要被设置为无限循环
OS_CRITICAL_ENTER()
在os.h中声明定义,进入临界区
OSTimeDlyHMSM()
hours:时
minutes:分
seconds:秒
milli:毫秒
opt: 指定逻辑或的时间延迟位字段选项;标有 ***的默认选项:
****OS_OPT_TIME_DLY 指定从 OSTickCtr 的当前值开始的相对时间。
*OS_OPT_TIME_TIMEOUT 与 OS_OPT_TIME_DLY 相同。
*OS_OPT_TIME_MATCH 表示延迟指定 OSTickCtr 的绝对值
*必须在任务恢复之前到达。
*OS_OPT_TIME_PERIODIC 表示延迟指定 OSTickCtr 的周期值
*必须在任务恢复之前到达。
****OS_OPT_TIME_HMSM_STRICT 只允许小时 (0…99)
*分钟 (0…59)
*秒 (0…59)
*毫秒 (0…999)
*OS_OPT_TIME_HMSM_NON_STRICT 允许任何小时值 (0…999)
*分钟 (0…9999)
*秒 (0…65535)
*毫秒 (0…4294967295)
p_err: 是一个指向一个变量的指针,该变量将从这个调用中接收一个错误代码。
*OS_ERR_NONE 如果函数从期望的延迟返回
*OS_ERR_OPT_INVALID 如果你为 ‘opt’ 指定了一个无效的选项
*OS_ERR_SCHED_LOCKED 调度器锁定时不能延迟
*OS_ERR_TIME_DLY_ISR 如果从 ISR 调用
*OS_ERR_TIME_INVALID_HOURS 如果您没有为“小时”指定有效值
*OS_ERR_TIME_INVALID_MINUTES 如果您没有为“分钟”指定有效值
*OS_ERR_TIME_INVALID_SECONDS 如果您没有为“秒”指定有效值
*OS_ERR_TIME_INVALID_MILLISECONDS 如果你没有为 ‘milli’ 指定一个有效的值
*OS_ERR_TIME_ZERO_DLY 如果小时、分钟、秒和毫秒都为 0