當前位置:首頁 > 單片機 > 單片機
[導讀]Internet實現了全球范圍內計算機網絡的互連,不同主機之間必須遵循相同的網絡協(xié)議才能彼此通信。TCP/IP協(xié)議作為一種網絡互聯(lián)協(xié)議,在Internet中得到了最廣泛的支持以及應用。筆者此處就輕量級TCP/IP協(xié)議Lwip的移植作

Internet實現了全球范圍內計算機網絡的互連,不同主機之間必須遵循相同的網絡協(xié)議才能彼此通信。TCP/IP協(xié)議作為一種網絡互聯(lián)協(xié)議,在Internet中得到了最廣泛的支持以及應用。筆者此處就輕量級TCP/IP協(xié)議Lwip的移植作一個簡單的介紹。

1. TCP/IP協(xié)議概述

TCP/IP協(xié)議是Internet上使用最廣泛的通信協(xié)議,其實際上是一個協(xié)議簇,其中TCP協(xié)議和IP協(xié)議是其中兩個最重要的協(xié)議。

TCP/IP協(xié)議采用4層層級結構:應用層、運輸層、網絡層、鏈路層。相應的層級除了能夠向上一層提供服務,還需要使用下一層所提供的服務。

1.1. 鏈路層

數據鏈路層將網絡層交下來的IP數據報組裝成幀,在兩個相鄰結點間的鏈路上透明傳送以幀為單位的數據,另一結點若收到無差錯的幀,則從收到的幀中提取出IP數據報上交上一層,否則丟棄此包。這一層級幀格式通常采用Ethernet V2,有效的MAC幀長度為64~1518字節(jié),通常由網絡適配器實現這一層級。

1.2. 網絡層

網絡層把運輸層產生的報文段或用戶數據報封裝成分組或包進行傳送,由于網絡層使用無連接的網際協(xié)議IP,因此,分組也稱為IP數據報,并且是不可靠的。除了IP協(xié)議,網絡層還需配套使用以下幾個協(xié)議:地址解析協(xié)議ARP、逆地址解析協(xié)議RARP、因特網控制報文協(xié)議ICMP、因特網組管理協(xié)議IGMP。

1.3. 運輸層

運輸層向上面的應用層提供通信服務,具有復用和分用的功能。復用就是多個應用層進程可同時使用運輸層的服務,分用則為運輸層可以把收到的數據分別交付上面應用層中相應的進程。這一層級有兩個不同的協(xié)議:傳輸控制協(xié)議TCP和用戶數據報協(xié)議UDP。TCP提供面向連接的服務,數據傳輸單位為報文段,能夠保證提供可靠的交付。其傳輸數據前必須先建立連接,結束傳輸后要釋放連接,不提供廣播或多播服務。UDP傳輸數據前不需要建立連接,數據傳輸單位為用戶數據報,不保證提供可靠的交付。運輸層接收到UDP報文后,不需要給出任何確認,可以實現廣播或多播服務。

1.4. 應用層

應用層根據運輸層提供的服務,實現不同主機中多個應用進程之間的通信和協(xié)同工作,由實際的應用規(guī)劃應用進程在通信時所遵循的協(xié)議。在Internet中有很多標準的應用層協(xié)議如:域名系統(tǒng)DNS、文件傳輸協(xié)議FTP、超文本傳輸協(xié)議HTTP、遠程終端協(xié)議TELNET、動態(tài)主機配置協(xié)議DHCP、簡單網絡管理協(xié)議SNMP等等。

2. Lwip概述

Lwip是瑞典計算機科學院(SICS)的Adam Dunkels開發(fā)的一個小型開源TCP/IP協(xié)議棧。作為輕量級TCP/IP協(xié)議,Lwip支持有操作系統(tǒng)以及無操作系統(tǒng)運行,其在保持TCP/IP協(xié)議主要功能的基礎上,減少對RAM、ROM的占用,非常適合于嵌入式系統(tǒng)使用。

3. Lwip移植

對于一個可移植的開源協(xié)議棧,移植部分往往分成體系結構相關、操作系統(tǒng)相關、驅動接口相關這幾個部分。此處以Lwip-1.4.1版本為例說明移植的相關代碼文件。

3.1. 體系結構相關3.1.1. cc.h

在cc.h中需實現cpu以及編譯器相關的定義,Lwip為了可移植,使用了自身的數據類型,需根據使用的cpu以及編譯器進行定義。網絡字節(jié)序使用大端格式,并且其數據結構需嚴格按照字節(jié)對齊,此處定義cpu的字節(jié)序以及編譯器字節(jié)對齊宏等。

#ifndef __ARCH_CC_H__

#define __ARCH_CC_H__

#include /* printf, fflush, FILE */

#include /* abort */

#define LWIP_PROVIDE_ERRNO

/* Define platform endianness (might already bedefined) */

#define BYTE_ORDER LITTLE_ENDIAN

/* Define generic types used in lwIP */

typedef unsignedchar u8_t;

typedef signedchar s8_t;

typedef unsignedshort u16_t;

typedef signedshort s16_t;

typedef unsignedlong u32_t;

typedef signedlong s32_t;

typedef u32_t mem_ptr_t;

typedef u32_t sys_prot_t;

/* Define (sn)printf formatters for these lwIP types*/

#define U16_F "hu"

#define S16_F "hd"

#define X16_F "hx"

#define U32_F "lu"

#define S32_F "ld"

#define X32_F "lx"

/* Compiler hints for packing structures */

#define PACK_STRUCT_BEGIN

#define PACK_STRUCT_STRUCT __attribute__((__packed__))

#define PACK_STRUCT_END

#define PACK_STRUCT_FIELD(x) x

/* Plaform specific diagnostic output */

#define LWIP_PLATFORM_DIAG(x) do { printf x; } while(0)

#define LWIP_PLATFORM_ASSERT(x) do {

printf("Assertion "%s" failed at line%d in %sn",

x, __LINE__, __FILE__); fflush(NULL); abort(); }while(0)

#endif /* __ARCH_CC_H__ */

3.1.2. perf.h

perf.h用于實現系統(tǒng)統(tǒng)計和測量相關頭文件,在平時可以不用。

#ifndef __PERF_H__

#define __PERF_H__

#define PERF_START/* null definition */

#define PERF_STOP(x)/* null definition */

#endif /* __PERF_H__ */

3.2. 操作系統(tǒng)相關3.2.1. sys_arch.h/sys_arch.c

在sys_arch.h/sys_arch.c中需實現操作系統(tǒng)相關的接口,主要是提供信號量、郵箱、臨界區(qū)保護的接口實現,為了支持Lwip的完整功能,還需實現多線程接口,除此之外,Lwip還需使用系統(tǒng)時鐘來確定一些模塊(如ARP、TCP等)的超時處理。所有需在sys_arch.h/sys_arch.c中實現的接口函數均在sys.h中給出了原型,此處不使用操作系統(tǒng),只需實現Lwip的系統(tǒng)時鐘即可。

extern volatile uint32_t SystemTick;

uint32_t sys_now(void)

{

returnSystemTick;

}

3.3. 驅動接口相關3.3.1. ethernetif.c

Lwip最底層需要實現讀寫網卡,其中在源碼包中ethernetif.c,已經給出了底層驅動接口模板的實現,因此只需要在模板中加入網卡驅動接口函數即可,主要是網卡初始化、網卡接收、網卡發(fā)送這三個函數。筆者使用的是DM9000A,驅動的實現在前面章節(jié)有詳細的介紹,此處不再細述。

/* Define those to better describe your networkinterface. */

#define IFNAME0 'e'

#define IFNAME1 'n'

struct ethernetif {

structeth_addr *ethaddr;

/* Addwhatever per-interface state that is needed here. */

};

struct netifDM9000_netif;

static void low_level_init(struct netif *netif)

{

/* set MAC hardware address length */

netif->hwaddr_len = ETHARP_HWADDR_LEN;

/* set MAC hardware address */

netif->hwaddr[0] = default_enetaddr[0];

netif->hwaddr[1] = default_enetaddr[1];

netif->hwaddr[2] = default_enetaddr[2];

netif->hwaddr[3] = default_enetaddr[3];

netif->hwaddr[4] = default_enetaddr[4];

netif->hwaddr[5] = default_enetaddr[5];

/* maximum transfer unit */

netif->mtu = 1500;

/* device capabilities */

/* don't set NETIF_FLAG_ETHARP if this device is notan ethernet one */

netif->flags = NETIF_FLAG_BROADCAST |NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;

/* Do whatever else is needed to initialize interface.*/

DM9000_Init();

}

static err_t low_level_output(struct netif *netif,struct pbuf *p)

{

struct pbuf*q;

uint16_tBuffer[1514/2];

uint8_t*pBuffer;

#if ETH_PAD_SIZE

pbuf_header(p,-ETH_PAD_SIZE); /* drop the padding word */

#endif

pBuffer =(uint8_t *)Buffer;

for(q = p; q!= NULL; q = q->next) {

memcpy(pBuffer, q->payload, q->len);

pBuffer +=q->len;

}

// signal thatpacket should be sent();

DM9000_SendPacket(Buffer, p->tot_len);

#if ETH_PAD_SIZE

pbuf_header(p,ETH_PAD_SIZE); /* reclaim the padding word */

#endif

LINK_STATS_INC(link.xmit);

return ERR_OK;

}

static struct pbuf * low_level_input(struct netif*netif)

{

struct pbuf*p, *q;

uint16_tBuffer[1514/2];

uint8_t*pBuffer;

int16_t len;

/* Obtain thesize of the packet and put it into the "len" variable. */

len =DM90000_ReceivePacket(Buffer);

if (len <=0) {

return NULL;

}

#if ETH_PAD_SIZE

len +=ETH_PAD_SIZE; /* allow room for Ethernet padding */

#endif

/* We allocatea pbuf chain of pbufs from the pool. */

p =pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

if (p != NULL){

#if ETH_PAD_SIZE

pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */

#endif

pBuffer =(uint8_t *)Buffer;

for(q = p; q!= NULL; q = q->next) {

memcpy(q->payload, pBuffer, q->len);

pBuffer+= q->len;

}

#if ETH_PAD_SIZE

pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */

#endif

LINK_STATS_INC(link.recv);

} else {

LINK_STATS_INC(link.memerr);

LINK_STATS_INC(link.drop);

}

return p;

}

void ethernetif_input(struct netif *netif)

{

struct eth_hdr*ethhdr;

struct pbuf*p;

/* movereceived packet into a new pbuf */

p =low_level_input(netif);

/* no packetcould be read, silently ignore this */

if (p == NULL)return;

/* points topacket payload, which starts with an Ethernet header */

ethhdr =p->payload;

switch(htons(ethhdr->type)) {

/* IP or ARPpacket? */

caseETHTYPE_IP:

caseETHTYPE_ARP:

#if PPPOE_SUPPORT

/* PPPoEpacket? */

caseETHTYPE_PPPOEDISC:

caseETHTYPE_PPPOE:

#endif /* PPPOE_SUPPORT */

if(netif->input(p, netif)!=ERR_OK) {

LWIP_DEBUGF(NETIF_DEBUG, ("e

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據媒體報道,騰訊和網易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數據產業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數據產業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數字經濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉