网络是嵌入式应用的常备功能,在NIOS II中集成了UCOS II和LWIP,分析网络设备在NIOS II中的来龙去脉对学习NIOS II设备驱动程序有典型的意义。
1.驱动程序提供的freedev_rtl8019.h中定义一个freedev_rtl8019_if结构的全局变量dev
#define FREEDEV_RTL8019_INSTANCE(name, dev) \
freedev_rtl8019_if dev = \
{\
{\
ALT_LLIST_ENTRY,\
{\
0,\
name##_NAME,\
freedev_rtl8019_init, \
freedev_rtl8019_rx,\
},\
},\
name##_BASE,\
name##_IRQ,\
8,\
0,\
0\
}
结构freedev_rtl8019_if定义如下:
typedef struct
{
alt_lwip_dev_listlwip_dev_list;
intbase_addr;
intirq;
intbus_width;
sys_sem_tsemaphore;
sys_sem_tarp_semaphore;
alt_u8tx_packet_no; /* Number of packet allocated for Tx */
}freedev_rtl8019_if;
相关结构定义如下:
typedef struct
{
alt_llistllist;/* for internal use */
alt_lwip_devdev;
}alt_lwip_dev_list;
struct alt_lwip_dev
{
/* The netif pointer MUST be the first element in the structure */
struct netif`*netif;
const char*name;
err_t (*init_routine)(struct netif*);
void (*rx_routine)();
};
struct netif {
/** pointer to next in linked list */
struct netif *next;
/** IP address configuration in network byte order */
struct ip_addr ip_addr;
struct ip_addr netmask;
struct ip_addr gw;
/** This function is called by the network device driver
*to pass a packet up the TCP/IP stack. */
err_t (* input)(struct pbuf *p, struct netif *inp);
/** This function is called by the IP module when it wants
*to send a packet on the interface. This function typically
*first resolves the hardware address, then sends the packet. */
err_t (* output)(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr);
/** This function is called by the ARP module when it wants
*to send a packet on the interface. This function outputs
*the pbuf as-is on the link medium. */
err_t (* linkoutput)(struct netif *netif, struct pbuf *p);
/** This field can be set by the device driver and could point
*to state information for the device. */
void *state;
#if LWIP_DHCP
/** the DHCP client state information for this netif */
struct dhcp *dhcp;
#endif
/** number of bytes used in hwaddr */
unsigned char hwaddr_len;
/** link level hardware address of this interface */
unsigned char hwaddr[NETIF_MAX_HWADDR_LEN];
/** maximum transfer unit (in bytes) */
u16_t mtu;
/** flags (see NETIF_FLAG_ above) */
u8_t flags;
/** link type */
u8_t link_type;
/** descriptive abbreviation */
char name[2];
/** number of this interface */
u8_t num;
};
由以上的结构可以分析得出:全局变量dev中包含了网络通讯的所有要素。
2.驱动程序中freedev_rtl8019.h中还定义了FREEDEV_RTL8019_INIT(name, dev)
该宏定义最终调用alt_lwip_dev_reg(dev); 将设备全局变量注册到系统网络设备联表中。
#define alt_lwip_dev_reg(dev)\
alt_llist_insert(&alt_lwip_device_list, &dev.lwip_dev_list.llist)
alt_lwip_device_list是一个在alt_lwip_dev.c中定义的全局变量。第二个参数是alt_llist指针。alt_llist_insert完成双向联表插入操作。
以上两个步骤在系统生成时从驱动程序.h文件中生成到alt_sys_init.c中。在系统运行时FREEDEV_RTL8019_INIT将被运行。
在应用程序的函数main中首先调用lwip_stack_init。函数中提供了回调函数init_done_func初始化底层网络设备。
lwip_stack_init(LWIP_TCPIP_TASK_PRIORITY, init_done_func, 0);
lwip_stack_init初始化协议栈,在TCP线程工作前调用init_done_func函数。
Init_done_func函数中对设备初始化的调用由以下函数完成,
lwip_devices_init(LWIP_RX_ETHER_TASK_PRIORITY)
在lwip_devices_init函数中调用netif_add增加网络NIC。
调用应用程序函数get_ip_addr获取IP地址。
调用netif_set_addr设置IP地址。
注意:网络设备驱动程序的初始化在netif_add函数中被调用。