?? ethernetif.c
字號(hào):
//*------------------------------------------------------------------------------------------------//* 文件名 : ethernetif.c//* 功能描述 : 網(wǎng)卡的驅(qū)動(dòng)函數(shù)庫文件//* 作者 : 焦海波//* 版本 : 0.1//* 建立日期、時(shí)間 : 2006/06/07 14:05//* 最近修改日期、時(shí)間 : //* 修改原因 : //*------------------------------------------------------------------------------------------------//*------------------------------------------ 頭文件 -----------------------------------------------#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];//*--------------------------------------- 結(jié)構(gòu)體定義 ----------------------------------------------//* 以太網(wǎng)卡結(jié)構(gòu)體typedef struct ethernetif { st_eth_addr *pstEthaddr;}st_ethernetif;//*-------------------------------------- 函數(shù)原型聲明 ---------------------------------------------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);//*================================================================================================//* 函 數(shù) 區(qū)//*================================================================================================//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : ethernetif_init//* 功能描述 : 通過調(diào)用low_level_init()函數(shù)完成網(wǎng)卡初始設(shè)置工作。該函數(shù)應(yīng)該在操作系統(tǒng)啟動(dòng)后設(shè)置LwIP//* : 時(shí)調(diào)用,這個(gè)系統(tǒng)就是在SetupLwIP()函數(shù)中通過調(diào)用netif_add()函數(shù)調(diào)用該函數(shù)完成網(wǎng)卡初始//* : 設(shè)置工作。//* 入口參數(shù) : <pstNetif>[in] 指向st_netif結(jié)構(gòu)的指針,該結(jié)構(gòu)儲(chǔ)存著網(wǎng)卡的一些基本信息//* 出口參數(shù) : 如果無法申請(qǐng)下內(nèi)存則返回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;}//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : __ethernetif_output//* 功能描述 : 當(dāng)要發(fā)送一個(gè)IP信息包時(shí),該函數(shù)由TCP/IP協(xié)議棧調(diào)用。該函數(shù)通過調(diào)用__low_level_output()//* : 函數(shù)來完成實(shí)際的信息包發(fā)送。//* 入口參數(shù) : <pstNetif>[in] 指向st_netif結(jié)構(gòu)的指針,其指定IP信息包將被發(fā)送的哪一個(gè)網(wǎng)卡接口上//* : <pstPbuf>[in] 指向st_pbuf結(jié)構(gòu)的指針,其保存著將要發(fā)送的IP信息包//* : <pstIPAddr>[in] 指向st_ip_addr結(jié)構(gòu)的指針,其指定IP信息包的目的IP地址//* 出口參數(shù) : - ERR_RTE:不能路由到目的地址(沒有外網(wǎng)網(wǎng)關(guān))//* : - ERR_BUF:無法為以太網(wǎng)頭騰出空間//* : - etharp_query()函數(shù)或netif->linkoutput()函數(shù)的返回值//*------------------------------------------------------------------------------------------------static err_t __ethernetif_output(st_netif *pstNetif, st_pbuf *pstPbuf, st_ip_addr *pstIPAddr){ //* 解析硬件地址,然后發(fā)送或排隊(duì)信息包 return etharp_output(pstNetif, pstIPAddr, pstPbuf);}//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : __low_level_output//* 功能描述 : 完成實(shí)際的信息包發(fā)送//* 入口參數(shù) : <pstNetif>[in] 指向st_netif結(jié)構(gòu)的指針,其指定IP信息包將被發(fā)送的哪一個(gè)網(wǎng)卡接口上//* : <pstPbuf>[in] 指向st_pbuf結(jié)構(gòu)的指針,其保存著將要發(fā)送的IP信息包//* 出口參數(shù) : - 0: 發(fā)送成功//* : - -1: 發(fā)送失敗//*------------------------------------------------------------------------------------------------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 //* 阻塞對(duì)EMAC的訪問,以避免不同的任務(wù)同時(shí)訪問EMAC造成訪問沖突的問題,最長等待時(shí)間是2秒 if(OS_NO_ERR == OSAPIBlockEnter(__hBlockOutput, 2000)) { for(; __pstSendPbuf!=NULL; __pstSendPbuf=__pstSendPbuf->next) { //* 發(fā)送pbuf中的數(shù)據(jù),每次一個(gè)pbuf,如果__pstSendPbuf->next指針為空則表明已經(jīng)到達(dá)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;}//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : __low_level_input//* 功能描述 : 完成實(shí)際的信息包接收//* 入口參數(shù) : <pstNetif>[in] 指向st_netif結(jié)構(gòu)的指針//* 出口參數(shù) : 返回指向st_pbuf結(jié)構(gòu)的指針//*------------------------------------------------------------------------------------------------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); //* 阻塞對(duì)EMAC的訪問,以避免不同的任務(wù)同時(shí)訪問EMAC造成訪問沖突的問題,最長等待時(shí)間是1秒 if(OS_NO_ERR == OSAPIBlockEnter(__hBlockInput, 1000)) { //* 獲取收到的信息包的長度 __uwLen = GetInputPacketLen(); if(__uwLen) { #if ETH_PAD_SIZE __uwLen += ETH_PAD_SIZE; #endif //* 從pbuf pool中獲取一個(gè)pbuf鏈 __pstPbuf = pbuf_alloc(PBUF_RAW, __uwLen, PBUF_POOL); if(__pstPbuf != NULL) { #if ETH_PAD_SIZE pbuf_header(__pstPbuf, -ETH_PAD_SIZE); #endif //* 復(fù)制數(shù)據(jù) 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;}//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : __T_EthernetifInput//* 功能描述 : 以太網(wǎng)卡信息包接收任務(wù),它通過調(diào)用__low_level_output()函數(shù)來完成實(shí)際的信息包接收。//* 入口參數(shù) : <pReserved>[in] 保留//* 出口參數(shù) : 無//*------------------------------------------------------------------------------------------------static void __T_EthernetifInput(void *pReserved){ st_ethernetif *pstEthernetif; st_pbuf *__pstPbuf; st_eth_hdr *__pstEthhdr; while(TRUE) { pstEthernetif = (st_ethernetif*)__pstNetif->state; //* 從EMAC循環(huán)讀取數(shù)據(jù) 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); //* 跳過以太網(wǎng)頭部字段 pbuf_header(__pstPbuf, -sizeof(st_eth_hdr) ); //* 傳遞到網(wǎng)絡(luò)層 __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; } }}//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : __low_level_init//* 功能描述 : 對(duì)網(wǎng)卡進(jìn)行初始化設(shè)置//* 入口參數(shù) : <pstNetif>[in] 指向st_netif結(jié)構(gòu)的指針,該結(jié)構(gòu)儲(chǔ)存著網(wǎng)卡的一些基本信息//* 出口參數(shù) : 無//*------------------------------------------------------------------------------------------------static void __low_level_init(st_netif *pstNetif){ UBYTE __ubOldPrio; UBYTE __ubErr; pstNetif->hwaddr_len = NETIF_MAX_HWADDR_LEN; //* 設(shè)置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()函數(shù)包含查詢狀態(tài)位代碼,并且這些查詢代碼并沒有使用OSTimeDly()等函數(shù)主動(dòng)釋放 //* CPU使用權(quán)。如果網(wǎng)線在當(dāng)時(shí)并沒有接觸良好,則這個(gè)過程需要相當(dāng)長的時(shí)間。為了避免阻塞其它低優(yōu)先級(jí)任務(wù)的 //* 正常運(yùn)行,我們使用了uCOS提供的任務(wù)管理函數(shù),先將其所在任務(wù)的優(yōu)先級(jí)降低,等初始化完成之后再恢復(fù)其優(yōu) //* 先級(jí)。 __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);}//*------------------------------------------------------------------------------------------------//* 函數(shù)名稱 : __arp_timer//* 功能描述 : ARP表定時(shí)更新處理函數(shù)//* 入口參數(shù) : <pReserved>[in/out] 保留 //* 出口參數(shù) : 無//*------------------------------------------------------------------------------------------------static void __arp_timer(void *pReserved){ etharp_tmr(); sys_timeout(ARP_TMR_INTERVAL, __arp_timer, NULL);}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -