OMAPL138学习----DSPLINK DEMO解析之LOOP

loop例程中数据流向:

………………………………………………………………ARM端…………………………………………………………………

loop.c是实现loop例程的文件。

status = LOOP_Create (dspExecutable,strBufferSize,strNumIterations,processorId) ;

    --------status = PROC_setup (NULL) ;

    --------status = PROC_attach (processorId, NULL) ;

    -------- status = POOL_open (POOL_makePoolId(processorId, POOL_ID), &poolAttrs) ;

    -------- status = PROC_load (processorId, (Char8 *) &imageInfo, numArgs, args) ;

    --------status = CHNL_create (processorId, CHNL_ID_OUTPUT, &chnlAttrOutput) ;

    --------status = CHNL_create (processorId, CHNL_ID_INPUT, &chnlAttrInput) ;

    --------status = CHNL_allocateBuffer (processorId,CHNL_ID_OUTPUT,LOOP_Buffers,LOOP_BufferSize ,1) ;

    --------用有效数据初始化缓冲:

 if (DSP_SUCCEEDED (status)) {
        temp = LOOP_Buffers [0] ;

        for (i = 0 ; i < LOOP_BufferSize ; i++) {
            *temp++ = XFER_CHAR ;
        }
    }

status = LOOP_Execute (LOOP_NumIterations, processorId) ;

    -------- status = PROC_start (processorId) ;

    --------LOOP_IOReq.buffer = LOOP_Buffers [0] ;

        LOOP_IOReq.size = LOOP_BufferSize ;

    --------status = CHNL_issue (processorId, CHNL_ID_OUTPUT, &LOOP_IOReq) ;  //向DSP发送数据

    --------status = CHNL_reclaim (processorId,CHNL_ID_OUTPUT,WAIT_FOREVER,&LOOP_IOReq) ;

    --------status = CHNL_issue (processorId, CHNL_ID_INPUT, &LOOP_IOReq) ;  //从DSP端接收数据

    --------status = CHNL_reclaim (processorId,CHNL_ID_INPUT,WAIT_FOREVER,&LOOP_IOReq) ;

    -------- status = LOOP_VerifyData (LOOP_IOReq.buffer) ;

 

 LOOP_Delete (processorId) ;

    --------tmpStatus = CHNL_freeBuffer (processorId,CHNL_ID_OUTPUT,LOOP_Buffers,1) ;

    --------tmpStatus = CHNL_delete  (processorId, CHNL_ID_INPUT) ;

    -------- tmpStatus = CHNL_delete  (processorId, CHNL_ID_OUTPUT) ;

    --------status = PROC_stop (processorId) ;

    -------- tmpStatus = POOL_close (POOL_makePoolId(processorId, POOL_ID)) ;

    -------- tmpStatus = PROC_detach  (processorId) ;

    -------- tmpStatus = PROC_destroy () ;

 

………………………………………………………………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 来选择哪一种模式,如果没有指定,默认使用SWI。i如果定义SWI_MODE则从SWILOOP_create()开始执行,如果定义TSK_MODE则从tskLOOP()开始执行。 SWI_MODE使用了IOM驱动和DIO适配器、GIO模块来实现,TSK_MODE使用IOM驱动、DIO适配器和SIO模块来实现。

参考文档:1FC7-TMS320C55x DSP BIOS 5.x Application Programming Interface (API) Reference Guide.pdf

posted @ 2014-03-26 09:38  卧佛赐杯  阅读(750)  评论(1编辑  收藏  举报