跳转到主要内容

xilinx zynq RapidIO系统配置

judy 提交于

参考

书籍《RapidIO The Embedded System Interconnect》
xilinx手册pg007《Serial RapidIO Gen2 Endpoint v4.1 LogiCORE IP Product Guide》
Zynq-Linux移植学习笔记之14-RapidIO驱动开发

<font size="3"><strong>host初始化</strong></font>

直接看RapidIO的初始化,一些底层的比如物理层链路层之类的不需要关心,用到了再去看,毕竟都是基于芯片或者IP来开发。先从高层了解这个过程。

<strong>系统启动过程概述</strong>

1. host CPU获取引导代码,启动,如果有两个host,则两者是同时启动的。
2. 开始执行系统探测和枚举算法。
3. 枚举所有器件并将相关器件信息记录到器件数据库,建立host和所有endpoint之间的路由。
&nbsp;&nbsp;&nbsp; • &nbsp; 计算并配置host和所有endpoint之间的最优路径。
&nbsp;&nbsp;&nbsp; • &nbsp; 用最优路径信息配置switch。
&nbsp;&nbsp;&nbsp; • &nbsp; 更新路由表。
4. 映射地址空间。

上面提到的最优路径,就是所谓的枚举算法的目的,可以是最短路径或者包含一些用户约束。

<strong>启动要求</strong>

系统初始化之后,所有器件都会拥有一个ID,在系统初始化之前,按照下面设置。RapidIO系统应该只有一个引导代码器件。
&nbsp; • &nbsp; 设置endpoint ID为0xFF(0xFFFF)。
&nbsp; • &nbsp; 设置引导代码器件ID为0xFE(0x00FE)。
&nbsp; • &nbsp; 设置host ID为0x00(0x0000)。

<strong>枚举</strong>

枚举过程中,将给每个endpoint分配唯一的器件ID,为了增强容错性,RapidIO系统可以有两个host,经过竞争,最终只有一个host来完成枚举,如果主机枚举过程失败并发生超时事件,则另一主机重新枚举。枚举算法根据器件ID大小设置优先级,ID大的host竞争获胜,在枚举同一个endpoint时会发生竞争,失败host主动退出枚举,枚举结束之后,其他主机可以通过被动发现(passively discovery)收集网络中的路由拓扑信息。所以host的ID可以设置为0x00(0x0000)和0x01(0x0001),其中0x01的优先级更高。host应当将自己的主机使能位置1,switch没有这个位,当host释放对失败主机的锁定时,枚举完成,失败host自己检测是否被锁定和释放锁定。在开放式(open)8位器件ID系统中,如果host枚举失败,那么失败主机重新枚举时,必须等待15秒。在闭合式(closed)或者16位器件ID系统中,超时等待时间需要设计。

<font size="3"><strong> Xilinx Srio IP</strong></font>

<img src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40596-…; alt="xilinx zynq RapidIO系统配置">
<img src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40597-…; alt="xilinx zynq RapidIO系统配置">
<img src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40598-…; alt="xilinx zynq RapidIO系统配置">

列举用到的4个寄存器,详细参考pg007。

1. Port General Control CSR,使能Master Enable。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40588-…; alt="xilinx zynq RapidIO系统配置"></center>

2. Base Device ID CSR,设置器件ID,host可设为1,默认值在vivado里设置。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40589-…; alt="xilinx zynq RapidIO系统配置"></center>

3. Host Base Device ID Lock CSR,器件锁定寄存器,复位之后,这个寄存器只能被写一次(之后被锁定),配置之后如果写入值和寄存器值相等,则寄存器值被复位为0xFFFF,向该寄存器写入0xFFFF不会锁定寄存器。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40590-…; alt="xilinx zynq RapidIO系统配置"></center>

4. Maintenance Request Information Register,维护包配置寄存器,地址在0x10100,低16位用于配置目的ID,当用IP发维护包之前,需要配置这个寄存器。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40591-…; alt="xilinx zynq RapidIO系统配置"></center>

5. Processing Elements Features CAR,表示这个设备提供的功能,可以是Bridge,Memory,Processor,Switch 4种,SRIO IP支持前3种(endpoint),支持16位地址模式,可在vivado中通过GUI设置。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40599-…; alt="xilinx zynq RapidIO系统配置"></center>

<font size="3"><strong>IDT CPS1848</strong></font>

1. CPS1848结构图,注意的是port从0到17,即0x00到0x11。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40592-…; alt="xilinx zynq RapidIO系统配置"></center>

2. CPS1848路由方式,每个端口提供256个缓存来存储设备路由表,还有256个缓存来存储域路由表,这样设计的目的是,在大型的系统里会用到域路由表,大型系统有很多底板,每个底板上也会有很多子板,域路由表用来选择包被发送到哪一块板卡,而设备路由表用来将包发送到某个处理单元(某个芯片的SRIO端口)。RIO_DOMAIN由RapidIO Domain Register寄存器确定。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40593-…; alt="xilinx zynq RapidIO系统配置"></center>

3. 单播(unicast)编程,CPS1848每个端口都有自己的路由表,所以可以支持虚拟网络,路由配置时,有寄存器The Route Port Select Register selects来控制路由表项是添加到所有端口还是某个端口。路由配置主要是三个寄存器Standard Route Table Entries Configuration destID Select CSR,Standard Route Table Entry Configuration Port Select CSR和Standard Route Table Entry Default Port CSR。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40594-…; alt="xilinx zynq RapidIO系统配置"></center>

4. 多播编程,用到再说。

5. 上面配置路由的方法是非直接方式(Indirect Programming),配置路由需要操作多次,在多(线程)设备的环境下要做互斥,CPS1848支持另外一种直接方式(Direct Programming)可以支持这种情况。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40595-…; alt="xilinx zynq RapidIO系统配置"></center>

6. Switch Port Information CAR寄存器,这个寄存器很重要,在多个Switch互联的系统里,用于确定拓扑关系。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40600-…; alt="xilinx zynq RapidIO系统配置"></center>

7. Port General Control CSR寄存器,会用到DISCV位,是发现标志位。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40601-…; alt="xilinx zynq RapidIO系统配置"></center>

8. Port Error and Status CSR寄存器,第1位PORT_OK。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40602-…; alt="xilinx zynq RapidIO系统配置"></center>

9. Host Base deviceID Lock CSR寄存器,同xilinx SRIO IP。
<center><img width="600" src="http://xilinx.eetrend.com/files-eetrend-xilinx/blog/201811/13874-40603-…; alt="xilinx zynq RapidIO系统配置"></center>

<font size="3"><strong>zynq SRIO系统初始化过程</strong></font>

1. 使能host模式。
2. 配置ID。
3. 配置CPS1848路由,使能端口收发(手册默认是打开的)。
4. 锁定host。
5. 搜索系统拓扑。

<strong>锁定host</strong>

1. 读取Lock ID CSR,如果寄存器值等于host ID,则判定已经锁定,退出,否则进入2。
2. 写入host ID,再读取host ID,如果寄存器值大于host ID则进入退避状态,如果小于host ID,则已经被锁定(但和另一个host冲突),进入等待退避状态,等待另一个host退避。如果等于host ID,则锁定成功。

<strong>搜索系统拓扑</strong>

这里只考虑Switch是CPS1848的情况,TSI578原理是一致。

1. 如果这个CPS1848是直接与host zynq相连的switch。

&nbsp; • &nbsp; 搜索CPS1848,设置0x13c寄存器Port General Control CSR的DISCV位,表示这个switch已经被发现,设置Component Tag CSR,它是一个设备的身份标识。

&nbsp; • &nbsp; 读0x14寄存器Switch Port Information CAR得到port数量,就是18。

&nbsp; • &nbsp; 循环搜索每个port,如果是host port则使能端口收发,如果是其他port,读取链路状态,如果正常,用默认ID 0xFF配置路由,使能端口收发,然后尝试锁定该端口设备(Endpoint或Switch),锁定过程和锁定host是一样的。
&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;如果锁定成功,读取Processing Elements Features CAR寄存器,等到Function,判断设备类型,决定下一步拓扑方式。如果是Endpoint类型,关闭Master Enable,置位Discovered,分配ID号,配置该port的路由表。如果是Switch类型,则递归调用Switch枚举过程。
&nbsp;&nbsp;&nbsp;&nbsp;-&nbsp;如果是已经锁定状态(存在环路),直接更新拓扑,不做任何配置。

2. 如果这个CPS1848不和host直接相连。

&nbsp; • &nbsp; 设置DISCV位,得到与上级Switch相连的端口号,设置host的路由,设置默认路由为到host的端口。
&nbsp; • &nbsp; 同上。
&nbsp; • &nbsp; 同上。

现在拓扑关系已经搜索出来了。下面就是配置路由,因为上述搜索过程的路由配置不一定是最优配置,也不满足用户的需求。 所以现在需要按照设计需求,生成路由表然后写到各个Switch。

<strong>zynq SRIO驱动</strong>

这里实现Linux用户态的驱动,数据结构定义,

struct srioEndpoint
{
unsigned int devId;
unsigned int hopCnt;
struct srioSwitch* pSw;
unsigned int port;
};

#define SRIO_SW_MAX_PORT 18//get from cps1848
struct srioSwitch
{
unsigned int hopCnt;
unsigned int componentTag;//component tag

unsigned int portNum;
struct srioEndpoint* pEp[SRIO_SW_MAX_PORT];//port connected
unsigned int epNum;
unsigned int portEp[SRIO_SW_MAX_PORT];//for get ep info for certain port fastly
struct srioSwitch* pSw[SRIO_SW_MAX_PORT];//switch connected, complicate and will be implenmented laterly
unsigned int swNum;
unsigned int portSw[SRIO_SW_MAX_PORT];//for get sw info for certain port fastly
struct srioSwitch* pSwParent;
unsigned int portParent;
};

#define SRIO_SYS_MAX_EP_NUM 64
#define SRIO_SYS_MAX_SW_NUM 4
struct srioSystem
{
struct srioEndpoint epInfo[SRIO_SYS_MAX_EP_NUM];
unsigned int epNum;
struct srioSwitch swInfo[SRIO_SYS_MAX_SW_NUM];
unsigned int swNum;
};

转自:<a href="https://mp.weixin.qq.com/s/twzW4Y8uGvfYTmz3iZdJgQ"&gt; 青儿创客基地 </a>