Problem with FreeRTOS-Plus-TCP when using TouchGFX

Hello,

I’m working on a STM32F769I-Eval demoboard. I have a FreeRTOS and FreeRTOS-Plus-TCP running on it. I can ping the board with a 100% success.

The TCP-IP lib version is version 2.3.2. With the version of the LTS archive, there is no response at all to the ping, with the same application code.

When I start a basic TouchGFX 4.21 Application, even without any refresh, the Ping response fall to 30%.

i know this is probably a TouchGFX more than a TCP problem. But does any one has an idee how to solve this?

The priority of the TCP-IP task is the default one, so configMAX_PRIORITIES - 2. (The task is started in another task, does it change anything?)
The TouchGFX priority is lower (osPriorityVelowNormal) and the FreeRTOS is configured with configUSE_PREEMPTION 1

I have defined configUSE_MALLOC_FAILED_HOOK 1, and a
void vApplicationMallocFailedHook(void) { configASSERT(0); }
as suggested in another thread on the forum

There are not assert!

If some one knows TouchGFX, as the application has no animation, the refresh rate is not so important. How can I reduce it to avoid the TCP task miss some ping packet? Or is there any other possibility to reduce MCU consumption by TouchGFX?

Thank you

Antoine

Hi @AntoineN,

I will reach out to our FreeRTOS-Plus-TCP team and see if they may be able to help you, but I should mention that they are probably not very familiar with TouchGFX ( neither am I, sorry :frowning: ), so would recommend reaching out to the maintainers of that library if you haven’t already. The fact that it’s dropping to 30% would indicate that IP-Task may be getting starved and can’t respond to the ping in time. See FreeRTOS Run Time Stats to learn how you can output runtime statistics for your application - this may help identify resource consumption. I’m not terribly familiar with TouchGFX but if the IP task is at a higher priority - it should be starving GFX, not the other way around. Is it possible that TouchGFX starts a task underneath that is at a higher priority? It may also be possible that this is a case of priority inversion, in which TouchGFX has control of a resource that the IP-Task blocks on (Priority inversion - Wikipedia), but I’m just throwing that out there as a possibility. Please post the run-time statistics if you can :).

Blockquote With the version of the LTS archive, there is no response at all to the ping, with the same application code.

When you mention the LTS archive, do you mean version 3.1.1? It should still work from my understanding … so this may be an issue with the newer library version, so thank you for bringing this up. It would be helpful if you could give your config files for FreeRTOS+TCP :).

Blockquote The task is started in another task, does it change anything?

The task being started from another task won’t have any effect on its priority - FreeRTOS does not have “child” tasks, etc.

Hello,
Thank you for your reply. I will have a look to check the run-time statistics.

The problem with the LTS version 3.1.0 (there is a 3.1.1 version? :wink: ) was that I do not report 2 modifications in the lib NetworkInterface.c:

In the file, there is a definition of

static ETH_HandleTypeDef xETH;

I change it to (and all the reference to it)

extern ETH_HandleTypeDef heth;

This variable is define in the eth.c file of the Core directory in the STM32Cube generated projet. There is something not working when using the FreeRTOS-Plus-TCP lib without using the initialisation of the HAL_ETH_Init.

The other modification is that the file define

#ifndef ipconfigUSE_RMII
#ifdef STM32F7xx
#define ipconfigUSE_RMII 1
...

While the STM32F769i-eval board use a MII interface. Yes I know, I should have define ipconfigUSE_RMII firstly! :upside_down_face:

Hi,
I manage to get the run-time statistics
With the TouchGFX task:

MainTask 39225 < 1
LogTask 2496 < 1
IDLE 57369563 96
IP - Task 5719 < 1
EMAC 5991 < 1
TouchGFX 1826361 3
Tmr Svc<NUL>

MainTask 39876 < 1
LogTask 2539 < 1
IDLE 58341883 96
IP - Task 5797 < 1
EMAC 6098 < 1
Tmr Svc 6 < 1
TouchGFX<NUL>

And without the TouchGFX task

MainTask 261525 < 1
LogTask 945 < 1
IDLE 44976011 99
IP - Task 4420 < 1
EMAC 4189 < 1
Tmr Svc 6 < 1

MainTask 261858 < 1
LogTask 967 < 1
IDLE 45975511 99
IP - Task 4476 < 1
EMAC 4278 < 1
Tmr Svc 6 < 1

So the TouchGFX task is not consuming so much MPU. Those really useful statistics, are not so helpful for my problem! :thinking: With 95% of idle time, the IP task should be capable to answer all the ping no?

Just one question. Do you know why sometime there is a instead of the complete statistics?

Thank you

Yes, it should. Just to confirm, you are talking about ICMP pings? Is it possible for you to capture network traffic?

This line seems incomplete. If you are asking about <1%, that you can see here - when the percentage is zero, it is shown as <1%.

Hello,

Yes, I’m talking about ICMP pings. With Wireshark I can see the ping requests, and some get a reply, and some other not. When there is a reply, it is within 1ms (more 0.2ms)

I was talking about the “<NUL>” (sorry, is was not displayed in my question). The problem was in the UDPLogging task is was using. The buffer was too short for a correct display

Still investigating. I have simplified the TouchGFX task. Less than 3%, still got not response.

When there is no response, the ProcessICMPPacket() function is not called.

Can you check if prvNetworkInterfaceInput and prvPassEthMessages are getting called?

Also, what is configASSERT defined to in your FreeRTOSConfig.h?

Both functions seems to be called. Just I’m not sure it is because of ping. The ping is send form a Windows PC, and there are other packet being send

Edit:
I have build a network with just to board, so no other frame than ICMP Ping. And Yes, the functions are called, even when there is no outgoing ping

configASSERT( x ) if ( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;;); }

This functions are called when a packet is received by the device. The next step is to follow the path - prvHandleEthernetPacket --> prvProcessEthernetPacket --> prvProcessIPPacket --> ProcessICMPPacket and try to see why ProcessICMPPacket is not getting called.

Hello,

I have done some tests. With various results.

Sometime, prvProcessEthernetPacket is called, but when checking pxEthernetHeader->usFrameType it is seen as an ipARP_FRAME_TYPE and not a ipIPv4_FRAME_TYPE.

In other case, ProcessICMPPacket is called and return with eReturnEthernetFrame.
Finaly, xNetworkInterfaceOutput is called and return pdPASS but no response is seen from the Ping sender.

Thank you for doing those investigations - great work! I assume both the findings are for dropped PING responses.

This is okay as it means that the received packet is ARP packet.

This is problematic - We need to trace down what is happening here. Are we not even handing the packet to NIC or are we handing the packet to NIC and it is not putting it on wire?

Yes indeed

Sorry i am not pro to TCP-IP but why do the board receive ARP packet while Ping is ICMP?

I had another case where, in the prvProcessIPPacket, is stop after check APR resolution because the response of xCheckRequiredARPResolution was not true and so eRetrun = eWaitingARPResolution

But maybe it is the same case as previous

I will have a look to that! Tomorow.
Thank you

ARP is used for translating IP addresses to MAC address. It may be a broadcast ARP request for some other IP.

Hello,

Still investigating on the problem. I just reproduce it. Seems the xNetworkInterfaceOutput execute to the end and the xReturn = pdPASS I will have to go down in the code!

Ok, but why does the board receive only ARP packet while it should receive ICMP packet.

One of the case I have seen today, is:

  • Packet is received and prvProcessIPPacket is called
  • There is a xCheckRequiresARPResolution that return pdTrue. After that the ProcessICMPPacket is not called. at the end, FreeRTOS_OutputARPRequest is called.

I have seen it on the first ping. So maybe it is a normal behavior? Seems strange to me!

So, I think I have found the solution. I just made 962 ping with a 100% response!

In the networkinterface.c, there is a DMA definition (RX and TX) defined as:

/* Ethernet Rx MA Descriptor */
__attribute__((aligned(32))) __attribute__((section(".first_data")))ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB];

In the original eth.c file from the STM32Cube, the DMA are defined as:

ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((
    section(".RxDecripSection")));

ETH_RXBUFNB and ETH_RX_DESC_CNT are both defined as ‘4’.

I was using the one define in networkinterface.c. Removing this definion and using an

extern ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]

seems to solve the problems.

Thank you for reporting this.