APM32F4在RT-Thread系统上使用LwIP网络功能—基于ENV环境

APM32F4在RT-Thread系统上使用LwIP网络功能—基于ENV环境

1. ENV工具的安装和使用

这里只做基本的介绍,详细的使用方法请点击下面链接看RTT的官方文档中心中对ENV工具的介绍。

https://www.rt-thread.org/document/site/#/development-tools/env/env

Env 是 RT-Thread 推出的开发辅助工具,针对基于 RT-Thread 操作系统的项目工程,提供编译构建环境、图形化系统配置及软件包管理功能。

其内置的 menuconfig 提供了简单易用的配置剪裁工具,可对内核、组件和软件包进行自由裁剪,使系统以搭积木的方式进行构建。

ENV工具可以从下面的RTT官方网站下载。

https://www.rt-thread.org/download.html#download-rt-thread-env-tool

2. 下载RTT源码

到下面官网下载:

https://www.rt-thread.org/download.html#download-rt-thread-source-code

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lPiV2YsN-1666528413346)(../picture/image-20221023162742949.png)]

然后点击码云下载。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ws6xuiNw-1666528413347)(../picture/image-20221023162853939.png)]

点击下载ZIP就行。

当然,如果有git bash的话,可以使用 git clone 命令进行远程源码拉取到本地电脑中。

注意:请下载最新版本的RTT源码包,太老版本的话可能还没有APM32的BSP包。

3. 进入到APM32F4的bsp根目录下编译bsp

进入apm32f4的bsp根目录下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8kbSBMOH-1666528413347)(../picture/image-20221023164014069.png)]

然后右键在该目录下打开ENV工具(如果没有把ENV添加到右键菜单的话,自己看RTT文档进行操作,或者自行切换ENV路径到该目录下)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yqe6DSwM-1666528413348)(../picture/image-20221023164314428.png)]

打开ENV工具之后,在该目录下输入 scons 命令即可编译该BSP。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Db58md7A-1666528413348)(../picture/image-20221023164522330.png)]

最终编译成功如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFzjZu6G-1666528413349)(../picture/image-20221023164639357.png)]

如果使用 mdk/iar 来进行项目开发,可以直接使用 BSP 中的工程文件或者使用以下命令中的其中一种,重新生成工程,再进行编译下载。

scons --target=iar
scons --target=mdk4
scons --target=mdk5

4. 解决 shell 不能接收字符的bug

上面编译完成后的代码,其实就可以烧写到芯片上运行了的,打开串口终端软件,可以看到代码打印如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Az7yNaH1-1666528413349)(../picture/image-20221023172634988.png)]

但是发现串口终端怎么也输入不了字符,命令等。检查发现是在 void apm32_usart_init(void) 这个串口初始化函数中的引脚配置有问题,只要按照下面修改即可。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8CnHBibT-1666528413349)(../picture/image-20221023173011921.png)]

修改完之后,重新编译下载运行,shell就可以正常接收命令输入了。

5. 使能 LwIP 与 net dev

5.1 首先使能以太网板级外设驱动

在ENV工具中输入 menuconfig 命令:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hzrxmASp-1666528413350)(../picture/image-20221023170317300.png)]

本来在这个配置项下应该有板级外设驱动选项配置的,但是没有看到,很明显是该bsp包还没支持这个功能。那么后面只能自己把以太网板级外设驱动文件(drv_eth.c)添加到keil工程里面了。当然,就算支持该功能,如果没有drv_eth.c这个文件的支持那也没用。

5.2 启用 lwIP 与 net device

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VsydvTKs-1666528413350)(../picture/image-20221023170839555.png)]

然后再使能LwIP网络协议栈。其中,在该配置项下面我们把DHCP功能关闭了,使用静态IP地址。然后我们再使能 netif loopback 功能,该功能就是可以自己ping通自己的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JlV09uQ3-1666528413350)(../picture/image-20221023171329592.png)]

配置完成后,我们保存退出。

最后输入命令:scons --target=mdk5 把刚刚的配置同步到 MDK5 工程。

6. 编写基于RTT的以太网板级驱动drv_eth.c

当我们添加了LwIP网络协议栈之后,就可以编译代码后可以下载到开发板运行。如下,我们下载代码到开发板后,在串口终端运行 ifconfig 命令查看网络状态,可以看到有错误:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jgNGFrTd-1666528413350)(../picture/image-20221023173528490.png)]

这是因为以太网的驱动文件还没添加进去编译的原因。

6.1 添加编写好的drv_eth.c文件

因为apm32的BSP包里面并没有RTT的以太网板级驱动文件drv_eth.c,所以需要我们自己编写这个文件。这个文件我已经编写好了,然后我们自己把这个文件复制到apm32的bsp包里面,而且手动添加到MDK5的工程中即可:

在这里插入图片描述
在这里插入图片描述

6.2 打开ETH板级外设驱动,和选择PHY芯片型号

因为 drv_eth.c 文件使用了宏 BSP_USING_ETH 默认关闭了这个外设驱动的,需要定义这个宏才能打开这个外设驱动,另外开发板使用的PHY芯片的宏也需要定义,目前支持的芯片类型有,LAN8720、DP83848以及DM9161。

我们就在 drv_eth.c 文件(或者rtconfig.h文件也行)的最前面定义下面两个宏:

#define BSP_USING_ETH
#define PHY_USING_DP83848C		// 根据自己使用的phy芯片型号定义

6.3 添加标准外设驱动文件apm32f4xx_eth.c和apm32f4xx_eth.h

添加了上面那两个宏之后,编译一大堆报错,这是因为MDK还没有添加eth的标准库外设驱动文件apm32f4xx_eth.c和apm32f4xx_eth.h。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DAf0XJKR-1666528413352)(../picture/image-20221023175736185.png)]

我发现RTT的源码里面,apm32的bsp包竟然没有apm32f4xx_eth.c和apm32f4xx_eth.h这两个文件,那没办法了,只好到apm32的官网下载f4的SDK包,然后再把这两个文件复制到bsp包的库目录下面。然后再手动添加到MDK工程里面。

6.4 添加包含apm32f4xx_eth.h头文件代码

添加了标准外设驱动文件apm32f4xx_eth.c到MDK工程之后,这时编译,还是报上面步骤一样的错误,这是因为没有包含 apm32f4xx_eth.h 头文件,我们在 board.h 文件中写上包含该头文件。另外,因为后面的代码有用到apm32f4xx_syscfg.h这个头文件,所以这里一起写上,如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-12kWm10H-1666528413352)(../picture/image-20221023183254219.png)]

6.5 添加 phy_reset 和 ETH_GPIO_Configuration 函数

继续编译,会发现还有两个链接报错,说没有定义 phy_reset 和 ETH_GPIO_Configuration 函数,这两个函数一个是phy芯片硬件复位引脚进行复位的,另外一个函数是eth外设GPIO口的初始化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ce7CHb5-1666528413352)(../picture/image-20221023193326422.png)]

这两个函数是在 drv_eth.c 文件中要用到的,因为这两个函数和板级硬件的关联太大,并不能确定用户使用的是什么GPIO口,所以独立出来由用户自己添加。

我目前使用的事RMII接口和PD11作为复位引脚,我们在 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-ONDAxP6P-1666528413353)(../picture/image-20221023194116369.png)]

到这里已经完成了所有代码的添加和移植了,LwIP网络协议栈也可以正常运行起来了。

7. 验证网络功能是否正常

下载程序后运行,然后再串口终端输入 ifconfig 命令,可以看到网卡已经正常工作了,而且使用的是静态IP。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TVF2T9Q6-1666528413353)(../picture/image-20221023194405297.png)]

我们ping一下电脑主机IP(我的电脑主机IP是:1992.168.1.50),可以看到正常ping通,说明网络功能已经正常了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zHzcKDQs-1666528413353)(../picture/image-20221023194538967.png)]

8. 使用RTT的tcp client和server例程

8.1 配置menuconfig

首先,需要在menuconfig开启使用这两个例程,配置如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hFYxjbto-1666528413354)(../picture/image-20221023195529540.png)]

8.2 更新软件包

保存配置退出之后,我们要去下载在线软件包,在ENV输入 pkgs --update 命令即可,然后可以看到软件包下载下来了。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9YEnzzPu-1666528413354)(../picture/image-20221023200620038.png)]

最后,我们执行命令,scons --target=mdk5 同步到 MDK5 工程里面。

注意:前面我们手动添加了一些文件到 MDK 工程里面,如果我们这里执行了 scons --target=mdk5 这个命令之后,其实会把我们之前添加的配置文件全部都移除掉的,这是使用 ENV 的一个不好的地方。

8.3 测试验证

然后,编译下载程序到板子上运行。

这两个例程是以命令的形式放在串口终端下运行的,我们在串口终端下运行 tcpserv 命令,使用开发板作为服务器,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cARn0K1M-1666528413354)(../picture/image-20221023202536096.png)]

可以看到服务器端口端口是5000。

然后我们在电脑端使用网络调试工具作为客户端,去连接开发板,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5l9vDWIK-1666528413354)(../picture/image-20221023202839102.png)]

以上,就是在ENV环境下,APM32F4在RT-Thread系统上使用LwIP网络功能的详细过程。

猜你喜欢

转载自blog.csdn.net/luobeihai/article/details/127480251