在建立应用之前,还应该先设置OS_CFG.H头文件来确定uC/OS-II允许的各种功能,包括定义最大任务数,任务最低优先级,事件控制块数目,内存块数目,队列控制块数目等,不用的选项可以禁止掉,以减少编译后的代码长度。
本文设计一个运用uC/OS-II的简单应用,利用板上的一个七段数码管和3个LED,主要编程思路是:建立一个优先级较高的七段数码管显示任务,循环显示从1到9的数字;建立一个优先级较低的LED闪烁任务,同时循环控制3个LED的亮灭;建立一个最高优先级的任务后将之挂起,为外部中断0编写一个中断服务程序,用来恢复挂起的高优先级任务。高优先级任务将LED快速闪烁数次,然后将自身挂起以待下次中断发生。为保证同一时间只能有一个任务访问LED显示函数,使用了信号量保护资源。具体程序如下:
main.c
#include “includes.h”
#include “main.h”
OS_STK TaskStk[TASK_STK_SIZE];
OS_STK TaskStkStart[TASK_STK_SIZE];
OS_EVENT *RandomSem;
u_int num,led_num;
void TaskStart(void *);
void Task(void *);
int main(void)
{
OSInit();
RandomSem=OSSemCreate(1);
OSTaskCreate(TaskStart,(void*)0,&TaskStkStart[TASK_STK_SIZE-1],1);
OSTaskCreate(Task,(void*)0,&TaskStk[TASK_STK_SIZE-1],2);
OSStart();
}
main.c中先声明两个任务堆栈和一个信号量变量,主函数main中先调用OSInit()初始化系统,然后生成一个信号量。通过OSTaskCreate()函数建立两个任务TaskStart和Task,然后调用OSStart()运行内核,进行进程调度。
task.c
#include "includes.h"
#include "main.h"
void OSTimeDly (INT16U);
void TaskStart(void *);
INT8U OSTaskSuspend(INT8U);
INT8U OSTaskResume(INT8U);
void OSSemPend (OS_EVENT *,INT16U,INT8U *);
INT8U OSSemPost (OS_EVENT *);
void SP_Compensate(void);
void IRQ_ISR(void);
extern num;
extern led_num;
extern *RandomSem;
OS_STK TaskFIQStk[TASK_STK_SIZE];
void display(u_int num)
{
int *p;
p=T_PIO_CODR;
*p=0x00FF0000;
p=T_PIO_SODR;
switch (num)
{
case 0: *p=NUM0;break;
case 1: *p=NUM1;break;
case 2: *p=NUM2;break;
case 3: *p=NUM3;break;
case 4: *p=NUM4;break;
case 5: *p=NUM5;break;
case 6: *p=NUM6;break;
case 7: *p=NUM7;break;
case 8: *p=NUM8;break;
case 9: *p=NUM9;break;
}
}
void IRQ_Resume(void)
{
OSTaskResume(0);
}
void init(void)
{
int *p;
num=0;
led_num=1;
p=T_AIC_IDCR;
*p=0xffffffff;
p=T_AIC_SVR16;
*p=(u_int)IRQ_ISR;
p=T_AIC_SMR16;
*p=0x27;
p=T_AIC_SVR4;
*p=(u_int)OSTickISR;
p=T_AIC_SMR4;
*p=0x27;
p=T_AIC_ICCR;
*p=0xffffffff;
p=T_PIO_PDR;
*p=0xffffffff;
p=T_PIO_PER;
*p=0x00FF0016;
p=T_PIO_OER;
*p=0x00FF0016;
p=T_PIO_CODR;
*p=0x00FF0000;
p=T_PIO_SODR;
*p=NUM0;
p=T_PS_PCER;
*p=0x10;
p=T_TC_CCR;
*p=0x2;
p=T_TC_IDR;
*p=0xffffffff;
p=T_TC_CMR;
*p=0x4004;
p=T_TC_RC;
*p=15625;
p=T_TC_IER;
*p=0x10;
p=T_TC_CCR;
*p=0x01;
p=T_AIC_IECR;
*p=0x00010010;
p=T_TC_CCR;
*p=0x4;
}
void TaskISR(void *pdata)
{
int *p;
INT8U err;
int i;
pdata=pdata;
SP_Compensate();
while(1)
{
OSSemPend((OS_EVENT *)RandomSem,0,&err);
p=T_PIO_SODR;
*p=0x16;
for (i=0;i<100000;i++);
p=T_PIO_CODR;
*p=0x16;
for (i=0;i<100000;i++);
p=T_PIO_SODR;
*p=0x16;
for (i=0;i<100000;i++);
p=T_PIO_CODR;
*p=0x16;
for (i=0;i<100000;i++);
OSSemPost((OS_EVENT *)RandomSem);
OSTaskSuspend(OS_PRIO_SELF);
}
}
void TaskStart(void *pdata)
{
pdata=pdata;
OSTaskCreate(TaskISR,(void*)0,&TaskFIQStk[TASK_STK_SIZE-1],0);
init();
while(1)
{
num++;
if (num>9)
num=0;
display(num);
OSTimeDly(2);
}
}
void Task(void *pdata)
{
int *p;
INT8U err;
pdata=pdata;
SP_Compensate();
while(1)
{
OSSemPend((OS_EVENT *)RandomSem,0,&err);
p=T_PIO_CODR;
*p=0x16;
p=T_PIO_SODR;
if (led_num==1)
led_num=2;
else if (led_num==2)
led_num=3;
else
led_num=1;
switch(led_num)
{
case 1: *p=0x2; break;
case 2: *p=0x4; break;
case 3: *p=0x10;break;
}
OSSemPost((OS_EVENT *)RandomSem);
OSTimeDly(1);
}
}