目录
要实现千兆网,在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 address
Xil_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 register
cfg_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);
}
//定义中断向量表结构体,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 distributor
Xil_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 distributor
Xil_Out32(ICDDCR,0x01);
}
// CPU 中断设置
void CPU_Init(void)
{
//中断优先级都是A0,优先级高于F0,CPU可接受这些中断
Xil_Out32(ICCPMR,0xF0);
//处理器能接收IRQ,使能中断信号连接到处理器
Xil_Out32(ICCICR,0x07);
}
void Ethernet0_Int_Init(void)
{
Xil_Out32(ICDICER1, 0x400000);//不使能 #54
Xil_Out32(ICDICFR3, 0x1000);//电平触发
Xil_Out32(ICDIPR13, 0xA00000);//优先级A0
Xil_Out32(ICDIPTR13,0x010000);//处理器为CPU1
Xil_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;
//initialize
IntAllDisabled();
DistributorInit();
CPU_Init();
Ethernet0_Int_Init();
xil_printf("begin\r\n");
Xil_ExceptionEnable();
}
// 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 register
Xil_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 bit
Xil_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();
}
}
因能力所限,难免有理解不到位之处,欢迎大家批评指正
更多分享,请关注微信公众号:FPGA历险记