cancel
Showing results for 
Search instead for 
Did you mean: 

Can't communicate using lwIP other than with ICMP (ping)

AJOLY.2
Associate II

Hello,

Sorry in advance for my English. I am also very new to embedded systems and softwares worlds.

I am currently trying the lwIP TCP/IP stack on a STM32756G-EVAL2 (STM32F756NGH) board. On one end, I have a Red Hat PC with a network interface used specifically to connect with the board through Ethernet. On the other end, the board linked to the PC with RJ-45 cable. I use STM32CubeIDE v1.5.0 as the IDE for developping my softwares, and the board is connected to the PC via ST-LINK v2.1. I am able to flash and debug my binaries without any issues.

My PC is network-configured with a static IP address (192.168.0.2), a netmask (255.255.255.0), a gateway (192.168.0.1) and a MAC address. The board is configured with a static IP address (192.168.0.10), a netmask (255.255.255.0), a gateway (192.168.0.1) and a MAC address (by default 00:80:E1:00:00:00).

To reproduce the issue as stated in the title (I will explain more specifically the issue below), here is what I do:

  • First I create a new workspace, then a new STM32 project
  • I choose the STM32F756NGH target, a name for the project in C, as a project type of STM32Cube. The FW package used here is the STM32Cube FW_F7 v1.16.0.
  • In the ioc file, in Pinout & Configuration, I go to Connectivity, ETH and activate it as MII. There are the settings. PHY Address must be set to something different of 1 otherwise nothing works at runtime lwIP-side. I have seen some people talking about this being a bug on the STM HAL F7 Ethernet.0693W00000BbEVVQA3.png
  • In Middleware, I enable LWIP. I deactivate LWIP_DHCP in General Settings, and I enable LWIP_BROADCAST_PING and LWIP_MULTICAST_PING in Key Options (at IPv4 - ICMP Options). Other than these changes, everything else stays at default. 0693W00000BbEhCQAV.png
  • Before the code is being generated, I accept the request from the automatic clock resolver, as HCLK is not set to 216 MHz. Now it is set to 216 MHz and I generate the code.
  • In main.c, I copy paste my code for ping requests and UDP send process.
...
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
 
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/opt.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/timeouts.h"
#include "lwip/ip4_addr.h"
#include "netif/etharp.h"
#include "ethernetif.h"
/* USER CODE END Includes */
 
...
 
/* Private variables ---------------------------------------------------------*/
 
UART_HandleTypeDef huart1;
 
/* USER CODE BEGIN PV */
extern struct netif gnetif;
extern ip4_addr_t ipaddr;
extern ip4_addr_t netmask;
extern ip4_addr_t gw;
extern uint8_t IP_ADDRESS[4];
extern uint8_t NETMASK_ADDRESS[4];
extern uint8_t GATEWAY_ADDRESS[4];
/* USER CODE END PV */
 
...
 
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */
  char str[] = "Hello UDP World!";
  err_t err = 0;
  ip_addr_t dstaddr;
  ip_addr_t srcaddr;
 
  IP4_ADDR(&dstaddr, 192, 168, 0, 2);
  IP4_ADDR(&srcaddr, 192, 168, 0, 10);
 
  struct udp_pcb * pcb;
  struct pbuf * pb;
 
  pcb = udp_new();
 
  err = udp_bind(pcb, &srcaddr, 55151);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {  
    err = 0;
    pb = pbuf_alloc(PBUF_TRANSPORT, sizeof(str), PBUF_REF);
    pb->payload = str;
    pb->len = pb->tot_len = sizeof(str);
 
    err = udp_bind(pcb, &srcaddr, 55151);
    err = udp_connect(pcb, &dstaddr, 55151);
    err = udp_sendto(pcb, pb, &dstaddr, 55151);
 
    udp_disconnect(pcb);
    udp_remove(pcb);
    pbuf_free(pb);
    HAL_Delay(1000);
 
    MX_LWIP_Process();
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
...

  • Now I can build my program, and debug it. I usually debug it via STLINK (OpenOCD). Here is an output of a ping command from the PC:0693W00000BbEmCQAV.png
  • If I want to listen to UDP packets coming from the board (192.168.0.10) to the PC (192.168.0.2), I use netcat but it does not seem able to receive/listen to these UDP packets (it is blank after the command line), using the next command:
nc -ul 192.168.0.2 55151
  • Nonetheless, with the program running on the board, I refresh an ifconfig command on my PC terminal and I can see that I indeed receive UDP packets each second approximately (as written in my program). These are not ICMP packets as I do not run the ping command for this purpose.

Thus, I do not really understand why it is not working. I tried to change a lot of settings of the ETH and LWIP in the ioc, as well as doing some little debugging with breakpoints and running through each functions. No errors returned also. I tried with Netconn API and FreeRTOS, same problem: ping requests and responses work but not UDP or TCP. I did not tried sockets but i thought that if RAW API and Netconn API didn't worked, I will be more successful with socket API.

Do you have any ideas or solutions for this kind of issue?

1 ACCEPTED SOLUTION

Accepted Solutions
AJOLY.2
Associate II

Hello,

After debugging my program along with Netcat, I figured out what was the cause of the problem and now I can send and receive UDP packets.

The first thing I did was to activate the debug messages. About that, I had to manually define LWIP_DEBUG, as STM32CubeMX doesn't want to define it via the automatic generation.

I modified my code as this:

...
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
 
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/opt.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/timeouts.h"
#include "lwip/ip4_addr.h"
#include "netif/etharp.h"
#include "ethernetif.h"
/* USER CODE END Includes */
 
...
 
/* Private variables ---------------------------------------------------------*/
 
UART_HandleTypeDef huart1;
 
/* USER CODE BEGIN PV */
extern struct netif gnetif;
extern ip4_addr_t ipaddr;
extern ip4_addr_t netmask;
extern ip4_addr_t gw;
extern uint8_t IP_ADDRESS[4];
extern uint8_t NETMASK_ADDRESS[4];
extern uint8_t GATEWAY_ADDRESS[4];
/* USER CODE END PV */
 
...
 
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */
  char str[] = "Hello UDP World!";
  err_t err = 0;
  ip_addr_t dstaddr;
  ip_addr_t srcaddr;
  struct eth_addr dstmac;
  struct eth_addr srcmac;
 
  IP4_ADDR(&dstaddr, 192, 168, 0, 2);
  IP4_ADDR(&srcaddr, 192, 168, 0, 10);
 
  struct udp_pcb * pcb;
  struct pbuf * pb;
 
  pcb = udp_new();
 
  dstmac.addr[0] = 0x98;
  dstmac.addr[1] = 0xDE;
  dstmac.addr[2] = 0xD0;
  dstmac.addr[3] = 0x01;
  dstmac.addr[4] = 0x2C;
  dstmac.addr[5] = 0x8A;
  srcmac.addr[0] = 0x00;
  srcmac.addr[1] = 0x80;
  srcmac.addr[2] = 0xE1;
  srcmac.addr[3] = 0x00;
  srcmac.addr[4] = 0x00;
  srcmac.addr[5] = 0x00;
  etharp_add_static_entry(&dstaddr, &dstmac);
  etharp_add_static_entry(&srcaddr, &srcmac);
 
  err = udp_bind(pcb, &srcaddr, 55151);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {  
    err = 0;
    pb = pbuf_alloc(PBUF_TRANSPORT, sizeof(str), PBUF_RAM);
    memcpy(pb->payload, str, sizeof(str));
 
    err = udp_bind(pcb, &srcaddr, 55151);
    err = udp_connect(pcb, &dstaddr, 55151);
    err = udp_sendto(pcb, pb, &dstaddr, 55151);
    MX_LWIP_Process();
    udp_disconnect(pcb);
    udp_remove(pcb);
    pbuf_free(pb);
 
    HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
...

As you can see, I attached the MAC addresses to source and remote IPv4 address structures. I also modified the allocation of the buffer by using RAM then a memcpy function to copy the string to the buffer payload.

Using Netcat, I changed my receive command by this one which works better as it is less ambiguous than the previous command: "$nc -u -s 192.168.0.2 -p 55151 192.168.0.10 55151" for the reception command and "$echo -e 'Hello\0' | nc -u4 -w 1 -s 192.168.0.2 -p 55151 192.168.0.10 55151" for the sending command.

Finally, the main error was to disconnect then to remove the udp_pcb before the call of MX_LWIP_Process() function. Thus, when the programm was trying to send UDP packets (or on other programs that try to receive UDP packets), the udp_pcb was unusable.

View solution in original post

4 REPLIES 4
Amel NASRI
ST Employee

Hi @Community member​ ,

As this is not my area of expertise, I don't have a solution for your issue but I have a proposal: as you are using STM32756G-EVAL2 which is an ST board, why don't you select a ready to use example from STM32CubeF7 package and run it on your side? If all is working fine and as described in the readme.txt file, then you can update the example depending on your needs.

If you agree with that proposal, then look to the examples available under STM32Cube_FW_F7\Projects\STM32756G_EVAL\Applications\LwIP.

Please keep me informed if there is any progress.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

AJOLY.2
Associate II

Hello,

After debugging my program along with Netcat, I figured out what was the cause of the problem and now I can send and receive UDP packets.

The first thing I did was to activate the debug messages. About that, I had to manually define LWIP_DEBUG, as STM32CubeMX doesn't want to define it via the automatic generation.

I modified my code as this:

...
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
 
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
#include "lwip/opt.h"
#include "lwip/init.h"
#include "lwip/netif.h"
#include "lwip/timeouts.h"
#include "lwip/ip4_addr.h"
#include "netif/etharp.h"
#include "ethernetif.h"
/* USER CODE END Includes */
 
...
 
/* Private variables ---------------------------------------------------------*/
 
UART_HandleTypeDef huart1;
 
/* USER CODE BEGIN PV */
extern struct netif gnetif;
extern ip4_addr_t ipaddr;
extern ip4_addr_t netmask;
extern ip4_addr_t gw;
extern uint8_t IP_ADDRESS[4];
extern uint8_t NETMASK_ADDRESS[4];
extern uint8_t GATEWAY_ADDRESS[4];
/* USER CODE END PV */
 
...
 
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */
  char str[] = "Hello UDP World!";
  err_t err = 0;
  ip_addr_t dstaddr;
  ip_addr_t srcaddr;
  struct eth_addr dstmac;
  struct eth_addr srcmac;
 
  IP4_ADDR(&dstaddr, 192, 168, 0, 2);
  IP4_ADDR(&srcaddr, 192, 168, 0, 10);
 
  struct udp_pcb * pcb;
  struct pbuf * pb;
 
  pcb = udp_new();
 
  dstmac.addr[0] = 0x98;
  dstmac.addr[1] = 0xDE;
  dstmac.addr[2] = 0xD0;
  dstmac.addr[3] = 0x01;
  dstmac.addr[4] = 0x2C;
  dstmac.addr[5] = 0x8A;
  srcmac.addr[0] = 0x00;
  srcmac.addr[1] = 0x80;
  srcmac.addr[2] = 0xE1;
  srcmac.addr[3] = 0x00;
  srcmac.addr[4] = 0x00;
  srcmac.addr[5] = 0x00;
  etharp_add_static_entry(&dstaddr, &dstmac);
  etharp_add_static_entry(&srcaddr, &srcmac);
 
  err = udp_bind(pcb, &srcaddr, 55151);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {  
    err = 0;
    pb = pbuf_alloc(PBUF_TRANSPORT, sizeof(str), PBUF_RAM);
    memcpy(pb->payload, str, sizeof(str));
 
    err = udp_bind(pcb, &srcaddr, 55151);
    err = udp_connect(pcb, &dstaddr, 55151);
    err = udp_sendto(pcb, pb, &dstaddr, 55151);
    MX_LWIP_Process();
    udp_disconnect(pcb);
    udp_remove(pcb);
    pbuf_free(pb);
 
    HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
...

As you can see, I attached the MAC addresses to source and remote IPv4 address structures. I also modified the allocation of the buffer by using RAM then a memcpy function to copy the string to the buffer payload.

Using Netcat, I changed my receive command by this one which works better as it is less ambiguous than the previous command: "$nc -u -s 192.168.0.2 -p 55151 192.168.0.10 55151" for the reception command and "$echo -e 'Hello\0' | nc -u4 -w 1 -s 192.168.0.2 -p 55151 192.168.0.10 55151" for the sending command.

Finally, the main error was to disconnect then to remove the udp_pcb before the call of MX_LWIP_Process() function. Thus, when the programm was trying to send UDP packets (or on other programs that try to receive UDP packets), the udp_pcb was unusable.

Heu @Community member​ ,

Glad to see that you resolved your issue and thanks for sharing the solution.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Piranha
Chief II

Static ARP entries and whatnot... The selected "solution" is not a solution and is beyond ridiculous!

https://community.st.com/s/question/0D50X0000BOtfhnSQB/how-to-make-ethernet-and-lwip-working-on-stm32