Exemplo n.º 1
0
static void task00_class00(uint16_t initCondition)

{
    for(;;)
    {
        ++ _noLoopsTask00_C0;

        /* To see the stack reserve computation working we invoke a nested sub-routine
           after a while. */
        if(millis() > 20000ul)
            subRoutine(1);
        if(millis() > 30000ul)
            subRoutine(2);
        if(millis() > 40000ul)
            subRoutine(3);
        
        /* The next operation (Arduino delay function) takes the demanded world time in ms
           (as opposed to CPU time) even if it is interrupted because of an elapsed round
           robin counter.
             This task has a round robin time slice of 10 tics (20 ms) only, so it should
           surely be interrupted during execution of delay. The other round robin task has
           a time slice of 4 ms. No other tasks demand the CPU significantly. Consequently,
           the code in delay should not be interrupted for longer than about 4 ms. Coming
           back here means to immediately do the next check if the demanded time has
           elapsed. We expect thus to not prolongue the demanded time by more than about 4
           ms. */
        uint32_t ti0 = millis();
        delay(600 /* ms */);
        uint16_t dT = (uint16_t)(millis() - ti0);
        ASSERT(dT >= 599)
        ASSERT(dT < 609);

        /* Wait for an event from the idle task. The idle task is asynchrounous and its
           speed depends on the system load. The behavior is thus not perfectly
           predictable. Let's have a look on the overrrun counter for this task. It might
           occasionally be incremented. */
        if(rtos_waitForEvent( /* eventMask */ RTOS_EVT_EVENT_03 | RTOS_EVT_DELAY_TIMER
                            , /* all */ false
                            , /* timeout */ 1000 /* unit 2 ms */
                            )
           == RTOS_EVT_DELAY_TIMER
          )
        {
            ++ _task00_C0_cntWaitTimeout;
        }
    }
} /* End of task00_class00 */
static void subRoutine(uint8_t nestedCalls)
{
    volatile uint8_t stackUsage[43];
    if(nestedCalls > 1)
    {
        _touchedBySubRoutine += 2;
        stackUsage[0] =
        stackUsage[sizeof(stackUsage)-1] = 0;
        subRoutine(nestedCalls-1);
    }
    else
    {
        ++ _touchedBySubRoutine;
        stackUsage[0] =
        stackUsage[sizeof(stackUsage)-1] = nestedCalls;
    }
} /* End of subRoutine */
static void task00_class00(uint16_t initCondition)

{
    uint32_t ti1, ti2=0;

    for(;;)
    {
        ++ _noLoopsTask00_C0;

        /* To see the stack reserve computation working we invoke a nested sub-routine
           after a while. */
        if(millis() > 20000ul)
            subRoutine(1);
        if(millis() > 30000ul)
            subRoutine(2);
        if(millis() > 40000ul)
            subRoutine(3);

        /* Wait for an event from the idle task. The idle task is asynchrounous and its
           speed depends on the system load. The behavior is thus not perfectly
           predictable. */
        if(rtos_waitForEvent( /* eventMask */ RTOS_EVT_EVENT_03 | RTOS_EVT_DELAY_TIMER
                            , /* all */ false
                            , /* timeout */ 200 /*ms*/
                            )
           == RTOS_EVT_DELAY_TIMER
          )
        {
            ++ _task00_C0_cntWaitTimeout;
        }

        /* This tasks cycles with the lowest frequency, once per system timer cycle.
            CAUTION: Normally, this is not permitted. If the suspend time is more than
           half the range of the data type chosen for its system time RTuinOS is no longer
           capable to safely recognize task overruns. False recognitions would lead to bad
           task timing as the corrective action is to make the (only seemingly) late task
           due immediately. */
        rtos_suspendTaskTillTime(/* deltaTimeTillRelease */ 0);

        /* A task period of more than half the system timer cycle leads to a high
           probability of seeing task overruns where no such overruns happen. (See RTuinOS
           manual.)
             We therefore disable the standard corrective action in case of overruns; macro
           RTOS_OVERRUN_TASK_IS_IMMEDIATELY_DUE is set to RTOS_FEATURE_OFF.
             The false overruns are counted nonetheless by rtos_getTaskOverrunCounter.
           Here, we implement our own overrun counter by comparing the task cycle time with
           the Arduino timer which coexists with the RTuinOS system timer. */
        ti1 = millis();
        if(ti2 > 0)
        {
            ti2 = ti1-ti2;
            if(ti2 < (uint32_t)(0.9*256.0*RTOS_TIC*1000.0)
               ||  ti2 > (uint32_t)(1.1*256.0*RTOS_TIC*1000.0)
              )
            {
                ++ _task00_C0_trueTaskOverrunCnt;
            }
        }
        ti2 = ti1;

        /* What looks like CPU consuming floating point operations actually is a
           compile time operation. Here's the prove - which also produces no CPU load
           as it is removed by the optimizer. (Sounds contradictory but it isn't.) */
        ASSERT(__builtin_constant_p((uint32_t)(0.9*256.0*RTOS_TIC*1000.0))
               &&  __builtin_constant_p((uint32_t)(1.1*256.0*RTOS_TIC*1000.0))
              );

    } /* End for(ever) */

} /* End of task00_class00 */