3

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)
            ;
    }
}
Martin Denion
  • 352
  • 1
  • 3
  • 22

0 Answers0