xQueueReceive blocks the execution of other tasks

I am developing a FreeRTOS application on a Cortex-M4 (NXP i.MX8MM) that creates 4 tasks.
The first task is waiting to receive a character on a UART. As soon as a buffer is received, it is sent to task 3 with xQueueSend.
The second task is the transmission task via the UART. It waits permanently for the reception of a buffer (sent by task 4) with xQueueReceive.

Currently, I manage to create these 4 tasks, but only the first 2 are executed. I have the impression that the second task, and particularly the “xQueueReceive” function, is blocking (or not executing properly) the execution of the last 2 tasks. If I comment out the “xQueueReceive” function, all tasks run without any problem. All configASSERT in the xQueueReceive function pass without problem.

Where do you think this can come from?

My code:

main.c


/* System includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Kernel includes */
#include "FreeRTOS.h"
#include "task.h"
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "rsc_table.h"

/* Other includes */
#include "A_version.h"
#include "A_rpmsg.h"
#include "A_ip_task.h"
#include "A_queue.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Globals
 ******************************************************************************/
/* Queue RPMSG -> UART RS-485 */
static QueueHandle_t rpmsg_to_uart_queue = NULL;
/* Queue RPMSG <- UART RS-485 */
static QueueHandle_t uart_to_rpmsg_queue = NULL;
/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Code
 ******************************************************************************/

/*!
 * @brief Main function
 */
int main(void)
{
	uint8_t status = 1;

    /* Initialize standard SDK demo application pins */
    /* Board specific RDC settings */
    BOARD_RdcInit();

    BOARD_InitBootPins();
    BOARD_BootClockRUN();
    BOARD_InitDebugConsole();
    BOARD_InitMemory();

    copyResourceTable();

#ifdef MCMGR_USED
    /* Initialize MCMGR before calling its API */
    (void)MCMGR_Init();
#endif /* MCMGR_USED */

    PRINTF("Start Appli_metier: %s\r\n", NUM_ET_DATE_VERSION_CARTE_CM);

    /* Chargement des paramètres de l'UART */
    F_ip_485_load_params();

    /* Initialisation de l'UART */
    status = F_init_ip_485();

    /* Initialisation de RPMsg */
    if(status != 0)
    {
    	PRINTF("ERROR INIT UART\r\n");
    } else {
    	status = rpmsg_init();
    }

	rpmsg_to_uart_queue = xQueueCreate(10, sizeof(struct Message *));
	if (rpmsg_to_uart_queue != NULL)
	{
		vQueueAddToRegistry(rpmsg_to_uart_queue, "RPMsg to UART queue");
	}

	uart_to_rpmsg_queue = xQueueCreate(10, sizeof(struct Message *));
	if (uart_to_rpmsg_queue != NULL)
	{
		vQueueAddToRegistry(uart_to_rpmsg_queue, "UART to RPMsg queue");
	}

    /* Lancement des taches */
    if(status != 0)
    {
    	PRINTF("ERROR INIT RPMSG\r\n");
    } else {
    	PRINTF("Avant F_ip_485_task\r\n");
        /* Lancement de la tache UART */
    	F_ip_485_task(rpmsg_to_uart_queue, uart_to_rpmsg_queue);

    	PRINTF("Avant rpmsg_task\r\n");
        /* Lancement de la tache RPMSG (cote A53) */
        rpmsg_task(rpmsg_to_uart_queue, uart_to_rpmsg_queue);
    }

    vTaskStartScheduler();

    PRINTF("Failed to start FreeRTOS on core0.\n");
    for (;;)
        ;
}

tasks 1 and 2:

#include "A_ip_task.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "board.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

#include "fsl_debug_console.h"

#include "A_ip_485.h"
#include "A_queue.h"


/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define IP_485_RX_TASK_STACK_SIZE (256)
#define IP_485_TX_TASK_STACK_SIZE (256)

#define MAX_BUF_TRAME_ETHERNET 1520

/* Task priorities. */
#define hello_task_PRIORITY (configMAX_PRIORITIES - 1)

#define TASK_DELAY_IP_485 200
/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/*******************************************************************************
 * Variables
 ******************************************************************************/
typedef struct _uart_struct
{
	QueueHandle_t my_queue_to_uart;
	QueueHandle_t my_queue_to_rpmsg;
} uart_struct;

static uart_struct my_uart_struct;

static TaskHandle_t ip_485_rx_task_handle = NULL;
static TaskHandle_t ip_485_tx_task_handle = NULL;

STRUCT_parametre_uart S_device_UART[NBR_MAX_UART];

unsigned char TUCH_ip_485_buffer[MAX_BUF_TRAME_ETHERNET];

static void F_ip_485_rx_task(void *pvParameters)
{
	uart_struct * param_struct = pvParameters;
	Message st_msg;
	uint16_t UI_lg;
	/* Block for 5µs. */
	const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);

	PRINTF("\r\nF_ip_485_rx_task running ...\r\n");

	/* On attend la réception d'une trame sur la file */
    for (;;)
    {
		if ((UI_lg = F_driverUART_read(UART_IP485, TUCH_ip_485_buffer, MAX_BUF_TRAME_ETHERNET)) != 0)
		{
			//TODO: F_traitement_RX_IP_485(TUCH_ip_485_buffer, UI_lg); /* Traitement dans MQX */
			/* Remplacer par écriture dans la queue de RPMsg pour envoi vers Cortex-A53 */
			st_msg.size = UI_lg;
			xQueueSend(param_struct->my_queue_to_rpmsg, (void *)&st_msg, 10);
		}
		vTaskDelay(xDelay);
    }
    vTaskSuspend(NULL);
}

static void F_ip_485_tx_task(void *pvParameters)
{
	uart_struct * param_struct = pvParameters;
	Message rcv_msg;
	/* Block for 5µs. */
	const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);

	PRINTF("\r\nF_ip_485_tx_task running ...\r\n");

    for (;;)
    {
		if (xQueueReceive(param_struct->my_queue_to_uart, (void *)&rcv_msg, 0) != pdTRUE)
		{
			PRINTF("Failed to receive queue.\r\n");
		}
		else
		{
			/* On envoie tous les octets */
			F_driverUART_IP485_write(rcv_msg.body, rcv_msg.size);
		}
		vTaskDelay(xDelay);
    }
    vTaskSuspend(NULL);
}

void F_ip_485_task(QueueHandle_t r_to_u, QueueHandle_t u_to_r)
{
	my_uart_struct.my_queue_to_uart = r_to_u;
	my_uart_struct.my_queue_to_rpmsg = u_to_r;

    if (xTaskCreate(F_ip_485_rx_task, "IP 485 RX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &ip_485_rx_task_handle) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;    }

    if (xTaskCreate(F_ip_485_tx_task, "IP 485 TX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &ip_485_tx_task_handle) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
}

tasks 3 and 4:

#include "A_rpmsg.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "board.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

#include "rpmsg_lite.h"
#include "rpmsg_queue.h"
#include "rpmsg_ns.h"

#include "A_queue.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define RPMSG_LITE_SHMEM_BASE         (VDEV0_VRING_BASE)
#define RPMSG_LITE_LINK_ID            (RL_PLATFORM_IMX8MM_M4_USER_LINK_ID)
#define RPMSG_LITE_NS_ANNOUNCE_STRING "rpmsg-virtual-tty-channel-1"
#define RPMSG_RX_TASK_STACK_SIZE (128)
#define RPMSG_TX_TASK_STACK_SIZE (128)
#ifndef LOCAL_EPT_ADDR
#define LOCAL_EPT_ADDR (30)
#endif

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

typedef struct _rpmsg_struct
{
	struct rpmsg_lite_endpoint *volatile my_ept;
	volatile rpmsg_queue_handle my_queue;
	struct rpmsg_lite_instance *volatile my_rpmsg;
	QueueHandle_t my_queue_to_uart;
	QueueHandle_t my_queue_to_rpmsg;
} rpmsg_struct;

static TaskHandle_t rpmsg_rx_task_handle = NULL;
static TaskHandle_t rpmsg_tx_task_handle = NULL;

static SemaphoreHandle_t mutex;

static rpmsg_struct my_rpmsg_struct;

static volatile uint32_t remote_addr;

static char app_rx_buf[1500]; /* Each RPMSG buffer can carry less than 512 payload */
static char app_tx_buf[1500]; /* Each RPMSG buffer can carry less than 512 payload */

static void rpmsg_rx_task(void *param)
{
	rpmsg_struct * param_struct = param;
	Message st_msg;
    volatile uint32_t local_remote_addr;
    void *rx_buf;
    uint32_t len;
    int32_t result;
    void *tx_buf;
    uint32_t size;
    boolean init = false;

    /* Block for 5µs. */
    const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);

    for (;;)
    {
        /* Get RPMsg rx buffer with message */
        result =
            rpmsg_queue_recv_nocopy(param_struct->my_rpmsg, param_struct->my_queue, (uint32_t *)&remote_addr, (char **)&rx_buf, &len, RL_BLOCK);
        if (result != 0)
        {
            assert(false);
        } else {
            PRINTF("RPMsg received !\r\n");
        }

        /* Copy string from RPMsg rx buffer */
        assert(len < sizeof(app_rx_buf));
        memcpy(st_msg.body, rx_buf, len);
        st_msg.size = len;
        xQueueSend(param_struct->my_queue_to_uart, (void *)&st_msg, 10);
        //app_rx_buf[len] = 0; /* End string by '\0' */

        if ((len == 2) && (app_rx_buf[0] == 0xd) && (app_rx_buf[1] == 0xa))
            PRINTF("Get New Line From Master Side\r\n");
        else
            PRINTF("Get Message From Master Side : \"%s\" [len : %d]\r\n", app_rx_buf, len);

        if(!init) {
            local_remote_addr = remote_addr;

            // Release the mutex so that the creating function can finish
            xSemaphoreGive(mutex);

            init = true;
        }

        /* Release held RPMsg rx buffer */
        result = rpmsg_queue_nocopy_free(param_struct->my_rpmsg, rx_buf);
        if (result != 0)
        {
            assert(false);
        }
    }
    vTaskSuspend(NULL);
}

static void rpmsg_tx_task(void *param)
{
	rpmsg_struct * param_struct = param;
	Message rcv_msg;
    volatile uint32_t local_remote_addr;
    void *rx_buf;
    uint32_t len;
    int32_t result;
    void *tx_buf;
    uint32_t size;

	/* Block for 5µs. */
	const TickType_t xDelay = 5 / (portTICK_PERIOD_MS * 1000);

    /* On attend de recevoir l'adresse de destination */
    PRINTF("\r\nM4 waiting for destination address ...\r\n");

    // Take the mutex
    xSemaphoreTake(mutex, portMAX_DELAY);

    local_remote_addr = remote_addr;

    for (;;)
    {
        if (xQueueReceive(param_struct->my_queue_to_rpmsg, (void *)&rcv_msg, portMAX_DELAY) != pdTRUE)
        {
            PRINTF("Failed to receive queue.\r\n");
        }
        else
        {
            /* Get tx buffer from RPMsg */
            tx_buf = rpmsg_lite_alloc_tx_buffer(param_struct->my_rpmsg, &size, RL_BLOCK);
            assert(tx_buf);

            /* Copy string to RPMsg tx buffer */
            memcpy(tx_buf, rcv_msg.body, rcv_msg.size);
            /* Echo back received message with nocopy send */
            result = rpmsg_lite_send_nocopy(param_struct->my_rpmsg, param_struct->my_ept, local_remote_addr, tx_buf, rcv_msg.size);
            if (result != 0)
            {
                assert(false);
            } else {
                PRINTF("RPMsg sent !\r\n");
            }
        }
    }
    vTaskSuspend(NULL);
}

uint8_t rpmsg_init(QueueHandle_t r_to_u, QueueHandle_t u_to_r)
{
	uint8_t status;

#ifdef MCMGR_USED
    uint32_t startupData;

    /* Get the startup data */
    (void)MCMGR_GetStartupData(kMCMGR_Core1, &startupData);

    my_rpmsg = rpmsg_lite_remote_init((void *)startupData, RPMSG_LITE_LINK_ID, RL_NO_FLAGS);

    /* Signal the other core we are ready */
    (void)MCMGR_SignalReady(kMCMGR_Core1);
#else
    my_rpmsg_struct.my_rpmsg = rpmsg_lite_remote_init((void *)RPMSG_LITE_SHMEM_BASE, RPMSG_LITE_LINK_ID, RL_NO_FLAGS);
#endif /* MCMGR_USED */

    PRINTF("En attente du chargement du module RPMsg...\r\n");

    while (0 == rpmsg_lite_is_link_up(my_rpmsg_struct.my_rpmsg))
        ;

    my_rpmsg_struct.my_queue = rpmsg_queue_create(my_rpmsg_struct.my_rpmsg);
    my_rpmsg_struct.my_ept   = rpmsg_lite_create_ept(my_rpmsg_struct.my_rpmsg, LOCAL_EPT_ADDR, rpmsg_queue_rx_cb, my_rpmsg_struct.my_queue);
    (void)rpmsg_ns_announce(my_rpmsg_struct.my_rpmsg, my_rpmsg_struct.my_ept, RPMSG_LITE_NS_ANNOUNCE_STRING, RL_NS_CREATE);

    PRINTF("\r\nNameservice sent, ready for incoming messages...\r\n");

    // Create mutex before starting tasks
    mutex = xSemaphoreCreateMutex();

    // Take the mutex
    if(xSemaphoreTake(mutex, portMAX_DELAY) == pdTRUE)
    {
    	status = 0;
    } else {
    	status = -1;
    }

    return status;
}

void rpmsg_task(QueueHandle_t r_to_u, QueueHandle_t u_to_r)
{
	my_rpmsg_struct.my_queue_to_uart = r_to_u;
	my_rpmsg_struct.my_queue_to_rpmsg = u_to_r;

    if (xTaskCreate(rpmsg_rx_task, "RPMSG RX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &rpmsg_rx_task_handle) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }

    if (xTaskCreate(rpmsg_tx_task, "RPMSG TX", configMINIMAL_STACK_SIZE + 100, NULL, tskIDLE_PRIORITY + 1, &rpmsg_tx_task_handle) !=
        pdPASS)
    {
        PRINTF("Task creation failed!.\r\n");
        while (1)
            ;
    }
}

Are you talking about this call? Can you change portMAX_DELAY with a finite delay and see if is always timing out and never reeving anything? Then you’ll need to check the sender side.

You should check the return value to see if this send is successful.