cancel
Showing results for 
Search instead for 
Did you mean: 

UDP packet drop on STM32H7, HAL_ETH_Transmit problem!!

Saghi.1
Associate II

 Hi

I have a customized stm32h750 board, my work is to read data from SD memory of board and send through UDP to a client PC.I use stm32cubeMX v5.6.1,STM32H7 MCU package v1.7 and LWIP cubeMX supported v2.0.3. when I send small size files everything is OK and I get the same data and file on PC,but for bigger size files(in MByte size and over) the data I get on PC is less than sent and clearly some packets are dropped.for example in sending of 26Mbyte data I receive  21Mbyte .

I tried to debug the code,first thing I checked was reading from SD by fatfs function f_read,it was OK. The second thing I checked was udp_send function that seems to be the reason.it returns no error,but When I add time delay(in few miliseconds range) before udp_send in my for loop, the problem goes away.but if I send a bigger size data I need to increase delay time. For example it must be 30 ms for a 26Mbyte data file.I read many posts in community about bug fix (specially from Alister and Piranha)in STM32H7 ethernet,I think I have correct MPU config and it seems other bugs are fixed in v.1.7 package. But I think also there is a problem with HAL_ETH_Transmit function that use a polling mode to send Ethernet data.

Has anyone similar experience? Would anyone give me a hint or solution to fix this problem.

Below is a piece of my code related to UDP send, also necessary files for review of set parameters in cube are attached.

Dcache and Icache,are enabled, but I also tested the code by disabling them,and again failed.

Phy = DP83848.

BYTE SD_read_buffer[8192];  /* File copy buffer */

Chunk of server_rec function:                  

                               if(data_read[0]=='9')

                               {

                                               HAL_Delay(2000);

                                               f_open(&SDFile, "REC_26MB.DAT", FA_READ); //640kb file

                                               for (;;)

                                               {

                                                               f_read(&SDFile, SD_read_buffer, sizeof SD_read_buffer, &br); // Read a chunk of data from the source file

                                                               if (br == 0) break; // error or eof

                                                               HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_SET);

                                                               server_send(upcb);

                                                               HAL_GPIO_WritePin(GPIOE,GPIO_PIN_8,GPIO_PIN_RESET);

                                                               HAL_Delay(10);

                                               }

                                               f_close(&SDFile);

                                               

Server_send function:

void server_send(struct udp_pcb *upcb)

{

               struct pbuf *sb;

               err_t err;

 /* allocate pbuf from RAM*/

               

               sb = pbuf_alloc(PBUF_TRANSPORT,sizeof SD_read_buffer, PBUF_RAM);

               memcpy(sb->payload,SD_read_buffer,sizeof SD_read_buffer);

               err=udp_send(upcb, sb);

               pbuf_free(sb); 

}

this got me crazy and i can't debug it, please help me.

9 REPLIES 9
Saghi.1
Associate II

also my MPU config:

void MPU_Config(void)

{

 MPU_Region_InitTypeDef MPU_InitStruct = {0};

 /* Disables the MPU */

 HAL_MPU_Disable();

 /** Initializes and configures the Region and the memory to be protected

 */

 MPU_InitStruct.Enable = MPU_REGION_ENABLE;

 MPU_InitStruct.Number = MPU_REGION_NUMBER0;

 MPU_InitStruct.BaseAddress = 0x30040000;

 MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;

 MPU_InitStruct.SubRegionDisable = 0x0;

 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;

 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;

 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected

 */

 MPU_InitStruct.Enable = MPU_REGION_ENABLE;

 MPU_InitStruct.Number = MPU_REGION_NUMBER1;

 MPU_InitStruct.BaseAddress = 0x30040000;

 MPU_InitStruct.Size = MPU_REGION_SIZE_256B;

 MPU_InitStruct.SubRegionDisable = 0x0;

 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;

 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;

 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;

 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;

 MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /* Enables the MPU */

 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

TDK
Guru

>        sb = pbuf_alloc(PBUF_TRANSPORT,sizeof SD_read_buffer, PBUF_RAM);

If you're dealing with megabytes of data, you should be checking this to ensure it's able to allocate enough memory. You could be running out.

>               err=udp_send(upcb, sb);

You should also check the return status here.

Instead of having a fixed delay, poll the port to see when it's finished before you send more data.

Note also that UDP is a send and forget scheme and packets can get lost without any sort of notification. If you need a robust protocol, you'll need to use TCP or implement your own handshaking protocol.

If you feel a post has answered your question, please click "Accept as Solution".
alister
Lead

> it seems other bugs are fixed in v.1.7 package

Which bugs are those?

thanks for your reply TDK.

as you see I sd buffer size is 8kbyte and I send megabytes data in chunk of 8kbytes, how should I check this allocation, do you mean ​maybe its not enough ram when I do this allocation in a for loop?I make it free at end of sending every 8kbyte.

about checking of udp_send error, in this code it does not done, but as I said I did it in my debugging and it returns no error in whole for loop!​

I think udp_send finally calls hal_eth_transmit, and this function has a polling scheme, but seems it does not work properly.

I your right about udp forgetting scheme, but I used this for it's speed and have to go with that.

it seems polling function in hal_eth_transmit does not work properly sometimes!​have you ever tried to send burst data with it?

No eth bugs were fixed in H7_FW V1.7.0. All the bugs described at https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet apply it.

The last post that thread by @Community member​  says it appears to have solved some number of eth bugs , but none of the implementation improvements I'd provided.

>have you ever tried to send burst data with it?

I don't recall. I'd found most of the bugs I'd listed by inspection.

The list includes ethernetif.c's low_level_output and the driver's HAL_ETH_Transmit.

You may also need to check your lwIP heap is dimensioned appropriately as transmit pbufs are typically allocated from there.

Saghi.1
Associate II

thanks

I did not find the thread by adunc.1 you mentioned, would u send the link here?

I 'll check the heap,thanks​.

> I did not find the thread by adunc.1 you mentioned, would u send the link here?

I'm referring his post recently to https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet.

AAnt.1
Associate II

Hi @Saghi.1​ 

I have stm32H7 Nucleo board and i want to send data from ADC to PC via Ethernet, because It is faster that transmision via Rs232.

For getting data from rs232 i use terminal program (Realterm) that give me occunity to save data to file and i could comunicate with MCU from PC.

What program you use for getting data from MCU via Ethernet UDP ?

Best regards.