当前位置: 代码迷 >> 综合 >> Open Ethernet IP core 介绍及其 ucLinux 驱动
  详细解决方案

Open Ethernet IP core 介绍及其 ucLinux 驱动

热度:20   发布时间:2023-12-15 03:39:50.0

Open Ethernet IP core 介绍及其 ucLinux 驱动

杨 勇 ( yyong@cn.ibm.com), 软件工程师, IBM

简介: Open Ethernet IP core 是一种支持 10M/100Mbps 以太网的开发源代码 MAC IP core,实现IEEE 802.3 MAC 层功能,对上下接口分别采用 Wishbone 总线和 MII 接口,由于其免费公开,可移植性和可定制性,在 FPGA SOC(System On Chip) 系统及嵌入式系统中被广泛采用,而在 ucLinux 操作系统中也有相应完善的设备驱动支持。在设计中采用 Open Ethernet IP core,可大大降低开发成本和缩短产品上市时间。

发布日期: 2009 年 1 月 15 日 
级别: 初级 
访问情况 : 2697 次浏览 
评论: 0 (查看 | 添加评论 - 登录)

 平均分 (1个评分)
为本文评分

Open Ethernet IP core 介绍

Open Ethernet IP core 是一种支持 10M/100Mbps 以太网的 MAC IP core,实现数据链路层的功能,其最大的特点便是公开免费,它不同于常见的 ASIC 网卡芯片,能够很方便的集成到片上系统(SOC)设计中去。

基本结构

MAC, 即 Media Access control, 位于 OSI 七层模型中数据链路部分,主要负责控制与物理层的物理介质通信。Ethernet IP core自身实现MAC收发和控制的功能,本身不具有物理层(PHY)的功能。MAC core 对外接口有两个:和 Host 端采用 Wishbone 总线通信,对外 PHY 芯片采用通用的 MII 接口。

  • MAC 包含接收,发送和控制模块;
  • 支持 MII 管理 (Media Independent Interface Management),MII 串行信号连接至外部PHY;
  • 主机接口采用开放的 Wishbone 总线。

Wishbone 是一种片上(SOC)总线,常见的片上总线有 ARM 的 AMBA, Altera 公司的 Avalon,以及 Silicon公司的 Wishbone。以上三种总线只有 Wishbone是开放并且完全免费的总线标准。 Wishbone 由 Silicon 开发并目前由 Opencores 组织维护。

MII 实际上可分为两部分,分别是数据流和管理流。MIIM(MII Management) 是用于对外围 PHY 芯片的管理所用的,通过 MIIM 串行接口可以查看 PHY 寄存器状态等信息。


图 1. Ethernet MAC core overview
 

主要特性

Open Ethernet core 处于 Host(CPU) 和外围 PHY 芯片之间,实现了 MAC 层的所有功能,并且采用开放的 wishbone 总线接口,源码公开便于移植,广泛应用于 FPGA SOC(System On Chip) 设计中, Flextronics Semiconductor 公司在设计中就选用了该IP core。该 IP core 的主要特性如下:

  • 实现 IEEE 802.3 以太网 MAC 功能
  • 10M/100Mbps 速率;
  • 全双工支持;
  • IEEE 802.3 MII;
  • Wishbone SOC总线接口;
  • 内部RAM可存放128 TX/RX BD(Buffer Descriptors);
  • 事件触发中断。

MAC registers

MAC register用于MAC操作,提供MAC core控制和状态信息。ucLinux设备驱动需要对这些寄存器进行配置。有关MAC register的操作在后面章节会有描述,在此不再赘述。

Open Ethernet Core在ucLinux-2.6上的设备驱动

目前 ucLinux-2.6已经支持 Open Ethernet MAC,在 make menuconfig 配置菜单中选中

Device driver->Network device support->Ethernet (10 or 100Mbit)->Opencores (Igor) Emac support

这样 Open Ethernet 的设备驱动将会被编译进 ucLinux 内核,负责 MAC 物理网络设备的支持。


图 2. Open Ethernet device driver in ucLinux-2.6
 

参见 linux/drivers/net/open_eth.c

重要的数据结构

参考 linux-2.6/include/linux/netdevice.h

a) struct net_device;

在 Linux 系统中每一个网络设备接口都对应着一个 net_device 的数据结构体, net_device 记录了网络接口的所有信息,其成员可以分为四类:

  • 全局信息: 接口名字,状态以及初始化函数;
  • 硬件信息:占用内存起始地址,IO 基地址和中断号以及 DMA 使用等;
  • 接口信息:MAC接口本身的信息,比如发送队列长度,MAC地址,和接口标志(UP/BROADCAST/PROMISC) 等;
  • 设备方法:open(), stop(), hard_start_xmit(), tx_timeout(), get_stats(), set_config() 等。

ucLinux 网络设备驱动初始化函数的部分工作便是填充上述结构成员。

b) struct oeth_private是 ucLinux open Ethernet 驱动层用于记录网络数据包的环型缓冲区而建立的数据结构,sk_buff 是用于和上层 TCP/IP 协议处理层交互的,而 oeth_bd 是用于和MAC 硬件层交互的。

struct oeth_private {struct sk_buff  *rx_skbuff[OETH_RXBD_NUM];struct sk_buff  *tx_skbuff[OETH_TXBD_NUM];ushort  tx_next;   /* Next buffer to be sent */ushort  tx_last;   /* Next buffer to be checked if packet sent */ushort  tx_full;   /* Buffer ring full indicator */ushort rx_cur; /* Next buffer to be checked if packet received */volatile oeth_regs  *regs; /* Address of controller registers. */volatile oeth_bd    *rx_bd_base;/* Address of Rx BDs. */volatile oeth_bd    *tx_bd_base;/* Address of Tx BDs. */struct net_device_stats stats;struct tasklet_struct	 oeth_rx_tasklet;struct tasklet_struct	 oeth_tx_tasklet;struct mii_if_info mii;spinlock_t  lock;
};

c) Buffer Descriptor (BD) 结构是是用于 MAC 控制和数据传递的核心数据结构。每个 BD描述 MAC 层收发的数据包,包括 len_status 和 addr 成员,len_status 描述每个数据包的长度和状态信息;addr 表示数据包存放的 RAM 地址,便于设备驱动的访问。MAC core支持最多128个 BD,每 BD 占用64bit。

struct _oeth_bd {uint    len_status;uint    addr;           /* Buffer address */
} oeth_bd;

下面两个表格分别描述了 len_status 和 addr 的位域信息

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Packet length
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
RD IRQ WR PAD CRC Reserved UR RTRY[3:0] RL LC DF CS

Fig.3 len_status in struct _oeth_bd

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
Buffer address[31:16]
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Buffer address[15:0]

Fig.4 addr in struct _oeth_bd

oeth_private 包含了数据收发 oeth_bd 单向队列,打开设备时驱动必须给每个 oeth_bd addr 分配 RAM 空间, MAC 层接收到数据包会将数据自动放到 BD addr 指向的内存空间,并设置相应 len_status 状态信息,然后(在中断使能的情况下)产生中断;Linux 需要发送数据时,open Ethernet 接口驱动将从上层 TCP/IP 协议驱动层的 skbuff 数据包转移到发送缓冲 BD 的内存地址空间(BD address), 并设置好 len_status 的长度,这样便会触发 MAC 将数据包适当处理后发送出去,并在发送完成后(在中断使能的情况下)产生中断。

open ethernet 设备初始化(Device initialization)

struct net_device * __init oeth_init(int unit);

oeth_init() 是 open Ethernet 设备驱动的入口,它只会在 Linux 初始化时调用一次,之后其占用的空间会被释放掉。oeth_init() 会调用 oeth_probe() 函数分配 IO 空间(通过 iomap())对 MAC 控制器的相关配置寄存器进行设置,比如工作模式,以太帧最大最小长度,TX/RX BD pointer, 设置 MAC 地址,清除状态标志以及中断使能等;然后会调用 register_netdev() 向 Linux 内核注册该网络设备。

这里主要介绍一下 open Ethernet MAC core 几个重要的寄存器,这几个寄存器的配置正确与否直接决定着该网络设备的工作稳定性。

typedef struct _oeth_regs {uint    moder;          /* Mode Register */uint    int_src;        /* Interrupt Source Register */uint    int_mask;       /* Interrupt Mask Register */uint    ipgt;           /* Back to Bak Inter Packet Gap Register */uint    ipgr1;          /* Non Back to Back Inter Packet Gap Register 1 */uint    ipgr2;          /* Non Back to Back Inter Packet Gap Register 2 */uint    packet_len;     /* Packet Length Register (min. and max.) */uint    collconf;       /* Collision and Retry Configuration Register */uint    tx_bd_num;      /* Transmit Buffer Descriptor Number Register */uint    ctrlmoder;      /* Control Module Mode Register */uint    miimoder;       /* MII Mode Register */uint    miicommand;     /* MII Command Register */uint    miiaddress;     /* MII Address Register */uint    miitx_data;     /* MII Transmit Data Register */uint    miirx_data;     /* MII Receive Data Register */uint    miistatus;      /* MII Status Register */uint    mac_addr0;      /* MAC Individual Address Register 0 */uint    mac_addr1;      /* MAC Individual Address Register 1 */uint    hash_addr0;     /* Hash Register 0 */uint    hash_addr1;     /* Hash Register 1 */                           
} oeth_regs;

参考 ucLinux 代码 Linux-2.6/drivers/net/open_eth.c 中 oeth_probe() 函数有对上述寄存器具体设置。

这里值得一提的是以 mii* 命名开头的寄存器相关设置。MII Management (MIIM) 用于PHY 寄存器控制和相关状态信息的访问,比如 Link status。 与此相应,PHY 便提供了一些寄存器便于这样的操作。MIIM 物理接口包括一根双向数据线 MDIO(Management Data Input/Output) 和一根时钟线 MDC(Management Data Clock),MIIM 操作的命令和数据便通过这串行接口在 MAC 和 PHY 传递。如果使能了 OETH_SYSFS_MDIO_ACCESS,则在 Linux 用户可通过 sysfs 文件系统实现从 userspace 访问 MIIM 管理数据的访问。

open ethernet 设备方法(Device methods)

网络设备的设备方法可以分为两种,基本方法和可选方法。以下代码是初始化函数调用 oeth_probe() 对 net_device * net 结构体成员的填充。

    dev->open = oeth_open;dev->hard_start_xmit = oeth_start_xmit;dev->stop = oeth_close;dev->get_stats = oeth_get_stats;dev->set_multicast_list = oeth_set_multicast_list;dev->set_mac_address = oeth_set_mac_add;bmcr_val = eth_mdread(dev, PHY_ADDRESS, MII_BMCR);dev->do_ioctl = mii_ioctl;cep->mii.dev = dev;cep->mii.mdio_read = eth_mdread;cep->mii.mdio_write = eth_mdwrite;

oeth_open() 打开该网络接口。用户命令 ifconfig 激活该网络接口时,该接口函数会被调用。Oeth_open() 向系统注册内存使用空间,申请中断号注册中断处理函数等。中断号宏 MACIRQ_NUM 和寄存器基地址 ETH_BASE_ADD 根据实际的硬件设计相应的设置。

    /*Install eth interrupt handler*/
request_irq(MACIRQ_NUM, oeth_interrupt, 0, "eth", (void *)dev);/*Enable receiver and transmitter */regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN;/*set tasklet for receiver and transmitter*/
tasklet_init(&cep->oeth_rx_tasklet, oeth_rx, (unsigned long)dev);tasklet_init(&cep->oeth_tx_tasklet, oeth_tx, (unsigned long)dev);

通常对于10/100M 的网卡设备,驱动会采用中断方式(对于更高速(10Gb) 的网卡,采用通常意义的中断方式效率较低)。中断处理函数 (ISR) oeth_interrupt 必须精短,只需要做最少的事情,而具体的数据包处理由 taskelet 去完成。在这里, oeth_interrupt 的任务就是根据中断事件标志调度数据收发相应的 tasklet, 如下:

/* Handle receive event in its own function.*/if (int_events & (OETH_INT_RXF | OETH_INT_RXE | OETH_INT_BUSY))tasklet_schedule(&cep->oeth_rx_tasklet);       /* Handle transmit event in its own function. */if (int_events & (OETH_INT_TXB | OETH_INT_TXE))tasklet_schedule(&cep->oeth_tx_tasklet);       


图 3. oeth interrupt service routine
 

oeth_start_xmit() 是由设备驱动发起数据包的传送。


图 4. oeth_start_xmit()
 

oeth_get_stats() 返回网络接口的统计状态,譬如接收和发送字节数,以及错误丢包等信息。用户用“ifconfig” 命令可以查看到这些统计信息。

此外,还提供了 MIIM 相关的设备方法用于对 PHY 的访问控制。

cep->mii.mdio_read = eth_mdread;//读PHY寄存器cep->mii.mdio_write = eth_mdwrite;//写PHY寄存器cep->mii.phy_id_mask = 0x1f;cep->mii.reg_num_mask = 0x1f;cep->mii.phy_id = PHY_ADDRESS;

ucLinux 也提供了通用的 MII 访问方法用于访问修改 PHY 收发器的工作模式,参见 unLinux 源代码<linux/mii.h>

结束语

在嵌入式领域通常需要涉及到软硬件接口的问题,open ethernet MAC core 是一个开放公开的结构,不光是软件可以开源,硬件设计也可以开放,开源,这种硬件的公开性为软件开放提供更多便利性,可以为软件需要定制特定硬件,譬如 TOE(TCP/IP Offload Engine) 技术将传统的 TCP/IP 协议从软件处理搬移到网卡 (NIC) 硬件完成,这种软硬件的开放性必然促进IT技术,尤其是嵌入式系统的创新。

免责声明:

1,本文所提出的方式方法仅代表作者个人观点。

2,本文属于原创作品,资料来源不超出参考文献所列范畴,其中任何部分都不会侵犯任何第三方的知识产权。


参考资料

  • 参考网站 www.opencores.org/cvsweb.shtml/ethernet/doc/ 介绍 opencores 开源项目 Ethernet IP Core design document。

  • 参考网站 www.opencores.org/cvsweb.shtml/ethernet/doc/ Ethernet IP Core Specification 

  • 参考 www.uclinux.org ucLinux官方网站,可下载 ucLinux-2.6 source code 

  • 参考书籍《Linux 设备驱动程序(影印版)》,第 17 章 Network Drivers, Jonathan Corbet,Alessandro Rubini & Greg Kroah-hartman 著,东南大学出版社。 

  • 参考 http://www.10gea.org/tcp-ip-offload-engine-toe.htm 介绍TOE(TCP/IP Offload Engine) technology。 

  • 参考 http://www.arasan.com/products/prod_overview/Gigabit-Ethernet-AHB-Flyer-1-0.pdf, Arasan 提供的 Gigabit Ethernet- AHB IP core。 

  • 参考 http://www.altera.com.cn/products/ip/processors/nios2/tools/embed-partners/ni2-network-stack.html Altera 公司提供的 Network solutions。 

关于作者

我:嵌入式软件工程师,熟悉 Linux 驱动开发,现从事marvell平台驱动移植及系统功能集成。

  相关解决方案