vTaskDelayUntil()

amarjith wrote on Friday, November 01, 2013:

Please help me I’m not much familiar with rtos I have a doubt in vTaskDelayUntil(), it used to implement a task that executes periodically and with a fixed frequency. My doubt is if i want to execute five different tasks in every 5 seconds using vTaskDelayUntil() as shown below

vTaskDelayUntil( &xLastWakeTimeLog, 5000 / portTICK_RATE_MS ) );

I calld this in five different tasks and my configTICK_RATE_HZ is 100. My single task will take 3 seconds to complete its process.Then how will it execute the code??

davedoors wrote on Friday, November 01, 2013:

It depends on the priorities you assign to the tasks.

If the task that takes 3 seconds to complete has a priority above the other tasks then the other tasks will not run until it completes.

If the task that takes 3 seconds to complete has a priority below the other tasks then it will get preempted as soon as the other tasks need to run.

If all the tasks have the same priority then they will time slice and it will probably appear that all the tasks run just when they want to.

amarjith wrote on Saturday, November 02, 2013:

Thank you for reply. So if i want to execute five different tasks in every 5 seconds i have to set same priority for all my tasks right?. if so will it execute in every 5 seconds exactly?

richard_damon wrote on Saturday, November 02, 2013:

No. Using VTaskDelayUntil in the task loop will make that task run as close to that rate as possible. It will only be late if:

  1. Some higher or equal priority task is running at the point, in which case the task will be delayed until the higher priority task blocks, or the same priority task blocks or continues for a tick.

  2. It takes longer to finish than the repeat period, at which point the vTaskDelay Until doesn’t block, but just updates the next execution time an returns.

You mentioned one task taking a long period to execute, If that is compute bound time, then you probably don’t want that task higher priority than the others, as it would affect their timing. Long executing tasks (if CPU bound) tend to be lower in priority to avoid them impacting more important quick operations.

amarjith wrote on Monday, November 04, 2013:

Ok :-). Thank you so much.

amarjith wrote on Tuesday, November 12, 2013:

Hello sir, How much is the maximum available delay in vTaskDelayUntil() ? The xTimeIncrement is Short, so i can set only up to 65536( 6.5 seconds) right? If i want a delay more than this what will i do? i set unsigned long xTimeIncrement instead of portTickType xTimeIncrement is this a proper way?. i want to set delay up to 1hr in some tasks.

rtel wrote on Tuesday, November 12, 2013:

I have no idea what xTimeIncrement is, so the answer to your question is probably “no”.

Block times are specified in ticks, so the maximum time you can block for depends on your tick frequency (configTICK_RATE_HZ in FreeRTOSConfig.h) and the type used for portTickType. If configUSE_16_BIT_TICKS is 1 then the maximum block time is 0xffff ticks. If configUSE_16_BIT_TICKS is 0 then the maximum block time is 0xffffffff ticks.

If you want to convert milliseconds into ticks then divide it by portTICK_RATE_MS. For example, of you want to delay for 1000 milliseconds then call vTaskDelay( 1000 / portTICK_RATE_MS );

When you are blocking on an object such as a queue, semaphore or mutex then you can block indefinitely (without a timeout) if INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h and you set portMAX_DELAY as the block time.

Regards.

amarjith wrote on Tuesday, November 12, 2013:

xTimeIncrement is in void vTaskDelayUntil() (task.c) shown below

void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )

i was saying about portTickType before xTimeIncrement, i changed in to unsigned long xTimeIncrement.

rtel wrote on Tuesday, November 12, 2013:

The only valid way of changing the portTickType value is to use the configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h, as already described.

Regards.

richard_damon wrote on Wednesday, November 13, 2013:

At a 1 ms timer tick, and 16 bit ticks, you get 65.5 seconds as the maximum delay you can request. Timer ticks faster than 1 ms are really impractical, and some of the coding techniques in the examples don’t work (as MS_PER_TICK is 0). In most application you can actually use a slower tick rate. A 10ms tick would allow a delay of 655 seconds, nearly 11 minutes. If you want real long delays, you need to turn off 16 bits as mentioned, then you get VERY long delays (Over a month with 1 ms ticks).

amarjith wrote on Friday, November 15, 2013:

I’m Still confused!!

Forgive me if i’am doing wrong.i wrote program for delay as shown below, here i can set any delay 20mins, 50mins, 1 or 2 hrs or more. But i didnt change my code as you said.

#define configUSE_16_BIT_TICKS 1
#define configTICK_RATE_HZ ( ( portTickType ) 100 )
#define configCPU_CLOCK_HZ ( ( unsigned long ) 12000000 ) /* Fosc / 2 */

i just changed the function shown below in task.c

void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, portTickType xTimeIncrement )

as

void vTaskDelayUntil( portTickType * const pxPreviousWakeTime, unsigned long xTimeIncrement )

//UploadTimeInterval = 20 // will get 20 mins

xTaskCreate( vMT_Upload, “vMT_Upload”, MEDIUM_STACK_SIZE,UploadTimeInterval, 9, &xUploadHandle );

void vMT_Upload( void *pvParameters)
{
unsigned long UploadTime;

portTickType xLastWakeTimeUpload;
UploadTime = ( unsigned long ) pvParameters;
for(; ;)
{


////upload code

 xLastWakeTimeUpload = xTaskGetTickCount();
 vTaskDelayUntil( &xLastWakeTimeUpload, ((UploadTime*1000) / portTICK_RATE_MS  ));

}

}

amarjith wrote on Wednesday, November 27, 2013:

Please reply…

richard_damon wrote on Wednesday, November 27, 2013:

UploadTime * 1000 / portTICK_RATE_MS sys UploadTime is in SECONDS, not minutes.

At 100Hz, a 16 bit tick will allow a maximum delay of 655 seconds, i.e. about 11 minutes.

Note that if you have a 16 bit processor, then your calculation will overflow long before the timer call, and this will actually limit your max delay to about 65 seconds.

amarjith wrote on Sunday, December 01, 2013:

Ho!sorry its in seconds. Yes i’m using pic24 microcontroller(16bit) can i set configUSE_16_BIT_TICKS is 0 in 16 bit controller?

richard_damon wrote on Sunday, December 01, 2013:

Yes, 16 bit processors can set configUSE_16_BIT_TICKS to 0, and get a 32 bit tick size. There will be slightly extra work done to process ticks as tick arithmetic will use 32 bit longs, which will require twice the instructions to do the math (in most cases), but this is not that big of a hit, especially if you need the long time measurement/delays.

amarjith wrote on Monday, December 02, 2013:

Okay. Thank you for your valuable time.

dragonflight1 wrote on Monday, December 02, 2013:

Rather than incur the 32 bit penalty all the time (though it really isn’t that much), if you only want to delay a task some long time then you can use

void sleep( unsigned int sec ) {
	long ticks = sec * 1000 * portTICK_RATE_MS;
	while(ticks >= portMAX_DELAY ) {
		vTaskDelay( portMAX_DELAY-1 );
		ticks -= portMAX_DELAY-1;
	}
	vTaskDelay( ticks );
}

or

void sleepUntil( portTickType *prevWakeTime,  unsigned int sec ) {
	long ticks = sec * 1000 * portTICK_RATE_MS;
	while(ticks >= portMAX_DELAY ) {
		vTaskDelayUntil( prevWakeTime, portMAX_DELAY-1 );
		ticks -= portMAX_DELAY-1;
	}
	vTaskDelayUntil( prevWakeTime, ticks );
}

if you really want to wake up exactly every sec seconds.
NOTE: if you use sleepUntil then you must call it before the base timer overflows - 65 secs with 1000Hz or 655 secs with 100Hz which I assume is not an issue.

amarjith wrote on Friday, December 06, 2013:

Thank you mike.