一、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 <stdio.h>
#include <stdint.h>
#include <math.h>
#include <string.h>
#include <c6x.h>
/* CSL Chip Functional Layer */
#include <ti/csl/csl_chipAux.h>
#include <ti/csl/csl_chip.h>
/* PSC CSL Include Files */
#include <ti/csl/csl_psc.h>
#include <ti/csl/csl_pscAux.h>
/* CSL SRIO Functional Layer */
#include <ti/csl/csl_srio.h>
#include <ti/csl/csl_srioAux.h>
#include <ti\csl\csl_srioAuxPhyLayer.h>
#include <ti/csl/tistdtypes.h>
#include <ti/csl/cslr_device.h>
#include <ti/csl/csl_tsc.h>
#include <ti/csl/csl_cacheAux.h>
SRIO_LSU_TRANSFER lsuTransfer0;//声明一个LSU传输对象
/* 函数名:Lsu0_Init
* 函数作用:对LSU传输对象LsuTransfer0进行配置
* 在配置LSU时本身不需要这么多参数,一般只设置几个参数就行,在博客最后我会给出简化版配置 */
void Lsu0_Init()
{
lsuTransfer0.rapidIOMSB = 0x0;//传输目标地址扩展高32bit域,即如果地址位数比32bit多时,会用到它,一般为0
//lsuTransfer0.rapidIOLSB = (unsigned int)0x00100000;//传输目标地址低32bit,一般情况的目标地址就是这个
//lsuTransfer0.bytecount = 32768;//LSU传输多少个byte
//lsuTransfer0.dspaddress = 0x32c00000;//需要LSU发送的数的地址
lsuTransfer0.doorbellValid = 0;//是否需要在传输完成后发送doorbell,0表示不需要
lsuTransfer0.intrRequest = 1;//传输完成后是否需要产生中断,1表示需要
lsuTransfer0.supInt = 0;//是否需要“压制”传输完成后的中断,0表示不压制
lsuTransfer0.xambs = 0;//指明扩展地址最高位,一般情况下不需要
lsuTransfer0.priority = 0;//LSU传输的优先级,该属性只有在多个LSU传输时才有意义
lsuTransfer0.outPortID = 0;//LSU要用哪个port传出,由CPU和nodeID共同决定
lsuTransfer0.idSize = 1;//DEVICEID使用8bit还是16bit格式的。1表示使用16bit格式。
lsuTransfer0.srcIDMap = 0;//确定在该LSU中使用哪个srcID映射寄存器
lsuTransfer0.dstID = 0xABCD;//LSU传输目标的DEVICEID,可以看到这里是16bit格式的
lsuTransfer0.ttype = 4;//包的类型由ttype和ftype同时决定,一般主要有写、读、带响应写、带响应读等包类型。具体见参考文献
lsuTransfer0.ftype = 2;
lsuTransfer0.hopCount = 0;//Hop Count域是为类型8的维护包准备的。
lsuTransfer0.doorbellInfo = 0;//DRbll Info域是为类型10的包(doorbell包)准备的。具体包类型见下文中的Table2-23
}
/*
* 函数名:SRIO_READ
* 函数功能:配置好LSU的源地址、目的地址、传输总字节数,并启动传输
*/
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;
// 得到LSU背景传输信息
CSL_SRIO_GetLSUContextTransaction (hSrio, &context, &transID);
// 在LSU0上启动传输
CSL_SRIO_SetLSUTransfer (hSrio, 0, &lsuTransfer0);
// 循环直到LSU传输完成.
while (1)
{
if (CSL_SRIO_IsLSUBusy (hSrio, 0) == FALSE)
break;
}
//得到完成码(调试用)
CSL_SRIO_GetLSUCompletionCode (hSrio, 1, transID, &compCode, &contextBit);
}
/*
* main.c
*/
void main(void) {
/*
* 对于函数enable_srio,SrioDevice_init,都在我在上篇**中提到的device_srio_loopback.c文件中,主要就是通道配置和DEVICEID配置,前两篇博客也都讲述过。文末会附上该文件的下载地址。
*/
/* 给SRIO模块供电 */
if (enable_srio () < 0)
{
printf ("Error: SRIO PSC Initialization Failed\n");
return;
}
/* 初始化SRIO */
if (SrioDevice_init() < 0)
return;
/* SRIO已经能够操作了. */
printf ("SRIO Driver has been initialized\n");
Lsu0_Init();
/* 从地址0x00000001 发送256bytes数据到 deviceID为0xABCD的设备上的地址0x00000002去 */
SRIO_READ(0x00000001, 256, 0x00000002);
}
注意图中的包类型指的是Ftype的值,而不是最前面的标号。
|