cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H723ZG DHCP memory allocation problem in LwIP

Louie88
Senior II

Hello,

I implemented the How to use SNTP over LwIP and RTC with an STM32 - STMicroelectronics Community example (not using FreeTOS) in the suggested STM32H723ZG NUCLEO-144 board. The app runs, but when it tries to allocate memory for DHCP with the mem_memalloc() function in dhcp:start (dhc.c lib file) it always returns null pointer. I t can't allocate memory for DHCP structure, the dhcp pointer is always 0 and dhcp_start() always returns with ERR_MEM error.

dhcp_start(struct netif *netif)
{
  struct dhcp *dhcp;
  ...
  /* no DHCP client attached yet? */
  if (dhcp == NULL) {
    dhcp = (struct dhcp *)mem_malloc(sizeof(struct dhcp));
    if (dhcp == NULL) {
      return ERR_MEM;
    }
  ...
}

In STM32H723ZGTX_FLASH.ld I have:

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

...

  /* ETH_CODE: add placement of DMA descriptors, rest is used by RX_POOL */
  .lwip_sec (NOLOAD) : {
    . = ABSOLUTE(0x30000000);
    *(.RxDecripSection)
    
    . = ABSOLUTE(0x30000080);
    *(.TxDecripSection)
    
    . = ABSOLUTE(0x30000100);
    *(.Rx_PoolSection)
  } >RAM_D2 AT> FLASH

 Can sombody help, what is wrong in the code?

Thanks,

Louis

5 REPLIES 5
sergey23
Associate II

Increase MEM_SIZE in lwipopts.h . Enable memory stats too: LWIP_STATS, MEM_STATS. Or, better, share your lwipopts.h here.

 

Alternatively, you can use Mongoose instead of LWIP on your Nucleo-H723ZG, baremetal. See this 3 minute explainer video on SNTP: https://www.youtube.com/watch?v=eGMZ5Eobx7c

Louie88
Senior II

Hi @sergey23,

Thanks for the suggestions. Here is my lwipopts.h file:

#ifndef __LWIPOPTS__H__
#define __LWIPOPTS__H__
#include "main.h"

#ifdef __cplusplus
 extern "C" {
#endif
/*----- WITH_RTOS disabled (Since FREERTOS is not set) -----*/
#define WITH_RTOS 0
/*----- 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 -*/
/*----- Value in opt.h for LWIP_DHCP: 0 -----*/
#define LWIP_DHCP 1
/*----- Default value in ETH configuration GUI in CubeMx: 1524 -----*/
#define ETH_RX_BUFFER_SIZE 1000
/*----- Value in opt.h for NO_SYS: 0 -----*/
#define NO_SYS 1
/*----- Value in opt.h for SYS_LIGHTWEIGHT_PROT: 1 -----*/
#define SYS_LIGHTWEIGHT_PROT 0
/*----- Value in opt.h for MEM_ALIGNMENT: 1 -----*/
#define MEM_ALIGNMENT 4
/*----- Default Value for H7 devices: 0x30004000 -----*/
#define LWIP_RAM_HEAP_POINTER 0x30004000
/*----- Value in opt.h for MEMP_NUM_SYS_TIMEOUT: (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + (PPP_SUPPORT*6*MEMP_NUM_PPP_PCB) + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)) -*/
#define MEMP_NUM_SYS_TIMEOUT 5
/*----- 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 9
/*----- 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
/*----- Value in opt.h for LWIP_NETIF_LINK_CALLBACK: 0 -----*/
#define LWIP_NETIF_LINK_CALLBACK 1
/*----- Value in opt.h for LWIP_NETCONN: 1 -----*/
#define LWIP_NETCONN 0
/*----- Value in opt.h for LWIP_SOCKET: 1 -----*/
#define LWIP_SOCKET 0
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
#define RECV_BUFSIZE_DEFAULT 2000000000
/*----- Default Value for LWIP_SNTP: 0 ---*/
#define LWIP_SNTP 1
/*----- Default Value for SNTP_CHECK_RESPONSE: 0 ---*/
#define SNTP_CHECK_RESPONSE 1
/*----- Default Value for SNTP_COMP_ROUNDTRIP: 0 ---*/
#define SNTP_COMP_ROUNDTRIP 1
/*----- Default Value for SNTP_UPDATE_DELAY: 3600000 ---*/
#define SNTP_UPDATE_DELAY 15000
/*----- Default Value for LWIP_STATS: 0 ---*/
#define LWIP_STATS 1
/*----- Value in opt.h for MIB2_STATS: 0 or SNMP_LWIP_MIB2 -----*/
#define MIB2_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
/*----- Default Value for IP_DEBUG: LWIP_DBG_OFF ---*/
#define IP_DEBUG LWIP_DBG_ON
/*----- Default Value for MEM_DEBUG: LWIP_DBG_OFF ---*/
#define MEM_DEBUG LWIP_DBG_ON
/*----- Default Value for MEMP_DEBUG: LWIP_DBG_OFF ---*/
#define MEMP_DEBUG LWIP_DBG_ON
/*----- Default Value for SYS_DEBUG: LWIP_DBG_OFF ---*/
#define SYS_DEBUG LWIP_DBG_ON
/*----- Default Value for TCP_DEBUG: LWIP_DBG_OFF ---*/
#define TCP_DEBUG LWIP_DBG_ON
/*----- Default Value for TCPIP_DEBUG: LWIP_DBG_OFF ---*/
#define TCPIP_DEBUG LWIP_DBG_ON
/*----- Default Value for DHCP_DEBUG: LWIP_DBG_OFF ---*/
#define DHCP_DEBUG LWIP_DBG_ON
/*----- Default Value for SNTP_DEBUG: LWIP_DBG_OFF ---*/
#define SNTP_DEBUG LWIP_DBG_ON
/*-----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
#ifdef __cplusplus
}
#endif
#endif /*__LWIPOPTS__H__ */

I couldn't find which one increases the memory size...

Thanks,

Louis

LCE
Principal II

Search your sources for MEM_SIZE, this file only "overwrites" some defines in the *opt.h file found somewhere in Middlewares\Third_Party\LwIP .

Interesting that they moved MEM_SIZE away from the target folder.

Hi @LCE

Good idea, I did it and you know what? It is in the main.h. I would not say it is not logical decision because the generated (by STM32CubeMX) main.h must be changed anyway. This is 14 * 1024 by default which is around 14KB.

 

...

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32h7xx_hal.h"

#include "stm32h7xx_nucleo.h"
#include <stdio.h>

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */

/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
/* USER CODE END ET */

/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
#define MEM_SIZE 14 * 1024  // <-- Here it is

#define DEST_IP_ADDR0   ((uint8_t)10U)
#define DEST_IP_ADDR1   ((uint8_t)157U)
#define DEST_IP_ADDR2   ((uint8_t)21U)
#define DEST_IP_ADDR3   ((uint8_t)79U)
#define DEST_PORT       ((uint16_t)7U)

/*Static IP ADDRESS: IP_ADDR0.IP_ADDR1.IP_ADDR2.IP_ADDR3 */
#define IP_ADDR0   ((uint8_t) 192U)
#define IP_ADDR1   ((uint8_t) 168U)
#define IP_ADDR2   ((uint8_t) 1U)
#define IP_ADDR3   ((uint8_t) 192U)

...

Thanks,

Louis

Louie88
Senior II

Hi,

The problem is not the MEM_SIZE. When I created my ETH-SNTP-H723 app I used STM32CubeMX and enabled to generate code for Board Support Options (BSP), for USART3= VCOM serial port, the LEDs and the blue button. It also automatically created initialization conde for MPU with disabled IChache and DCache, and configured D1 RAM memory only. It did not enable MPU for D1 and D2 RAM.

So, I restarted the whole project, but I did not allow to generate BSP options in STM32CubeMX this time. I manually configured MPU according to the above example app. I also enabled IChache and DCache.

Then I found a bug. In STM32CubeMX when you enable the Ethernet in RMII mode it generates the GPIO pins but there are to mistakes in the generated ports:

  1. The ETH_TX_EN is assigned to PB11 but int the schematics it is connected to PG11.
  2. The ETH_TXD0 is assigned to PB12 but int the schematics it is connected to PG13.

This caused errors in my first version, because believed to the machine, I did not check whether the auto-generated ports are correct or not... Big fault.

So, finally I have working version of the app without any HARD_FAULT a memory allocation errors. The app uses a DHCP server to assign an IP address for the board. If the user presses the Blue User button, then it asks the SNTP server (in Sau Paolo, Brazil, why?) for the exact timestamp, it converts it to data and time and writes it into RTC of MPU. It logs the whole process vial USART3 VCOM. (See attaches terminal screenshot)

During the power on the RTC contains 2000.01.01 00:00:00. Some seconds later when the user presses the blue button it prints date/time from RTC. When it got answer from SNTP server, it converts the got UNIX time to date/time (GMT + 1hour, Central EU time zone), then stores it in RTC of MPU, and sends the changed date/time to the terminal.

Thanks for the help for everybody.

Louis