介绍一种实时操作系统DSP/BIOS
/* functions */
void func_load();
/* Objects created by the Configuration Tool */
extern STS_Obj stsLoad;
/*
* ======== main ========
*/
void main()
{
/* fall into DSP/BIOS idle loop */
return;
}
void func_load()
{
STS_set(&stsPrintf、 CLK_gethtime());
/* 测试程序段 */
...
STS_delta(&stsPrintf、 CLK_gethtime());
}
func_load()为一个中断服务程序(ISR)。在C6211,150MHz的情况下,仅插入33个周期,约0.22μs。
4 任务调度(HWI/SWI/TSK)
一个操作系统的核心永远都是任务的调度。在DSP/BIOS中任务的调度是通过HWI、SWI和 TSK 三个模块来实现的。这三个模块分别对应于不同的调度方法。HWI即硬件中断。在 DSP/BIOS中硬件中断主要负责从外部设备中读写数据。由于硬件中断直接与硬件打交道,所以对应的中断服务程序ISR应该尽可能地短小精悍。需要注意的是HWI并不引起任务调度,因此在ISR的入口和出口成对地调用_HWI_enter()和_HWI_exit()这两个宏是必须的。HWI在处理完数据的输入输出后调用SWI_post()来调度相应的软件中断,SWI来完成数据处理工作。SWI是 DSP/BIOS任务调度的核心,共有14个优先级,每个优先级可以有多个任务。SWI任务是抢断式的,即高优先级的任务可以抢断低优先级的任务。但是SWI任务是不可阻塞的。它的运行状态如图1所示。
所有SWI任务共享一个堆栈,SWI任务只能在程序编制时预先定义好。DSP/BIOS中对任务的动态产生和对阻塞状态的支持是通过TSK模块来实现的。TSK有15个优先级,也是可以抢断的,但是每个TSK任务使用独立的堆栈。TSK任务是通过TSK_create()和TSK_delete()来动态生成和结束的。它的运行状态如图2所示。
5 同步(SEM/ATM/QUE/MBX)
多任务系统中多个任务之间的协调同步工作可以通过多种方法来实现。常用方法如信号量、原子量、队列和邮箱等。在DSP/BIOS中对这些方法的支持分别通过模块SEM、ATM、QUE和MBX来实现。由于这些方法的使用与一般的操作系统完全一样,在这里就不再赘述了。仅就最灵活的在SWI中使用Mailbox的方法来加以简单地说明。每个SWI任务都带有一个Mailbox,对它的操作可以是计数型的SWI_inc()、SWI_dec()也可以是比特位操作型的 SWI_or()、 SWI_andn()。Mailbox控制SWI任务被调度的条件。这些操作的功能如表2所示。
or操作是将Mailbox中的某一位置1,同时引起SWI任务的调度。当一个SWI任务可能由多个事件触发时,使用or操作可以方便地表示出触发的事件。如例3使用or操作指示触发事件:
andn操作是将Mailbox中的某一位清0,如果Mailbox为0,则引起SWI任务的调度。一个SWI任务需要多个条件都满足时才运行的情况下,使用andn操作可以方便地表示出这些条件的状态。如例4用andn操作来表示多条件时SWI任务调度:
inc和dec操作则更加灵活,用户可以借此实现多种应用。唯一需要注意的是,inc操作总是引起任务调度,而dec操作仅在Mailbox减到0时才引起一次任务调度。
6 通讯(PIP/SIO/HST)
一个系统如何从外部设备中取得数据,向外部设备输出数据,如何在两个任务之间进行数据正常交换是多样灵活的。但是这种多样性也给软件的维护升级以及模块化工作带来许多不利因素。因此在保持多样性的同时,保持接口的一致性对于一个软件来说是非常有帮助的。考虑到DSP大多数是通过某种类型的串行接口如中继线E1、IIS、SPI、同步串行口等与外部设备进行数据交换的,所以在DSP/BIOS中提供了两种非常有用的接口对象PIP和SIO。
PIP对象包含一个缓冲队列,与之对应的有两个任务读和写。图3很好地说明了PIP的逻辑关系和操作方式。例5,例6分别是一个PIP对象对应的读任务和写任务的示范程序。
例5 PIP对应的读任务:
extern far PIP_Obj pip;
reader()
{
Uns size;
Ptr addr;
if(PIP_getReaderNumFrames(&pip)>0)
{
PIP_get(&pip);
addr=PIP_getReaderAddr(&pip);
size=PIP_getReaderSize(&pip);
/*Code to empty the frame*/
PIP_free(&pip);
}
else{
LOG_error(″no frames available″);
/* or you could just return;*/
}
}
例6 PIP对应的写任务:
extern far PIP_Obj pip;
writer()
{
Uns size;
Ptr addr;
if(PIP_getWriterNumFrames(&pip)>0){
PIP_alloc(&pip);
addr=PIP_getWriterAddr(&pip);
size=PIP_getWriterSize(&pip);
/* fill the frame up to size */
PIP_put(&pip);
}
else{
LOG_error(″no frames available″);
/* or you could just return;*/
}
}
由逻辑关系可以看到,通过使用PIP应用程序可以保持一个简单统一接口而不必关心具体的硬件操作,因此当该软件移植到不同环境中时,至多只需要改写设备驱动程序。使用PIP的一个具体实例就是HST模块。HST模块在主机和DSP之间建立起一条数据链路,该链路就是一个PIP对象。对HST的操作方式与PIP一致。其差别仅仅在于HST在初始化时指向了预定义的DSP上的HPI接口而已。
SIO:从PIP的逻辑关系可以看出,读写PIP就是一个数据拷贝的过程。这在某些应用中,如实现网络协议TCP/IP时,不是非常有效。因为数据每向上传递一层就需要进行一次数据拷贝,其效率非常差。如果采用SIO来实现就会有很大的改善。SIO的操作只有get()和 put()两种。与PIP不同的是SIO没有自己的缓冲队列。每次get() 或 put() 操作时都会在应用程序和设备驱动程序之间交换缓冲的指针。所以SIO操作的实质是数据地址的交换。由于没有数据拷贝,其运行效率就很高。SIO的运行逻辑如图4所示。
- 采用Linux与DSP/BIOS RTOS实施双OS信号处理技术(02-13)
- 基于DSP/BIOS的数字电视传输流网络采集系统设计(04-12)
- 基于DSP BIOS的数字电视传输流网络采集系统设计(05-13)
- VxWorks for x86系统中实时时钟的应用(07-06)
- 基于DSP/BIOS的门禁系统设计与实现(07-10)
- 中断在TMS320C54x系列DSP中的应用(10-01)