FreeRTOS TCP IP implementation on STM32F767ZI

Hello,

Yes, I forgot to upload those new ones yesterday. They can be found here:
FilteredWireshark.zip (2.1 KB)

I have also applied filters to both files.

File ‘Wireshark_TCP_MCU_to_Python_Port10001’ has the filter:
‘ip.addr ==192.168.0.2 && tcp.port == 10001’

and File ‘Wireshark_TCP_MCU_to_Webserver_Port80’ has the filter:
‘ip.addr ==192.168.0.2 && tcp.port == 80’

Thanks for looking into it!

Kind regards.

@NeusAap, does UDP now run in both directions and with a high speed?

@NeusAap wrote:

I can’t seem to find much about how often the ETH_IRQHandler() function needs to be called

An Ethernet IRQ handler normally has three reasons to be called:

  1. When a packet has been received
  2. When a packet has been sent
  3. When an error has occurred ( or a drop in the Link Status )

So you will get as many RX-interrupts as there are packets received. Looking at your earlier Wireshark_defunct_TCP_package.pcapng, it seems to me that you do not have RX-interrupts.

You must have seen this declaration in NetworkInterface.c :

void ETH_IRQHandler( void )
{
    HAL_ETH_IRQHandler( &xETH );
}

Do you have the following code somewhere?

void HAL_ETH_MspInit( ETH_HandleTypeDef* heth )
{
    ...
    /* Enable the Ethernet global Interrupt */
    HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0);
    HAL_NVIC_EnableIRQ(ETH_IRQn);
    ...
}

Do you have a version of HAL_ETH_MspInit() somewhere in the project?
You can find an example in this STM32F7 demo project.

Could you attach stm32f7xx_hal_conf.h to your post?

ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM to either 1 or 0. But I believe the STM32F7 does have hardware IP checksum checking, so this should be set to a 1 value right (for optimal performance)?

Absolutely right.

Also check this, setting CRC offloading:

#if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
    /* using the ETH_CHECKSUM_BY_HARDWARE option:
     * both the IP and the protocol checksums will be calculated
     * by the peripheral. */
    xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
#else
    xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
#endif

Your project sets them both in FreeRTOSIPConfig.h :

#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM        1
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM        1

and that should work well.

Do you enable data caching by calling SCB_EnableDCache() ?
If so, have you put the DMA buffers in non-cached memory?
See this readme.md about non-cached memory.

Are you using BufferAllocation_1.c or BufferAllocation_2.c?

I just prepared a simple TCP-client session to run in an MCU:
tcp_connect_demo.zip (1.5 KB)

If you copy it to your project ( or link it ), then you can run it as follows:

uint32_t ulAddress = FreeRTOS_inet_addr_quick( 192, 168, 2, 5 );
uint16_t usPort = FreeRTOS_htons( 32002 );
handle_user_test (ulAddress, usPort );

Could you try to run it?

It is very verbose:

0.022 connect-test: socket() OK, calling bind()
0.022 connect-test: bind() OK, calling connect()
0.022 FreeRTOS_connect: 45878 to 192.168.2.5:32002
0.022 Socket 45878 -> 192.168.2.5:32002 State eCLOSED->eCONNECT_SYN
0.023 prvSocketSetMSS: 1460 bytes for 192.168.2.5:32002
0.023 prvWinScaleFactor: uxRxWinSize 1 MSS 1460 Factor 0
0.023 Connect[192.168.2.5:32002]: next timeout 1: 3000 ms
0.023 MSS change 1460 -> 9158
0.024 TCP: active 45878 => 192.168.2.5:32002 set ESTAB (scaling 1)
0.024 Socket 45878 -> 192.168.2.5:32002 State eCONNECT_SYN->eESTABLISHED
0.024 connect-test: connect() OK, calling send()
0.124 connect-test: calling shutdown()
0.124 Socket 45878 -> 192.168.2.5:32002 State eESTABLISHED->eFIN_WAIT_1
0.124 connect-test: Received 80 bytes
0.127 Socket 45878 -> 192.168.2.5:32002 State eFIN_WAIT_1->eCLOSE_WAIT
0.127 connect-test: calling closesocket()
0.127 FreeRTOS_closesocket[45878 to 192.168.2.5:32002]: buffers 13 socks 1

The test takes about 100 ms, because of a delay between send() and shutdown(). I had an echo server running on my laptop 192.168.2.5, port 32002. It echoed the 80 bytes of data.

Dear Hein,

In the mean time, I have found out about initializing the Interrupts for each received package.

Yes, I since I found out about it’s workings, I have added it to my stm32f7xx_hal_msp.c file in the initialization function. It seems to be called at the correct moment now.

Do you enable data caching by calling SCB_EnableDCache() ?
If so, have you put the DMA buffers in non-cached memory?
See this readme.md about non-cached memory.

I have tried both manually enabling and disabling the DCache, but in both cases, does not seem to make a difference.

Are you using BufferAllocation_1.c or BufferAllocation_2.c ?

I am using BufferAllocation_2.c, and according to the STM32F7 readme (the one you have also send me) I don’t need to tell the linker script to make sure the first 64KB is uncached, correct?

Thanks for all the help!
Mats de Waard

Could you try to run it?

I have added it to my project, but it does not work either. It hangs at the first line, after creating the socket and before the bind/connect functions.

I’ll send you the minimal example project you asked for in the private message, and update this thread if we get any further on this issue.

Thanks again!

Hi Mats, here is a copy of a linker script that I use:
STM32F746NGHx_FLASH.zip (1.8 KB)

All DMA buffers will be stored in .first_data:

.first :
{
  . = ALIGN(8);
  *(.first_data .first_data.*)  /* .first_data sections */
  . = ALIGN(8);
  } >RAM

which will sit in the first 64KB of RAM, which is “uncached memory”. This part of RAM is just not wired to the caching system.
Please do not use the entire linker script, as I am using a different STM32 part.

Now if you never call SCB_EnableDCache(), it doesn’t matter where you place the buffers. I do recommend to use caching because the application will run faster.

You wrote:

I have added it to my project, but it does not work either. It hangs at the first line, after creating the socket and before the bind/connect functions

Oops, are you running out of stack or out of heap memory? The function FreeRTOS_Socket() will allocate memory on the heap and initialise it. Very innocent :slight_smile:

To be continued

Thanks for the example linker script!

I’ve added the .first entry, and now it does seem to enable caching. Sill keeps hanging before bind/connect. The whole MCU seems to be blocking, since my LedBlinker Task, also stops blinking the LED.

Oops, are you running out of stack or out of heap memory? The function FreeRTOS_Socket() will allocate memory on the heap and initialise it. Very innocent :slight_smile:

My stackoverflow hook does not get called. And my flash has more than 70% space left, so that should not be a problem. I’ll try and reproduce this setup in a new Eclipse Workspace, with the Multi Interface version of the TCP IP stack.

Okay, a small update based on the findings and suggestions from @htibosch.

Turns out that my heap was configured incorrectly. I only had a maximum heap size of 15*1024 bytes, which is quite small for a STM32F7. When I declare:
#define configTOTAL_HEAP_SIZE ((size_t)1024 * 30)
In FreeRTOSConfig.h, the TCP packets seem to get transmitted.

To free up more overhead/heap, I have also gotten rid of my standard Libc printf and sprintf statements, and have replaced them with an alternate version (printf-stdarg.c): https://github.com/htibosch/freertos_plus_projects/blob/master/plus/Common/Utilities/printf-stdarg.c

I’ve declared my own version of the weak function called vOutputChar:

void vOutputChar( const char cChar, const TickType_t xTicksToWait )
{
HAL_UART_Transmit(&huart3, (unsigned const char *) &cChar, sizeof(cChar), xTicksToWait);
}

This function transmits the bytes of the custom sprintf characters to my USART3 pheriperal, which is connected to the USB port on my Nucleo-F7.

I still get TCP packet retransmission errors, but atleast my send text is visible in Wireshark now. I’ll update the forum again if I find the cause of the TCP packet retransmission I keep seeing in Wireshark.

Thanks everyone (especially @htibosch) for all the help so far!

Mats.