本文轉自公眾號歡迎關注
基于DWC_ether_qos的以太網驅動開發-無OS環境移植LWIP (qq.com)
https://mp.weixin.qq.com/s/u1Bv6s_oh7jZ3sjS3nxbEA
一.前言
前面我們實現了數據的收發,現在我們就可以移植協議棧了。LWIP是一個適合嵌入式平臺的著名的輕量級協議棧,我們這一篇就來無OS環境移植LWIP,下一篇再基于RTOS移植LWIP。
二.源碼
LWIP官網如下
https://savannah.nongnu.org/projects/lwip/
下載源碼git clone https://git.savannah.nongnu.org/git/lwip.git
LWIP的代碼可移植性非常好src下的源碼完全可移植不需要任何修改,移植參考contribports下的模板即可,已經有了unix,freertos,win32的移植可參考。
三.NONEOS移植
3.1添加文件
將src復制到自己的工程路徑
然后添加一個port文件夾和src并列,無OS移植就添加一個noneos子目錄。
.
其中port如下,相關的文件可以從其他port下復制過來修改。
ports/
添加源文件
將src文件夾復制到自己的工程,添加源碼
src/api下所有c
src/core下所有c
src/core/ipv4下所有c
src/core/ipv6下所有c
src/netif/ethernet.c,netif下還有其他很多接口實現,用到可以使用對應的,我們這里只需要使用ethernet.c
頭文件路徑
將目錄src/include,ports/noneos/include添加到頭文件包含路徑。
3.2 移植文件
修改修改的文件
Ports下文件是需要修改的
ports/
lwipopts.h
配置文件,使用宏對LWIP進行配置。
Cc.h
必須位于arch目錄下
Perf.h/perf.c
portethif.h/portethif.c
sys_arch.c
錯誤碼
lwipopts.h中定義#define LWIP_PROVIDE_ERRNO 1則
src/include/lwip/errno.h中定義錯誤編碼和變量errno。
(我們這里使用該方式)
否則cc.h中需要include 或者自己實現錯誤碼宏定義和errno變量。
src/include/lwip/errno.h中可知,如果已經有了對應的頭文件則
可以定義LWIP_ERRNO_STDINCLUDE則自動#include
否則錯誤頭文件由LWIP_ERRNO_INCLUDE定義。
隨機數產生接口
如果有stdint.h則直接使用庫函數,否則自行實現
Cc.h中
#include
extern unsigned int lwip_port_rand(void);
#define LWIP_RAND() (lwip_port_rand())
portethif.c中實現
#include
uint32_t lwip_port_rand(void)
{
return (uint32_t)rand();
}
斷言
不使用斷言,Cc.h中定義
#define LWIP_NOASSERT 1
如果定義了LWIP_NOASSERT則LWIP_ASSERT為空
如果使用斷言,沒有定義LWIP_NOASSERT
則src/lib/lwip/lwip/src/include/lwip/debug.h中
#define LWIP_ASSERT(message, assertion) do { if (!(assertion)) {
LWIP_PLATFORM_ASSERT(message); }} while(0)
此時需要實現LWIP_PLATFORM_ASSERT宏,
如果沒有定義LWIP_PLATFORM_ASSERT宏則默認使用printf
則src/lib/lwip/lwip/src/include/lwip/arch.h中
#define LWIP_PLATFORM_ASSERT(x) do {printf("Assertion "%s" failed at line %d in %sn",
x, __LINE__, __FILE__); fflush(NULL); abort();} while(0)
atoi
Stdlib.h中有實現,如果沒有該庫可以如下源碼實現
/*----------------------------------------------*/
lwip/ports/noneos/sys_arch.c下實現
u32_t sys_now(void)返回mS的全局時間。
存儲管理
lwip/ports/noneos/include/lwipopts.h中配置
堆管理
LWIP_RAM_HEAP_POINTER定義堆地址,必須要空間足夠大。
未定義則mem.c中定義大數組ram_heap
MEM_ALIGNMENT設置堆對齊
MEM_SIZE設置堆字節大小
lwip_init->mem_init時初始化,代碼位于mem.c
內存池
pbuf.c調用memp.的接口
lwip_init->memp_init時初始化,代碼位于memp.c
lwip/priv/memp_priv.h中定義各個組件需要的內存池
lwip/ports/noneos/include/lwipopts.h中MEMP_NUM_xxx定義大小。
性能測試接口
lwipopts.h中如果配置LWIP_PERF宏則
arch/perf.h需要實現兩個宏
PERF_START
PERF_STOP
在perf.c/perf.h中具體實現
否則這兩個宏自動置空。
一個參考實現如下
Perf.h
#ifndef LWIP_ARCH_PERF_H
perf.c
#include
可以看到指定接口執行時間打印如下
系統層接口
無OS時不需要實現相關接口
src/lib/lwip/ports/noneos/include/lwipopts.h中
#define NO_SYS 1
NO_SYS=1時不能使用socket相關接口
#define LWIP_NETCONN 0
#define LWIP_SOCKET 0
以太網收發接口相關
實現以下幾個函數即可
實現初始化函數lwip_port_eth_init
在netif_add(&netif, (const ip_addr_t *)&ipaddr, (const ip_addr_t *)&netmask, (const ip_addr_t *)&gw, NULL, &lwip_port_eth_init, eernet_input);時調用執行lwip_port_eth_init
實現low_level_output,在執行lwip_port_eth_init時綁定到回調函數
netif->linkoutput = low_level_output;
收到一包數據時調用
lwip_port_eth_input
Portethif.h
#ifndef LWIP_TAPIF_H
Portethif.c
#include
四.測試
以下忽略了平臺相關的操作,比如以太網驅動初始化等,僅保留lwip相關內容。
#include "lwip/netif.h"
收到包時調用
lwip_port_eth_input(&netif, p_data, len);
初始化與主循環
/* 在PHY初始化后,尤其是RXC輸出之后才調用,因為GMAC復位需要RXC */
使用網口調試工具,發送數據收到后原樣返回。
五.總結
LWIP代碼移植性非常好,無OS支持也非常好,移植只需要實現平臺相關的配置和宏,實現網口收發接口即可。
審核編輯 黃宇
-
以太網
+關注
關注
40文章
5419瀏覽量
171594 -
LwIP
+關注
關注
2文章
86瀏覽量
27146 -
驅動開發
+關注
關注
0文章
130瀏覽量
12072
發布評論請先 登錄
相關推薦
評論