STM32F4 LAN8720以及LWIP的移植调试记录 (2)

背景

在硬件工程师完成了PCB和原理图设计后,根据正点原子的教程对例程进行修改,验证了硬件的正确性。
STM32F407和LAN8720调试记录.
正点原子 网络通信实验

下一步的工作需要在产品的板子上实现功能。
原产品采用W5500的硬TCP/IP协议方案。
调试路线尝试先从UDP回环开始。

约定

所有调用接口全部按照 lwip\src\include\lwip\sockets.h中描述,使能LWIP_COMPAT_SOCKETS宏,依照BSD socket风格进行封装。
API接口如下:

#define accept(a,b,c)         lwip_accept(a,b,c)
#define bind(a,b,c)           lwip_bind(a,b,c)
#define shutdown(a,b)         lwip_shutdown(a,b)
#define closesocket(s)        lwip_close(s)
#define connect(a,b,c)        lwip_connect(a,b,c)
#define getsockname(a,b,c)    lwip_getsockname(a,b,c)
#define getpeername(a,b,c)    lwip_getpeername(a,b,c)
#define setsockopt(a,b,c,d,e) lwip_setsockopt(a,b,c,d,e)
#define getsockopt(a,b,c,d,e) lwip_getsockopt(a,b,c,d,e)
#define listen(a,b)           lwip_listen(a,b)
#define recv(a,b,c,d)         lwip_recv(a,b,c,d)
#define recvfrom(a,b,c,d,e,f) lwip_recvfrom(a,b,c,d,e,f)
#define send(a,b,c,d)         lwip_send(a,b,c,d)
#define sendto(a,b,c,d,e,f)   lwip_sendto(a,b,c,d,e,f)
#define socket(a,b,c)         lwip_socket(a,b,c)
#define select(a,b,c,d,e)     lwip_select(a,b,c,d,e)
#define ioctlsocket(a,b,c)    lwip_ioctl(a,b,c)

调试记录

1. 板级驱动需要调整

第一个问题即发现使用新的硬件时,虽然IP能ping通,串口的console没有任何输出。经检查发现USART2和USART3所使用的GPIO口已经改变,需要另一套板级支持包,即BSP。

2. UDP收包异常

例程里用的是RAW API,暂时还没法使用标准化bsd style的接口。按照例程,去掉按键的操作,初始化udp端口。

    udppcb=udp_new();
    if(udppcb)
    { 
        IP4_ADDR(&rmtipaddr,lwipdev.remoteip[0],lwipdev.remoteip[1],lwipdev.remoteip[2],lwipdev.remoteip[3]);
        err=udp_connect(udppcb,&rmtipaddr,UDP_DEMO_PORT);
        if(err==ERR_OK)
        {
            err=udp_bind(udppcb,IP_ADDR_ANY,UDP_DEMO_PORT);
            if(err==ERR_OK)
            {
                udp_recv(udppcb,udp_demo_recv,NULL);
                Console::Instance()->printf("====== STATUS:Connected\r\n");
            }else res=1;
        }else res=1;        
    }else res=1;

其中UDP_DEMO_PORT为8089,LAN8720 IP地址为192.168.192.30 。
可以从console看到输出”===== STATUS:Connected”。
然而此时向192.168.192.30:8089发送一个UDP字节,程序并没有跳转到接收回调函数中。
通过wireshark抓包,内容如下:
STM32F4 LAN8720以及LWIP的移植调试记录 (2)_第1张图片
可以看到第一条报文,从192.15发往192.30。确实为UDP协议包。
第二条报文是192.30 回复192.15的报文,协议为ICMP。
ICMP协议的介绍
可以看到协议里指出,错误类型属于端口无法到达。
拿其他程序测试了一下,果然当目标设备的IP正确,而目标设备上没有对应的端口时,确实会回复ICMP报文。
可见问题出在端口初始化上。

3. 原厂例程测试

无奈之下只能和原子原本的例程对比。能够正常发送报文并接受消息。
在测试过程中无意中截到这样的报文:
STM32F4 LAN8720以及LWIP的移植调试记录 (2)_第2张图片
可以观察到,只有当原地址和目标地址均为8089时,ICMP才没有回错误报文。
当两者中任意一者不是8089时均会报错。
回去仔细查看代码,确实有两个地方用到了UDP_DEMO_PORT。
分别是

err = udp_connect(udppcb, &rmtipaddr, UDP_DEMO_PORT);

err = udp_bind(udppcb, IP_ADDR_ANY, UDP_DEMO_PORT);

一个绑定了本地的端口和IP,另一个绑定了远程设备的IP和端口。
其中udp_connect这个函数是之前没有用过的。LWIP的手册对该函数作了描述:
LwIP Application Developers Manual

Connected pcbs only receive data from the connected remote address, while unconected pcbs receive datagrams from any remote address.

因此经过connect的UDP端口将只接收绑定过的源地址源端口的报文。
尝试把udp_connect这句函数注释掉,果然所有报文都能顺利接收。

你可能感兴趣的:(通信接口,C++,单片机)