首页 > 其他分享 >STM32H7基于STM32CubeMX的以太网示例

STM32H7基于STM32CubeMX的以太网示例

时间:2024-07-21 15:32:50浏览次数:16  
标签:udp LwIP 示例 RAM should STM32H7 address D2 以太网

本自述文件适用于STM32CubeIDE版本1.9.0和STM32CubeH7版本1.10.0。对于较旧的工具版本,请参阅存储库中的此自述文件的较旧版本

基于LwIP和FreeRTOS的简单以太网示例,运行在ST Nucleo和Discovery板上。
这些例子附在ST社区的FAQ文章中。
下面也提供了同样的步骤

#特性

*固定IP地址192.168.1.10
*即使在STM32CubeMX中重新生成代码,代码也应该工作
*代码的变化可以通过搜索' ETH_CODE '关键字来查找

##发布说明

版本 STM32CubeIDE版本 STM32CubeH7版本 描述/更新 日期
1.2 1.9.0 1.10.0 移植到新的IDE/库版本。以太驱动程序在新的库版本中重新工作。增加了性能测量和TCP/IP设置调优。发布于Github 8月9日 the 2022
1.1 1.6.1 1.9.0 新增Cortex-M4基础示例 7月19日 2021
1.0 1.6.1 1.9.0 ST社区首次发布(在Github上有微小的变化) 6月21日 ST 2021

使用GIT标记应该很容易找到特定版本的STM32CubeIDE和HAL库的示例

LwIP中的TCP/IP配置

下面的配置是实现良好TCP/IP性能所必需的

参数 公式 需要在MX中修改
TCP_MSS 1460 ' 1500-40 ' yes
TCP_SND_BUF 5840 ' 4 * TCP_MSS ' yes
TCP_WND 5840 ' 4 * TCP_MSS ' no
TCP_SND_QUEUELEN 16 ' UPPER((4 * TCP_SND_BUF) / TCP_MSS) ' yes

##内存布局

在STM32H74x/H75x设备上,所有与以太网和LwIP相关的数据都放在D2 SRAM存储器(288kB)中。
该内存的前128kB预留给双核设备上的Cortex-M4。在单核器件上,这部分可用于其他目的。

变量 STM32H74x/H75x地址 Cortex-M4别名 大小 源文件
DMARxDscrTab 0x30040000 0x10040000 96 (256 max.) ethernetif.c
DMATxDscrTab 0x30040100 0x10040100 96 (256 max.) ethernetif.c
memp_memory_RX_POOL_base 0x30040200 0x10040200 12*(1536 + 24) ethernetif.c
LwIP堆 0x30020000 0x10020000 131048 (128kB - 24) lwipopts.h

对于STM32H72x/H73x器件,D2 SRAM更有限(只有32kB)。RX缓冲区需要放在AXI SRAM中,因为它们不适合D2 RAM,以及LwIP堆。
LwIP堆减少到适合D2 RAM和DMA描述符的剩余部分。

Variable STM32H72x/H73x address Size Source file
DMARxDscrTab 0x30000000 96 (256 max.) ethernetif.c
DMATxDscrTab 0x30000100 96 (256 max.) ethernetif.c
memp_memory_RX_POOL_base AXI SRAM (32-byte aligned) 12*(1536 + 24) ethernetif.c
LwIP heap 0x30000200 32232 (32kB - 512 - 24) lwipopts.h

这里提供的值是一个示例实现,其他配置也可以优化内存使用。更改内存布局时,需要同步更新主控板配置

#许可证

库和中间件取自STM32CubeH7包。同样的许可也适用于这些例子。在STM32CubeMX和HAL库上添加了最少的代码,该代码是按原样提供的。

#如何从头开始创建项目

目标

这个例子的目标是:

  • 为STM32H750-Discovery在STM32CubeMX中配置项目
  • 正确配置FreeRTOS和LwIP中间件
  • 定期发送UDP消息(可选)

虽然示例使用的是stm32h50 - discovery,但对于其他基于STM32H7的板,可能很容易使用相同的步骤。主要的区别通常是引脚和时钟配置。您可能还需要检查电路板焊接桥接,以确保以太网连接到MCU。

STM32CubeMX项目配置

  • 在STM32CubeMX中新建项目,选择STM32H750-Discovery board,选择“No”,弹出“Initialize all peripheral in default mode?”
  • 这将有助于pin分配。

基本配置

配置时钟树:

  • 在pinout/RCC中,将HSE配置为旁路模式
  • 在时钟树中配置400MHz内核

Clock tree
Clock tree

  • 在pinout/SYS中配置与SysTick不同的时基(建议使用FreeRTOS时)
  • TIM6通常是一个很好的选择,因为它是一个简单的计时器

以太网配置

  • 在MII模式下启用以太网外设pinout视图(MII在板上使用)。
  • 启用以太网中断,并设置抢占优先级为5。这是FreeRTOS要求的,以便从中断处理程序调用其函数。
    将以太网CRS和COL信号从PH2/PH3重新定位到PA0/PA3
  • 这些信号在全双工模式下是可选的,在默认配置下不连接
    这也将允许使用PH2/PH3的QSPI
  • 其他引脚应该正确放置,因为我们从板选择器创建项目。

Pinout
Pinout

  • Set GPIO pin speed to Very High.

GPIO speed setting
GPIO speed setting


由于某些原因,ETH_MDC的速度无法更改,但它不会影响应用程序,并且已经在新版本中修复了

Cortex-M7配置

当使用Cortex-M4内核时,可以跳过此步骤。

  • 启用ICache和DCache。
  • 在“Background Region Privileged access only + MPU Disabled ... ”中启用内存保护单元(MPU)”模式。按照下图配置区域:
    MPU configuration
    MPU configuration

Above example is for STM32H743 device. For other devices or Cortex-M4 core on dual-core device, different addresses and size might be necessary. Please refer to section Memory layout

When using dual-core device and running Ethernet on Cortex-M7 core, it must be ensured that memory used by Ethernet is not used by Cortex-M4. Also note the Cortex-M4 can use different address alias for D2 RAM

FreeRTOS configuration

  • Enable the FreeRTOS with CMSIS_V1 API.
  • Increase the size of defaultTask stack to 512 words1
  • Lower stack values cause memory corruptions
  • Please check also that the generated code is correct, since there is bug when increasing the MINIMAL_STACK_SIZE and there might be old value in code (this should be fixed in new versions)

FreeRTOS stack configuration
FreeRTOS stack configuration

LwIP configuration

  • Enable LwIP in middleware.
  • In "General settings" tab, disable DHCP server and configure fixed IP address (unless you know how to configure and use DHCP).

LwIP IP address configuration
LwIP IP address configuration

  • In the attached examples, the 192.168.1.10 IP address is used (instead of 192.168.0.10 shown on the screenshot).
  • In "Platform settings" tab select "LAN8742" in both select boxes. The LAN8742 driver is also compatible with LAN8740 device, which is actually present on the STM32H750-Discovery board. The main difference between these devices is support of MII interface. On other boards LAN8742 PHY chip is used.

LwIP BSP selection
LwIP BSP selection

In "Key options" tab:

  • Configure MEM_SIZE to 16360. This specifies the heap size, which we will relocated to D2 SRAM (16kb minus 24 bytes for allocator metadata).
  • Also enable LWIP_NETIF_LINK_CALLBACK (needed for cable plugging/unplugging detection).
  • Set the LWIP_RAM_HEAP_POINTER to proper address2
  • Set the MEM_SIZE parameter to proper size2

LwIP heap configuration
LwIP heap configuration

  • (Should be done automatically by new CubeMX) In "Checksum" tab enable CHECKSUM_BY_HARDWARE. Other options should automatically reconfigure and you can leave them in this state.

LwIP checksum selection
LwIP checksum selection

Generate project

Save project to some folder of your selection. Now you can generate the project for IDE. We will use STM32CubeIDE in this example, but it should work with other IDEs.

Modyfying the code (STM32CubeIDE)

There are several places where some additional code should be placed, also depending on selected device. In the examples all these places are marked with comment containing ETH_CODE and some basic explanation. Searching for ETH_CODE can show all these places.

Only main interesting points are mentioned below:

  • Placement of the RX_POOL buffers (although we configured the address in CubeMX) in ethernetif.c2:
/* USER CODE BEGIN 2 */
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma location = 0x30040200
extern u8_t memp_memory_RX_POOL_base[];

#elif defined ( __CC_ARM )  /* MDK ARM Compiler */
__attribute__((at(0x30040200)) extern u8_t memp_memory_RX_POOL_base[];

#elif defined ( __GNUC__ ) /* GNU Compiler */
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];

#endif
/* USER CODE END 2 */
/* USER CODE BEGIN 1 /
#undef LWIP_PROVIDE_ERRNO
#define LWIP_ERRNO_STDINCLUDE
/ USER CODE END 1 */
  • Add DATA_IN_D2_SRAM to macro definitions in project:

Define symbols in STM32CubeIDE
Define symbols in STM32CubeIDE

Modify linkerscript (not valid for Keil/IAR)2

This step should be skipped for Keil and IAR, since they support placing variables at specific address in C code.
Modify the linkerscript (*.ld) that the ETH descriptors and buffers are located in D2 SRAM. Also it is recommended to place all RAM to RAM_D1.
In STM32CubeMX generated project, the "_FLASH" suffix linkerscript should be modified, which is used by default (e.g.: STM32H750XBHx_FLASH.ld). The "_RAM" suffix linkerscript is template for executing code from internal RAM memory.

  } >RAM_D1

  /* Modification start */
  .lwip_sec (NOLOAD) :
  {
    . = ABSOLUTE(0x30040000);
    *(.RxDecripSection) 
    
    . = ABSOLUTE(0x30040060);
    *(.TxDecripSection)
    
    . = ABSOLUTE(0x30040200);
    *(.Rx_PoolSection)  
  } >RAM_D2
  /* Modification end */

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

The memory definitions at the beginning of the linkerscript should look like:

MEMORY
{
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 128K
  DTCMRAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 128K
  RAM_D1 (xrw)   : ORIGIN = 0x24000000, LENGTH = 512K
  RAM_D2 (xrw)   : ORIGIN = 0x30000000, LENGTH = 288K
  RAM_D3 (xrw)   : ORIGIN = 0x38000000, LENGTH = 64K
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
}

For dual core devices it is better to restrict RAM_D2 section to avoid collision with Cortex-M4. Please see the linkerscripts in examples.

(Optional) Adding simple Hello UDP message

  • Add following include files at the beginning of main.c:
#include “lwip/udp.h”
#include <string.h>
  • Modify the StartDefaultTask in main.c with the following code:
/* USER CODE BEGIN 5 */
const char* message = "Hello UDP message!\n\r";

osDelay(1000);

ip_addr_t PC_IPADDR;
IP_ADDR4(&PC_IPADDR, 192, 168, 1, 1);

struct udp_pcb* my_udp = udp_new();
udp_connect(my_udp, &PC_IPADDR, 55151);
struct pbuf* udp_buffer = NULL;

/* Infinite loop */
for (;;) {
  osDelay(1000);
  /* !! PBUF_RAM is critical for correct operation !! */
  udp_buffer = pbuf_alloc(PBUF_TRANSPORT, strlen(message), PBUF_RAM);

  if (udp_buffer != NULL) {
    memcpy(udp_buffer->payload, message, strlen(message));
    udp_send(my_udp, udp_buffer);
    pbuf_free(udp_buffer);
  }
}
/* USER CODE END 5 */

Now you should be able to ping the device and receive UDP messages, assuming that you configure IP address 192.168.1.1 for the receiving device (the 192.168.1.0/24 network is used by attached examples). On Linux machine you can observe the messages with the following command:

netcat –ul 55151

Tips & common mistakes

  1. For STM32H72x/H73x devices, the Ethernet buffers can't be placed in address range 0x30040000 - 0x30048000, since that range is not valid. D2 SRAM on those devices is much smaller, so the buffers need to be placed starting at 0x30000000. This affects RX & TX descriptors and RX buffer addresses (ETH configuration in CubeMX) and LWIP_RAM_HEAP_POINTER used for TX buffers (LWIP > Key options in CubeMX).
  2. When running the stack on Cortex-M4, the buffers can be placed at the same address (0x30040000), but it is better to place them at 0x10040000 which is alias for the same address. This alias is accessible by Cortex-M4 D-bus and helps to utilize the Harvard architecture.
  3. When not using FreeRTOS, the Ethernet interrupt should be disabled and MX_LWIP_Process should be called periodically (in main loop).
  4. On STM32H747-Discovery board, modification needs to be done to default solder bridge configuration. SB8 should be closed and SB21 should be open for Ethernet to work, otherwise the MDC signal is not properly connected.

When facing issues with your own project:

  1. First try example and see if there is proper configuration on PC side. With corporate firewalls and restrictions, it might be difficult to perform simple ping to specific IP address. In some cases it is easier to test from personal PC, or some PC with firewall disabled.
  2. Check if Ethernet interrupt is called and if RX callback is called
    • If not, GPIOs are set to proper speed (very high)
    • and ETH global interrupt is enabled (only for FreeRTOS)
      • Interrupt priority should be 5 - preemption and 0 - subpriority. This is required by default FreeRTOS configuration.
  3. If Hardfault is called, the problem might be in MPU configuration
    • Please check carefully (e.g. slight mistake like having "256KB" instead "256B" can make big difference)
      1 RX callback is called but ping still not work
    • check that the buffers are properly placed in linkerscript (the one ending with "_FLASH.ld")
    • in STM32CubeIDE you can use "Build analyzer" window
  4. When allocating buffers via pbuf_alloc (or similar), PBUF_RAM must be used as 3rd parameter. This is necessary to ensure that the allocated buffer is placed in D2 SRAM and synchronized with DMA
  5. Not sufficient stack size for different thread can cause issues.

Questions & Feedback

If you see any issue with these examples please fill an issue inside this repository. If you face some difficulties, but not sure if this is an issue you can start discussion inside this repository, or you can start thread on ST community

  1. Exact size required for different stacks might depend on used compiler and optimization flags. Same goes for FreeRTOS heap size, since thread stacks are allocated from this heap.

  2. Some addresses and sizes depend on the device or core used. Please refer to section Memory layout. 2 3 4

标签:udp,LwIP,示例,RAM,should,STM32H7,address,D2,以太网
From: https://www.cnblogs.com/sparkle-now/p/18314472/stm32h7ji-yustm32cubemx-de-yi-tai-wang-shi-

相关文章

  • STM32H7基于STM32CubeMX的以太网示例
    本自述文件适用于STM32CubeIDE版本1.9.0和STM32CubeH7版本1.10.0。对于较旧的工具版本,请参阅存储库中的此自述文件的较旧版本基于LwIP和FreeRTOS的简单以太网示例,运行在STNucleo和Discovery板上。这些例子附在ST社区的FAQ文章中。下面也提供了同样的步骤#特性*固定IP地址192......
  • STM32H7基于STM32CubeMX的以太网示例
    本自述文件适用于STM32CubeIDE版本1.9.0和STM32CubeH7版本1.10.0。对于较旧的工具版本,请参阅存储库中的此自述文件的较旧版本基于LwIP和FreeRTOS的简单以太网示例,运行在STNucleo和Discovery板上。这些例子附在ST社区的FAQ文章中。下面也提供了同样的步骤#特性*固定IP地址192......
  • xlsx 前端插件 导出 elment表格示例
    安装yarnaddxlsxyarnaddfile-savergit文档:https://github.com/rockboom/SheetJS-docs-zh-CNnpm地址:https://www.npmjs.com/package/xlsx代码<template> <divclass='box'> pageC <el-buttontype="primary"size="defa......
  • 在 PowerShell 中,可以编写脚本来检测本地加载和远程加载的情况。这通常涉及到检查计算
    在PowerShell中,可以编写脚本来检测本地加载和远程加载的情况。这通常涉及到检查计算机上的特定服务或应用程序的状态或配置。以下是一些示例脚本和方法,可以用来实现这些检测:检测本地加载示例:检查本地服务的运行状态powershellCopyCode#检查本地服务状态$serviceName="M......
  • 在 PowerShell 中,"本地加载"和"远程加载"通常指的是运行脚本或命令的位置或方式。以下
    在PowerShell中,"本地加载"和"远程加载"通常指的是运行脚本或命令的位置或方式。以下是关于本地加载和远程加载的一些基本概念和示例:本地加载本地加载指的是在当前计算机上执行PowerShell脚本或命令。这些脚本和命令直接在本地计算机上运行,无需通过网络连接到其他计算机或服......
  • SeleniumBase 示例失败 Cloudflare Turnstile
    我在尝试自动提交包含CloudflareTurnstileCAPTCHA的表单时遇到了SeleniumBase的问题。等待7秒后尝试查找iframe元素时,脚本失败并出现NoSuchElementException。https://github.com/seleniumbase/SeleniumBase/blob/master/examples/raw_form_turnstile.pyfr......
  • 简单的 DiffSharp 示例
    如何将这个简单的PyTorch片段转换为DiffSharp?应该是类似的,但是很多功能没找到。#Definetensorswithrequires_grad=Truetotrackcomputationhistoryx=torch.tensor(2.0,requires_grad=True)y=torch.tensor(3.0,requires_grad=True)#Performacomputation......
  • 音频文件降噪及python示例
    操作系统:Windows10_x64Python版本:3.9.2noisereduce版本:3.0.2从事音频相关工作,大概率会碰到降噪问题,今天整理下之前学习音频文件降噪的笔记,并提供Audacity和python示例。我将从以下几个方面展开:noisereduce库介绍使用Audacity进行降噪使用fft滤波降噪使用noisereduce进......
  • 短链接接口使用场景及Java调用示例
    今天给大家案例短链接接口,短链接接口是一种用于将长网址转换为短网址的技术接口。那大家知道短链接接口的应用场景吗?它具有以下一些主要特点和作用:1.节省空间:在有限的显示区域,如社交媒体帖子、短信等中,短链接更简洁,不占太多字符。2.便于传播:简短且易记,更易于用户分享和传播......
  • 继电器模块的使用与代码示例
     目录前言继电器简介模块接线工作原理驱动代码relay.hrelay.cmain.c参考手册继电器(英文名称:relay)是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出......