APM32F4在RT-Thread系统上使用LwIP网络功能—基于RT-Thread Studio环境
   
RT-Thread Studio 是RTT官方的一款集成开发环境,可以很方便的进行RT-Thread实时系统的程序开发,而且对应RT-Thread系统常用的组件可以进行图形化配置,非常的方便。
    RT-Thread Studio可以访问官网
    
     RT-Thread Studio 下载地址
    
    ,在官网下载最新的 RT-Thread Studio 软件安装包。
   
下面基于 RT-Thread Studio ,把 LwIP 网络协议栈和RT-Thread系统移植到 APM32F4 上运行。
    
    
    1. 创建APM32F4的工程项目
   
1、首先点击新建RT-Thread项目
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4IecIpKB-1666625339065)(../picture/image-20221024215344825.png)]](https://img-blog.csdnimg.cn/ab43de6701064bcdaeb4b9d71530ca06.png) 
   
2、然后选择下面的配置,如果你的RTT Studio还没有APM32F4的软件包的话,选择添加更多资源,然后找到geehy厂商的软件包,然后安装即可。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2RXdM7Pf-1666625339066)(../picture/image-20221024215616541.png)]](https://img-blog.csdnimg.cn/872bc50135c54316b60e99d585b82e81.png) 
   
上面的一些配置可以看自己板子的实际情况进行选择,比如可以选择其他串口作为控制台,或者选择其他调试模式等等。最后点击完成即可。
    
    
    2. 编译下载生成的基本工程项目
   
点击完成之后,就可以在左边的资源管理器看到生成的项目文件了,如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OsIxDd0r-1666625339066)(../picture/image-20221024220110372.png)]](https://img-blog.csdnimg.cn/5484b397ed20447c9802dfe7333bf848.png) 
   
我们可以点击编译,可以看到编译完成没有任何警告和错误。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IuQh8Rdu-1666625339066)(../picture/image-20221024220158710.png)]](https://img-blog.csdnimg.cn/e1d7bb707c4b469596437ea63f0ac9eb.png) 
   
这个时候,是可以把程序下载到我们的板子上运行的。下载程序后,打开串口终端软件,可以看到RT-Thread打印的信息,如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X1dhm9Hd-1666625339066)(../picture/image-20221024220405063.png)]](https://img-blog.csdnimg.cn/1e025dabd3fc4e6fa68b4ae03e9d8ec3.png) 
   
其中,程序会不断打印 Hello … 字符串,这是因为Main函数里面输出的打印,如果觉得占用了控制台可以把该语句屏蔽。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AEBlHDKE-1666625339067)(../picture/image-20221024220542166.png)]](https://img-blog.csdnimg.cn/a4cd20b30a7e4cb89b23d463859256c9.png) 
   
    
    
    3. 解决shell不能输入字符bug
   
这时,我们在串口终端发现,shell不能接收字符输入。这是一个bug,原因就是串口的GPIO配置有问题,我们把下面文件函数修改一下即可:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fxvslNXH-1666625339067)(../picture/image-20221024220918532.png)]](https://img-blog.csdnimg.cn/a1615d386687423e927f43196f720304.png) 
   
修改完之后,在重新编译下载,shell就可以正常输入字符、命令了,如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g8OXUoKT-1666625339067)(../picture/image-20221024221109120.png)]](https://img-blog.csdnimg.cn/aa0f05855a594e86acb131d69995c382.png) 
   
    
    
    4. 使能网络接口设备和LwIP
   
    双击打开配置文件
    
     RT-Thread Settings
    
    , 然后找到组件这里,使能网络接口设备和LwIP堆栈。
   
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DBAmjr95-1666625339068)(../picture/image-20221024221847519.png)]](https://img-blog.csdnimg.cn/21dff39d5a864ab3b152a44dd3adbaa5.png) 
   
其中,我们点击使能之后,里面还有更详细的细节配置可供用户进行配置,比如是否使用DHCP进行动态获取IP地址等,这里我设置为静态IP,因为我没用插路由器。
然后点击保存后,再重新进行编译,可以看到没有任何警告和错误。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9eD3gA5Q-1666625339068)(../picture/image-20221024222419194.png)]](https://img-blog.csdnimg.cn/675d0ebda7804fe7ab7ae6d4825a026c.png) 
   
这个时候,我们其实可以下载程序运行了的,但是网络功能是还不能正常使用的,因为底层的网络驱动文件还没编写。
    下载程序后,在终端输入
    
     ifconfig
    
    命令,可以看到说网络设备有错误,如下:
   
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YjPSc3y0-1666625339069)(../picture/image-20221024222744222.png)]](https://img-blog.csdnimg.cn/ed0fd741462840e0869e0c5f49ab959d.png) 
   
    
    
    5. 添加RTT的网络驱动文件
   
这个驱动文件如果bsp包里面有的话,应该是可以配置加入 RTT Studio 里面的吧,但是APM32并没有这个文件的支持,所以只能我们自己编写这个网络驱动文件了,可以参考下面RTT官方文档的介绍,看看需要我们提供什么样的接口函数。
    这里,我已经提前写好了这个文件,分别是
    
     drv_eth.c
    
    和
    
     drv_eth.h
    
    。我们把这两个文件复制到工程目录的drivers目录下。
   
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ssuM8lOb-1666625339069)(../picture/image-20221024223511374.png)]](https://img-blog.csdnimg.cn/5979c36ae8d841988dd5f3c73abcac43.png) 
   
    
    
    6. 然后打开 BSP_USING_ETH 宏定义
   
我们在 board.h 文件中,打开 BSP_USING_ETH 这个宏定义,以及定义 phy 物理芯片的型号(根据自己板子的芯片类型选择),如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PCyPovfl-1666625339069)(../picture/image-20221024223842262.png)]](https://img-blog.csdnimg.cn/0ce9e8bc0cea4757a0eeeef5791fef87.png) 
   
定义了 BSP_USING_ETH 和 PHY_USING_DP83848C 宏定义后,就相当于把 drv_eth.c 文件内容开启了。这时全部重新编译,然后可以看到超级多的报错。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A2u3UOzg-1666625339070)(../picture/image-20221024224037808.png)]](https://img-blog.csdnimg.cn/b835d3567b6f45dbadd3970732be5d28.png) 
   
这些报错不要被吓到了,其实都是因为缺少文件造成的。
    
    
    7. 添加缺少的文件到工程目录中
   
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zueiAfBL-1666625339070)(../picture/image-20221024224513533.png)]](https://img-blog.csdnimg.cn/c13d79739bfe423ca91af4a4791277a0.png) 
   
我们打开右边的文件资源管理器,查看芯片的标准外设驱动库,可以看到并没有 apm32f4xx_eth.c 文件,这应该是 RTT Studio 没有合并进去吧。这个需要我们去geehy的官网下载f4的SDK包,然后把网口外设的标准驱动文件复制到这个目录下(包括头文件)。
然后再在drv_common.h文件中,添加下面两句语句:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PDWSFV9O-1666625339070)(../picture/image-20221024224751100.png)]](https://img-blog.csdnimg.cn/9e242aaea5304052894d7d9806260074.png) 
   
然后这时,全部重新编译。
    
    
    8. 添加 phy_reset 和 ETH_GPIO_Configuration 函数
   
上面全部重新编译,然后就只有3个报错了,如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XDoJth9B-1666625339071)(../picture/image-20221024225235407.png)]](https://img-blog.csdnimg.cn/10ffc4ab156f4aaabe17fe46d04f05e1.png) 
   
报错提示说没有phy_reset 和 ETH_GPIO_Configuration 这两个函数,这两个函数实际上时 drv_eth.c 文件要用到的,主要是复位phy芯片和初始化MCU的以太网外设的GPIO口,我们独立出来就是要用户去添加的,这里我已经写好了针对我们板子硬件的函数。
在board.c文件中添加上面两个函数:
phy_reset 函数:
/*
 * phy reset
 */
void phy_reset(void)
{
    /* PHY RESET PIN: PD11 */
    GPIO_Config_T GPIO_ConfigStruct;
    GPIO_ConfigStruct.mode  = GPIO_MODE_OUT;
    GPIO_ConfigStruct.speed = GPIO_SPEED_2MHz;
    GPIO_ConfigStruct.otype = GPIO_OTYPE_PP;
    GPIO_ConfigStruct.pupd  = GPIO_PUPD_NOPULL;
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOD);
    GPIO_ConfigStruct.pin = GPIO_PIN_11;
    GPIO_Config(GPIOD, &GPIO_ConfigStruct);
    GPIO_ResetBit(GPIOD, GPIO_PIN_11);
    rt_thread_delay(2);
    GPIO_SetBit(GPIOD, GPIO_PIN_11);
    rt_thread_delay(2);
}
ETH_GPIO_Configuration 函数:
/* MII/RMII Media interface selection */
//#define MII_MODE
#define RMII_MODE
/*
 * GPIO Configuration for ETH
 */
void ETH_GPIO_Configuration(void)
{
    GPIO_Config_T GPIO_ConfigStruct;
    /* Enable SYSCFG clock */
    RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
    /* Enable GPIOs clocks */
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA | RCM_AHB1_PERIPH_GPIOC | RCM_AHB1_PERIPH_GPIOG);
    /* MII/RMII Media interface selection */
#if defined(MII_MODE)     /* Mode MII. */
    SYSCFG_ConfigMediaInterface(SYSCFG_INTERFACE_MII);
#elif defined(RMII_MODE)  /* Mode RMII. */
    SYSCFG_ConfigMediaInterface(SYSCFG_INTERFACE_RMII);
#endif
    /*********************** Ethernet pins configuration ***************************/
    /*
        ETH_MDIO -------------------------> PA2
        ETH_MDC --------------------------> PC1
        ETH_MII_RX_CLK/ETH_RMII_REF_CLK---> PA1
        ETH_MII_RX_DV/ETH_RMII_CRS_DV ----> PA7
        ETH_MII_RXD0/ETH_RMII_RXD0 -------> PC4
        ETH_MII_RXD1/ETH_RMII_RXD1 -------> PC5
        ETH_MII_TX_EN/ETH_RMII_TX_EN -----> PG11
        ETH_MII_TXD0/ETH_RMII_TXD0 -------> PG13
        ETH_MII_TXD1/ETH_RMII_TXD1 -------> PG14
        **** Just for MII Mode ****
        ETH_MII_CRS ----------------------> PA0
        ETH_MII_COL ----------------------> PA3
        ETH_MII_TX_CLK -------------------> PC3
        ETH_MII_RX_ER --------------------> PB10
        ETH_MII_RXD2 ---------------------> PB0
        ETH_MII_RXD3 ---------------------> PB1
        ETH_MII_TXD2 ---------------------> PC2
        ETH_MII_TXD3 ---------------------> PB8
    */
    /* Configure PC1, PC4 and PC5 */
    GPIO_ConfigStruct.pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
    GPIO_ConfigStruct.speed = GPIO_SPEED_100MHz;
    GPIO_ConfigStruct.mode  = GPIO_MODE_AF;
    GPIO_ConfigStruct.otype = GPIO_OTYPE_PP;
    GPIO_ConfigStruct.pupd  = GPIO_PUPD_NOPULL;
    GPIO_Config(GPIOC, &GPIO_ConfigStruct);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_1, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_4, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_5, GPIO_AF_ETH);
    /* Configure PG11, PG13 and PG14 */
    GPIO_ConfigStruct.pin =  GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
    GPIO_Config(GPIOG, &GPIO_ConfigStruct);
    GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_11, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_13, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOG, GPIO_PIN_SOURCE_14, GPIO_AF_ETH);
    /* Configure PA1, PA2 and PA7 */
    GPIO_ConfigStruct.pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
    GPIO_Config(GPIOA, &GPIO_ConfigStruct);
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_1, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_2, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_ETH);
#ifdef MII_MODE
    RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
    /* Configure PC2, PC3 */
    GPIO_ConfigStruct.pin = GPIO_PIN_2 | GPIO_PIN_3;
    GPIO_Config(GPIOC, &GPIO_ConfigStruct);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_2, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOC, GPIO_PIN_SOURCE_3, GPIO_AF_ETH);
    /* Configure PB0, PB1, PB10 and PB8 */
    GPIO_ConfigStruct.pin =  GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_10 | GPIO_PIN_8;
    GPIO_Config(GPIOB, &GPIO_ConfigStruct);
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_0, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_1, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_10, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_ETH);
    /* Configure PA0, PA3 */
    GPIO_ConfigStruct.pin = GPIO_PIN_0 | GPIO_PIN_3;
    GPIO_Config(GPIOA, &GPIO_ConfigStruct);
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_0, GPIO_AF_ETH);
    GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_3, GPIO_AF_ETH);
#endif
}
当添加完上面的代码之后,再次编译就可以编译通过了,没有任何警告和错误,如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bScy847B-1666625339071)(../picture/image-20221024225641398.png)]](https://img-blog.csdnimg.cn/c8b457ef4b6444a386d4b38746920c0f.png) 
   
这时的代码就相当于把LwIP全部移植成功了,包括底层的网卡驱动。
    
    
    9. 验证网络功能是否正常
   
下载程序后运行,然后再串口终端输入 ifconfig 命令,可以看到网卡已经正常工作了,而且使用的是静态IP。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0sLmc4Cm-1666625339072)(../picture/image-20221024225941439.png)]](https://img-blog.csdnimg.cn/3b3e8257584f4049b5d0f4620d282074.png) 
   
我们ping一下电脑主机IP(我的电脑主机IP是:1992.168.1.50),可以看到正常ping通,说明网络功能已经正常了。
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ab0OgSi0-1666625339072)(../picture/image-20221024230026994.png)]](https://img-blog.csdnimg.cn/91ad154161604f65b516c7f93fb69901.png) 
   
    
    
    10. 使用RTT的tcp client和server例程
   
RTT还有各种软件包,其中tcp client和server例程就属于软件包的一部分,我们可以使能这两个例程,这样就可以在shell命令行下面运行tcp客户端或者服务器例程了。
1、先使能这两个软件包
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kHPFT5dv-1666625339072)(../picture/image-20221024232313884.png)]](https://img-blog.csdnimg.cn/46555ae90dc845eea88b5ab54e7a0458.png) 
   
2、保存配置,然后重新编译下载,可以在shell终端看到多了两个命令:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TENDjLX3-1666625339072)(../picture/image-20221024232501000.png)]](https://img-blog.csdnimg.cn/a990797ede014c20aa0cd736779f4f5f.png) 
   
3、然后可以运行 tcpserv 命令,使得开发板作为服务器。然后可以在电脑端打开网络调试工具,作为客户端去连接开发板,如下:
    ![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NZpElSsR-1666625339073)(../picture/image-20221024232703665.png)]](https://img-blog.csdnimg.cn/33016141a4ab4e1e87a2c1f4fb6da685.png) 
   
可以看到开发板接收到了客户端发过来的数据。
 
