xilinx zynq RapidIO系统配置

热度49票  浏览238次 【共0条评论】【我要评论 时间:2018年11月20日 15:37

参考

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

host初始化

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

系统启动过程概述

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

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

启动要求

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

枚举

枚举过程中,将给每个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系统中,超时等待时间需要设计。

Xilinx Srio IP

xilinx zynq RapidIO系统配置
xilinx zynq RapidIO系统配置
xilinx zynq RapidIO系统配置

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

1. Port General Control CSR,使能Master Enable。

xilinx zynq RapidIO系统配置

2. Base Device ID CSR,设置器件ID,host可设为1,默认值在vivado里设置。

xilinx zynq RapidIO系统配置

3. Host Base Device ID Lock CSR,器件锁定寄存器,复位之后,这个寄存器只能被写一次(之后被锁定),配置之后如果写入值和寄存器值相等,则寄存器值被复位为0xFFFF,向该寄存器写入0xFFFF不会锁定寄存器。

xilinx zynq RapidIO系统配置

4. Maintenance Request Information Register,维护包配置寄存器,地址在0x10100,低16位用于配置目的ID,当用IP发维护包之前,需要配置这个寄存器。

xilinx zynq RapidIO系统配置

5. Processing Elements Features CAR,表示这个设备提供的功能,可以是Bridge,Memory,Processor,Switch 4种,SRIO IP支持前3种(endpoint),支持16位地址模式,可在vivado中通过GUI设置。

xilinx zynq RapidIO系统配置

IDT CPS1848

1. CPS1848结构图,注意的是port从0到17,即0x00到0x11。

xilinx zynq RapidIO系统配置

2. CPS1848路由方式,每个端口提供256个缓存来存储设备路由表,还有256个缓存来存储域路由表,这样设计的目的是,在大型的系统里会用到域路由表,大型系统有很多底板,每个底板上也会有很多子板,域路由表用来选择包被发送到哪一块板卡,而设备路由表用来将包发送到某个处理单元(某个芯片的SRIO端口)。RIO_DOMAIN由RapidIO Domain Register寄存器确定。

xilinx zynq RapidIO系统配置

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。

xilinx zynq RapidIO系统配置

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

5. 上面配置路由的方法是非直接方式(Indirect Programming),配置路由需要操作多次,在多(线程)设备的环境下要做互斥,CPS1848支持另外一种直接方式(Direct Programming)可以支持这种情况。

xilinx zynq RapidIO系统配置

6. Switch Port Information CAR寄存器,这个寄存器很重要,在多个Switch互联的系统里,用于确定拓扑关系。

xilinx zynq RapidIO系统配置

7. Port General Control CSR寄存器,会用到DISCV位,是发现标志位。

xilinx zynq RapidIO系统配置

8. Port Error and Status CSR寄存器,第1位PORT_OK。

xilinx zynq RapidIO系统配置

9. Host Base deviceID Lock CSR寄存器,同xilinx SRIO IP。

xilinx zynq RapidIO系统配置

zynq SRIO系统初始化过程

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

锁定host

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

搜索系统拓扑

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

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

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

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

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

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

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

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

zynq SRIO驱动

这里实现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;
};

转自: 青儿创客基地

对本篇资讯内容的质量打分:
当前平均分:-0.21 (29次打分)
【已经有20人表态】
2票
感动
3票
路过
3票
高兴
3票
难过
2票
搞笑
2票
愤怒
3票
无聊
2票
同情
上一篇 下一篇
查看全部回复【已有0位网友发表了看法】