Electrical – LWIP Raw UDP API on STM32F2/F7 generated by CubeMX not sending on startup, requires an arbitrary amount of resets to work

lwipstm32stm32cubemx

I'm working on a project using the LWIP raw API with the stm32f2 and cannot get it to work. The basic concept of the project is to have the stm32f2 acting as the actuator and gets instructions from another machine over the UDP connection.

I went the usual route and setup the RMII interface for the ethernet, configured LWIP to include the UDP modules, disabled DHCP (we are using static IPs), enabled the arp function, and then generated the code.

For testing I connected my laptop to a router, connected the board to the router, and then had a UDP socket on my laptop spew data at the board which the board was supposed to echo, while I watched the whole thing on Wireshark and output the echoed data to the terminal.

When I ran the program I saw absolutely nothing coming out of the board and no responses to the ARP requests that my local machine was generating.

After fiddling around with some settings to no avail, I turned the board on and off several times only to find the application suddenly come to life without any issues! I tried running it several more times and found that after pushing the reset button a few times (the amount changed each time I ran it) it would eventually respond to the ARP request and things would work fine from there, but that's the total sum of my progress thus far.

I've been able to run the NETCONN API example uncluded with the stm32f2 package without an issue and checked the register and clock configurations of the LAN Phy and found no problems.

I've tried using TCP sockets, running basic examples for an echo-server from the LWIP page, and they all have the same issue.

Then I tried to get it working on my STM32F7 and had the exact same issue. Until reset the board is absolutely quiet.
I'm concerned I forgot something in the setup, but really I'm a bit at a loss here… Anyone have any ideas?

Below is my lwip.c where the structures are implemented and the main function in main.c which calls LWIP_INIT() and LWIP_Process():

lwip.c

long total_msgs;
uint8_t data[100];
struct udp_pcb* upcb;
ip4_addr_t destIPAddr;
/* USER CODE END 0 */
/* Private function prototypes -----------------------------------------------*/
/* ETH Variables initialization ----------------------------------------------*/
void _Error_Handler(char * file, int line);

/* USER CODE BEGIN 1 */

/* USER CODE END 1 */

/* Variables Initialization */
struct netif gnetif;
ip4_addr_t ipaddr;
ip4_addr_t netmask;
ip4_addr_t gw;
uint8_t IP_ADDRESS[4];
uint8_t NETMASK_ADDRESS[4];
uint8_t GATEWAY_ADDRESS[4];

/* USER CODE BEGIN 2 */
void udp_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port){
      struct pbuf *p;
      sprintf((char*)data, "sending udp client message %d", (int)message_count);
      /* allocate pbuf from pool*/
      p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);
      if (p != NULL)
      {
        /* copy data to pbuf */
        pbuf_take(p, (char*)data, strlen((char*)data));

        /* send udp data */
        udp_send(upcb, p);

        /* free pbuf */
        pbuf_free(p);
      }
}


err_t create_udp_socket(){
    err_t err = ERR_OK;
    upcb = udp_new();

    if (upcb == NULL){
        return ERR_MEM;
    }
    // Load the static IP of the destination address
    IP4_ADDR(&destIPAddr,192,168,1,10);
    upcb->local_port = 4004; // Set our local port to 4004
    // Should bind to the local ip and port
    err = udp_bind(upcb,IP4_ADDR_ANY,4004);
    if (err != ERR_OK){
        return err;
    }
    // Connect to the other port
    err = udp_connect(upcb,&destIPAddr,1234);
    if (err != ERR_OK){
        return err;
    }
    // Set the receive function
    udp_recv(upcb,udp_receive_callback,NULL);
    return err;
}

err_t send_msg_to_dest(){
    struct pbuf *p;

    sprintf((char*)data, "sending udp client message %d", (int)total_msgs);

    /* allocate pbuf from pool*/
    p = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)data), PBUF_POOL);

    if (p != NULL)
    {
        /* copy data to pbuf */
        pbuf_take(p, (char*)data, strlen((char*)data));

        /* send udp data */
        udp_send(upcb, p);

        /* free pbuf */
        pbuf_free(p);
        return ERR_OK;
    }
    return ERR_MEM;
}
/* USER CODE END 2 */

/**
  * LwIP initialization function
  */
void MX_LWIP_Init(void)
{
  /* IP addresses initialization */
  IP_ADDRESS[0] = 192;
  IP_ADDRESS[1] = 168;
  IP_ADDRESS[2] = 1;
  IP_ADDRESS[3] = 100;
  NETMASK_ADDRESS[0] = 255;
  NETMASK_ADDRESS[1] = 255;
  NETMASK_ADDRESS[2] = 255;
  NETMASK_ADDRESS[3] = 0;
  GATEWAY_ADDRESS[0] = 192;
  GATEWAY_ADDRESS[1] = 168;
  GATEWAY_ADDRESS[2] = 1;
  GATEWAY_ADDRESS[3] = 1;

  /* Initilialize the LwIP stack without RTOS */
  lwip_init();

  /* IP addresses initialization without DHCP (IPv4) */
  IP4_ADDR(&ipaddr, IP_ADDRESS[0], IP_ADDRESS[1], IP_ADDRESS[2], IP_ADDRESS[3]);
  IP4_ADDR(&netmask, NETMASK_ADDRESS[0], NETMASK_ADDRESS[1] , NETMASK_ADDRESS[2], NETMASK_ADDRESS[3]);
  IP4_ADDR(&gw, GATEWAY_ADDRESS[0], GATEWAY_ADDRESS[1], GATEWAY_ADDRESS[2], GATEWAY_ADDRESS[3]);

  /* add the network interface (IPv4/IPv6) without RTOS */
  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernet_input);

  /* Registers the default network interface */
  netif_set_default(&gnetif);

  if (netif_is_link_up(&gnetif))
  {
    /* When the netif is fully configured this function must be called */
    netif_set_up(&gnetif);
  }
  else
  {
    /* When the netif link is down this function must be called */
    netif_set_down(&gnetif);
  }

  /* Set the link callback function, this function is called on change of link status*/
  netif_set_link_callback(&gnetif, ethernetif_update_config);

  // Setup the udp port
  create_udp_socket();
}
void MX_LWIP_Process(void)
{
  ethernetif_set_link(&gnetif);
  ethernetif_input(&gnetif);

  send_msg_to_dest();
  sys_check_timeouts();
}

main.c

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LWIP_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      MX_LWIP_Process();
      HAL_Delay(800);
  }
  /* USER CODE END 3 */

}

Best Answer

I had the same problem and solved it.

This is probably caused by a negotiation that will end up at a too high speed for the Nucleo. For example, the Nucleo F429ZI is rated 10MbS and 100MbS but it's possible that the router where it is connected negotiates a too high speed.

So what I did was to fix the speed.

While troubleshooting, I started with 10MbS and it started to work perfectly, then I tried 100MbS and it also worked perfectly.

  1. Open the CUBE-MX or CUBE IDE
  2. Go in system view
  3. In the column "Connectivity" go in ETH
  4. Go in parameter setting
  5. Disable "Auto Negotiation"
  6. A Speed option will appear, fix the speed at 10/100MbS

enter image description here