Home > Net >  How to pass a structure as a parameter when creating a FreeRTOS task?
How to pass a structure as a parameter when creating a FreeRTOS task?

Time:12-22

I am currently working on the Cortex-M4 of the NXP i.MX8 M Mini processor. I am developing the application of the M4 (OS FreeRTOS). What I would like to do is to fill a structure, create a task, pass this structure as a parameter to this task and reuse this structure in this task.

However, I can't get the values of the structure passed as parameter in the created task. At compile time, I get "warning: dereferencing 'void *' pointer" or "error: request for member 'my_rpmsg' in something not a structure or union"

Here is my code :

/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rpmsg_lite.h"
#include "rpmsg_queue.h"
#include "rpmsg_ns.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_debug_console.h"
#include "FreeRTOS.h"
#include "task.h"

#include "fsl_uart.h"
#include "rsc_table.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_TASK_STACK_SIZE (256)
#define RPMSG_RX_TASK_STACK_SIZE (256)
#define RPMSG_TX_TASK_STACK_SIZE (256)
#ifndef LOCAL_EPT_ADDR
#define LOCAL_EPT_ADDR (30)
#endif

/* Globals */
static char app_buf[512]; /* Each RPMSG buffer can carry less than 512 payload */

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

/*******************************************************************************
 * Code
 ******************************************************************************/
static TaskHandle_t rpmsg_task_handle = NULL;
static TaskHandle_t rpmsg_tx_task_handle = NULL;

struct rpmsg_struct
{
    struct rpmsg_lite_endpoint *volatile my_ept;
    volatile rpmsg_queue_handle my_queue;
    struct rpmsg_lite_instance *volatile my_rpmsg;
};

static void rpmsg_tx_task(void *param)
{
    volatile uint32_t remote_addr;
//    struct rpmsg_lite_endpoint *volatile my_ept;
//    volatile rpmsg_queue_handle my_queue;
//    struct rpmsg_lite_instance *volatile my_rpmsg;
    void *rx_buf;
    uint32_t len;
    int32_t result;
    void *tx_buf;
    uint32_t size;

    /* Print the initial banner */
    PRINTF("\r\nRPMSG String Echo FreeRTOS RTOS API Demo...\r\n");

    for (;;)
    {
        /* Get RPMsg rx buffer with message */
        result =
            rpmsg_queue_recv_nocopy(param->my_rpmsg, param->my_queue, (uint32_t *)&remote_addr, (char **)&rx_buf, &len, RL_BLOCK);
        if (result != 0)
        {
            assert(false);
        }

        /* Copy string from RPMsg rx buffer */
        assert(len < sizeof(app_buf));
        memcpy(app_buf, rx_buf, len);
        app_buf[len] = 0; /* End string by '\0' */

        if ((len == 2) && (app_buf[0] == 0xd) && (app_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_buf, len);

        /* Get tx buffer from RPMsg */
        tx_buf = rpmsg_lite_alloc_tx_buffer(param->my_rpmsg, &size, RL_BLOCK);
        assert(tx_buf);
        /* Copy string to RPMsg tx buffer */
        memcpy(tx_buf, app_buf, len);
        /* Echo back received message with nocopy send */
        result = rpmsg_lite_send_nocopy(param->my_rpmsg, param->my_ept, remote_addr, tx_buf, len);
        if (result != 0)
        {
            assert(false);
        }
        /* Release held RPMsg rx buffer */
        result = rpmsg_queue_nocopy_free(param->my_rpmsg, rx_buf);
        if (result != 0)
        {
            assert(false);
        }
    }
}

static void rpmsg_task(void *param)
{
    static struct rpmsg_struct my_rpmsg_struct;

    /* Print the initial banner */
    PRINTF("\r\nRPMSG String Echo FreeRTOS RTOS API Demo...\r\n");

#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 */

    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");

    if (xTaskCreate(rpmsg_tx_task, "rpmsg_tx_task", RPMSG_TX_TASK_STACK_SIZE, &my_rpmsg_struct, tskIDLE_PRIORITY   1, &rpmsg_tx_task_handle) != pdPASS)
    {
        PRINTF("\r\nFailed to create rpmsg_tx_task\r\n");
        for (;;)
            ;
    }
}

/*!
 * @brief Main function
 */
int main(void)
{
    /* 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 */

    if (xTaskCreate(rpmsg_task, "rpmsg_task", RPMSG_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY   1, &rpmsg_task_handle) != pdPASS)
    {
        PRINTF("\r\nFailed to create rpmsg_rx_task\r\n");
        for (;;)
            ;
    }

    vTaskStartScheduler();

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

CodePudding user response:

  1. You overuse volatile. None of your volatiles are needed in this code.
  2. Your pmsg_task exits by return after creating rpmsg_tx_task. It is bad for two reasons. You pass the reference to the local to the other task and then exit the function. It is undefined behaviour. The second reason is - you cant terminate tasks this way. You need to call vTaskDelete function with the task handle or NULL if you delete the current task.
  3. You need to learn a bit of the C language - especially pointers, types, casting, scopes etc before programming embedded targets with RTOS. It requires a very good knowledge of the C language. You are trying to dereference the void * pointer. This kind of pointer does not have any type information. Even if you passed a pointer to struct it still references no type. You need to cast or use the temp variable.
struct rpmsg_struct *paramstruct = param;
paramstruct -> ...

or

((struct rpmsg_struct *)param) -> ....

CodePudding user response:

From the reference of xTaskCreate(), a private parameter can be passed into it that shall be supplied as the argument to the task entry function. So something like

:
struct rpmsg_struct* pvtParam = calloc(1, struct rpmsg_struct);

if (xTaskCreate(rpmsg_task, "rpmsg_task", RPMSG_TASK_STACK_SIZE, pvtParam /* pass it here*/, tskIDLE_PRIORITY   1, &rpmsg_task_handle) != pdPASS)
{
:

and then in the rpmsg_task function, one can just cast the incoming parameter back to a struct rpmsg_struct

static void rpmsg_task(void *param)
{
   struct rpmsg_struct* my_rpmsg_struct = param;
   :

Note that the pvtParam is created on the heap (via calloc in this example) and not on the stack to avoid cases of the stack variable going our of scope during the task's lifecycle.

  • Related