AnsweredAssumed Answered

Call to _timer_start_periodic_at corrupts task descriptor list in kernel data

Question asked by Hugo Bouchard on Jul 21, 2015
Latest reply on Jul 23, 2015 by Hugo Bouchard

Hello all,

 

First, I'm using MQX 4.1 and CW 10.5.

 

I did a little application which has 3 tasks. One init task and two other tasks that I want to make cyclic. To do so, I create a periodic timer for each of my cyclic tasks and I pass the corresponding task descriptor pointer as timer callback function parameter. I did a test with one init and one cyclic task and it worked fine. Now with two tasks, it doesn't work at all, the task are not made ready by the timer callback function.

 

I tracked down the problem and I found out that when I call _timer_start_periodic_at() it create a timer task. In this creation of the task the function _task_alloc_td_internal() is called in file task.c. At line 3585 INSERT_TD_PTR pointer is copied into a local pointer (insert_td_ptr = kernel_data->INSERT_TD_PTR;). This line corrupts the TD_LIST in kernel data:

 

Before execution of line 3585 (TD_LIST is OK):

before.jpg

 

Before execution of line 3585 (TD_LIST is not OK):

 

after.jpg

 

I don't understand why this line does that because it should only modify a local variable. This variable is a pointer but the pointed value shouldn't be modified...

 

Here is a copy of my code in case you see something wrong:

 

TASK_TEMPLATE_STRUCT MQX_template_list[] =

{

/*  Task number,                        Entry point,       Stack,  Pri, String,          attr,                                       param,  time slice */

   {TASK_KU32_STARTUP,       TaskStartup,      100,    0,    "startup",      MQX_AUTO_START_TASK, 0,          0},

   {TASK_KU32_1MS_CYCLE,  Task1msCycle,  2000,  2,    "1 ms task",  0,                                          0,          0},

   {TASK_KU32_5MS_CYCLE,  Task5msCycle,  2000,  4,    "5 ms task",  0,                                          0,          0},

   {0,                                          0,                      0,        0,    0,                  0,                                          0,          0}

};

 

void TaskStartup(uint32_t u32Parameter)

{

    _task_id u32Task1msId;

    _task_id u32Task5msId;

    TIME_STRUCT stTimePtr;

    void * pvTaskDescriptor;

 

    /* To avoid unused parameter warning */

    u32Parameter = u32Parameter;

 

    /* Create tasks */

    u32Task1msId = _task_create_blocked(0U, TASK_KU32_1MS_CYCLE, 0U);

    u32Task5msId = _task_create_blocked(0U, TASK_KU32_5MS_CYCLE, 0U);

 

    /* If all tasks could be created */

    if(    (MQX_NULL_TASK_ID != u32Task1msId)

        && (MQX_NULL_TASK_ID != u32Task5msId) )

    {

        _time_get(&stTimePtr);              /* Get actual time */

 

        /**** Initialize periodic timers to make cyclic tasks ****/

 

        /*** 1 ms Task ***/

 

        pvTaskDescriptor = _task_get_td(u32Task1msId);

        (void)_timer_start_periodic_at(CallbackFct1msTimer, pvTaskDescriptor, TIMER_ELAPSED_TIME_MODE, &stTimePtr, (uint32_t)1);

 

        /*** 5 ms Task ***/

 

        pvTaskDescriptor = _task_get_td(u32Task5msId);

        (void)_timer_start_periodic_at(CallbackFct5msTimer, pvTaskDescriptor, TIMER_ELAPSED_TIME_MODE, &stTimePtr, (uint32_t)5);

    }

 

    /* Destroy task to avoid further call */

    _task_destroy(_task_get_id());

}

 

void Task1msCycle(uint32_t u32Parameter)

{

    /* To avoid unused parameter warning */

    u32Parameter = u32Parameter;

 

    while(1)

    {

        /* Do something */

        _task_block();

    }

}

 

void Task5msCycle(uint32_t u32Parameter)

{

    /* To avoid unused parameter warning */

    u32Parameter = u32Parameter;

 

    while(1)

    {

        /* Do something */

        _task_block();

    }

}

 

void CallbackFct1msTimer(_timer_id u32TimerId, void * pvTaskDescriptor, uint32_t u32Seconds, uint32_t u32MilliSeconds)

{

    /* To avoid unused parameter warnings */

    u32TimerId = u32TimerId;

    u32Seconds = u32Seconds;

    u32MilliSeconds = u32MilliSeconds;

 

    /* Set task ready cyclically when timer expires to make a cyclic task */

    _task_ready(pvTaskDescriptor);

}

 

void CallbackFct5msTimer(_timer_id u32TimerId, void * pvTaskDescriptor, uint32_t u32Seconds, uint32_t u32MilliSeconds)

{

    /* To avoid unused parameter warnings */

    u32TimerId = u32TimerId;

    u32Seconds = u32Seconds;

    u32MilliSeconds = u32MilliSeconds;

 

    /* Set task ready cyclically when timer expires to make a cyclic task */

    _task_ready(pvTaskDescriptor);

}

 

Does anyone have an idea of where the problem could come from?

 

Thanks

Hugo

Outcomes