Is there a mechanism for a new task to copy data pointed to by *pvParameters to be saved by the new task before the calling task (the one that calls xTaskCreate) erases the memory?
So a structure is created on a local stack,
xTaskCreate called, and returns
When can the function release the stack memory - when has the new task taken its copy of the data?
Do I need an interlock, a flag in the structure that is cleared by the new task when it has its copy, or another signalling method?
If I get your question right, you have task A that creates task B, and task B wants some to copy some stack (that is not static) data from task A but does not know if the data is still valid or not as task A may have gone away and done something else. pvParameters being used to point to the data.
You can achieve this by having task A create task B at a priority higher than task A. This way you are guaranteed that task B will run before task A even exits the xTaskCreate() function. Once task B has got the data it requires it can set its own priority to its real wanted value.
I had a situation where trimming task priorities resulted in a NULL pointer reference, which scared me slightly.
Also the code to start the new task was a function call used by lots of tasks of differing priorities.
The way I got round this was to use pvPortMalloc() and let the newly generated task free the memory using vPortFree().
WHAT DOES THE CODE DO?
Its a one shot timer. It fires off a new tasks that waits for the specified period of time, posts a message to a queue and then destroys itself.
HOW?
I allocate memory for a ‘param_*’ struct and stuff it with local variables from calling task
A new task is started and receives a pointer to the struct. The struct is cast to access data. Once used it can be freed.
CONCLUSION
It did strike me as a safe way, but rather long winded.
Has anyone else solved this problem in a less round about way?
int
TaskStart_OneShotTimer (portTickType timerperiod, uint32_t event, uint32_t data)
{
int retval = PASS;
param_oneshottimer_t *param_oneshottimer;
// Allocate storage for the timer variables. Pointer to this is
// passed to the task and used by the task created
param_oneshottimer = ( param_oneshottimer_t * )
pvPortMalloc( sizeof( param_oneshottimer_t ) );
// Assign passed arguments to the task
param_oneshottimer->timerperiod = timerperiod;
param_oneshottimer->event = event;
param_oneshottimer->data = data;
// Pass arguments to the task that starts the timer
if (xTaskCreate
(Task_OneShotTimer, "OneShotTimer", TASKSTACK_TIMER,
(void *)param_oneshottimer, (tskIDLE_PRIORITY + 3),
(xTaskHandle *) NULL) != PASS)
{
retval = FAIL;
}
return (retval);
}
static
portTASK_FUNCTION (Task_OneShotTimer, pvParameters)
{
// Cast data passed to task
param_oneshottimer_t *prt_param_oneshottimer;
prt_param_oneshottimer = (param_oneshottimer_t *) pvParameters;
// Wait for the specified period of time
vTaskDelay(prt_param_oneshottimer->timerperiod);
// We have waited the required amount of time. Post the required
// message to the queue
MessageQueueSendData(prt_param_oneshottimer->event,
prt_param_oneshottimer->data, "oneshottimer");
// Deallocate memory used
vPortFree( (void *)prt_param_oneshottimer );
// Now delete the task
vTaskDelete (NULL);
}