之前的配置中我们知道如何配置通道速率、设置deviceID。
也就是马路已经铺设好了,我们应该造车了。
搏一搏,单车变摩托!
SRIO不是单车,而是摩托车,我们需要搏一搏,把这个摩托车造出来,在我们已经铺设好的高速路上飞驰。
目录
下面提及的关于
LSU寄存器的详细知识,在我的以下两篇博客中都大篇幅详细讲过,如果本文说的不清楚,大家可以看一下我之前的这两篇博客:
SRIO学习(六)——Direct I/O 操作(一)
SRIO学习(七)——Direct I/O 操作(二)
一、LSU寄存器基本介绍
SRIO用来高速传输大量数据,用的就是LSU,LSU的全称是Load/Store Unit,一共有8个LSU(Load/Store Unit),每个LSU都有自己的7个寄存器,即LSU_REG0-LSU_REG6,REG0-REG4用来存储控制信息,REG5、REG6用来存储命令和状态信息。除了REG6,其它寄存器都是可读可写的,只有REG6有只读和只写两种模式。
所有关于SRIO传输的重要属性都在LSU的7个寄存器中,我们所要做的,就是对这7个寄存器赋上不同的值,以实现我们的目的。对于这7个寄存器的说明,都在我之前的博客里,说的不清楚的地方,在文末的参考文献里有详细说明。
LSU的这7个寄存器就像摩托车的零件,每一个零件都有不同的功能,但是只有组装起来,成为一辆完整的车架,才能有具体功能。
而对于这7个寄存器的赋值,TI官方给出的两种方式,我都提供出来:
1、对每一个寄存器单独赋值,这需要知道每个寄存器的每个域的具体功能,才能得心应手地配置。因为我的ti文件夹安装在c盘,所以我的SRIO文档的路径为:
C:/ti/pdk_C6678_1_1_2_6/packages/ti/csl/docs/doxygen/html/csl__srio_aux_8h.html
该文档中有以下API是用来对每个寄存器单独赋值的(截图):
任意点开上面的一个API,就会有其使用方式,这里我以
reg0为例,提供其使用方式:
2、对指定的功能进行编辑
这种配置方式只需要知道一些特定名词,如bytecount,即传输的字节数,dstID,即目的地的deviceID等等。该方式的API也可以在下面的路径中找到。
C:/ti/pdk_C6678_1_1_2_6/packages/ti/csl/docs/doxygen/html/csl__srio_aux_8h.html
下面是一段示例程序,我的工程中采用的就是这种配置方法,简明易懂,也比较推荐这种方法:
CSL_SrioHandle hSrio;//声明一个SRIO句柄
SRIO_LSU_TRANSFER lsuTransfer;//声明一个LSU传输
// Open the CSL SRIO Module 0
hSrio = CSL_SRIO_Open (0);//打开CSL SRIO模块0
...
// 对该LSU传输的信息进行赋值.
lsuTransfer.rapidIOMSB = 0x0;
lsuTransfer.rapidIOLSB = (Uint32)&tx_buffer[0];
lsuTransfer.dspAddress = (Uint32)&rx_buffer[0];
lsuTransfer.bytecount = 256;
lsuTransfer.doorbellValid = 0;
lsuTransfer.intrRequest = 1;
lsuTransfer.supInt = 0;
lsuTransfer.xambs = 0;
lsuTransfer.priority = 2;
lsuTransfer.outPortID = 1;
lsuTransfer.idSize = 1;
lsuTransfer.srcIDMap = 0;
lsuTransfer.dstID = 0xDEAD;
lsuTransfer.ttype = 4;
lsuTransfer.ftype = 5;
lsuTransfer.hopCount = 0;
lsuTransfer.doorbellInfo = 0;
// 赋值完成之后,用下面的函数完成对整个传输的启动和配置
CSL_SRIO_SetLSUTransfer (hSrio, 1, &lsuTransfer);
...
二、LSU传输流程
知道了如何组装LSU,我们还需要知道LSU具体是如何运作的。关于LSU的运作,我之前的文章
SRIO学习(六)——Direct I/O 操作(一)也详细说过,具体分3个步骤:
1、查询REG6来确定LSU是否繁忙,如果繁忙则等待,如果不繁忙,则通过对REG6的写入来锁定LSU。
2、对REG0-REG4进行写入,来确定具体传输的目标,地址等信息。
3、对REG5进行写入,写明包类型(Ftype、Ttype),并触发传输。
三、LSU方式_发送代码的实现
综上所述,我们在最终使用LSU传输时,就要融合上面提到的两方面内容,一是LSU寄存器编辑,二是LSU数据传输流程。具体见以下代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
SRIO_LSU_TRANSFER lsuTransfer0;
void Lsu0_Init()
{
lsuTransfer0.rapidIOMSB = 0x0;
lsuTransfer0.doorbellValid = 0;
lsuTransfer0.intrRequest = 1;
lsuTransfer0.supInt = 0;
lsuTransfer0.xambs = 0;
lsuTransfer0.priority = 0;
lsuTransfer0.outPortID = 0;
lsuTransfer0.idSize = 1;
lsuTransfer0.srcIDMap = 0;
lsuTransfer0.dstID = 0xABCD;
lsuTransfer0.ttype = 4;
lsuTransfer0.ftype = 2;
lsuTransfer0.hopCount = 0;
lsuTransfer0.doorbellInfo = 0;
}
void SRIO_READ(unsigned int SRC_ADDR,unsigned int BYTES,unsigned int DST_ADDR)
{
int print = 0;
unsigned char context;
unsigned char transID;
unsigned char count;
unsigned char compCode = 1;
unsigned char contextBit = 0;
lsuTransfer0.dspAddress = SRC_ADDR;
lsuTransfer0.bytecount = BYTES;
lsuTransfer0.rapidIOLSB = DST_ADDR;
CSL_SRIO_GetLSUContextTransaction (hSrio, &context, &transID);
CSL_SRIO_SetLSUTransfer (hSrio, 0, &lsuTransfer0);
while (1)
{
if (CSL_SRIO_IsLSUBusy (hSrio, 0) == FALSE)
break;
}
CSL_SRIO_GetLSUCompletionCode (hSrio, 1, transID, &compCode, &contextBit);
}
void main(void) {
if (enable_srio () < 0)
{
printf ("Error: SRIO PSC Initialization Failed
");
return;
}
if (SrioDevice_init() < 0)
return;
printf ("SRIO Driver has been initialized
");
Lsu0_Init();
SRIO_READ(0x00000001, 256, 0x00000002);
}
注意图中的包类型指的是Ftype的值,而不是最前面的标号。
SRIO配置文件下载:
device_srio_loopback.c
这样,我们的摩托也完成了,摩托可以载着货物在高速上飞奔了,但是有时候来了个电话,你必须停下来,那要怎么停下来呢?,请看下章——中断系统。
参考文献
http://www.ti.com/cn/litv/pdf/sprugw1b
PS:欢迎大家与我讨论文章中的问题,包括反对我的观点。
本章特别致谢:感谢北航的王悦人学长在我什么都不懂的时候耐心回答我的萌新问题。