![]() |
|
||||||||||||||
| . 网站首页 . 产品新知 . 业界资讯 . 技术文库 . 下载中心 . 服务导航 . 邮购需知 . 技术论坛 . | ||
|
||
|
|||||
| NIOS II设备管理分析 | |||||
作者:Free 文章来源:本站原创 点击数: 更新时间:2008-2-15 ![]() |
|||||
|
Nios II设备分析 Nios设备体系总体说明 Nios II 设备与硬件系统定义的相关性 外设系统资源的分配和设备环境的初始化 1. 全局设备链表的定义 在系统库alt_lwip_dev.c中通过宏ALT_LLIST_HEAD(alt_lwip_device_list)定义了alt_lwip_device_list的设备双向链表。 在alt_llist.h中宏ALT_LLIST_HEAD相关定义如下: 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. */ }; #define ALT_LLIST_HEAD(head) alt_llist head = {&head, &head} 从定义中可知初始定义是一个指向自身的双向链表结构。 2. 全局外设系统资源分配 l Nios II IDE生成的应用项目system.h中Lan91c111外设相关部分如下: /* * lan91c111_0 configuration * */ #define LAN91C111_0_NAME "/dev/lan91c111_0" #define LAN91C111_0_TYPE "altera_avalon_lan91c111" #define LAN91C111_0_BASE 0x01200000 #define LAN91C111_0_IRQ 1 #define LAN91C111_0_IS_ETHERNET_MAC 1 #define LAN91C111_0_LAN91C111_REGISTERS_OFFSET 0x0300 #define LAN91C111_0_LAN91C111_DATA_BUS_WIDTH 32 l 分配外设系统资源: 在alt_sys_init.c中分配外设系统资源 /* * Allocate the device storage * */ ALTERA_AVALON_CFI_FLASH_INSTANCE( CFI_FLASH_0, cfi_flash_0 ); ALTERA_AVALON_JTAG_UART_INSTANCE( JTAG_UART_0, jtag_uart_0 ); ALTERA_AVALON_LAN91C111_INSTANCE( LAN91C111_0, lan91c111_0 ); 从以上代码中可以知Nios II以相对一致的宏定义了外设系统资源。 其中ALTERA_AVALON_LAN91C111_INSTANCE宏在altera_avalon_lan_91c111.h定义: #define ALTERA_AVALON_LAN91C111_INSTANCE(name, dev) \ alt_avalon_lan91c111_if dev = \ {\ {\ ALT_LLIST_ENTRY,\ {\ 0,\ name##_NAME,\ alt_avalon_lan91c111_init, \ alt_avalon_lan91c111_rx,\ },\ },\ name##_BASE + name##_LAN91C111_REGISTERS_OFFSET,\ name##_IRQ,\ name##_LAN91C111_DATA_BUS_WIDTH,\ 0,\ 0\ }; 语法上理解这个宏有两个关键点,首先定义了类型为alt_avalon_lan91c111_if的结构变量lan91c111_0(dev替换的结果),其次name##在编译预处理时被替换为LAN91C111_0,例:name##_IRQ编译后为LAN91C111_0_IRQ,这个宏在 system.h中被定义,进一步替换为1。 逻辑功能上理解这个宏,还需要明确alt_avalon_lan91c111_if类型的定义,在altera_avalon_lan_91c111.h中alt_avalon_lan91c111_if结构定义如下: typedef struct { alt_lwip_dev_list lwip_dev_list; int base_addr; int irq; int bus_width; sys_sem_t semaphore; alt_u8 tx_packet_no; /* Number of packet allocated for Tx */ }alt_avalon_lan91c111_if; 上述结构定义中,base_addr、irq、bus_width在system.h中定义,sys_sem_t为设备使用信号量,将在设备初始化时被赋值,tx_packet_no在使用中分配。Alt_lwip_dev_list结构在alt_lwip_de.h中相关定义如下: 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; 从以上代码可知,alt_lwip_list中llist是设备链表,在宏中被赋为内容为NULL指针的结构。alt_lwip_dev_list中dev 结构中除netif被赋0外其他域都被设置,netif将在设备初始化时被设置,其中网络设备lan91c111的初始化函数和读设备函数被设置, alt_avalon_lan91c111_init函数和alt_avalon_lan91c111_rx函数在网络设备驱动程序中定义,如果我们要开发其他网络芯片的驱动程序HAL就需要提供类似的函数。 1. 设备环境初始化 通过上一节的分析,我们清楚的看到,设备管理链表被定义为全局结构变量,设备资源在宏定义中被分配为全局变量,这些资源都是静态的被定义和分配。设备环境初始化动态的组织这些资源数据,在alt_sys_init.c中alt_sys_ini()函数在main()函数前被执行,程序相关部分如下: /* * Initialise the devices */ void alt_sys_init( void ) { ALTERA_AVALON_CFI_FLASH_INIT( CFI_FLASH_0, cfi_flash_0 ); ALTERA_AVALON_JTAG_UART_INIT( JTAG_UART_0, jtag_uart_0 ); ALTERA_AVALON_LAN91C111_INIT( LAN91C111_0, lan91c111_0 ); } alt_sys_init函数中相关设备环境初始化函数被调用,ALTERA_AVALON_LAN91C111_INIT是一个宏被定义在altera_avalon_lan91c111.h中: #define ALTERA_AVALON_LAN91C111_INIT(name, dev) \ if (name##_IRQ == ALT_IRQ_NOT_CONNECTED) \ { \ ALT_LINK_ERROR ("Error: Interrupt not connected for " #dev ". " \ "The ALTERA Avalon lan91c111 driver requires that an "\ "interrupt is connected. Please select an IRQ for " \ "this device in SOPC builder."); \ } \ else if (name##_LAN91C111_DATA_BUS_WIDTH != 32) \ { \ ALT_LINK_ERROR ("Error: Invalid configuration for " #dev ". " \ "The ALTERA Avalon lan91c111 driver currently only " \ "supports the configuration of MAC/PHY on the " \ "development board. Please select this option " \ "in SOPC builder."); \ } \ else \ { \ alt_lwip_dev_reg(dev); \ } 以上代码清楚的说明alt_lwip_dev_reg(dev)函数被执行,其参数宏替换后应该为 lan91c111_0,而 lan91c111_0在第2节叙述中可知被定义为alt_avalon_lan91c111_if的全局变量。 函数alt_lwip_dev_reg 在alt_lwip_dev.h中被定义为以下宏: #define alt_lwip_dev_reg(dev) alt_llist_insert(&alt_lwip_device_list, &dev.lwip_dev_list.llist) 函数调用被转换成alt_llist_insert(&alt_lwip_device_list,& lan91c111_0.lwip_dev_list.llist);前一个参数是我们在第1节中叙述的全局链表结构,后一个参数是第2节中叙述的设备链表地址。通过上述分析,我们知道设备环境初始化被具体为设备双向环形链表结构的增加,在实际应用开发中我们也可以通过类似的手法管理设备。下面我们具体的分析alt_llist_insert()函数。 Alt_llist_insert()函数在alt_llist.h中定义: static ALT_INLINE void ALT_ALWAYS_INLINE alt_llist_insert(alt_llist* list, alt_llist* entry) { entry->previous = list; entry->next = list->next;
list->next->previous = entry; list->next = entry; } 网络协议栈和网络设备初始化 /* * Our very first call in an lwIP example design is to start up lwIP TCP/IP * stack. We specify a MicroC/OS-II thread priority for the tcp_ip thread, * as well as a call-back routine, init_done_func(), which is called once * the stack is alive and well. */ lwip_stack_init(LWIP_TCPIP_TASK_PRIORITY, init_done_func, 0); …… /* * As with all MicroC/OS-II designs, once the initial thread(s) and * associated RTOS resources are declared, we start the RTOS. That''s it! */ OSStart(); 第一行语句初始化网络协议栈和网络设备初始化,OSStart()启动UCOS多任务实时系统。 在上一篇叙述中我们分析了网络设备分配了系统资源并加入到网络设备链表中,但网络接口芯片和相关接口电路并未被初始化,现在我们来逐步分析Nios II的网络协议栈是如何建立并初始化底层设备的,我们分析的侧重点不是lwip,而是准备写自己的网络HAL,所以我们分析的重点是网络HAL和lwip 结合的部分。 Lwip_stack_init函数在alt_lwip_dev.c中定义,其第二个参数为回调初始化函数,Lwip_stack_init定义如下: void lwip_stack_init(int thread_prio, void (* initfunc)(void *), void *arg) { sys_init(); #ifdef STATS stats_init(); #endif /* STATS */ mem_init(); memp_init(); pbuf_init(); netif_init(); tcpip_init(thread_prio, initfunc, arg); return; } 其中tcpip_init()函数中在启动tcpip任务时回调initfunc函数即init_done_func函数,init_done_func 函数在用户主程序中(一般和main函数在同一文件中)。在init_done_func函数中初始化以太网设备: /* * At this point LWIP has been initialized, but the Ethernet interface has * not; the initialise_lwip_devices() call does so, adding in MicroC-OS/II * threads for low-level Ethernet MAC interface and TCP protocol timer. */ if (!lwip_devices_init(ETHER_PRIO)) die_with_error("[tcpip_init_done] Fatal: Can''t add ethernet interface!");
在lwip_devices_init(ETHER_PRIO)函数中,分配netif空间,并调用 dev_list_ptr->dev.netif =netif_add(dev_list_ptr->dev.netif, &ipaddr, &netmask, &gw, (void*)dev_list_ptr, dev_list_ptr->dev.init_routine, tcpip_input); } 在设备环境初始化时被设置的dev.init_routine被调用,设置网络接口电路和芯片寄存器完成网络设备初始化。 |
|||||
| 文章录入:admin 责任编辑:admin | |||||
| 【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口】 | |||||
| 网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!) |
| | 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 | 网站公告 | 管理登录 | | |||
|