Currently running a task where I have GPIO lines toggle within a for loop. For Loop Screenshot

However, as the task goes on and the GPIO lines toggle, I noticed some strange behavior on my logic analyzer where there will be instances of the tasks running normally while using the vTaskDelayUntil() function which runs for about 22us Normal vTaskDelayUntil() operation and other instances where it appears the tasks get called twice Extended vTaskDelayUntil() operation and the vTaskDelayUntil() function runs for about 100ms in that instance. Here's a screenshot where both instances occur during a session. vTaskDelayUntil() operation within a task

My question here is why does this happen every so often with using this function?

I have been reading the RTOS docs and I haven't found any information on why these types of events occur unless I've missed a few pages. Any help or reading material would be appreciative.

4

1 Answer

It is not plausible that vTaskDelayUntil runs to 22us unless the target time has already passed. Either that is the case or there is a pre-emption of this task, by some other task, or an interrupt handler:

Possibly i In this instance: enter image description here

gpioSetBit( hetPORT1, 26, 0u ) ; // Pin2 low . . // <- Preempted for ~22us . gpioSetBit( hetPORT1, 27, 0u ) ; // Pin1 low 

Wrapping the pin toggle in a critical section to prevent pre-emption (which will effect the timing of higher-priority tasks), or if it is a task that is pre-empting, making this a higher priority than that. However the "busy-loop" here will then affect the timing of lower priority tasks. Neither solution is particularly satisfactory in the general case. If possible it would be better to use a timer peripheral to generate the pulses if possible. Or perhaps a 22us pulse is fine in this application and you just need an explanation for the behaviour?

Another solution is to use a software timer. The timer service task runs at the highest priority, so would be more deterministic. However your apparently variable No-Op loop using a global variable would be a concern if count were large and the pulse width more than a few microseconds (depending on the real-time requirements of your system).

I would suggest that your No-Op loop is unsafe in any case, and can be optimised out by the compiler, even with the assembler instruction:

for( volatile int i = 0; i < count; i++ ) { asm( " nop" ) ; } 

The second trace is less easy to explain from the information provided; you mention "tasks" (plural), but previously only mentioned one task. It seems likely that something else in your system at a higher priority than this has executed without blocking for more than 100ms, such that the the next call to vTaskDelayUntil returns immediately because the target time has expired already. The last trace is consistent with that theory.

In short the issue is almost certainly caused by the behaviour and priority of other tasks or interrupts in your system not shown.

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.