谈论到以太网,对于 单片机,大多数人都会直接使用Lwip库,对于MPU,使用系统带的驱动程序;然而,单片机使用网口,不是一定需要使用Lwip,不是一定需要走通常的7层TCPIP,在工业上,普通的TCPIP实时性很差,故此有Modbus TCP这种相对实时的网络协议。本系列不使用LWIP库,从PHY芯片配置一步一步实现与上位机进行Modbus TCP 通信。 实现网络通信的基础在于配置PHY芯片和MAC控制器,如果PHY芯片和MAC控制器都配置不对,那更不用说实现网络通信,实现PHY的配置,重要的接口是MDIO,这本质就是IIC接口,但应用于网络PHY芯片的配置,故名为MDIO。对于CZU3EG板卡,PHY芯片使用的是DP83867,这是一款 ti的用于千兆以太网通信的PHY芯片,支持RGMII、GMII和MII三种Mac控制器接口,正好可以在ZU+使用MIO接入MAC控制器、EMIO接入控制器的需求,而不需要额外的接口转换芯片(MIO使用RGMII接口,EMIO由于速度问题,最大只能支持百兆,走MII或GMII接口形式)。 使用ZU+读写以太网需要遵循以下步骤: 1. 启用MDIO,通过将network_control寄存器_port_en位置1; 2. 设置MDIO时钟(MDC pin)的分频比,MDIO是从LPD域分频来,同时要满足IEEE 802.3标准,MDC不能大于2.5M,SDK参考程序设置为224分频,而寄存器描述却是只支持8、16、32、48分配,其他为保留,很奇怪
3. 通过设置network_config寄存器的mdc_clock_division字段为合适值即可; 4. 读取network_status寄存器的man_done,确认MDIO处于空闲状态; 5. 写入合适的值到phy_management寄存器内,包括Phy设备地址,phy寄存器地址,phy读写操作以及phy寄存器数据(如果读,phy寄存器数据可设0) 6. 读取network_status寄存器的man_done,确认MDIO操作完成; 7. 如果是读操作,这一步读取phy_management寄存器,获取phy寄存器内的值; 下面的程序是通过枚举获得phy设备地址,并读取Phy芯片Identified
- #include
- #include "platform.h"
- #include "xil_printf.h"
- #include "xil_io.h"
-
- #define GEM_BASE 0xFF0E0000
- #define GEM_PHY_MANAGEMENT 0x34
- #define GEM_NETWORK_CONFIG 0x04
- #define GEM_NETWORK_STATUS 0x08
-
- enum {
- MDC_CLOCK_DIV8,
- MDC_CLOCK_DIV16,
- MDC_CLOCK_DIV32,
- MDC_CLOCK_DIV48
- }MDC_CLOCK_DIV;
-
- int main()
- {
- u32 temp;
- u32 phy_address;
- u32 phy_reg_address;
- u32 mdc_clock_div = 7;
- u32 phy_addr1;
- u32 phy_addr2;
- init_platform();
- temp = Xil_In32(GEM_BASE+0);
- Xil_Out32(GEM_BASE+0, (temp & (~(0x1 << 4)))| (1<<4));
- temp = Xil_In32(GEM_BASE+GEM_NETWORK_CONFIG);
- Xil_Out32(GEM_BASE+GEM_NETWORK_CONFIG, (temp & (~(0x7 << 18)))| (mdc_clock_div<<18));
-
- for(int i=0; i<32; i++)
- {
- while((Xil_In32(GEM_BASE+GEM_NETWORK_STATUS)&0x4)!=0x4);
- phy_address = i;
- phy_reg_address = 2;
- temp = 0x60020000|(phy_reg_address<<18)|(phy_address<<23);
- Xil_Out32(GEM_BASE+GEM_PHY_MANAGEMENT, temp);
- while((Xil_In32(GEM_BASE+GEM_NETWORK_STATUS)&0x4)!=0x4);
- phy_addr1 = Xil_In32(GEM_BASE+GEM_PHY_MANAGEMENT) & 0xFFFF;
- if(phy_addr1>0&&phy_addr1<0xffff)
- goto READTWO;
- }
- goto RETURN;
- READTWO:
- phy_reg_address = 3;
- temp = 0x60020000|(phy_reg_address<<18)|(phy_address<<23);
- Xil_Out32(GEM_BASE+GEM_PHY_MANAGEMENT, temp);
- while((Xil_In32(GEM_BASE+GEM_NETWORK_STATUS)&0x4)!=0x4);
- phy_addr2 = Xil_In32(GEM_BASE+GEM_PHY_MANAGEMENT) & 0xFFFF;
-
- xil_printf("Detected Eth Phy_Address:%d, Phy id: %04x%04xnr", phy_address, phy_addr1, phy_addr2);
- RETURN:
- cleanup_platform();
- return 0;
- }
复制代码
结果如下:
可以看到PHY设备地址为5,Phy芯片标识符为0x2000A231.
|