DE2开发板:NiosII+LWIP环境下DM9000A的驱动程序分析(web_server.c)
2014-10-12 16:30
337 查看
在DE2的开发板上,利用NiosII软核与LWIP,可以实现web服务。Terasic公司提供的DE2_WEB_SERVER DEMO提供了一个很好的范本,可以作为很好的研究对象。NIOS IDE提供了Lan91C11的驱动,对于其他以太网接口芯片没有提供相应的驱动。而DE2开发板提供了DM9000A的驱动,为我们研究NIOS系统中Avalon外部设备的驱动编程提供了有益的参考。
首先需要关注LWIP提供的几个重要的结构体:
//netif结构体作为LWIP中网络接口的基础数据类型,描述了网络接口的基本属性以及输入、输出函数
//alt_lwip_dev结构体描述了符合LWIP规范的网络端口设备
//alt_lwip_dev_list:设备链表
在LWIP定义的这些结构体类型的基础上,DE2_WEB_SERVER定义了针对DM9000网络接口的一个结构体
有了这个结构体,DM9000的寄存器读写操作开始与LWIP的工作机制发生了联系。
我们来看包含main()函数的主程序文件web_server.c,在包含相应的头文件之后,最重要的一个宏命令出现了:
ALTERA_AVALON_DM9K_INSTANCE(DM9000A, dm9k);
这个宏的定义十分晦涩难懂:
例化之后,相当于定义了一个alt_avalon_dm9k_if类型的变量dm9k。dm9k的属性包括:
dm9k. lwip_dev_list =
{
ALT_LLIST_ENTRY, //对应的dm9k. lwip_dev_list.llist
{
dm9k. lwip_dev_list.dev. netif = NULL;
dm9k. lwip_dev_list.dev. name = DM9000A_NAME;
dm9k. lwip_dev_list.dev. init_routine = alt_avalon_dm9k_init;
dm9k. lwip_dev_list.dev. rx_routine = alt_avalon_dm9k_rx;
}
}
dm9k. base_addr= DM9000A_BASE;
dm9k. irq= DM9000A_IRQ;
dm9k. hwaddr[6] = { 0x00, 0x90, 0x00, 0xAE, 0x00, 0x01};
//...
而tcpip_init_done函数中的一个宏则使得dm9k开始担当起底层网络接口通信的重任。
这个ALTERA_AVALON_DM9K_INIT是如此定义的:
#define ALTERA_AVALON_DM9K_INIT(dev) alt_lwip_dev_reg(dev)
而alt_lwip_dev_reg是LWIP中定义的一个设备注册的宏:
#define alt_lwip_dev_reg(dev) alt_llist_insert(&alt_lwip_device_list, &dev.lwip_dev_list.llist)
再看看下面这个全局变量的定义,一切疑惑终于烟消云散了:
extern alt_llist alt_lwip_device_list;
总的思路应该是这样的:LWIP定义了一个全局变量alt_lwip_device_list,所有LWIP提供的API均可以对这一变量进行操作。而DM9000通过ALTERA_AVALON_DM9K_INSTANCE宏指令将DM9000作为alt_lwip_device_list中的一个alt_lwip_dev(实际上就是唯一的一个alt_lwip_dev),使得LWIP的API函数的操作将转换为对DM9000的寄存器读写操作。
首先需要关注LWIP提供的几个重要的结构体:
//netif结构体作为LWIP中网络接口的基础数据类型,描述了网络接口的基本属性以及输入、输出函数
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; err_t (* input)(struct pbuf *p, struct netif *inp); err_t (* output)(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr); err_t (* linkoutput)(struct netif *netif, struct pbuf *p); 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; }; |
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)(); //数据接收函数 }; |
typedef struct { alt_llist llist; /* for internal use */ alt_lwip_dev dev; }alt_lwip_dev_list; typedef struct alt_llist_s alt_llist; struct alt_llist_s { alt_llist* next; /* Pointer to the next element in the list. */ alt_llist* previous; /* Pointer to the previous element in the list. */ }; |
alt_avalon_dm9k_if: // dm9k private date structure typedef struct { alt_lwip_dev_list lwip_dev_list; //与之关联的设备链表 int base_addr; //寄存器的基地址 int irq; //中断编号 u_char hwaddr[6]; //MAC地址 int index_offset; int data_offset; int dm9k_tx_space; int dm9k_linked; sys_sem_t arp_semaphore; sys_sem_t tx_semaphore; } alt_avalon_dm9k_if; |
我们来看包含main()函数的主程序文件web_server.c,在包含相应的头文件之后,最重要的一个宏命令出现了:
ALTERA_AVALON_DM9K_INSTANCE(DM9000A, dm9k);
这个宏的定义十分晦涩难懂:
#define ALTERA_AVALON_DM9K_INSTANCE(name, dev) / alt_avalon_dm9k_if dev = / {/ {/ ALT_LLIST_ENTRY,/ {/ 0,/ name##_NAME,/ alt_avalon_dm9k_init, / //初始化子程序 alt_avalon_dm9k_rx,/ //接收子程序 },/ },/ name##_BASE, / name##_IRQ,/ { 0x00, 0x90, 0x00, 0xAE, 0x00, 0x01}, / 0, 1, 2/ } |
dm9k. lwip_dev_list =
{
ALT_LLIST_ENTRY, //对应的dm9k. lwip_dev_list.llist
{
dm9k. lwip_dev_list.dev. netif = NULL;
dm9k. lwip_dev_list.dev. name = DM9000A_NAME;
dm9k. lwip_dev_list.dev. init_routine = alt_avalon_dm9k_init;
dm9k. lwip_dev_list.dev. rx_routine = alt_avalon_dm9k_rx;
}
}
dm9k. base_addr= DM9000A_BASE;
dm9k. irq= DM9000A_IRQ;
dm9k. hwaddr[6] = { 0x00, 0x90, 0x00, 0xAE, 0x00, 0x01};
//...
而tcpip_init_done函数中的一个宏则使得dm9k开始担当起底层网络接口通信的重任。
static void tcpip_init_done(void *arg) { ALTERA_AVALON_DM9K_INIT(dm9k); //... } |
#define ALTERA_AVALON_DM9K_INIT(dev) alt_lwip_dev_reg(dev)
而alt_lwip_dev_reg是LWIP中定义的一个设备注册的宏:
#define alt_lwip_dev_reg(dev) alt_llist_insert(&alt_lwip_device_list, &dev.lwip_dev_list.llist)
再看看下面这个全局变量的定义,一切疑惑终于烟消云散了:
extern alt_llist alt_lwip_device_list;
总的思路应该是这样的:LWIP定义了一个全局变量alt_lwip_device_list,所有LWIP提供的API均可以对这一变量进行操作。而DM9000通过ALTERA_AVALON_DM9K_INSTANCE宏指令将DM9000作为alt_lwip_device_list中的一个alt_lwip_dev(实际上就是唯一的一个alt_lwip_dev),使得LWIP的API函数的操作将转换为对DM9000的寄存器读写操作。
相关文章推荐
- DE2开发板:NiosII+LWIP环境下DM9000A的驱动程序分析(web_server.c)
- Ubuntu 7.1 server从无到有搭建jsp/php/rails全能WEB生产环境(一)
- Ubuntu 7.1 server从无到有搭建jsp/php/rails全能WEB生产环境(三)
- 如何使用USBWebserver在本机快速建立网站测试环境
- 基于Nios软核CPU的uC/OS-II和LwIP移植 (2)
- 基于Nios软核CPU的uC/OS-II和LwIP移植 (1)
- Weblogic Server 8.1 环境下Web布署DIY
- Shiro框架Web环境下过滤器结构分析
- Shiro框架Web环境下过滤器结构分析
- 基于Nios软核CPU的uC/OS-II和LwIP移植 (3)
- 网络驱动程序 各个函数详解及图解 DM9000A网卡驱动框架源码分析
- Ubuntu 7.1 server从无到有搭建jsp/php/rails全能WEB生产环境(二)
- 为 Python Server Pages 和 Oracle 构建快速 Web 开发环境。
- DE2 NIOS snapshot by web ( uIP on DE2 )
- Weblogic Server 8.1 环境下Web布署DIY
- Ubuntu 7.1 server从无到有搭建jsp/php/rails全能WEB生产环境(六)
- Ubuntu 7.1 server从无到有搭建jsp/php/rails全能WEB生产环境(四)
- (原創) DE2_NIOS_Lite 1.1 (SOC) (Nios II) (SOPC Builder) (μC/OS-II) (DE2)
- Web server调研分析
- linux Apache 环境下安装AWStatsWEB日志分析工具