Producer and consumer task, differences vTaskDelay and normal Delay loop

herophil wrote on Sunday, November 15, 2015:

Hey i have a question, im not totally sure why this is going to happen in this way.

I have created two task, both of them turn a led on and off.
The scenario is that task1 has the lowest priority and toggels the led 3 times and then gives a semaphore, instantly the task1 is interrupted by task2, because task2 has the higher priority. Futhermore if task2 gets the semaphore the task should toggel the led on time and then go again into blocked mode because he cant take the semaphore again.

Example one with delay loops;

void vTask1( void * pvParameters ){
	
	int i=0;
	
		for(;;){
			for(i=0;i<3;i++){
				LED_Task1_on();
				delay1s();
				LED_Task1_off();
				delay1s();
			}
			xSemaphoreGive( xSemaphore );
		}
}

void vTask2( void * pvParameters ){
	
		for(;;){
			if( xSemaphoreTake( xSemaphore, portMAX_DELAY ) == pdTRUE ){
				LED_Task2_on();
				delay1s();
				LED_Task2_off();
				delay1s();
			}
		}
}

Example2, with tickrate 1Mhz

void vTask1( void * pvParameters ){
	
	int i=0;
	
		for(;;){
			for(i=0;i<3;i++){
				LED_Task1_on();
				delay1s();
				LED_Task1_off();
				delay1s();
			}
			xSemaphoreGive( xSemaphore );
		}
}

void vTask2( void * pvParameters ){
	
		for(;;){
			if( xSemaphoreTake( xSemaphore, portMAX_DELAY ) == pdTRUE ){
				LED_Task2_on();
				vTaskDelay(1000);
				LED_Task2_off();
				vTaskDelay(1000);
			}
		}
}

If i use example one everthing is fine, but when is use example two, task1 is going to execute only once and the the led of task2 is blinking forever.

For my understanding it shouldn’t change a thing if i use vTaskDelay or a loop delay(task2), right? Or am i totally wrong?

kind regard phil

rtel wrote on Sunday, November 15, 2015:

How is delay1s() implemented? Is it just a null loop? Are you 100% certain it is indeed delaying for 1s, and that your tick frequency is 1KHz (you say 1MHz in your post, but I assume that is a typo).

If so, I would expect example 2 to execute as follows:

  1. Task 2 will run first because it has the higher priority.
  2. Task 2 attempts to take the semaphore, assuming the semaphore is not available, task 2 will enter the Blocked state - which allows Task 1 to run.
  3. Task 1 will toggle the LED on and off three times, then give the semaphore.
  4. As soon as the semaphore is given, Task 2 will pre-empt Task 1 and turn LED2 on.
  5. Task 2 will then enter the Blocked state again for 1000 ticks, allowing Task 1 to run again.
  6. Task 1 will turn an LED on, then sit in a NULL loop for 1s. During that time Task 2 will leave the Blocked state and turn LED2 off again.
  7. Task 2 will enter the Blocked state again, again allowing Task 1 to run.
  8. Task 1 will finishing executing its NULL loop, turn LED1 off again, and then start running its second NULL loop.
  9. While Task 1 is executing its NULL loop Task 2 will leave the Blocked state again, go back to the start of its for() loop, and block on the semaphore again.
  10. Task 1 will toggle its LED another 2 times, before it gives the semaphore.

…Then we are back to the start.