loop例程中数据流向:
loop.c是实现loop例程的文件。
在LOOP_Main()主函数中调用Loop_Create()、LOOP_Execute()、LOOP_Delete()三个函数来创建执行和删除。
LOOP_Create()中PROC_setup()初始化proc对象,PROC_attach()附加要使用的DSP,随后打开POOL
PROC_load() 下载代码到DSP端
status = CHNL_create (processorId, CHNL_ID_OUTPUT, &chnlAttrOutput) ;创建到DSP的channel
status = CHNL_create (processorId, CHNL_ID_INPUT, &chnlAttrInput) ; 创建来自DSP的channel
status = CHNL_allocateBuffer (processorId,
CHNL_ID_OUTPUT,
LOOP_Buffers,
分配传输到DSP的缓冲
LOOP_BufferSize ,
1) ;
temp = LOOP_Buffers [0] ;
for (i = 0 ; i <
LOOP_BufferSize ; i++) { 初始化缓冲有效数据
*temp++ = XFER_CHAR ;}
status = LOOP_Execute (LOOP_NumIterations, processorId) ; 执行数据传输
----------PROC_start()//让DSP开始运行
----------status = CHNL_issue (processorId, CHNL_ID_OUTPUT, &LOOP_IOReq) ; //向DSP发送数据,把已经填充好的数据发送到channel
-----------status = CHNL_reclaim (processorId,
//回收空缓冲
CHNL_ID_OUTPUT,
WAIT_FOREVER,
&LOOP_IOReq) ;
………………………………………………………………DSP端…………………………………………………………………
在DSP端进行ISR初始化、DSPLINK初始化以后进入SWILOOP_create()
SWILOOP_create()
------------DSPLINK_init()
------------status=POOL_open(0,&poolObj)
------------ status = DEV_createDevice("/dsplink", &ZCPYDATA_FXNS, (Fxn) &ZCPYDATA_init, &devAttrs) ;
这一步是动态建立IOM 驱动,这个IOM驱动是什么东西。DSP/BIOS提供了两种设备驱动来使能应用程序与DSP周边进行通信传输:IOM和SIO/DEV。
---------- status = DEV_createDevice("/dio_dsplink", &DIO_tskDynamicFxns, NULL, &dioDevAttrs);//
上图是在使用DIO 驱动和mini-driver 各个模块的依赖关系。
-------------*infoPtr = MEM_calloc (DSPLINK_SEGID,
//为SWILOOP传输信息结构体分配
sizeof
(SWILOOP_TransferInfo),
DSPLINK_BUF_ALIGN) ;
-------------GIO_Attrs gioAttrs = GIO_ATTRS ;
//这一步是创建channel handle
info->gioInputChan = GIO_create
(INPUT_CHANNEL,
IOM_INPUT,
NULL,
NULL,
&gioAttrs)
;
info->gioOutputChan = GIO_create
(OUTPUT_CHANNEL,
IOM_OUTPUT,
NULL,
NULL,
&gioAttrs) ;
这个GIO又是什么东西呢?GIO模块是DSP/BIOS用于输入输出的模块,它是应用程序和mini-driver的通信基础。DEV模块负责维护系统设备驱动表,GIO模块通过使用函数来获得设备信息,比如说DEV_match。
GIO_create()是分配和初始化GIO对象。应用程序调用GIO_create 来建立GIO_Obj 对象和打开channel 通信。这个函数初始化I/Ochannel ,打开最底层的设备驱动channel。也创建了同步对象并存储在GIO_obj对象里。
----------- swiAttrs.fxn = loopbackSWI ; //这一段为发送和接收数据创建SWI
swiAttrs.arg0
= (Arg) info ;
swiAttrs.mailbox = INITIAL_MAILBOX_VAL ;
info->swi = SWI_create
(&swiAttrs) ;
if (info->swi == NULL)
{
status = SYS_EALLOC ;
SET_FAILURE_REASON (status) ;
}
----------loopbackSWI()
--------- for (i = 0 ; i < info->readWords ; i++) {//处理数据
info->outputBuffer [i] = info->inputBuffer [i] ;
--------- iomStatus = GIO_submit (info->gioInputChan,
//提交读请求
IOM_READ,
info->inputBuffer,
(size_t *)
&(info->bufferSize),
&(info->appReadCb))
;
-------iomStatus = GIO_submit (info->gioOutputChan,
IOM_WRITE,
info->outputBuffer,
&numWordsToWrite,
&(info->appWriteCb)) ;
GIO_submin()是向mini-driver提交 GIO数据包,成功返回IOM_COMPLETED,如果请求被排列则返回IOM_PENDING。
GIO_write()同步写命令,应用程序使用这个函数写数据到通信channel。
-------- status = POOL_alloc (SAMPLE_POOL_ID,
(Ptr *) &(info->inputBuffer),
info->bufferSize) ;
if (status == SYS_OK) {
status = POOL_alloc (SAMPLE_POOL_ID,
(Ptr *) &(info->outputBuffer),
info->bufferSize) ;
为输入和输出分配缓冲区
SWILOOP_execute()
----------iomStatus = GIO_submit (info->gioInputChan,
IOM_READ,
info->inputBuffer,
(size_t *) &(info->bufferSize),
&(info->appReadCb)) ;
提交读请求
----------SWI_andn (info->swi, WRITE_MAILBOX_MASK) ;
这是SWI模型中的一个函数,SWI模块是软件中断管理,SWI_andn()是清除软件中断邮箱位,如果值为0则提交,它用于提交一个软件中断
tskLoopTask = TSK_create(tskLoop, NULL, 0); //为TSKLOOP 应用程序创建任务
----------DSPLINK_init();
----------TSKLOOP_create()
----------POOL_open()
-----------status = DEV_createDevice("/dsplink", &ZCPYDATA_FXNS, (Fxn) &ZCPYDATA_init, &devAttrs) ;
动态创建IOM驱动
----------status = DEV_createDevice("/dio_dsplink", &DIO_tskDynamicFxns, NULL, &dioDevAttrs);
动态创建DIO适配器
---------- *infoPtr = MEM_calloc (DSPLINK_SEGID,
sizeof (TSKLOOP_TransferInfo),
DSPLINK_BUF_ALIGN) ;
分配TSKLOOP_TransferInfo,初始化并传递给其他应用程序参数
----------- info->numTransfers = numTransfers
; //填充传输数据
info->bufferSize =
xferBufSize ;
info->numBuffers
= TSK_NUM_BUFFERS ;
-----------info->inputStream = SIO_create (INPUT_CHANNEL, //创建输入输出流
SIO_INPUT,
info->bufferSize,
&attrs)
;
info->outputStream = SIO_create
(OUTPUT_CHANNEL,
SIO_OUTPUT,
info->bufferSize,
&attrs)
;
SIO是什么?SIO就是输入输出流管理模块,通过调用SIO_create()和SIO_delete()函数来打开和关闭数据流。SWI和TSK都可以使用SIO模块。SIO_create()会调用MEM_alloc()来动态创建对象数据结构体。SWI和HWI都不能调用SIO_create()。SIO_issue()发送一个缓冲到数据流。调用一次SIO_issue则至少调用一次SIO_reclaim()。SIO_reclaim()是请求一个缓冲流,如果是来自TSK线程的调用,全一直阻塞,直到有一个缓冲返回调用者或数据流超时。如果是SWI线程调用SIO_reclaim()没有可用数据缓冲则会返回错误,所以如果是SWI 调用它,就不会有阻塞。
-----------status = POOL_alloc (SAMPLE_POOL_ID,(Ptr *) &(info->buffers [i]),info->bufferSize) ;
if (status != SYS_OK) {
for (j = 0 ; j < i ; j++)
{
POOL_free (SAMPLE_POOL_ID,info->buffers [i],info->bufferSize)
;
info->buffers [j] = NULL ;
}
为传输分配缓冲区
TSKLOOP_execute()
------status = SIO_issue(info->inputStream,buffer,info->bufferSize,arg) ;//SIO_issue()作用是向数据流发送缓冲
-------SIO_reclaim (info->inputStream,(Ptr *) &buffer,&arg)//SIO_reclaim()的作用是请求一个缓冲流
从GPP端接收数据
-------SIO_issue(info->outputStream,buffer,info->receivedSize,arg);//
--------nmadus = SIO_reclaim (info->outputStream,(Ptr *) &(buffer),&arg) ;//
把处理过的数据返回给GPP
TSKLOOP_delete()
--------status = SIO_delete (info->inputStream) //删除输入流
--------tmpStatus = SIO_delete(info->outputStream);//删除输出流
--------POOL_free (SAMPLE_POOL_ID, info->buffers [j], info->bufferSize) ;//删除缓冲区
-------- freeStatus = MEM_free (DSPLINK_SEGID, info, sizeof (TSKLOOP_TransferInfo)) ;//删除消息数据结构
总结:从DSP端来看,总的用了两各方式来实现,一是SWI_MODE,一是TSK_MODE,两种mode是在dsplink的配置文件中dsplinkcfg.pl定义,可以用–DspTskMode = 1 来选择哪一种模式。i如果定义SWI_MODE则从SWILOOP_create()开始执行,如果定义TSK_MODE则从tskLOOP()开始执行。 SWI_MODE使用了IOM驱动和DIO适配器、GIO模块来实现,TSK_MODE使用IOM驱动、DIO适配器和SIO模块来实现。
OMAPL138学习----DSPLINK DEMO解析之LOOP,布布扣,bubuko.com
OMAPL138学习----DSPLINK DEMO解析之LOOP
原文:http://www.cnblogs.com/zxycele/p/3624804.html