【从0到0.5】基于STM32F427+DP83848+FreeRTOS+LWIP+CubeMx+Keil搭建TCP服务端与客户端
1.说明
本次测试使用的板卡是基于STM32F427ZI MCU制作的,使用的PHY芯片是DP83848。
测试目的是从0开始搭建一套可以在keil执行的基于FreeRTOS和lwip的例程。
STM32F427ZI:
- 最大主频180MHz
- 2 MB Flash
- 256+4 KB SRAM
- 64-KB CCM(DMA不能访问,只能内核访问)
- 其他特性:
2. CubeMX配置
新建项目:
双击即可。
2.1 RCC与时钟树
- HSE选择外部晶振。
- Power 参数中Power Regulator 选择Scale 1全功率运行,低功耗模式本次不考虑。
时钟树如下,外部晶振采用8MHz:
2.2 SYS
- Debug选择Sw,使用的是ST-Link。
- TimeBase时基采用硬定时器TIM14。
2.3 USART
该串口用来打印信息,根据外部预留的IO口,本次使用的是6号。
2.4 FreeRTOS
选择CMSIS_V2版本。
其他修改项:
- TOTAL_HEAP_SIZE:总的堆大小,默认15k,可以根据实际分配的内存再改大一些,本项目使用50k;
- USE_MALLOC_FAILED_HOOK:内存分配失败的回调启用,本次启用;
2.5 ETH
Mode选择RMII,DP83848芯片仅支持该模式。
精简介质独立接口 (RMII) 规范降低了 10/100 Mbit/s 下微控制器以太网外设与外部 PHY 间的引脚数。根据 IEEE 802.3u 标准, MII 包括 16 个数据和控制信号的引脚。 RMII 规范将引脚数减少为 7 个(引脚数减少 62.5%),并具有如下特点:
1)支持 10-Mbit/s 和 100-Mbit/s 的运行速率
2)参考时钟必须是 50 MHz
3)相同的参考时钟必须从外部提供给 MAC 和外部以太网 PHY
4)它提供了独立的 2 位宽(双位)的发送和接收数据路径
**注意本次设计的板子,单独提供了50MHz的晶振给PHY使用。**如果没有单独的晶振,需要自己配置时钟树,引出50MHZ的频率输出给PHY芯片使用!
注意MAC地址,每次建立的工程都是相同的,当需要多个板卡同时在一个局域网工作时,需进行修改。并且MAC地址的最高一位有特殊的含义,修改的时候最好从最低位修改(最右边的):
- 如果最高位为 0,则该 MAC 地址是单播地址,表示该地址唯一地标识一个网络接口;
- 如果最高位为 1,且其他位表示特定组播地址,则该地址为组播地址;
- 所有位FF:FF:FF:FF:FF:FF表示广播地址,在使用UDP广播时,会自动修改目标地址为全F。
RxMode选择中断方式,性能更好,资源消耗更低。
2.6 GPIO
因为是自定义的板子,所以DP83848芯片的管脚需重新进行配置。
当要修改某个管脚时,直接在右边选中进行选择就可以了:
2.7 LWIP
本节是本次实验最关键的设置,注意必须先配置ETH后,才能配置LWIP。
先看【Key Point】选项卡:
- MEM_SIZE (Heap Memory Size):所使用的堆大小,这里设置为了16000即16k,LWIP申请的发送、接收、控制块的内存都在该堆上;
- TCP_WIND:接收的窗口大小,为了提升发送速率,可以改大点,本次21440
- TCP_MSS:TCP的网络段大小,本次1460,发送时超过该大小的报文会被切片;
- TCP_SND_BUF:发送缓冲区,本次设置为2920,最大可缓存两个1460的报文;
- TCP_SND_QUEUELEN:发送时排队的消息个数,超过该个数,发送会返回失败,本次为32个;
- TCP_WND_UPDATE_THRESHOLD :设置了一个阈值,用于判断何时更新 TCP 窗口大小。当接收方的可用窗口大小超过这个阈值时,发送方才会更新其发送窗口。通过设置这个阈值,可以减少频繁的窗口更新,避免在网络环境不稳定时造成过多的控制消息,从而提高性能,本次设置为5360;
- 其余采用默认配置。
本次采用静态IP。
平台采用DP83848。
2.8 Project Manager
注意选择固件版本为V1.28.0,1.28.1有bug。
Copy all或者部分都可以。
创建代码。
3. LWIP测试
3.1 基于RAW接口的TCPClient
RAW API 是基于回调函数实现的 API 接口,需要自己注册很多回调函数,相对来说还是比较麻烦的,出了问题资料也比较少,可能还得自己抠代码,如果资源很紧张可以考虑,否则不推荐。
本次是基于TCPClient进行测试的,大概的使用思路如下:
- 【连接服务器】利用osTimer,启动一个重连定时器,当检测到对端主动断开或者心跳探测超时时,进行重连;
- 【数据发送】利用
tcp_poll()
注册的回调进行数据发送,这个回调默认500ms调用一次,可通过修改TCP_TMR_INTERVAL宏来控制调用频率,比如10ms调用一次。 - 【数据接收】
tcp_recv
实现数据接收回调,利用环形buffer进行解黏包处理。
3.2 基于Socket接口的TCPServer
略,按照一般的tcpserver实现方式即可。