移植lwIP至U-Boot
来源:互联网 发布:matlab 初始化零矩阵 编辑:程序博客网 时间:2024/05/17 08:56
U-Boot是嵌入式系統上被廣為運用的boot loader,它擁有極為活躍的開發社群,也支援許多不同類型的CPU核心架構。U-Boot目前並不支援完整的TCP/IP,僅有限度地支援TFTP,方便開發者上傳韌體或是網路開機(BOOTP)。U-Boot身為boot loader非嵌入式作業系統,依據開放原始碼社群秉持地「精簡就是美」原則,不支援TCP/IP是可以理解的。萬一真的需要網路功能,移植一套完整的TCP/IP協定堆疊的任務雖然富有挑戰性,實務上亦是可行之道。
麻雀雖小五臟俱全的「lwIP」
lightweight IP(lwIP)是一個輕巧的開放原始碼之TCP/IP通訊協定之實作。lwIP首先由Adam Dunkels發表,目前則是以Kieran Mansley為計畫主持人,帶領開放原始碼社群進行該專案的維護與開發。
目前lwIP已實做的協定如下:
- IP (Internet Protocol) including packet forwarding over multiple network interfaces
- ICMP (Internet Control Message Protocol) for network maintenance and debugging
- IGMP (Internet Group Management Protocol) for multicast traffic management
- UDP (User Datagram Protocol) including experimental UDP-lite extensions
- TCP (Transmission Control Protocol) with congestion control, RTT estimation and fast recovery/fast retransmit
- Raw/native API for enhanced performance
- DNS (Domain names resolver)
- SNMP (Simple Network Management Protocol)
- DHCP (Dynamic Host Configuration Protocol)
- AUTOIP (for IPv4, conform with RFC 3927)
- PPP (Point-to-Point Protocol)
- ARP (Address Resolution Protocol) for Ethernet
- Optional Berkeley-like socket API
lwIP設計理念主要是希望於支援TCP/IP協定的同時,於執行時期也能精簡記憶體之運用,以達成支援小型的嵌入式裝置、平台或即時作業系統(RTOS)的目標;除此之外,lwIP也已經移植到眾多RTOS平台上,例如:eCos…等等。由此這些特性來看,使用lwIP搭配U-Boot是一個好的選擇。
lwIP移植步驟
lwIP的的核心部份由ANSI C撰寫,使用目前的GCC應該可以直接交叉編譯(cross compiling)。整體來說要將lwIP移植到不同平台上,只要完成三件工作即可。首先要決定lwIP的組態;接著,補完lwIP需要之OS抽象層的實作;最後,撰寫lwIP之網路卡驅動程式。
一、選擇你要的lwIP組態
移植lwIP的第一步,要先決定將要啟用之lwIP的功能。由於lwIP包含許多通訊協定堆疊的實作以及許多系統開發除錯(debug)相關的功能,有些功能可能暫時使用不到,我們可以選擇將之關閉。
首先,建立並編輯「lwipopts.h」。以下為範例:
lwipopts.h123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
#ifndef __LWIPOPTS_H__#define __LWIPOPTS_H__#define NO_SYS 1#define MEM_LIBC_MALLOC 1#define MEMP_MEM_MALLOC 0#define MEMP_SEPARATE_POOLS 0#define MEM_ALIGNMENT 4#define MEM_SIZE (4 * 1024 * 1024)#define MEMP_NUM_PBUF 1024#define MEMP_NUM_UDP_PCB 20#define MEMP_NUM_TCP_PCB 20#define MEMP_NUM_TCP_PCB_LISTEN 16#define MEMP_NUM_TCP_SEG 128#define MEMP_NUM_REASSDATA 32#define MEMP_NUM_ARP_QUEUE 10#define PBUF_POOL_SIZE 512#define LWIP_ARP 1#define LWIP_TCP 1#define LWIP_UDP 1#define LWIP_DHCP 1#define IP_REASS_MAX_PBUFS 64#define IP_FRAG_USES_STATIC_BUF 0#define IP_DEFAULT_TTL 255#define IP_SOF_BROADCAST 1#define IP_SOF_BROADCAST_RECV 1#define LWIP_ICMP 1#define LWIP_BROADCAST_PING 1#define LWIP_MULTICAST_PING 1#define LWIP_RAW 1#define TCP_WND (4 * TCP_MSS)#define TCP_MSS 1460#define TCP_SND_BUF (8 * TCP_MSS)#define TCP_LISTEN_BACKLOG 1#define LWIP_NETIF_STATUS_CALLBACK 1#define LWIP_NETIF_LINK_CALLBACK 1#define LWIP_NETIF_HWADDRHINT 1#define LWIP_NETCONN 0#define LWIP_SOCKET 0#define LWIP_STATS_DISPLAY 1#define MEM_STATS 0#define SYS_STATS 0#define MEMP_STATS 0#define LINK_STATS 0#define ETHARP_TRUST_IP_MAC 0#define ETH_PAD_SIZE 0#define LWIP_CHKSUM_ALGORITHM 2#define LWIP_TCP_KEEPALIVE 1#define MEMP_NUM_SYS_TIMEOUT 5// Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing#define TCP_KEEPIDLE_DEFAULT 10000UL // Default KEEPALIVE timer in milliseconds#define TCP_KEEPINTVL_DEFAULT 2000UL // Default Time between KEEPALIVE probes in milliseconds#define TCP_KEEPCNT_DEFAULT 9U // Default Counter for KEEPALIVE probesextern void* dma_memory_alloc(unsigned int size);extern void* dma_memory_calloc(unsigned int size, unsigned int number);extern void dma_memory_free(void* ptr);#define mem_init()#define mem_free dma_memory_free#define mem_malloc dma_memory_alloc#define mem_calloc(c, n) dma_memory_calloc((c) * (n))#define mem_realloc(p, sz) (p)#define LWIP_MEM_ALIGN(addr) ((void *)(((u32_t)(addr) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT - 1)))#define LWIP_DEBUG 0#define ETHARP_DEBUG LWIP_DBG_OFF#define NETIF_DEBUG LWIP_DBG_OFF#define PBUF_DEBUG LWIP_DBG_OFF#define API_LIB_DEBUG LWIP_DBG_OFF#define API_MSG_DEBUG LWIP_DBG_OFF#define SOCKETS_DEBUG LWIP_DBG_OFF#define ICMP_DEBUG LWIP_DBG_OFF#define INET_DEBUG LWIP_DBG_OFF#define IP_DEBUG LWIP_DBG_OFF#define IP_REASS_DEBUG LWIP_DBG_OFF#define RAW_DEBUG LWIP_DBG_OFF#define MEM_DEBUG LWIP_DBG_OFF#define MEMP_DEBUG LWIP_DBG_OFF#define SYS_DEBUG LWIP_DBG_OFF#define TCP_DEBUG LWIP_DBG_OFF#define TCP_INPUT_DEBUG LWIP_DBG_OFF#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF#define TCP_RTO_DEBUG LWIP_DBG_OFF#define TCP_CWND_DEBUG LWIP_DBG_OFF#define TCP_WND_DEBUG LWIP_DBG_OFF#define TCP_FR_DEBUG LWIP_DBG_OFF#define TCP_QLEN_DEBUG LWIP_DBG_OFF#define TCP_RST_DEBUG LWIP_DBG_OFF#define UDP_DEBUG LWIP_DBG_OFF#define TCPIP_DEBUG LWIP_DBG_OFF#define PPP_DEBUG LWIP_DBG_OFF#define SLIP_DEBUG LWIP_DBG_OFF#define DHCP_DEBUG LWIP_DBG_OFF#endif /* __LWIPOPTS_H__ */
在lwipopts.h中,我們可以選擇開啟或關閉某些lwIP的模組、決定debug訊息的層級以及lwIP執行時的記憶體配置模型。尤有甚者,U-Boot缺乏多工、多執行緒能力,僅能支援lwIP提供之Raw API,所以需要關閉BSD socket支援。關於每個選項的意義,可以交叉參考「lwip/src/include/lwip/opt.h」裡的說明。
二、移植lwIP之OS抽象層
移植之抽象層至U-Boot並不會太複雜,且U-Boot並沒有多執行緒及其衍生之關於資源競爭(race condition)的議題,移植工程的複雜度可以大幅減輕。所以在這個階段,基本上我們只要解決C compiler的互通性問題即可。lwIP將與此議題相關的選項歸納於cc.h。
cc.h1234567891011121314151617181920212223242526272829303132333435363738394041424344
#ifndef __ARCH_CC_H__#define __ARCH_CC_H__// Includes definition of macro to do printfextern int printf(const char *fmt, ...);#define BYTE_ORDER LITTLE_ENDIAN#define LWIP_PLATFORM_BYTESWAP 0typedef unsigned char u8_t;typedef char s8_t;typedef unsigned short u16_t;typedef short s16_t;typedef unsigned int u32_t;typedef int s32_t;typedef unsigned int* mem_ptr_t;#define LWIP_ERR_T int/* Define (sn)printf formatters for these lwIP types */#define U16_F "u"#define S16_F "d"#define X16_F "x"#define U32_F "u"#define S32_F "d"#define X32_F "x"/* Compiler hints for packing structures */#define PACK_STRUCT_FIELD(x) x#define PACK_STRUCT_STRUCT __attribute__((packed))#define PACK_STRUCT_BEGIN#define PACK_STRUCT_END/* Plaform specific diagnostic output */#define LWIP_PLATFORM_DIAG(x, ...) do { \ printf(x, ##__VA_ARGS__); \ } while (0)#define LWIP_PLATFORM_ASSERT(x) do { \ printf("Assert \"%s\" failed at line %d in %s\n", \ x, __LINE__, __FILE__); \ } while (0)#endif /* __ARCH_CC_H__ */
移植時,需指定平台的「BYTE_ORDER」,可為”LITTLE_ENDIAN”或”BIG_ENDIAN”,與此選項相依的有「LWIP_PLATFORM_BYTESWAP」。若移植平台為32-bits little-endian ARM,將BYTE_ORDER設為LITTLE_ENDIAN,LWIP_PLATFORM_BYTESWAP指定為0即可。相關設定,可以參考範例。
三、移植timer相關函式
移植工作至此,除了驅動程式的撰寫外,僅剩下timer的移植。由於lwIP之通訊協定堆疊大多仰賴timer,因此timer的移植於lwIP重要性不言而喻。以U-Boot來說,關於timer的運用並無標準之API,彈性很大,移植者可以視平台狀況啟動timer,並撰寫合適的函式。有關此類函式,可集中於sys_arch.c
sys_arch.c123456789
#include "lwip/sys.h"extern unsigned int timer2_now();extern unsigned int timer2_interval();u32_t sys_now(void){ return timer2_now() * timer2_interval();}
四、撰寫網路卡驅動程式
lwIP透過網路卡驅動程式由實體層收送封包,關於驅動程式的撰寫方式,可參考lwIP原始碼提供之「netif/ethernetif.c」。
結論
整體來說,移植lwIP至U-Boot並不複雜,但是相關文件不多,需要些許耐心地閱讀甚至追蹤、觀察原始碼的運作。但由於lwIP設計完備,些許心力即可換來與U-Boot的良好搭配,在在顯示open source的彈性與優點。
- 移植lwIP至U-Boot
- 准备移植u-boot至LPC2200
- XSBase255B -- u-boot移植
- u-boot移植心得
- u-boot移植日记
- U-BOOT移植
- 移植u-boot
- u-boot移植三
- U-BOOT移植总结
- U-boot移植说明
- at91rm9200移植u-boot
- lpc2210 u-boot移植
- U-BOOT移植小解
- U-BOOT全线移植
- u-boot移植s3c2410
- IXP425 U-boot移植
- u-boot移植手册
- U-boot移植过程
- JS中的Math对象
- 调式子进程方法
- [安卓]2dx android font 相关问题*
- Android设计模式系列(1)--SDK源码之组合模式
- nsdate1016
- 移植lwIP至U-Boot
- Javascript闭包篇(Closure)
- Emacs模式(Mode)
- android Edittext 输入法软键盘屏蔽,有光标
- Powershell: Read in file without converting into string array
- maven build lifecycle
- IOS 由RGB、UIColor生成UIImage
- 【树形贪心】【UVA1267】Network
- color.xml