想要在自己设计的嵌入式系统中使用操作系统,先要配置或者移植操作系统。相关的文集比较多,在这里我就不说了,我还是想多聊些应用方面的东西。
关于任务的建立和运行。
任务的建立是指写一个任务程序。
任务的运行是指让系统执行一个任务。
RTX51Tiny例:
void mytask2(void) _task_ 1 //任务编号为1的任务
{
...;
while(1){
...;
}
}
void mytask1(void) _task_ 0 //任务编号为0的任务,首先执行
{
...;//必要的初始化
os_create_task(1); //建立编号为1的任务,即允许编号为1的任务执行,但不是立即执行
while(1){
...; //任务过程。
...; //在许多操作系统的例程中,都不约而同地把第一个任务运行后删除。我觉得没必要。
...; //毕竟开一个任务需要占用不少资源,没必要浪费。
}
}
RTX51任务程序不带输入参数。但其他大多数的任务程序都支持带参数,带参数的例子后面还会提到。
任务程序的后缀,只有在操作系统与编译系统捆绑在一起的情况下才有。keil下的RTX51和RL-RTX都是如此。
RTX51Tiny任务有后缀“_task_ TASKID”,需要指定任务编号。由于RTX51没有任务优先级,任务依靠时间片来调度,因此RTX51引入任务编号的概念,在这在其他操作系统中是不存在的。在RL-RTX中,后缀为“__task”。 在RTX51中,任务编号为0的任务是必须的,由于不需要main()程序,系统总是从任务编号为0任务程序开始运行。
大多数操作系统环境下,main()程序是必要的。在main()程序中,可以进行某些与操作系统无关的配置工作。更重要的是,操作系统的启动需要在main()程序中(除了少数系统如TiDSPBIOS)。
RTX51其他任务的执行需要在0号任务中使用os_create_task(TASKID)函数。“TASKID”就是需要运行的任务的编号。在大多数操作系统中,都是以类似的CREATE_TASK函数来启动其他需要运行的任务。但也有少数操作系统支持“静态”创建并运行任务的,如TiDSPBIOS,可以在操作系统中直接设置需要运行任务,系统运行时,操作系统就会按已配置的顺序和优先级启动各个任务的运行。
绝大多数操作系统都支持任务程序带输入参数。比较普遍的意义,就是可以在任务中减少使用全局变量,从而优化任务程序、方便任务的移植。还有比较实用的方面就是以一个任务程序建立多个应用。这就好比写一个类,在运行时,创建多个应用。下面举个简单的例子。
MCU的P0口,其8个输出各控制1个LED。第1个LED每5秒闪一下,第2个LED每2秒闪一下,等等。每次点亮时间100ms。
示例程序如下:
//定义通道及延时的数据结构
typedef struct channel{
int ch; //通道
int dly; //延时
}ChannelObj;
ChannelObj ch[8]={ //通道定义,全局变量
0,5, //通道0,延时5秒
1,2, //通道1,延时2秒
2,3, //...
3,7,
4,6,
5,4,
6,8,
7,1,
};
//定义任务优先级
#define TASK_MAIN_PRIO 1
#define TASK_APP_PRIO 2
int main(void){
//硬件初始化(已简略)
//P0.0-7端口初始化
SCS = 1; //启用高速IO口
PINSEL0 &= 0xFFFF0000; //选择IO口
FIO0DIR0 = 0xFF; //选择输出
FIO0CLR0 = 0xFF; //全部输出低电平
//与操作系统无关的初始化可以放在main()中。
//...
os_sys_init_prio(task_main,TASK_MAIN_PRIO);//启动task_main任务
while(1);
}
void task_main(void * pdata) __task {
char i;
OS_TID tskid[8];
for (i=0;i<8;i++){
//建立8个通道任务,传入相应参数。
tskid = os_tsk_create_ex(task_app,TASK_APP_PRIO,&ch);
}
while(1){
...;
...;//可以在此或其他任务中变更通道的延时参数ch.dly。
}
}
void task_app(void * para) __task {
ChannelObj * app_ch;
app_ch = (ChannelObj *)para;//导入通道参数
while(1){
int s;
ch_mask;
ch_mask = 0x01 << (app_ch->ch);
FIO0SET0 = ch_mask; //点亮该通道LED
os_dly_wait(10); //点亮延时100ms
FIO0CLR0 = ch_mask; //熄灭该通道LED
for (s=0;s<app_ch->dly;s++)os_dly_wait(100); //熄灭延时1s*延时参数
}
}
在该示例中,由于每个通道的运行模式是一样的,唯一不同的是延时参数不一致,因此可以只为通道的运行流程写一个任务程序(task_app),运行时由task_main任务建立多个task_app任务,即8个通道由8个任务实例独立运行。这充分地突出了多任务操作系统的优势。
上述示例表明了多任务的一种应用方法。其他的应用,诸如多线程的网络服务应用,分布式信号采集等等,都可以应用类似的方法。
文章评论(0条评论)
登录后参与讨论