Issue with TCP Echo Qemu mps2 Demo

Hi I am quite new to FreeRTOS here and am learning about it’s internals.
I am trying to run the Demo FreeRTOS_Plus_TCP_Echo_Qemu_mps2 with no modifications other than the information specific to my network. Trying to run the Demo as I want to build on it to simulate with MQTT on Qemu on linux. I’m currently running Ubuntu 21.10.
I’m finding that the application hangs after recieving an ARP response. After using the traceARP_PACKET_RECEIVED() and iptraceCREATING_ARP_REQUEST( ulIPAddress ) macros I can see that an ARP request goes out but none is received.
When using the Debugger it seems to end up in this function in defined in main.c:

void vAssertCalled( void )
{
    volatile unsigned long looping = 0;
    taskENTER_CRITICAL();
    {
        /* Use the debugger to set ul to a non-zero value in order to step out
                of this function to determine why it was called. */
        while( looping == 0LU )
        {
            portNOP();
        }
    }
    taskEXIT_CRITICAL();
}

After changing the while loop check to be
while( looping == 1LU )
the program seems to continue, the ARP response is received and a message is received on the echo server.
I’m not sure exactly what is causing this but I suspect it has something to do with task priorities.
vAssertCalled is called after a call to taskENTER_CRITICAL(); inside xQueueSemaphoreTake. I’d like to understand better for future reference.

Please provide a link to the assert that is failing. Here is an example of how to link to a line in github: https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/V10.4.6/queue.c#L1507 - as you see from the URL, that is linking to line 1507, which is an assert in xQueueSemaphoreTake() - but it’s not inside a critical section.

Unfortunately as a new user I’m not allowed to post links. Apologies I think I was mistaken earlier, it is not being called from xQueueSemaphoreTake. After looking through the call stack configASSERT() is being called from FreeRTOS/FreeRTOS-Kernel/portable/GCC/ARM_CM3/port.c line 688.
ucCurrentPriority is set as 0.
It was called from vTaskNotifyGiveFromISR FreeRTOS/FreeRTOS-Kernel/tasks.c line 5157 which was in turn called from EthernetISR FreeRTOS/FreeRTOS-Plus-TCP/source/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c line 208.
It seems to be a task priority issue.

In which case it sounds like you haven’t set the priority of the interrupt - it has to be less than or equal to whatever you set configMAX_SYSCALL_INTERRUPT_PRIORITY to. I think the code comments where the assert is will help - also this page https://freertos.org/RTOS-Cortex-M3-M4.html

It is however one of the demo applications supplied (and I have made no modifications other than relevant network configuration) so the interrupt priorities have already been defined in FreeRTOSConfig.h and FreeRTOSIPConfig.h. As I understand it these priorities wouldn’t change based on running on a different linux distro/version? No where in the readme is it mentioned. I have read through that document and tried to alter interrupt priorities to values I thought were reasonable with no luck.

I will see if we can replicate it here. It is possible the QEMU version may make a difference as the version used during testing implemented eight priority bits - which no real Cortex-M devices do - and if there were eight you would not hit that assert.

Has anyone advanced the ball on this issue? I seem to be having the same problem, when I run it the logging stops at:

0x2000bbe8->prvTCPPrepareConnect 1198: ARP for a000071ip (using a000071ip): rc=0 00:00:00 00:00:00

When I run a Wireshark capture on virbr0-nic I see the ARP request and response from the echo server, but the application does not seem to process it.

Similarly if I run with DHCP enabled, the logging at:

0x2000bc20->prvSendDHCPDiscover 1187: vDHCPProcess: discover

In Wireshark I can see the DHCP request and response.

OK, so I ran it in the debugger and found out the EthernetISR was failing vPortValidateInterruptPriority at line 688 because ISRs are all set in FreeRTOS to run at priority 0 by default and to satisfy the configASSERT it must be >= ucMaxSysCallPriority (5).

I got the demo working by adding NVIC_SetPriority(13, 6) to the _start function. The comments to the isr_vector table note that although EthernetISR is at element 29, internally there is an offset so that NVIC_SetPriority expects 13.

Thank you for taking time to report your solution. Would you create a PR for this or would you like us to do that?

Since I am new to this, I would prefer that you did it. Then after I take a look at what it looks like maybe I can start reporting them going forward.

I would also alert you to the fact that the method of retrieving the ulCurrentInterrupt on line 657 of port.c returns the priority with the bits shifted left as contained in the register, while configASSERT on line 688 incorrectly compares this shifted value with the un-shifted ucMaxSysCallPriority. So in my case, with ucMaxSysCallPriority set at 5, if I had set the priority of EthernetISR to 4, the comparison of the shifted value would be 128 >= 5, which would incorrectly succeed! As currently configured the configASSERT only catches the case where the ISR priority is defaulted to zero.

That is not correct. As described on this page, configMAX_SYSCALL_INTERRUPT_PRIORITY is shifted already -

The configMAX_SYSCALL_INTERRUPT_PRIORITY and configKERNEL_INTERRUPT_PRIORITY settings found in FreeRTOSConfig.h require their priority values to be specified as the ARM Cortex-M core itself wants them - already shifted to the most significant bits of the byte.

Here is an example - https://github.com/FreeRTOS/FreeRTOS/blob/main/FreeRTOS/Demo/CORTEX_MPU_M7_NUCLEO_H743ZI2_GCC_IAR_Keil/Config/FreeRTOSConfig.h#L118

Thanks.

That makes a lot more sense! But as jasUman noted above I’m just running this demo “as is”. In the FreeRTOSConfig.h in this demo, configMAX_SYSCALL_INTERRUPT_PRIORITY is simply defined as 5. And configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY and configPRIO_BITS are not even defined in my build. As I stated, when I run in the debugger, I see ucMaxSysCallPriority set to 5 when I break at line 688 of port.c. If I define configMAX_SYSCALL_INTERRUPT_PRIORITY to 0xA0, then I see that.

Thank you for reporting. We will get that fixed.