最近在做图像处理和加速,芯片是xilinx 的 zynq xc7z020。需要用到千兆网,由于网上很多都是直接移植lwip,但是个人感觉用着不爽(个人感觉),不能实现随心所欲的控制,代码量又多,所以自己研究了一下,直接操作寄存器,实现千兆网通信。以下是个人的理解及操作,仅供大家参考。

要实现千兆网,在xc7z020需要做到以下几点:

目录

要实现千兆网,在xc7z020需要做到以下几点:

一 配置网络寄存器

二 配置PYH 芯片

三 配置中断寄存器(如果要用中断的话)

四 创建Descriptors

以下效果图,可以达到970多Mpbs的速度


一 配置网络寄存器

在配置网络寄存器之前,先对控制器进行复位操作,代码如下

//Initialize the Controller
void Initialize_Controller()
{//1. Clear the Network Control register. Write 0x0 to gem.net_ctrl register.Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET,0x00000000);//2. Clear the Statistics registers. Write a 1 to gem.net_ctrl[clear_stat_regs].Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET,XEMACPS_NWCTRL_STATCLR_MASK);//3. Clear the Status registers. Write a 1 to the Status registers. gem.rx_status = 0x0F andgem.tx_status = 0xFF.Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_RXSR_OFFSET,0x0f);Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_TXSR_OFFSET,0xff);//4. Disable all interrupts. Write 0x7FF_FEFF to the gem.intr_dis register.Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_IDR_OFFSET,0x7FFFEFF);//5. Clear the buffer queues. Write 0x0 to the gem.rx_qbar and gem.tx_qbar registers.Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR  + XEMACPS_RXQBASE_OFFSET,0x00000000);Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_TXQBASE_OFFSET,0x00000000);}

接下来 寄存器配置

//Configure the Controller
void Configure_Controller()
{unsigned int cfg_value;unsigned int Divisor  = 0x07;//<< XEMACPS_NWCFG_MDC_SHIFT_MASK
//1. Program the Network Configuration register (gem.net_cfg)cfg_value = XEMACPS_NWCFG_FDEN_MASK| XEMACPS_NWCFG_1000_MASK| XEMACPS_NWCFG_LENERRDSCRD_MASK| XEMACPS_NWCFG_RXCHKSUMEN_MASK| XEMACPS_NWCFG_PAUSEEN_MASK| XEMACPS_NWCFG_FCSREM_MASK| XEMACPS_NWCFG_UCASTHASHEN_MASK| (Divisor << XEMACPS_NWCFG_MDC_SHIFT_MASK);Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCFG_OFFSET,cfg_value);xil_printf("cfg_value = %x \r\n",cfg_value);//2. Set the MAC addressXil_Out32(XEMACPS_GEM0_BAYSE_ADDR+XEMACPS_LADDR1L_OFFSET,LOCAL_MAC0);Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR+XEMACPS_LADDR1H_OFFSET,LOCAL_MAC1);xil_printf("LADDR1L = %x \r\n",Xil_In32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_LADDR1L_OFFSET));xil_printf("LADDR1H = %x \r\n",Xil_In32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_LADDR1H_OFFSET));//3. Program the DMA Configuration registercfg_value = XEMACPS_DMACR_RXBUF_MASK| XEMACPS_DMACR_RXSIZE_MASK| XEMACPS_DMACR_TXSIZE_MASK| XEMACPS_DMACR_DISC_WHEN_NO_AHB| XEMACPS_DMACR_TCPCKSUM_MASK| XEMACPS_DMACR_ENDIAN_MASK| XEMACPS_DMACR_INCR16_AHB_BURST;xil_printf("cfg_value_dma = %x \r\n",cfg_value);Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_DMACR_OFFSET,cfg_value);//4. Program the Network Control Register (gem.net_ctrl)cfg_value = Xil_In32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET);cfg_value = cfg_value| XEMACPS_NWCTRL_MDEN_MASK;//+ XEMACPS_NWCTRL_TXEN_MASK//+ XEMACPS_NWCTRL_RXEN_MASK;Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET,cfg_value);}

中断寄存器配置

void Configure_Interrupts()
{//Enable interrupts/* Enable TX and RX interrupts */u32 mask = XEMACPS_IXR_TX_ERR_MASK|XEMACPS_IXR_RX_ERR_MASK|XEMACPS_IXR_FRAMERX_MASK|XEMACPS_IXR_TXCOMPL_MASK;Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_IER_OFFSET,mask);}

二 配置PYH 芯片

PYH 芯片配置,需要根据芯片的手册,我用的是KSZ9031RNX-EVA,因为代码比较多,这里的代码就不贴了,可以根据你使用的芯片型号,在网上找对应的配置程序。

三 配置中断寄存器(如果需要用中断的话)

中断对于嵌入式来说,是一个比较复杂的梗,首先要开启系统级中断(PS中断系统),其次要使能个体中断(eth0中断),这里把代码贴出来,如果用需要用到的朋友可以作为简单的参考。

系统级中断控制代码(PS中断系统)

//定义中断向量表结构体,Handler为函数,Data为函数Handler的参数
typedef struct {Xil_ExceptionHandler Handler;void *Data;
} XExc_VectorTableEntry;
//申明中断向量表
extern XExc_VectorTableEntry XExc_VectorTable[];
// 复位中断
void IntAllDisabled(void)
{/* Remove current CPU from interrupt target register */Xil_Out32(ICDICER0, 0xffffffff);//不使能中断Xil_Out32(ICDICER1, 0xffffffff);//不使能中断Xil_Out32(ICDICER2, 0xffffffff);//不使能中断//disables the distributorXil_Out32(ICDDCR,0x00);}
//分发中断
void DistributorInit(void)
{u32 reg_addr;reg_addr = ICDICFR0;u32  default_priority = 0xa0a0a0a0;//清除触发模式for(char i=0;i<6;i++){reg_addr += i*4;Xil_Out32(reg_addr,0x00000000);}// 设置default 优先级reg_addr = ICDIPR0;for(char i=0;i<24;i++){reg_addr += i*4;Xil_Out32(reg_addr,default_priority);}// enables the distributorXil_Out32(ICDDCR,0x01);}// CPU 中断设置
void CPU_Init(void)
{//中断优先级都是A0,优先级高于F0,CPU可接受这些中断Xil_Out32(ICCPMR,0xF0);//处理器能接收IRQ,使能中断信号连接到处理器Xil_Out32(ICCICR,0x07);
}

个体中断使能(eth0中断)

void Ethernet0_Int_Init(void)
{Xil_Out32(ICDICER1, 0x400000);//不使能 #54Xil_Out32(ICDICFR3, 0x1000);//电平触发Xil_Out32(ICDIPR13, 0xA00000);//优先级A0Xil_Out32(ICDIPTR13,0x010000);//处理器为CPU1Xil_Out32(ICDISER1, 0x400000);//使能 #54}

初始化中断的代码

 void Int_init(void)
{u32 data = 30;Xil_ExceptionInit();XExc_VectorTable[5].Handler =(Xil_ExceptionHandler)InterruptHandler_IRQ;// 中断处理函数XExc_VectorTable[5].Data = data;//initializeIntAllDisabled();DistributorInit();CPU_Init();Ethernet0_Int_Init();xil_printf("begin\r\n");Xil_ExceptionEnable();}

四 创建Descriptors

要实现千兆网的收发需要一个叫 Buffer Descriptors List 的东西,在这里暂且把它叫做“缓存描述表”,收发各需要一个。这里只单独讨论发的时候,其实“缓存描述表”可以理解为结构体(本人是按结构体来申请和定义),这个结构体里面包含多个Buffer Descriptors(简称BD),每个BD包含两个word(word0 和 word1, 一个word = 4bytes)。word0 里存放了一个地址,指向需要发送数据的起始地址。word1是一些状态位。对于更详细的描述,可以看 《ug585-Zynq-7000-TRM(Technical Reference Manual).pdf》手册p495的 Rx Buffer描述。

以下是代码

// Descriptor strcut
struct DESC_DEF
{u32 word0;u32 word1;
};// Descriptor List strcut
struct DESC_LIST_DEF
{struct DESC_DEF Descriptor[32];
};struct DESC_LIST_DEF Tx_List __attribute__ ((aligned(64)));void BdBaseAddr(struct DESC_LIST_DEF *p_List)
{p_List->Descriptor[0].word0 = (u32)p_header->eth_remote_mac;// 以太网数据报头p_List->Descriptor[1].word0 = eth0_ctrl.frame_addr[0];// 需要发送的数据的首地址//write gem.tx_qbar registerXil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_TXQBASE_OFFSET,(u32)Tx_List.Descriptor);Xil_DCacheFlushRange((UINTPTR)(u32)p_header->eth_remote_mac, sizeof(struct HEAD_DEF));}void BdSetLength(struct DESC_LIST_DEF *p_List)
{p_List->Descriptor[0].word1 = sizeof(struct HEAD_DEF);//p_header->ip_IHL*5 + 14 + 8;p_List->Descriptor[1].word1 = PAYLOAD_BYTES;}void BdClearTxUsed(struct DESC_LIST_DEF *p_List)
{p_List->Descriptor[0].word1 &=(~XEMACPS_TXBUF_USED_MASK);p_List->Descriptor[1].word1 &=(~XEMACPS_TXBUF_USED_MASK);}void BdSetLast(struct DESC_LIST_DEF *p_List)
{p_List->Descriptor[1].word1 = p_List->Descriptor[1].word1 | XEMACPS_TXBUF_LAST_MASK |XEMACPS_TXBUF_WRAP_MASK;
}

到这里,初始化阶段几乎算是完成了,只是以太网数据报头这些需要自己去组装,这里涉及到以太网的知识,知识点比较多就不一一表述了,大家可以网上查

整体的初始化代码

void eth0_init()
{Initialize_Controller();Configure_Controller();init_phy();Configure_Interrupts();BdBaseAddr(&Tx_List);BdSetLength(&Tx_List);BdSetLast(&Tx_List);}

接下来是发送代码

void Enable_Controller()
{u32 value;//1. Enable the Transmitter. Write a 1 to gem.net_ctrl[tx_en]//2. Enable the Receiver. Write a 1 to gem.net_ctrl[rx_en].value = Xil_In32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET);value = value | XEMACPS_NWCTRL_TXEN_MASK | XEMACPS_NWCTRL_RXEN_MASK;Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET,value);
}void start_trasnission()
{u32 value;value = Xil_In32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET);Xil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_NWCTRL_OFFSET,value |XEMACPS_NWCTRL_STARTTX_MASK);}// 发送一帧图像void Trans_Frames()
{u32 txsr;//u32 *p_dptr;txsr  = Xil_In32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_TXSR_OFFSET);txsr &= XEMACPS_TXSR_TXCOMPL_MASK;if(eth0_ctrl.flg | txsr){eth0_ctrl.flg  = 0;// clear trans compelet bitXil_Out32(XEMACPS_GEM0_BAYSE_ADDR + XEMACPS_TXSR_OFFSET,(txsr & XEMACPS_TXSR_TXCOMPL_MASK));BdClearTxUsed(&Tx_List);u32 value = sizeof(struct DESC_LIST_DEF);Xil_DCacheFlushRange((UINTPTR)Tx_List.Descriptor, value);Enable_Controller();start_trasnission();}}

由于篇幅,里面还有很多知识点没有写,比如以太网数据结构、网络字节序、crc验证等,有需要的朋友可以到网上查询。将来也许我会把这些知识点作为一个系列写出来,不过这是以后的事了。

今天这个只是实现从相机发送数据到PC端,至于从PC端发到相机,留在下一节分享。

由于个人不太爱写注释(很坏很坏的习惯),以上代码注释比较少,可能阅读起来不是很爽,不过好在代码量不是很多,如果此代码有用得上的朋友,若有疑问的地方可以留言,我会尽量回复。

以下效果图,可以达到970多Mpbs的速度

因能力所限,难免有理解不到位之处,欢迎大家批评指正

更多分享,请关注微信公众号:FPGA历险记

ZYNQ 图像处理之千兆网传(一)【寄存器级操作】相关推荐

  1. 基于zynq的千兆网udp项目_米联客 ZYNQ/SOC 精品教程 S05-CH05 PS 千兆 UDP 加速

    软件版本:VIVADO2017.4 操作系统:WIN10 64bit 硬件平台:适用米联客 ZYNQ系列开发板 米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!! ...

  2. 基于ZYNQ的千兆网项目(1)

    基于ZYNQ的TCP Client实现 参考文献 项目描述 TCP协议简述 TCP 三次握手 TCP 数据传输 TCP 四次挥手 PL端设计 PS端设计 下板测试 总结 参考文献 [1].inner_ ...

  3. 基于ZYNQ的千兆网项目(3)

    基于ZYNQ的UDP实现 项目简述 UDP简述 PL端设计 PS端设计 下板测试 总结 项目简述 前面的文章讲解了TCP客户机与主机在ZYNQ上面的实现,其实说白了就是调用现成的API函数,这点与FP ...

  4. 基于zynq的千兆网udp项目_基于FPGA的千兆网UDP通信分析

    千兆网UDP通信 以太网帧格式 图8‑12 以太网帧格式 表8‑5 以太网帧格式说明 UDP协议分析 为什么UDP协议在FPGA实现时很受欢迎,最主要一个原因就是简单,简答到什么地步呢?UDP协议只是 ...

  5. zynq linux千兆网卡驱动,zynq linux ar8031驱动 使得支持千兆网

    使用相同的环境,目前稍好点,mii info能看到东西了: U-Boot 2018.01 (Jun 04 2020 - 02:02:40 +0000) Xilinx ZynqMP ZCU102 rev ...

  6. 一个udp用户数据报的数据字段为8192_基于FPGA的千兆网UDP通信分析

    千兆网UDP通信 以太网帧格式 图8‑12 以太网帧格式 表8‑5 以太网帧格式说明 UDP协议分析 为什么UDP协议在FPGA实现时很受欢迎,最主要一个原因就是简单,简答到什么地步呢?UDP协议只是 ...

  7. 千兆网综合布线系统的线缆选型

    综合布线系统包含建筑群布线子系统.建筑物主干布线子系统.水平布线子系统(包含工作区电缆)三大布线子系统.千兆网综合布线系统除具有一般快速以太网综合布线系统设计的特点之外,更重要的是要合理选择UTP.光 ...

  8. linux libpcap 效率,Linux ubuntu PF_RING+libpcap 极速捕获千兆网数据包,不丢包

    本文转自:http://blog.chinaunix.net/uid-23225855-id-3228867.html 上一篇文章讲到了,尤其在千兆网的条件下,大量的丢包,网上搜索好久,大概都是PF_ ...

  9. 华为S5700S-52P-LI-AC千兆网管交换机web登录界面配置

    研究一下午,包装附的说明书根本就是错误的,通过技术售后和官方的文档结合,总算可以登录交换机的web管理界面. 首先需要使用通讯控制线缆(包装中附)连接电脑和交换机,一头接交换机的Console口,一头 ...

最新文章

  1. LDO的最小输入输出压差和最小负载电流
  2. C和C++中include 搜索路径的一般形式以及gcc搜索头文件的路径
  3. python命令方式和关键字
  4. 基于X-Engine引擎的实时历史数据库解决方案揭秘
  5. 将python源文件打包成exe文件
  6. 20181220 Oracle程序包基本开发逻辑
  7. 百度Q1营收241亿,李彦宏挥刀改革:“尽力了”没用,要确保在必须赢的战场上胜利...
  8. 清华软件工程硕士放弃百万年薪后,4年狂赚1100亿,却被央视点名批评!
  9. GAN 生成mnist数据
  10. c语言字符型计算器,C语言字符计算器
  11. 数据库视图效率低下一例
  12. 【历史上的今天】12 月 26 日:现代计算机鼻祖诞生;手机之父出生;美国史上最大信息盗窃案
  13. hdu 2087 剪花布条 kmp小水
  14. 送别贴:《李兴》 秋风为落叶所破歌!
  15. 递归展示树状图/树状表格
  16. 利用Linux的/proc/stat获取指定进程的cpu占有率及内存
  17. flink hop window测试
  18. 软考知识点——Gant图与Pert图、McCabe复杂度计算
  19. 如何设置鼠标悬浮在一张图片上变成另外一张图片
  20. pandas计算含缺失值中列平均值_Pandas进阶修炼120题,给你深度和广度的船新体验...

热门文章

  1. 打造属于你自己的Mac 机器人助手
  2. 电信运营商云计算战略定位分析
  3. ant中table组件全选选中所有行(ant design2.2.8)
  4. android 连接商米POSV1内置打印机
  5. Nginx——nginx作为静态资源web服务(配置语法)
  6. android抖音自动刷新,Android SwipeRefreshLayout仿抖音app静态刷新
  7. yoloV5 教程——tensorboard使用
  8. 断之不疑,奸不能惑,佞不能移
  9. CSDN 编程竞赛十九期题解
  10. docker push: retrying in 5 seconds... keep doing this