📄 ethernetif.c
字号:
//*------------------------------------------------------------------------------------------------//* 文件名 : ethernetif.c//* 功能描述 : 网卡的驱动函数库文件//* 作者 : 焦海波//* 版本 : 0.1//* 建立日期、时间 : 2006/06/07 14:05//* 最近修改日期、时间 : //* 修改原因 : //*------------------------------------------------------------------------------------------------//*------------------------------------------ 头文件 -----------------------------------------------#include "/uCOS_II/includes.h"#include "/LwIP/include/lwip/opt.h"#include "/LwIP/include/lwip/def.h"#include "/LwIP/include/lwip/mem.h"#include "/LwIP/include/lwip/pbuf.h"#include "/LwIP/include/lwip/sys.h"#include "/LwIP/include/lwip/stats.h"#include "/LwIP/include/netif/etharp.h"#include "/at91sam7x256/periph/emac/lib_emac.h"#include "/task.h" //*------------------------------------- 常量、变量、宏 --------------------------------------------#define IFNAME0 'e'#define IFNAME1 'n'#define MTU 1500static const st_eth_addr __stEthBroadcastAddr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};static st_netif *__pstNetif = NULL;HANDLER hEthernetInput;OS_STK T_ETHERNETIF_INPUT_STK[T_ETHERNETIF_INPUT_STKSIZE];//*--------------------------------------- 结构体定义 ----------------------------------------------//* 以太网卡结构体typedef struct ethernetif { st_eth_addr *pstEthaddr;}st_ethernetif;//*-------------------------------------- 函数原型声明 ---------------------------------------------err_t ethernetif_init(st_netif *pstNetif);static err_t __ethernetif_output(st_netif *pstNetif, st_pbuf *pstPbuf, st_ip_addr *pstIPAddr);static err_t __low_level_output(st_netif *pstNetif, st_pbuf *pstPbuf);static st_pbuf *__low_level_input(st_netif *pstNetif);static void __T_EthernetifInput(void *pReserved);static void __low_level_init(st_netif *pstNetif);static void __arp_timer(void *pReserved);//*================================================================================================//* 函 数 区//*================================================================================================//*------------------------------------------------------------------------------------------------//* 函数名称 : ethernetif_init//* 功能描述 : 通过调用low_level_init()函数完成网卡初始设置工作。该函数应该在操作系统启动后设置LwIP//* : 时调用,这个系统就是在SetupLwIP()函数中通过调用netif_add()函数调用该函数完成网卡初始//* : 设置工作。//* 入口参数 : <pstNetif>[in] 指向st_netif结构的指针,该结构储存着网卡的一些基本信息//* 出口参数 : 如果无法申请下内存则返回ERR_MEM,成功则返回ERR_OK//*------------------------------------------------------------------------------------------------err_t ethernetif_init(st_netif *pstNetif){ st_ethernetif *__pstEthernetif; __pstEthernetif = mem_malloc(sizeof(st_ethernetif)); if(__pstEthernetif == NULL) return ERR_MEM; pstNetif->state = __pstEthernetif; pstNetif->name[0] = IFNAME0; pstNetif->name[1] = IFNAME1; pstNetif->output = __ethernetif_output; pstNetif->linkoutput = __low_level_output; __pstEthernetif->pstEthaddr = (st_eth_addr*)&(pstNetif->hwaddr[0]); __low_level_init(pstNetif); etharp_init(); sys_timeout(ARP_TMR_INTERVAL, __arp_timer, NULL); return ERR_OK;}//*------------------------------------------------------------------------------------------------//* 函数名称 : __ethernetif_output//* 功能描述 : 当要发送一个IP信息包时,该函数由TCP/IP协议栈调用。该函数通过调用__low_level_output()//* : 函数来完成实际的信息包发送。//* 入口参数 : <pstNetif>[in] 指向st_netif结构的指针,其指定IP信息包将被发送的哪一个网卡接口上//* : <pstPbuf>[in] 指向st_pbuf结构的指针,其保存着将要发送的IP信息包//* : <pstIPAddr>[in] 指向st_ip_addr结构的指针,其指定IP信息包的目的IP地址//* 出口参数 : - ERR_RTE:不能路由到目的地址(没有外网网关)//* : - ERR_BUF:无法为以太网头腾出空间//* : - etharp_query()函数或netif->linkoutput()函数的返回值//*------------------------------------------------------------------------------------------------static err_t __ethernetif_output(st_netif *pstNetif, st_pbuf *pstPbuf, st_ip_addr *pstIPAddr){ //* 解析硬件地址,然后发送或排队信息包 return etharp_output(pstNetif, pstIPAddr, pstPbuf);}//*------------------------------------------------------------------------------------------------//* 函数名称 : __low_level_output//* 功能描述 : 完成实际的信息包发送//* 入口参数 : <pstNetif>[in] 指向st_netif结构的指针,其指定IP信息包将被发送的哪一个网卡接口上//* : <pstPbuf>[in] 指向st_pbuf结构的指针,其保存着将要发送的IP信息包//* 出口参数 : - 0: 发送成功//* : - -1: 发送失败//*------------------------------------------------------------------------------------------------static err_t __low_level_output(st_netif *pstNetif, st_pbuf *pstPbuf){ st_pbuf *__pstSendPbuf = pstPbuf; static HANDLER __hBlockOutput = NULL; err_t __errReturn = ERR_OK; if(__hBlockOutput == NULL) __hBlockOutput = OSAPIBlockNew(PIP_LOW_LEVEL_OUTPUT); #if ETH_PAD_SIZE pbuf_header(pstPbuf, -ETH_PAD_SIZE); #endif //* 阻塞对EMAC的访问,以避免不同的任务同时访问EMAC造成访问冲突的问题,最长等待时间是2秒 if(OS_NO_ERR == OSAPIBlockEnter(__hBlockOutput, 2000)) { for(; __pstSendPbuf!=NULL; __pstSendPbuf=__pstSendPbuf->next) { //* 发送pbuf中的数据,每次一个pbuf,如果__pstSendPbuf->next指针为空则表明已经到达pbuf链表的末尾 if(!EMACSendPacket(__pstSendPbuf->payload, __pstSendPbuf->len, (__pstSendPbuf->next == NULL))) { __errReturn = ~ERR_OK; } } OSAPIBlockExit(__hBlockOutput); } #if ETH_PAD_SIZE pbuf_header(pstPbuf, ETH_PAD_SIZE); #endif #if LINK_STATS lwip_stats.link.xmit++; #endif return __errReturn;}//*------------------------------------------------------------------------------------------------//* 函数名称 : __low_level_input//* 功能描述 : 完成实际的信息包接收//* 入口参数 : <pstNetif>[in] 指向st_netif结构的指针//* 出口参数 : 返回指向st_pbuf结构的指针//*------------------------------------------------------------------------------------------------static st_pbuf *__low_level_input(st_netif *pstNetif){ st_pbuf *__pstPbuf = NULL, *__pstCurPbuf; UWORD __uwLen; static HANDLER __hBlockInput = NULL; if(__hBlockInput == NULL) __hBlockInput = OSAPIBlockNew(PIP_LOW_LEVEL_INPUT); //* 阻塞对EMAC的访问,以避免不同的任务同时访问EMAC造成访问冲突的问题,最长等待时间是1秒 if(OS_NO_ERR == OSAPIBlockEnter(__hBlockInput, 1000)) { //* 获取收到的信息包的长度 __uwLen = GetInputPacketLen(); if(__uwLen) { #if ETH_PAD_SIZE __uwLen += ETH_PAD_SIZE; #endif //* 从pbuf pool中获取一个pbuf链 __pstPbuf = pbuf_alloc(PBUF_RAW, __uwLen, PBUF_POOL); if(__pstPbuf != NULL) { #if ETH_PAD_SIZE pbuf_header(__pstPbuf, -ETH_PAD_SIZE); #endif //* 复制数据 for(__pstCurPbuf=__pstPbuf; __pstCurPbuf!=NULL; __pstCurPbuf=__pstCurPbuf->next) EMACReadPacket(__pstCurPbuf->payload, __pstCurPbuf->len, (__pstCurPbuf->next == NULL)); #if ETH_PAD_SIZE pbuf_header( p, ETH_PAD_SIZE ); #endif #if LINK_STATS lwip_stats.link.recv++; #endif } else { #if LINK_STATS lwip_stats.link.memerr++; lwip_stats.link.drop++; #endif } } OSAPIBlockExit(__hBlockInput); } return __pstPbuf;}//*------------------------------------------------------------------------------------------------//* 函数名称 : __T_EthernetifInput//* 功能描述 : 以太网卡信息包接收任务,它通过调用__low_level_output()函数来完成实际的信息包接收。//* 入口参数 : <pReserved>[in] 保留//* 出口参数 : 无//*------------------------------------------------------------------------------------------------static void __T_EthernetifInput(void *pReserved){ st_ethernetif *pstEthernetif; st_pbuf *__pstPbuf; st_eth_hdr *__pstEthhdr; while(TRUE) { pstEthernetif = (st_ethernetif*)__pstNetif->state; //* 从EMAC循环读取数据 do{ __pstPbuf = __low_level_input(__pstNetif); if(__pstPbuf == NULL) OSAPISemWait(hEthernetInput, 100); }while(__pstPbuf == NULL); __pstEthhdr = __pstPbuf->payload; #if LINK_STATS lwip_stats.link.recv++; #endif __pstEthhdr = __pstPbuf->payload; switch(htons(__pstEthhdr->type)) { case ETHTYPE_IP: //* 更新ARP表 etharp_ip_input(__pstNetif, __pstPbuf); //* 跳过以太网头部字段 pbuf_header(__pstPbuf, -sizeof(st_eth_hdr) ); //* 传递到网络层 __pstNetif->input(__pstPbuf, __pstNetif); break; case ETHTYPE_ARP: //* 将__pstPbuf传递到ARP模块 etharp_arp_input(__pstNetif, pstEthernetif->pstEthaddr, __pstPbuf); break; default: pbuf_free(__pstPbuf); __pstPbuf = NULL; break; } }}//*------------------------------------------------------------------------------------------------//* 函数名称 : __low_level_init//* 功能描述 : 对网卡进行初始化设置//* 入口参数 : <pstNetif>[in] 指向st_netif结构的指针,该结构储存着网卡的一些基本信息//* 出口参数 : 无//*------------------------------------------------------------------------------------------------static void __low_level_init(st_netif *pstNetif){ UBYTE __ubOldPrio; UBYTE __ubErr; pstNetif->hwaddr_len = NETIF_MAX_HWADDR_LEN; //* 设置MAC地址 pstNetif->hwaddr[0] = MAC_ADDR_0; pstNetif->hwaddr[1] = MAC_ADDR_1; pstNetif->hwaddr[2] = MAC_ADDR_2; pstNetif->hwaddr[3] = MAC_ADDR_3; pstNetif->hwaddr[4] = MAC_ADDR_4; pstNetif->hwaddr[5] = MAC_ADDR_5; pstNetif->mtu = MTU; pstNetif->flags = NETIF_FLAG_BROADCAST; __pstNetif = pstNetif; //* 初始化EMAC。EMACInit()函数包含查询状态位代码,并且这些查询代码并没有使用OSTimeDly()等函数主动释放 //* CPU使用权。如果网线在当时并没有接触良好,则这个过程需要相当长的时间。为了避免阻塞其它低优先级任务的 //* 正常运行,我们使用了uCOS提供的任务管理函数,先将其所在任务的优先级降低,等初始化完成之后再恢复其优 //* 先级。 __ubOldPrio = OSTCBCur->OSTCBPrio; __ubErr = OSTaskChangePrio(OS_PRIO_SELF, OS_IDLE_PRIO - 1); EMACInit(); if(__ubErr == OS_NO_ERR) OSTaskChangePrio(OS_PRIO_SELF, __ubOldPrio); OSTaskCreate(__T_EthernetifInput, (void*)NULL, &T_ETHERNETIF_INPUT_STK[T_ETHERNETIF_INPUT_STKSIZE-1], T_ETHERNETIF_INPUT_PRIOR);}//*------------------------------------------------------------------------------------------------//* 函数名称 : __arp_timer//* 功能描述 : ARP表定时更新处理函数//* 入口参数 : <pReserved>[in/out] 保留 //* 出口参数 : 无//*------------------------------------------------------------------------------------------------static void __arp_timer(void *pReserved){ etharp_tmr(); sys_timeout(ARP_TMR_INTERVAL, __arp_timer, NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -