STM32 + LWIP + RT-Thread 组播/多播测试

概述:本文以 正点原子 阿波罗 STM32F767ZI 开发板作为硬件平台,以RT-Thread Studio作为开发工具,基于lwip协议栈,验证了UDP多播数据传输功能

1. 预备知识

1.1. IP 地址组成

IP 地址由四段组成,每个字段是一个字节,8 位,最大值是 255,,

IP 地址由两部分组成,即网络地址和主机地址。网络地址表示其属于互联网的哪一个网络,主机地址表示其属于该网络中的哪一台主机。二者是主从关系。

IP 地址的四大类型标识的是网络中的某台主机。IPv4 的地址长度为 32 位,共 4 个字节,但实际中我们用点分十进制记法。

1.2. IP地址分类

类型组成地址范围子网掩码
A类第一个字节为网络号,后三个字节为主机号。该类IP地址的最前面为“0”,所以地址的网络号取值于1~126之间。一般用于大型网络。0.0.0.0~127.255.255.255255.0.0.0
B类前两个字节为网络号,后两个字节为主机号。该类IP地址的最前面为“10”,所以地址的网络号取值于128.xxx~191.xxx之间。一般用于中等规模网络。128.0.0.0~191.255.255.255255.255.0.0
C类前三个字节为网络号,最后一个字节为主机号。该类IP地址的最前面为“110”,所以地址的网络号取值于192.xxx.xxx~223.xxx.xxx之间。一般用于小型网络。192.0.0.0~223.255.255.255255.255.255.0
D类多播地址。该类IP地址的最前面为“1110”,所以地址的网络号取值于224~239之间。一般用于多路广播用户224.0.0.0~239.255.255.255-------------------
E 类是保留地址。该类IP地址的最前面为“1111”,所以地址的网络号取值于240~255之间240.0.0.0~247.255.255.255--------------------

1.3. 私有 IP 地址

在IP地址3种主要类型里 A 类、B 类、C 类,各保留了 3 个区域作为私有地址,其地址范围如下:

类型地址范围
A 类10.0.0.0~10.255.255.255
B 类172.16.0.0~172.31.255.255
C 类192.168.0.0~192.168.255.255

1.4. 以太网数据接收过程

在以太网中,数据以帧的形式进行传输,某设备判断一帧数据是否为发送给自己的,需要根据帧头部分的目的 MAC 地址与自身 MAC 地址(MAC 芯片可以配置多个 MAC 地址,常用于过滤特定 MAC 地址)进行对比,对比通过,则将该数据帧提交到 IP 层进行后续处理,比较 IP 报文的目的 IP 地址与自身 IP 地址是否相同,若相同则进行 TCP/UDP 层进行后续处理,由传输层控制数据交由哪个应用进行处理。

1.5. 多播帧构成

使用多播方式进行数据传输时,会根据多播的目的IP地址,构造出一个多播目的MAC地址,用于填充以太网帧的目的 MAC 地址字段,构造方法为0x01 0x00 0x5E(高24位) + 0 + 多播 IP 地址低 23 位,组成 48 位的多播 MAC 地址。

多播 IP 地址共 32 位,高 4 位固定为 1110 因此,可用地址bit为 28 位,而二层组播 MAC 地址,前 24 位恒定为 01 00 5E,剩余 24 位,由于历史原因仅有低 23 位可使用,因此将 多播IP 地址的低23位与之映射,这样得到的 MAC 组播地址也就是该 IPv4 组播地址对应的 MAC 地址。同时也造成每 32 个组播 IPv4 地址会映射到同一个 MAC 组播地址。

2. 开发测试环境

硬件环境:

  1. 开发板:正点原子 阿波罗 STM32F767ZI 板载百兆以太网(LAN8720 PHY芯片)
  2. 调试工具:ST Linker V2
  3. 配件:网线、MiniUSB --> USB 转接线

软件环境:

  1. 开发IDE:RTThread Studio V2
  2. RT-Thread: Version 4.0.2
  3. BSP:RTThread Studio 自带 stm32f767-atk-apollo BSP
  4. LWIP:Version 2.0.2
  5. 电脑必须联网

3. 工程创建

  1. 新建 RT-Thread 项目
  1. 选择项目存储位置、RT-Thread 版本、BSP版本、调试接口等信息

4. 配置RT-Thread Settings

  1. 在软件包中心点击 更多配置
  1. 使能 ETH 硬件驱动
  1. 使能 网络组件 相关选项, 并关闭 LWIP 中的 DHCP 功能(如果开发板与电脑不是直接网线连接 而是均连接到路由器 则最好开启), 默认使用静态 IP,可按照实际情况修改静态 IP 地址
  1. CTRL + S , 保存配置,该过程会根据配置需求,联网下载本地缺少的依赖文件,所以必须保证电脑连接互联网

5. 添加测试源文件

  1. 在工程中添加测试源文件,并复制如下测试代码
// muticast_test.c
/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-09-01     DJT       the first version
 */
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date             Author      Notes
 *
 */
#include <sys/socket.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <rtthread.h>
#include <finsh.h>

void udp_mulicast(void)
{
    // 多播 IP 地址
    char muticast_addr[16] = "239.255.0.1";
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock < 0) {
        rt_kprintf("socket failed!\n");
        return;
    }

    struct sockaddr_in local_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*<! 待与 socket 绑定的本地网络接口 IP */   
    local_addr.sin_port = htons(8888); /*<! 待与 socket 绑定的本地端口号 */   

    // 将 Socket 与本地某网络接口绑定 
    int ret = bind(sock, (struct sockaddr*)&local_addr, sizeof(local_addr));
    if(ret < 0) {
        rt_kprintf(" bind error!\n ");
    }

    // 多播地址结构体
    struct ip_mreq mreq; 
    mreq.imr_multiaddr.s_addr=inet_addr(muticast_addr); /*<! 多播组 IP 地址设置 */
    mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*<! 待加入多播组的 IP 地址 */   

    // 添加多播组成员(该语句之前,socket 只与 某单播IP地址相关联 执行该语句后 将与多播地址相关联)
    ret = setsockopt(sock,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
    if(ret < 0)
    {
        rt_kprintf("setsockopt failed !");
        return;
    }
    else
    {
        rt_kprintf("setsockopt success\n");
    }
    char buf[1024];
    int length=0;
    struct sockaddr_in sender;
    int sender_len=sizeof(sender);
    while(1)
    {
        memset(buf, 0, sizeof(buf));
        length = recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr*)&sender,(socklen_t *)&sender_len);
        buf[length]='\0';
        rt_kprintf("%s %d : %s\n", inet_ntoa(sender.sin_addr), ntohs(sender.sin_port), buf);
    }
    setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq));
    closesocket(sock);
}

MSH_CMD_EXPORT(udp_mulicast, a udp muticast recv sample);

6. 关闭 MAC 多播帧过滤功能

RT-Thread提供的BSP中,默认是开启了MAC 地址完美过滤, 即所有和本设备 MAC 地址不同的以太网帧,都将直接被 MAC 层过滤掉,不会将数据包提交到 IP 层,导致无法接收数据包。

使用多播进行数据传输时,会根据多播的目的IP地址,构造出一个多播目的MAC地址,用于填充以太网帧的目的MAC地址字段,因此对于开启了MAC 地址完美过滤功能的接收设备来说,其收到多播以太网帧后,首先将该帧的 MAC 地址与自身 MAC 地址进行比对,若完全相同则对数据帧进行解析并提交 IP 层协议进行后续处理,否则丢弃该数据帧。因此若要使得设备能够接收以太网多播帧,必须关闭 MAC 地址完美过滤或者配置MAC部分过滤功能,此处使用关闭完美过滤的方法。

  1. MAC 配置由 ETH_MACDMAConfig 函数实现,该函数位于 stm32f7xx_hal_eth.c 文件中,将 MAC 多播帧过滤设置为 ETH_MULTICASTFRAMESFILTER_NONE

7. 编译、下载工程

  1. 点击 Build 图标对工程进行编译,成功后,点击下载图标将程序下载到设备上

8. 多播测试

  1. 通过串口交互终端工具,在 RT-Thread shell 中输入 udp_muticast,并回车启动多播接收线程
  1. 主机端通过网络调试助手,指定发送 IP 地址,目的多播地址及端口号,发送测试数据
  1. 串口交互终端显示主机端发送的数据,表明多播测试成功
RT-ThreadLwIP移植到STM32F4平台需要一些步骤,下面是一个简单的指南: 1.下载RT-Thread源代码和LwIP源代码。可以从官方网站获取最新版本。 2.将RT-ThreadLwIP源代码添加到您的工程中。可以直接将源代码文件复制到您的工程目录中,也可以在工程中创建一个新的文件夹,并将源代码添加到该文件夹中。 3.根据您的硬件配置,对STM32F4的寄存器和外设进行初始化。通常,您需要根据硬件手册编写一些初始化代码,以使STM32F4与RT-ThreadLwIP兼容。 4.配置LwIP选项。通过修改lwipopts.h文件,您可以配置LwIP的各种选项,例如IP地址、子网掩码、网关等。 5.在RT-Thread的配置文件rtconfig.h中启用LwIP组件。找到RT-Thread中的lwip组件选项,并确保它被启用。 6.修改RT-Thread的初始化代码,以初始化并启动LwIP。在RT-Thread的应用程序入口函数中,添加初始化LwIP的代码。这包括为LwIP创建一个线程,并为网络接口分配内存等。 7.根据您的需求配置LwIPRT-Thread的线程、任务和堆栈大小。这些参数的默认值可能不适合您的应用,您可以根据需要进行调整。 8.编译并烧录您的应用程序到STM32F4上。使用合适的编译工具和烧录器,将代码编译成二进制文件,并烧录到STM32F4上。 9.测试和调试。在STM32F4上运行您的应用程序,并使用适当的工具(例如串口终端)检查网络连接。您还可以使用调试器来调试您的应用程序,并解决可能遇到的问题。 这只是一个初步指南,具体的移植过程可能因个人需求和硬件平台的差异而有所不同。对于更深入的了解,建议参考LwIPRT-Thread的官方文档和社区讨论。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值