Search code examples
scheduled-tasksreal-timeschedulingvxworksrtos

Delayed task never returns back


A task spawned from shell (t2) instantiates a new task (tTask1). t2's priority is 100 and tTask1's priority is 120 which is lover than t2. t2 is running until it's first delayed state and never come back again so that tTask1 stays suspended state and can't resume again. I couldn't find what causes the problem. Here is my code:

include "vxWorks.h"
#include <iostream.h>
#include "taskLib.h"
#include "sysLib.h"


VX_TASK(tTask1,20000);
int tickCount = 0;
int oldTickValue = 0;

#define SCHEDULER_ERROR -1
#define SCHEDULER_WORKING 0


void subTask()
{
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        std::cout << "sub Task " << i << std::endl;
    }
}

bool isTickChanged() {
    uint32_t newTickValue;
    bool flag;
    flag = false;
    newTickValue = tickCount;
    std::cout << "newTickValue = " << newTickValue << std::endl;
    if (newTickValue != oldTickValue)
    {
        if (1U < (newTickValue - oldTickValue))
        {
            std::cout << "scheduler error = " << newTickValue << std::endl;
        }
        else
        {
            std::cout << "scheduler is working = " << newTickValue << std::endl;
        }

        flag = true;
        oldTickValue = newTickValue; 
    }
    return flag;
}

void timerHandler()
{
    ++tickCount;
}

void task1()
{
    std::cout << "task 1 begin" << std::endl;
    sysAuxClkEnable();
    sysAuxClkRateSet(10);            
    sysClkConnect( reinterpret_cast<FUNCPTR>(timerHandler), NULL );
    std::cout << "Aux Clock Rate = " <<  sysAuxClkRateGet( ) << std::endl;

    while(1)
    {
        if (isTickChanged())
        {               
            std::cout << "task 1 tick changed" << std::endl;
            subTask();
            taskSuspend(0);
        }

    }
}

void sch(void)
{
    int myTaskId;
    myTaskId = VX_TASK_INSTANTIATE(tTask1, 120,  VX_FP_TASK|VX_SUPERVISOR_MODE|VX_DEALLOC_STACK|VX_STDIO|VX_DEALLOC_EXC_STACK|VX_DEALLOC_TCB|VX_SPE_TASK, 20000, (FUNCPTR) task1, 0,0,0,0,0,0,0,0,0,0);
    FOREVER {
        taskResume(myTaskId);
        taskDelay(10);
    }


}

and output like below:

-> sp sch
Task spawned: id = 0x1897c00, name = t2
value = 25787392 = 0x1897c00
-> task 1 begin
Aux Clock Rate = 10
newTickValue = 0
newTickValue = 0
newTickValue = 0
newTickValue = 0
newTickValue = 0
newTickValue = 0
newTickValue = 0
newTickValue = 0
newTickValue = 1
scheduler working = 1
task 1 tick changed
sub Task 0
sub Task 1
sub Task 2

t2 is waiting in "delayed" state and tTask1 is waiting in "suspended" state.


Solution

  • The OS timer related functions, such as taskDelay(), require that the kernel gets notice of a timer tick. The kernel can't do anything time related if it's not getting those tick notifications. With VxWorks, I believe you're supposed to call tickAnnounce() in order to notify the kernel of a tick.

    But in your task1() function you call sysClkConnect() and register your timerHandler() routine. timerHandler() only increments your application's tickCount and it does not notify the kernel of the tick. So the kernel has no way of knowing that a tick occurred so it will be unable to track time and the taskDelay() function will not work.

    I guess you could call tickAnnounce() from your timerHandler() routine and that might fix the problem. But it seems strange to me that you're replacing the system tick handler with something for your application. Shouldn't your application use another timer, or perhaps a software timer service provided by the OS, rather than repurposing the system clock?