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