STM32之LWIP网络协议栈移植
1.LWIP介绍
??lwip是瑞典计算机科学院网络嵌入式系统小组(SICS)的Adam Dunkels(亚当·邓克尔) 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持 TCP 协议主要功能的基础上减少对RAM的占用。 ??LwIP是Light Weight(轻型)IP 协议,有无操作系统的支持都可以运行。LwIP 实现的重点是在保持TCP协议 主要功能的基础上减少对RAM的占用,它只需十几KB的RAM和 40K左右的ROM就可以运行,这使LwIP协议栈适合在低端的嵌入式系统中使用。lwip提供三种API: ??? ?RAW API ??? ?(NETCONN)lwip API ??? ?BSD API。
2.LWIP源码下载
源码下载地址:LWIP源码
3 LWIP源码移植
DM9000网卡驱动参考:https://blog.csdn.net/weixin_44453694/article/details/123119060
??这里以1.4.1为例。 ?1.解压文件
?2.打开已完成DM9000驱动的工程,在工程中创建lwip文件夹,在lwip文件夹中创建src文件夹和lwip1.4_config文件夹: ?3.将lwip-1.4.1源码中的src中所有文件复制到用户创建的src中: ?4.复制contrib中文件 ?5.删除不必要文件
?6.打开工程,添加.c文件到工程中 ?7.添加.h文件路径 ?8.编译工程 ?9.修改sys_arch.c文件,只保留下面函数,其它全部删除。 ?10.修改lwipopts.h文件 ?11.修改ethernetif.c文件
4.LWIP协议栈使用示例之 — 获取动态IP
??在LWIP_confg目录下创建lwip_config.c和lwip_config.h文件 ??lwip_config.c文件:
#include "lwip_config.h"
#include "lwip/ip_addr.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "lwip/dhcp.h"
#include "lwip/tcp_impl.h"
extern err_t ethernetif_init(struct netif *netif);
extern void ethernetif_input(struct netif *netif);
struct netif lwip_netif;
void LWIP_Config_Init(void)
{
ip_addr_t ip_addr={0};
ip_addr_t netmask={0};
ip_addr_t gw={0};
lwip_init();
netif_add(&lwip_netif,&ip_addr,&netmask,&gw,NULL,ethernetif_init,ethernet_input);
netif_set_default(&lwip_netif);
netif_set_up(&lwip_netif);
dhcp_start(&lwip_netif);
}
u32 LWIP_TCP_TIME_CNT=0;
u32 LWIP_ARP_TIME_CNT=0;
u32 LWIP_DHCP_TIME_CNT=0;
u32 LWIP_UPDATE_DHCP_TIME_CNT=0;
u8 lwip_dhcp_stat=0;
void LWIP_DataUpdata(void)
{
if(LWIP_TCP_TIME_CNT>=TCP_TMR_INTERVAL)
{
LWIP_TCP_TIME_CNT=0;
tcp_tmr();
}
if(LWIP_ARP_TIME_CNT>=ARP_TMR_INTERVAL)
{
LWIP_ARP_TIME_CNT=0;
etharp_tmr();
}
if(LWIP_DHCP_TIME_CNT>=DHCP_FINE_TIMER_MSECS )
{
LWIP_DHCP_TIME_CNT=0;
dhcp_fine_tmr();
}
if(LWIP_UPDATE_DHCP_TIME_CNT>=DHCP_COARSE_TIMER_MSECS)
{
LWIP_UPDATE_DHCP_TIME_CNT=0;
dhcp_coarse_tmr();
}
ethernetif_input(&lwip_netif);
if(lwip_dhcp_stat==0)
{
LWIP_GetDHCP_Addr();
}
}
void LWIP_GetDHCP_Addr(void)
{
char buff[200];
u32 ip_addr;
u32 netmask;
u32 gw;
ip_addr=lwip_netif.ip_addr.addr;
netmask=lwip_netif.netmask.addr;
gw=lwip_netif.gw.addr;
if(ip_addr!=0)
{
lwip_dhcp_stat=1;
printf("IP地址:%d.%d.%d.%d\r\n",(ip_addr>>0)&0xff,(ip_addr>>8)&0xff,(ip_addr>>16)&0xff,(ip_addr>>24)&0xff);
snprintf(buff,sizeof(buff),"IP地址:%d.%d.%d.%d",(ip_addr>>0)&0xff,(ip_addr>>8)&0xff,(ip_addr>>16)&0xff,(ip_addr>>24)&0xff);
LCD_ShowStr(30,30+20*4,16,(u8 *)buff);
printf("子网掩码:%d.%d.%d.%d\r\n",(netmask>>0)&0xff,(netmask>>8)&0xff,(netmask>>16)&0xff,(netmask>>24)&0xff);
snprintf(buff,sizeof(buff),"子网掩码:%d.%d.%d.%d\r\n",(netmask>>0)&0xff,(netmask>>8)&0xff,(netmask>>16)&0xff,(netmask>>24)&0xff);
LCD_ShowStr(30,30+20*5,16,(u8 *)buff);
printf("网关:%d.%d.%d.%d\r\n",(gw>>0)&0xff,(gw>>8)&0xff,(gw>>16)&0xff,(gw>>24)&0xff);
snprintf(buff,sizeof(buff),"网关:%d.%d.%d.%d\r\n",(gw>>0)&0xff,(gw>>8)&0xff,(gw>>16)&0xff,(gw>>24)&0xff);
LCD_ShowStr(30,30+20*6,16,(u8 *)buff);
}
}
5.主函数
#include "dm9000.h"
#include "lwip_config.h"
u8 dm9000_tx_buff[64]={0x11,0x22,0x33,0x44,0x55};
u8 dm9000_rx_buff[1024];
int main()
{
char buff[200];
u8 stat;
Beep_Init();
Led_Init();
Key_Init();
W25Q64_Init();
Usartx_Init(USART1,115200,72);
TIMx_Init(TIM2,72,20*1000);
IIC_Init();
printf("初始化完成\r\n");
NT35310_Init();
LCD_ShowStr(30,30,16,"DM9000初始化中。。。");
if(DM9000_Init()==0)
{
printf("DM9000初始化成功\r\n");
LCD_ShowStr(30,30+20,16,"DM9000\t OK!");
}
else
{
printf("DM9000初始化失败\r\n");
LCD_ShowStr(30,30+20,16,"DM9000\t ERR!");
}
LCD_ShowStr(128,30+20*2,16,"网卡信息");
stat=DM9000_Get_SpeedAndDuplex();
if(stat!=0xff)
{
printf("网卡速度:%d Mbps 模式:%s\r\n",(stat&0x02)?10:100,(stat&0x01)?"全双工":"半双工");
snprintf(buff,sizeof(buff),"网卡速度:%d MHZ\t %s",(stat&0x02)?10:100,(stat&0x01)?"全双工":"半双工");
LCD_ShowStr(30,30+20*3,16,(u8 *)buff);
}
else
{
printf("DM9000网卡状态信息获取失败!\r\n");
LCD_ShowStr(30,30+20*3,16,(u8 *)"获取网卡信息失败!");
}
LWIP_Config_Init();
TIMx_Init(TIM6,72,1000);
TIM6->CR1|=1<<0;
while(1)
{
LWIP_DataUpdata();
}
}
6.运行效果
参考示例:https://download.csdn.net/download/weixin_44453694/82220780
|