STM32H723 FreeRTOS LAN8742

STM32H723 FreeRTOS LAN8742
提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、硬件二、CubeMX配置步骤详解1. 创建工程新建一个项目选择STM32H723ZGT6芯片2. RCC和时钟树配置3. SYS4. 使能ETH外设5. 配置CORTEM_M7MPU内存保护单元6. GPIO配置-PHY的复位引脚配置7. LWIP配置8. FreeRTOS配置9. 生成工程三、代码部分1. 根据编译器设置 memp_memory_RX_POOL_base2.更改ARM Compilerarmclang / armcc的分散加载文件的内存布局3.使能D2SRAM2时钟4.ping 网络四、TCP连接和关闭前言本项目基于 FreeRTOS在 STM32H723 平台上实现了以太网通信功能。为此我从 CubeMX 工程配置入手完整梳理了从代码生成、网络连通性测试Ping到 TCP 连接建立与断开的全流程。本文既是对个人开发过程的复盘总结也希望能为正在调试 STM32 以太网功能的同学提供一份实操参考。文中如有疏漏恳请各位前辈指正欢迎交流探讨~一、硬件MCU芯片STM32H723ZGT6以太网芯片LAN8742A-CZ-TRRJ45HR915310A原理图如下以太网PHY芯片接线方式如上图所示。二、CubeMX配置步骤详解1. 创建工程新建一个项目选择STM32H723ZGT6芯片2. RCC和时钟树配置启用外部高速时钟 Crystal/Ceramic ResonatorFreeRTOS不适合内置晶振开启内置LDO设置0档支持芯片内核跑到500MHz以上。配置时钟树选择PLLCLK输入频率按实际来直接选择最大时钟频率550MHz。3. SYS使用FreeRTOS系统原本的systick要被FreeRTOS占用用于操作系统时钟节拍和上下文切换等所以SYS选择一个没用到的计时器TIM14. 使能ETH外设在Connectivity选项卡中激活ETH模式选择RMII。4.1 参数设置MAC地址随意STM32H7 系列采用多域总线架构ETH 外设挂载在 D2 域其内部的 DMA 控制器主要用于处理收发描述符和数据缓冲区ETH DMA 可访问范围ETH DMA 能够稳定访问的是 D2 域的 SRAM1 / SRAM2 / SRAM30x30000000 起。STM32H723ZGTx的SRAM1从0x30000000开始。STM32H723ZGT6的以太网ETH DMA 要求 32-byte 对齐每个描述符占用32bytesRxDescriptor和TX Descriptor都是4个描述符共占用32*4128bytes 设置ETH的RxDesc0x3000 0000对应的TxDesc:0x3000 00804.2 ETH GPIO设置GPIO的速度选择 Very high4.3 开启ETH全局中断5. 配置CORTEM_M7MPU内存保护单元在System Core的 CORTEX_M7中编辑内存保护单元配置这里需要说明一下因为本人在配置时对这里云里雾里的嫌烦直接抄配置哈。在 STM32H723 中以太网ETH外设的 DMA 只能访问 D2 域的 SRAM。为了避免数据错乱如 HardFault 或丢包通常需要将这块内存划分为两个 MPU 区域。Region 0以太网 DMA 描述符区Device 类型4.0配置的ETH描述符空间作用专门存放以太网的发送Tx和接收Rx描述符表。ETH DMA 控制器会频繁读写这里必须配置为 Device 或 Strongly Ordered 属性即禁用 Cache开启 Write Buffer以保证外设与 CPU 之间的数据强一致性。Base Address 0x30000000Size1KByte通常 2 个描述符表占用不到 256 字节留一点余量即可到0x3000 0400可以存放ETH rx和tx的描述符。Region 1LWIP 堆栈/数据缓冲区Normal 类型保护 LWIP 的内存池作用存放 LWIP 协议栈的动态内存池pbuf、收发数据缓冲区等。这里可以配置为 Normal 属性但为了配合 LWIP 的 Cache 一致性处理通常也建议禁用 CacheNon-cacheable。Base Address0x3000 4000紧接在描述符区之后避免重叠Size16KBSTM32H723ZGT6 的 D2 SRAM 总共只有 32KB前 1KB 给描述符剩下的约31KB 可划给 LWIP。配置 16KB 是比较保守且安全的做法具体取决于 LWIP 内存池大小。配置参考6. GPIO配置-PHY的复位引脚配置常态设置为高电平7. LWIP配置7.1 配置IPSTM32H723 / STM32H733 的 D2 RAM 是0x3000000开始H723内存与其他H7系列不同H723的RAM_D2 整体连续地址范围为0x3000 0000 ~ 0x3000 7FFF总计 32 KB。LWIP 堆栈/数据缓冲区必须从0x3000 4000开始LWIP_NETIF_LINK_CALLBACK检测网线插拔的要使能就行其他配置默认。选择PHY芯片这里直接选择LAN8742如果用的不是8742,生成代码后要在源码中修改PHY地址。使能SNTP其余的均保持默认即可8. FreeRTOS配置接口选择CMSIS_V1使能FPU总堆栈改大一点防止任务运行不起来一直进入HardFault修改默认任务的堆栈为10249. 生成工程9.1 选择MDK-ARM v5.32版本最小堆栈改成0x800开始。9.2 代码生成勾选参考完成后点击GENERATE CODE。三、代码部分1. 根据编译器设置 memp_memory_RX_POOL_base在Application/Users/LWIP/Target/ethernetif.c源码中第102行添加如下代码可以拷贝我的#ifdefined(__ICCARM__)/*! IAR Compiler 也可以用注释掉的代码*//* #pragma location0x30000000 ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */#pragmalocation0x30000080ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];/* Ethernet Tx DMA Descriptors *///#pragma location0x30000000//ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];//#pragma location0x30000040//ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];//#pragma location0x30000080//uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];#elifdefined(__CC_ARM)/* MDK ARM Compiler *///__attribute__((at(0x30000000))) ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];//__attribute__((at(0x30000040))) ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];//__attribute__((at(0x30000080))) uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];__attribute__((at(0x30000000)))ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];/* Ethernet Rx DMA Descriptors */__attribute__((at(0x30000080)))ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];/* Ethernet Tx DMA Descriptors */#elifdefined(__GNUC__)/* GNU Compiler */__attribute__((section(.RxDecripSection)))//ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT];//__attribute__((section(.TxDecripSection)))//ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT];//__attribute__((section(.Rx_PoolSection)))//uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE];ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]__attribute__((section(.RxDecripSection)));/* Ethernet Rx DMA Descriptors */ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]__attribute__((section(.TxDecripSection)));/* Ethernet Tx DMA Descriptors */#endif2.更改ARM Compilerarmclang / armcc的分散加载文件的内存布局在 STM32CubeMX 生成、使用 GCC 工具链如 STM32CubeIDE、VSCodeCMake 等​ 的工程中是.ld文件如果使用的是 Keil MDK工程里是 .sct 分散加载文件如果是 IAR则是 .icf 文件增加RW_IRAM3 0x30000000 0x00000200 { ; 512B - SRAM1 ´æ·ÅETH DMA RXÃèÊö·û.ANY(.RxDecripSection)}RW_IRAM4 0x30000200 0x00000200 { ; 512B - SRAM1 ´æ·ÅETH DMA TXÃèÊö·û.ANY(.TxDecripSection)}RW_IRAM5 0x30000400 0x00003C00 { ; 15KB - SRAM1 ´æ·ÅRX_POOLÄÚ´æ³Ø.ANY(.Rx_PoolSection)}如下图所示3.使能D2SRAM2时钟4.ping 网络完成上述配置就可以ping通了可以ping一下试试四、TCP连接和关闭TCP连接遵循3次握手、TCP断开遵循4次挥手目前是新建了一个tcpclient的任务码代码如下#includelwip/tcp.h#includelwip/init.h#includenetif/etharp.h#includelwip/udp.h#includelwip/pbuf.h#includestdio.h#includestring.h#includeusart.hvoidTcpClient_task(voidconst*argument);//声明tcpclient任务函数voidTcpclient_init(void){osThreadDef(TcpClient_Task,TcpClient_task,osPriorityNormal,0,1024);osThreadCreate(osThread(TcpClient_Task),NULL);}voidTcpClient_task(voidconst*argument){structnetconn*conn;//netconn 是LWIP的网络连接对象指针用于TCP和UDP连接的创建、连接、收发和关闭structnetbuf*rece_buf;//netbuf 用于存放接收数据的结构体定义缓冲区指针err_terr;//err_t 是LWIP的错误码变量LWIP所有API的返回值都用err_t ERR_OK代表返回正确其他值表示错误ip_addr_tserver_ip;//ip_addr_t 定义服务器IP地址结构体用IPV4charrx_buffer[256];//本地接收缓冲区用netbuf 中的数据拷贝出来chartx_buffer[]Hello from stm32h723 tcpclient \r\n;//发送给服务器的数据/******** 设置服务器 Ip(192.168.1.100) ********/IP4_ADDR(server_ip,192,168,1,100);while(1){/*** 创建tcp连接 ***/connnetconn_new(NETCONN_TCP);//创建一个tcp连接if(connNULL){//连接失败等待500ms后从while(1)开始vTaskDelay(500);continue;}/*** 连接服务器 ***/errnetconn_connect(conn,server_ip,5000);if(err!ERR_OK){netconn_close(conn);netconn_delete(conn);vTaskDelay(1000);continue;}/*** 发送数据 ***/errnetconn_write(conn,tx_buffer,strlen(tx_buffer),NETCONN_COPY);if(err!ERR_OK){netconn_close(conn);netconn_delete(conn);vTaskDelay(1000);continue;}/*** 接收数据 ***/errnetconn_recv(conn,rece_buf);if(errERR_OK){u16_tlen;void*data;netbuf_data(rece_buf,data,len);if(lensizeof(rx_buffer)-1)lensizeof(rx_buffer)-1;memcpy(rx_buffer,data,len);rx_buffer[len]\0;/*这里可以解析服务器返回的数据 *///printf(RX: %s\r\n, rx_buffer);netbuf_delete(rece_buf);}/* 关闭连接 */netconn_close(conn);netconn_delete(conn);/* 间隔1s重连 */vTaskDelay(pdMS_TO_TICKS(1000));}}在freertos.c中增加该任务调试是OK的我实验的时候是3s重连一次后边改成1s重连一次的。本文记录了基于STM32H723和LAN8742A芯片从CubeMX工程配置到实现以太网Ping通及TCP连接和关闭的基本流程。核心步骤包括工程创建与LwIP配置、PHY驱动适配、协议栈初始化、网络连通性测试以及TCP应用开发。希望这份记录能为有类似需求的开发者提供清晰的参考。配置过程中如遇问题欢迎在评论区交流讨论。