本次實驗參考自原子已經移植好的 LWIP(版本:1.4.1)模板來進行的,感謝!
由於要做的一個小項目要用到網絡通信,而且想要加上 UC/OS-II 跑個系統,感覺 LWIP 這個輕量級的 IP 協議棧再合適不過了,故瀏覽了下官方的下載地址(http://ftp.twaren.net/Unix/NonGNU/lwip/),發現此時的最新版是 2.0.3,下載下來對比原子的 1.4.1 版本,覺得新版本有以下優點便於移植:
1.4.1 版本中:
mempsize=memp_get_memorysize();
memp_memory=mymalloc(SRAMIN,mempsize);
ramheapsize=LWIP_MEM_ALIGN_SIZE(MEM_SIZE)+2*LWIP_MEM_ALIGN_SIZE(4*3)+MEM_ALIGNMENT;
ram_heap=mymalloc(SRAMIN,ramheapsize);
手動來分配 memp_memory 和 ram_heap 的內存,需要自己實現內存的動態分配(malloc free)等操作;
2.0.3 版本中:
const struct memp_desc* const memp_pools[MEMP_MAX] = {
#define LWIP_MEMPOOL(name,num,size,desc) &memp_ ## name,
#include "lwip/priv/memp_std.h"
};
#define LWIP_DECLARE_MEMORY_ALIGNED(variable_name, size) u8_t variable_name[LWIP_MEM_ALIGN_BUFFER(size)]
LWIP_DECLARE_MEMORY_ALIGNED(ram_heap, MEM_SIZE_ALIGNED + (2U*SIZEOF_STRUCT_MEM));
已經在 LWIP 的內核中完成了內存的分配,便於移植。
由於只是剛接觸 LWIP,目前只是發現這個膚淺的優點,但新版本肯定優化了很多內容,通過源碼中的 doc 文檔可以得知,以后學習到會再次記錄。
大體的移植步驟(細節已經不記得了....)
\1. 創建 LWIP_arch\arch 文件夾,加入以下文件(來自原子的 LWIP 例程):

\2. 將原子的 lwipopts.h 文件拷入 LWIP_include\lwip 目錄下
\3. 將源碼加入到 uc/os-ii 工程,如下圖所示:


enc28j60.c 與 spi.c 文件導入原子的文件即可,其它皆為 LWIP 源文件。
\4. 將 arch.h 中的 LWIP_NO_STDINT_H 值置為 1 以啟用 cc.h 文件。
\5. 導入 sys_arch.c 文件,屏蔽掉其中的 malloc 相關函數,自己分配靜態內存即可,屏蔽其中的 sys_msleep 函數,使用新版本中自帶的 sys_msleep 函數。
\6. 包含各目錄下的頭文件,其中有些文件需要注意: 例如 #include "lwip/opt.h" 只需要包含 lwip 文件夾所在目錄即可。
編寫 lwip_app.c 函數
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/init.h"
#include "lwip/tcpip.h"
#include "lwip/ip_addr.h"
#include "delay.h"
#include "usart.h"
#include "enc28j60.h"
#include "lwip_app.h"
#include <stdio.h>
__lwip_dev lwipdev;
struct netif lwip_netif;
extern err_t ethernetif_input(struct netif *netif);
extern err_t ethernetif_init(struct netif *netif);
void lwip_pkt_handle(void)
{
ethernetif_input(&lwip_netif);
}
void lwip_default_ip_set(__lwip_dev *lwipx)
{
//初步使用靜態方式分配 IP 地址,以后再啟用 DHCP
lwipx->remoteip[0]=192;
lwipx->remoteip[1]=168;
lwipx->remoteip[2]=0;
lwipx->remoteip[3]=124;
lwipx->mac[0]=enc28j60_dev.macaddr[0];
lwipx->mac[1]=enc28j60_dev.macaddr[1];
lwipx->mac[2]=enc28j60_dev.macaddr[2];
lwipx->mac[3]=enc28j60_dev.macaddr[3];
lwipx->mac[4]=enc28j60_dev.macaddr[4];
lwipx->mac[5]=enc28j60_dev.macaddr[5];
lwipx->ip[0]=192;
lwipx->ip[1]=168;
lwipx->ip[2]=0;
lwipx->ip[3]=123;
lwipx->netmask[0]=255;
lwipx->netmask[1]=255;
lwipx->netmask[2]=255;
lwipx->netmask[3]=0;
lwipx->gateway[0]=192;
lwipx->gateway[1]=168;
lwipx->gateway[2]=0;
lwipx->gateway[3]=1;
lwipx->dhcpstatus=0;
}
u8_t lwip_app_init(void)
{
struct netif *Netif_Init_Flag;
struct ip4_addr ipaddr;
struct ip4_addr netmask;
struct ip4_addr gw;
if(ENC28J60_Init())return 2;
tcpip_init(NULL,NULL);
lwip_default_ip_set(&lwipdev);
IP4_ADDR(&ipaddr,lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
IP4_ADDR(&netmask,lwipdev.netmask[0],lwipdev.netmask[1] ,lwipdev.netmask[2],lwipdev.netmask[3]);
IP4_ADDR(&gw,lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
printf("網卡的MAC地址為:................%d.%d.%d.%d.%d.%d\r\n",lwipdev.mac[0],lwipdev.mac[1],lwipdev.mac[2],lwipdev.mac[3],lwipdev.mac[4],lwipdev.mac[5]);
printf("網卡的IP地址為:........................%d.%d.%d.%d\r\n",lwipdev.ip[0],lwipdev.ip[1],lwipdev.ip[2],lwipdev.ip[3]);
printf("子網掩碼:..........................%d.%d.%d.%d\r\n",lwipdev.netmask[0],lwipdev.netmask[1],lwipdev.netmask[2],lwipdev.netmask[3]);
printf("默認網關:..........................%d.%d.%d.%d\r\n",lwipdev.gateway[0],lwipdev.gateway[1],lwipdev.gateway[2],lwipdev.gateway[3]);
Netif_Init_Flag = netif_add(&lwip_netif,&ipaddr,&netmask,&gw,NULL,ðernetif_init,&tcpip_input);
if(Netif_Init_Flag != NULL)
{
netif_set_default(&lwip_netif);
netif_set_up(&lwip_netif);
printf("\r\n******** Netif up ok! ********\r\n");
}
return 0;
}
運行效果
將 lwip_app_init() 接口加入到 main 主函數,編譯下載運行,效果如下所示:
串口收到以下信息:

ping 測試:

