硬汉嵌入式论坛

 找回密码
 立即注册
查看: 442|回复: 17
收起左侧

[以太网] STM32H723系列芯片移植lwip发送大包数据会卡死程序

  [复制链接]

5

主题

40

回帖

55

积分

初级会员

积分
55
发表于 2025-6-23 08:47:02 | 显示全部楼层 |阅读模式
使用STM32H723ZGT6芯片,phy芯片LAN8720A,直接通过STM32CUBEMX生成的lwip代码,调试正常ping成功,但是发现,当ping字节数设置为最大MTU时,会出现ping一会儿然后程序卡死,需要复位才能正常。LWIP使用的时默认的配置

[C] 纯文本查看 复制代码
/*----- WITH_RTOS enabled (Since FREERTOS is set) -----*/
#define WITH_RTOS 1
/*----- CHECKSUM_BY_HARDWARE enabled -----*/
#define CHECKSUM_BY_HARDWARE 1
/*-----------------------------------------------------------------------------*/

/* LwIP Stack Parameters (modified compared to initialization value in opt.h) -*/
/* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
/*----- Default value in ETH configuration GUI in CubeMx: 1524 -----*/
#define ETH_RX_BUFFER_SIZE 1536
/*----- Value in opt.h for MEM_ALIGNMENT: 1 -----*/
#define MEM_ALIGNMENT 4
/*----- Default Value for MEM_SIZE: 1600 ---*/
#define MEM_SIZE 14336
/*----- Default Value for H7 devices: 0x30004000 -----*/
#define LWIP_RAM_HEAP_POINTER 0x30004000
/*----- Value supported for H7 devices: 1 -----*/
#define LWIP_SUPPORT_CUSTOM_PBUF 1
/*----- Value in opt.h for LWIP_ETHERNET: LWIP_ARP || PPPOE_SUPPORT -*/
#define LWIP_ETHERNET 1
/*----- Value in opt.h for LWIP_DNS_SECURE: (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -*/
#define LWIP_DNS_SECURE 7
/*----- Value in opt.h for TCP_SND_QUEUELEN: (4*TCP_SND_BUF + (TCP_MSS - 1))/TCP_MSS -----*/
#define TCP_SND_QUEUELEN (4*TCP_SND_BUF + (TCP_MSS - 1))/TCP_MSS
/*----- Value in opt.h for TCP_SNDLOWAT: LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) -*/
#define TCP_SNDLOWAT 1071
/*----- Value in opt.h for TCP_SNDQUEUELOWAT: LWIP_MAX(TCP_SND_QUEUELEN)/2, 5) -*/
#define TCP_SNDQUEUELOWAT 5
/*----- Value in opt.h for TCP_WND_UPDATE_THRESHOLD: LWIP_MIN(TCP_WND/4, TCP_MSS*4) -----*/
#define TCP_WND_UPDATE_THRESHOLD 536
/*----- Default Value for LWIP_NETIF_STATUS_CALLBACK: 0 ---*/
#define LWIP_NETIF_STATUS_CALLBACK 1
/*----- Value in opt.h for LWIP_NETIF_LINK_CALLBACK: 0 -----*/
#define LWIP_NETIF_LINK_CALLBACK 1
/*----- Value in opt.h for TCPIP_THREAD_STACKSIZE: 0 -----*/
#define TCPIP_THREAD_STACKSIZE 1024
/*----- Value in opt.h for TCPIP_THREAD_PRIO: 1 -----*/
#define TCPIP_THREAD_PRIO 24
/*----- Value in opt.h for TCPIP_MBOX_SIZE: 0 -----*/
#define TCPIP_MBOX_SIZE 6
/*----- Value in opt.h for SLIPIF_THREAD_STACKSIZE: 0 -----*/
#define SLIPIF_THREAD_STACKSIZE 1024
/*----- Value in opt.h for SLIPIF_THREAD_PRIO: 1 -----*/
#define SLIPIF_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_THREAD_STACKSIZE: 0 -----*/
#define DEFAULT_THREAD_STACKSIZE 1024
/*----- Value in opt.h for DEFAULT_THREAD_PRIO: 1 -----*/
#define DEFAULT_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_UDP_RECVMBOX_SIZE 6
/*----- Value in opt.h for DEFAULT_TCP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_TCP_RECVMBOX_SIZE 6
/*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
#define DEFAULT_ACCEPTMBOX_SIZE 6
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
#define RECV_BUFSIZE_DEFAULT 2000000000
/*----- Value in opt.h for LWIP_STATS: 1 -----*/
#define LWIP_STATS 0
/*----- Value in opt.h for CHECKSUM_GEN_IP: 1 -----*/
#define CHECKSUM_GEN_IP 0
/*----- Value in opt.h for CHECKSUM_GEN_UDP: 1 -----*/
#define CHECKSUM_GEN_UDP 0
/*----- Value in opt.h for CHECKSUM_GEN_TCP: 1 -----*/
#define CHECKSUM_GEN_TCP 0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP6: 1 -----*/
#define CHECKSUM_GEN_ICMP6 0
/*----- Value in opt.h for CHECKSUM_CHECK_IP: 1 -----*/
#define CHECKSUM_CHECK_IP 0
/*----- Value in opt.h for CHECKSUM_CHECK_UDP: 1 -----*/
#define CHECKSUM_CHECK_UDP 0
/*----- Value in opt.h for CHECKSUM_CHECK_TCP: 1 -----*/
#define CHECKSUM_CHECK_TCP 0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP6: 1 -----*/
#define CHECKSUM_CHECK_ICMP6 0
/*-----------------------------------------------------------------------------*/

原来测试过100个字节,收发还是很稳定的PING也没有出现丢包情况,但是现在出现大数据量有问题,怀疑是否为内存分配或者是占用内存,没有及时释放。因为这款芯片使用网络通信的内存只有32KB.
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116746
QQ
发表于 2025-6-23 09:42:20 | 显示全部楼层
lwip有这个问题。

我们之前是设置大于MTU,ping操作,会卡死
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 2025-6-23 10:01:40 | 显示全部楼层
eric2013 发表于 2025-6-23 09:42
lwip有这个问题。

我们之前是设置大于MTU,ping操作,会卡死

目前测试设置ping字节在512字节数,也会有概率出现无法正常工作的情况。打开lwipdebug功能,报错指向
[C] 纯文本查看 复制代码
Assertion "p_to != NULL" failed at line 996 in /LwIP/src/core/pbuf.c
这个文件中:
[C] 纯文本查看 复制代码
    if (offset_to == p_to->len) {
      /* on to next p_to (if any) */
      offset_to = 0;
      p_to = p_to->next;
      LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return ERR_ARG;);
    }

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116746
QQ
发表于 2025-6-24 07:31:44 | 显示全部楼层
Ainit 发表于 2025-6-23 10:01
目前测试设置ping字节在512字节数,也会有概率出现无法正常工作的情况。打开lwipdebug功能,报错指向
[m ...

我们之前是ping 8192字节,直接卡死。
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 2025-6-24 09:01:44 | 显示全部楼层
目前测试的问题:ping字节数大于512字节会出现程序异常,测试数据收发,大于100字节有可能出现收发一段时间然后程序卡死,用的都是最新的软件和固件包生成的程序。有没有对这方面有研究的大佬,求有偿技术支持! +V wxid_q7e54pfgvcjn22 或者+Q 947785211
回复

使用道具 举报

22

主题

196

回帖

262

积分

高级会员

积分
262
发表于 2025-6-24 18:14:40 | 显示全部楼层
增大MEM_SIZE试试
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 2025-6-25 08:47:41 | 显示全部楼层

增加到最大了,效果没有明显改变,因为我使用的是STM32H723ZGT6这款芯片,它的eth整个空间只有32k。
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 2025-6-25 09:01:22 | 显示全部楼层
目前测试的问题:
1、我尝试修改链接脚本的中Rx_PoolSection的范围,从0x30000200修改为0x30002FFF,这种情况下,我尝试ping512字节,暂时是没有问题的,但是如果ping 最大MTU字节数,程序也会导致卡死。
[C] 纯文本查看 复制代码
    .lwip_sec (NOLOAD) :
      {
      . = ABSOLUTE(0x30000000);
      *(.RxDecripSection)
      . = ABSOLUTE(0x30000080);
      *(.TxDecripSection)
      . = ABSOLUTE(0x30002FFF);
      *(.Rx_PoolSection)
      } >RAM_D2 AT>FLASH
__attribute__((section(".Rx_PoolSection"))) extern u8_t memp_memory_RX_POOL_base[];

2、从官方给的数据手册(STM32H7系列芯片LwIP)中说明STM32H72x/H73x芯片需要有不同的位置存放数据。里面说明了需要将RX buffers存放在AXI SRAM中,但是没有指定具体的初始地址,我根据demo中的链接脚本存放在.bss段里,发现网络通信部分无法再ping通有大佬懂AXI SRAM这个内存段指向的地址是再哪段内存位置吗?
STM32H7芯片LwIP位置设置.png
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116746
QQ
发表于 2025-6-25 09:39:20 | 显示全部楼层
Ainit 发表于 2025-6-25 09:01
目前测试的问题:
1、我尝试修改链接脚本的中Rx_PoolSection的范围,从0x30000200修改为0x30002FFF,这种 ...

MDK版对应的例子查看比较方便,可以看下
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 2025-6-25 18:09:06 | 显示全部楼层
本帖最后由 Ainit 于 2025-6-25 18:20 编辑

根据数据手册中的说明,我将Rx_PoolSection的存储地址设置到RAM地址中,总共占18~19KB左右,这种情况下,ping 最大MTU1472字节,百万包数据出现一次超时的情况,情况还算好,但按照道理来说,RAM_D2这个内存段中也有足够的地址用于存放Rx_PoolSection,但是只要将Rx_PoolSection放在RAM_D2段内存中,就会出现ping有问题。
1、有问题的内存段分配:
[C] 纯文本查看 复制代码
    .lwip_sec (NOLOAD) :
      {
      . = ABSOLUTE(0x30000000);
      . = ALIGN(32);
      *(.RxDecripSection)
      . = ABSOLUTE(0x30000080);
      . = ALIGN(32);
      *(.TxDecripSection)
      . = ABSOLUTE(0x30000100);
      . = ALIGN(32);
      *(.Rx_PoolSection)
      } >RAM_D2 AT>FLASH

2、能正常ping大数据量的内存段
[C] 纯文本查看 复制代码
有懂的大佬能指点一下吗?
  .lwip_rx_pollsection(NOLOAD):
  {
      . = ABSOLUTE(0x24000000);
      . = ALIGN(32);
      *(.Rx_PoolSection)
  }>RAM AT>FLASH


    .lwip_sec (NOLOAD) :
      {
      . = ABSOLUTE(0x30000000);
      *(.RxDecripSection)
      . = ABSOLUTE(0x30000080);
      *(.TxDecripSection)
/*      . = ABSOLUTE(0x30000100);*/
/*      . = ALIGN(32);*/
/*      *(.Rx_PoolSection)*/
      } >RAM_D2 AT>FLASH
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116746
QQ
发表于 2025-6-26 09:59:30 | 显示全部楼层
Ainit 发表于 2025-6-25 18:09
根据数据手册中的说明,我将Rx_PoolSection的存储地址设置到RAM地址中,总共占18~19KB左右,这种情况下,pi ...

MDK的这个查看很方便,一目了然

[C] 纯文本查看 复制代码
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00100000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   .ANY (+RW +ZI)
  }
  RW_IRAM2 0x00000000 0x00010000  {
   .ANY (+RW +ZI)
  }
    RW_DMARxDscrTab 0x30000000 0x60 {
  *(.RxDecripSection)
  }
  RW_DMATxDscrTab 0x30000200 0x140 {
  *(.TxDecripSection)
  }
  memory_RX_POOL_base 0x30000400 0x12676 {
  *(.Rx_PoolSection)
  }
}



#if defined ( __ICCARM__ ) /*!< IAR Compiler */

#pragma location=0x30000000
ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30000200
ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */


#elif defined ( __CC_ARM )  /* MDK ARM Compiler */

__attribute__((section(".RxDecripSection"))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((section(".TxDecripSection"))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */

#elif defined ( __GNUC__ ) /* GNU Compiler */

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 */

#endif

/* Memory Pool Declaration */
LWIP_MEMPOOL_DECLARE(RX_POOL, ETH_RX_BUFFER_CNT, sizeof(RxBuff_t), "Zero-copy RX PBUF pool");

#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma location = 0x30000400
extern u8_t memp_memory_RX_POOL_base[];

#elif defined ( __CC_ARM )  /* MDK ARM Compiler */
__attribute__((section(".Rx_PoolSection"))) 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
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 7 天前 | 显示全部楼层
eric2013 发表于 2025-6-26 09:59
MDK的这个查看很方便,一目了然

[mw_shl_code=c,true]; ******************************************* ...

感谢硬汉,目前确定使用的STM32H723这款芯片的以太网RX缓冲区放在RAM_D2段内存中,并且内存也是足够的,但是这种情况会出现以太网单次ping100字节没什么问题,字节数多了以后就会导致以太网程序卡死。另外如果将以太网RX缓冲区放在RAM(0x24000000)中时,上述问题可以完美解决,但是实际运用中RAM的内存基本上用完。
我目前有疑问的就是RAM_D2内存段地址有内存的情况为啥无法将以太网RX缓冲区放入。或者有什么办法将RAM的存储数据转到其他地方,将以太网RX缓冲区放入RAM中。以上两种方法不知道有没有能够实现的可能。
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 7 天前 | 显示全部楼层
Ainit 发表于 2025-6-27 14:08
感谢硬汉,目前确定使用的STM32H723这款芯片的以太网RX缓冲区放在RAM_D2段内存中,并且内存也是足够的, ...

硬汉你好,我想我已经找到出现上述疑惑的原因了。
1、首先看我这款芯片的内存地址以及容量:
stm32h723芯片容量与地址.png
其中RAM_D2是指定用于以太网或者USB这些外设使用,因为我的芯片STM32H723ZGT6,它的RAM_D2容量只有32KB,起始地址为
[C] 纯文本查看 复制代码
0x30000000

2、我目前设置的从起始地址
[C] 纯文本查看 复制代码
0x30000000
开始的256B内存用于存储以太网的RX/TX描述符,并且我设置0x30004000地址开始作为LWIP的内存堆。从我的mpu设置以及lwip设置可以看出:
mpu设置.png
lwip配置.png
3、根据我给RAM_D2内存段的设置,地址段
[C] 纯文本查看 复制代码
0x30000100
~
[C] 纯文本查看 复制代码
0x30003fff
应该是我还能使用的,这段可使用的地址就是用于存放LWIP的RX_POOL内存池。这段内存大概是15KB左右,使用STM32CUBEMX默认参数生成的代码,会将
[C] 纯文本查看 复制代码
ETH_RX_BUFFER_CNT
默认设置成12,根据这个参数最终算出来的以太网RX/TX描述符和RX_POOL内存池应该要小于16KB。实际如果使用默认参数
[C] 纯文本查看 复制代码
/* Memory Pool Declaration */
#define ETH_RX_BUFFER_CNT             12U
,内存空间一定会大于16KB,这种情况下,能正常ping网络成功,但是如果字节数使用1472,就会出现问题。对比如下:
默认参数.png 修改后的内存占用.png 修改参数后的测试结果.png
修改参数后,ping最大mtu字节已经不会死机了,并且很稳定。另外测试中有将RX_POOL内存池移植到RAM内存中运行,也是可以的,但是ping的速度比在RAM_D2中要慢,平均是5ms一帧。
本人是一枚做嵌入式的小白,能力和技术有很大不足,在查找定位BUG中,感谢大家的帮助,给我带来了很多启发。此次BUG定位与解决在此告一段落,感谢STM32H723 + DP83848 + LWIP + RT-Thread(FreeRTOS) + STM32CubeMX + Keil MDK 超详细  How to create a project for STM32H7 with Ethernet and LwIP stack working 等帖子的帮助。
回复

使用道具 举报

22

主题

196

回帖

262

积分

高级会员

积分
262
发表于 6 天前 | 显示全部楼层
Ainit 发表于 2025-6-27 15:56
硬汉你好,我想我已经找到出现上述疑惑的原因了。
1、首先看我这款芯片的内存地址以及容量:

理解下来,是不是pool的内存分的分的超过了RAM的大小,减小到不超过ram大小就可以
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 5 天前 | 显示全部楼层
yuanzhongda 发表于 2025-6-28 20:20
理解下来,是不是pool的内存分的分的超过了RAM的大小,减小到不超过ram大小就可以

按照RAM_D2区总内存是32KB,你需要将这32KB分配给以太网的RX/TX描述符,RX/TX缓冲区,并且mpu设置时直接将0X30004000地址以后的内存用于TX缓冲区,那么你的RX缓冲区尾地址不能大于0X30004000即可,具体根据实际需求去定义即可
回复

使用道具 举报

5

主题

94

回帖

109

积分

初级会员

积分
109
发表于 前天 23:03 | 显示全部楼层
牛啊,果然技术细节都是一点点抠出来的
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
116746
QQ
发表于 昨天 08:33 | 显示全部楼层
Ainit 发表于 2025-6-27 15:56
硬汉你好,我想我已经找到出现上述疑惑的原因了。
1、首先看我这款芯片的内存地址以及容量:

ping 8192正常不
回复

使用道具 举报

5

主题

40

回帖

55

积分

初级会员

积分
55
 楼主| 发表于 1 小时前 | 显示全部楼层

测试了一下,ping超过4096就会出现超时情况,但是lwip没有挂掉,如果改小字节数,还能继续使用,内存方面应该是够用,可能一些lwip的配置文件需要优化,我使用的都是默认的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-7-4 18:30 , Processed in 0.412727 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表