cancel
Showing results for 
Search instead for 
Did you mean: 

HTTP request to STM32 + LwIP results that Ping stops working

DMårt
Senior II

Hello!

Recently I had problems with ping to my STM32 + LwIP + DP83848 + RMII. But the latest FW version 1.27.1, it works very well! But now I have problems with HTTP. Follow me and I show you how to create this bug.

First of all I'm using:

  • STM32CubeIDE 1.10.1
  • STM32F407VGT
  • FW 1.27.1

To reproduce this bug, do the following steps.

  • Step 1: Enable RMII by going to ETH -> RMII (Rx Buffer length 1524, MAC address 00:80:E1:00:00:00, Rx Mode = Interrupt, NVIC settings = Ethernet Global Interrupt)
  • Step 2: Go to FREERTOS and enable CMSIS V2 and go to Task & Queues. Change the Stack Size (Words) in defaultTask from 128 to 1024.
  • Step 3: Inside CMSIS V2, go to Advanced settings and set USE_NEWLIB_REENTRANT = Enabled. Leave everything else as default.
  • Step 4: Go to LWIP and enable it. Set LWIP_DHCP = disabled in General Settings and then write in the fixed IP address. In my case it is 192.168.1.35.
  • Step 5: Inside LWIP, go to HTTPD and set LWIP_HTTPD = enabled. Inside LWIP go to Key Options and set MEM_SIZE = 10*1024. Leave everything else as default.
  • Step 6: Download the FSDATA.zip folder and extract it.
  • Step 7: The FSDATA.zip folder contains a folder called FS and makeFSdata.exe. The makeFSdata.exe file will create a file called fsdata.c. Click on that.
  • Step 8: When the makeFSdata.exe file have created fsdata.c then rename fsdata.c to fsdata_custom.c.
  • Step 9: Place fsdata_custom.c at \Middlewares\Third_Party\LwIP\src\apps
  • Step 10: Right click fsdata_custom.c -> Resource Configurations -> Extract From Build ... -> Select All -> OK.
  • Step 11: Compile the project to your STM32 board and then ping.

0693W00000QN3y9QAD.png 

OK! It Working great!

  • Step 12: Download HTTP_Server.zip and extract it into the projects src folder.
  • Step 13: Write this into your main.c file
#include "HTTP_Server/httpserver.h"
  • Step 14: Add http_server_init(); to
/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
  /* init code for LWIP */
  MX_LWIP_Init();
  /* USER CODE BEGIN 5 */
  http_server_init();
  /* Infinite loop */
  for(;;)
  {
    osDelay(1);
  }
  /* USER CODE END 5 */
}
  • Step 15: Compile and go to your web browser and type in 192.168.1.35/index.html. No web site is displayed. Also if I ping now, then I get no response....BUT....if I restart the processor, then ping, the ping is working. But as long I don't go to the 192.168.1.35/index.html website, my STM32 processor have connection to the DHCP server and I can ping it.

Question:

Why does this happen?

I have followed this tutorial 100% (except that he are using another processor) https://www.youtube.com/watch?v=haO8_eLIDeI&ab_channel=ControllersTech

This must be a bug, becase in FW 1.27.0 version, I had problems with ping my processor. In FW 1.27.1, the ping works like a charm. But now FW 1.27.1 resulting that my HTTPD won't work.

Thank you.

46 REPLIES 46

It was far away from a detailed instruction. Sorry.

ST have confirmed that this was a bug. Yes, it takes long time for them to fix the issue. Perhaps ST could pay you to write that little piece of code? You seems to know exactly how to do that in a couple of minutes.

I understand. I will learn to setup a proper FreeRTOS installation.

Yes, it was detailled enough.

What he said:

  • low_level_output(struct netif *netIf, struct pbuf *pTx) is given a pointer to a pbuf pTx to be sent
  • check that pTx pointer: if it's not pointing to ethernet DMA accessible SRAM, allocate a new pbuf pRam from SRAM and copy the contents of pTx to the new pRam
  • give pRam to ETH
  • free input pTx (I am not sure about this right now concerning TCP and keeping the buffer until it is ACK'd)

> Therefore, yes, this is a deficiency of the lwIP driver

You mean, the low-level ETH driver? Because LwIP is not aware of what memory the ETH driver can access.

mmisz.1
Associate II
static err_t low_level_output(struct netif *netif, struct pbuf *p) {
  void *data = NULL;
 
  uint32_t i = 0U;
  struct pbuf *q = NULL;
  err_t errval = ERR_OK;
  ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = { 0 };
 
  memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));
 
  for (q = p; q != NULL; q = q->next) {
    if (i >= ETH_TX_DESC_CNT)
      return ERR_IF;
 
    Txbuffer[i].buffer = q->payload;
    Txbuffer[i].len = q->len;
 
    // check is it valid ram address {
    if ((q->payload) < (void*)0x20000000) { // RAM starts at => $2000 0000
                                     // FLASH is under => $0800 0000
      // when not, allocate memory in ram
      data = pvPortMalloc(q->len);
      // then copy data
      memcpy(data, q->payload, (q->len));
      // replace data pointer to valid new address
      Txbuffer[i].buffer = data;
    }
 
    if (i > 0) {
      Txbuffer[i - 1].next = &Txbuffer[i];
    }
 
    if (q->next == NULL) {
      Txbuffer[i].next = NULL;
    }
 
    i++;
  }
 
  TxConfig.Length = p->tot_len;
  TxConfig.TxBuffer = Txbuffer;
  TxConfig.pData = p;
 
  pbuf_ref(p);
 
  HAL_ETH_Transmit_IT(&heth, &TxConfig);
  while (osSemaphoreAcquire(TxPktSemaphore, TIME_WAITING_FOR_INPUT) != osOK)
 
  {
  }
 
  HAL_ETH_ReleaseTxPacket(&heth);
 
  // we need to free memory after sending data
  if (data != NULL) {
    vPortFree(data);
  }
 
  return errval;
}

Messy, but seems to work well. I tested the whole 2 minutes so I can't guarantee to nothing...

btw, where is info about eth driver dont have access to flash memory space?

Hi @mmisz.1​ ,

Thank you for sharing your solution.

The info about ETH access to flash memory is available in RM0090 page 60.

Regards

Mahdy

MSG_ST
ST Employee

Hi,

Thank you everyone for your cooperation.

The solution of deleting the "const" and placing data on Ram instead of flash is just a workaround proposed to unlock customers which encounter the issue.

But of course, in the next release, the most suitable solution will be implemented.

Regards

Mahdy

And don't forget a .ioc example with FreeRTOS + LwIP + Ajax for each hardware!

Thank you.

Most likely it's better and more consistent to allocate memory with pbuf_alloc(PBUF_RAW, len, PBUF_RAM). The problem with this code is that a Pbuf is a chain of buffers - every buffer can point to a different memory and there can be several buffers to memories, to which the DMA has no access. A proper solution is not as trivial as this code.