1. 程式人生 > >FreeRTOS二值訊號量的建立與使用

FreeRTOS二值訊號量的建立與使用

訊號量:訊號量(Semaphore),有時被稱為訊號燈,是在多執行緒環境下使用的一種設施,是可以用來保證兩個或多個關鍵程式碼段不被併發呼叫。在進入一個關鍵程式碼段之前,執行緒必須獲取一個訊號量;一旦該關鍵程式碼段完成了,那麼該執行緒必須釋放訊號量。其它想進入該關鍵程式碼段的執行緒必須等待直到第一個執行緒釋放訊號量。

以一個停車場的運作為例。簡單起見,假設停車場只有三個車位,一開始三個車位都是空的。這時如果同時來了五輛車,看門人允許其中三輛直接進入,然後放下車攔,剩下的車則必須在入口等待,此後來的車也都不得不在入口處等待。這時,有一輛車離開停車場,看門人得知後,開啟車攔,放入外面的一輛進去,如果又離開兩輛,則又可以放入兩輛,如此往復。在這個停車場系統中,車位是公共資源,每輛車好比一個
執行緒
,看門人起的就是訊號量的作用。二值訊號量是訊號量中的一個特殊值,就如同二值化影象的畫素點一樣,只能有兩個值,0和1!

1、訊號量的建立單獨在一個任務中進行,如下圖所示:

其中訊號量的建立使用的是xSemaphoreCreateBinary()函式,函式返回值為控制代碼,在後面加入判斷,如果訊號量建立失敗之後則進入if條件,提示建立失敗,最後進行任務的刪除,和starttask類似。其中xSemaphore1和xSemaphore2即為建立的二值訊號量。

2、釋放訊號量和獲取訊號量


每5S鍾釋放一次訊號量


對訊號量進行使用。

3、編寫任務函式;

4、開始作業系統的排程。

總體的測試程式碼如下:

#include "stm32f10x_conf.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

TaskHandle_t StartTask_Handle;
TaskHandle_t Semaphore_Handle;
SemaphoreHandle_t xSemaphore1 = NULL;
SemaphoreHandle_t xSemaphore2 = NULL;
uint8_t count = 0;

void vATask( void * pvParameters )
{
	xSemaphore1 = xSemaphoreCreateBinary();
	xSemaphore2 = xSemaphoreCreateBinary();
	if( xSemaphore1 == NULL || xSemaphore2 == NULL)
	{
			// The semaphore was created successfully.
			// The semaphore can now be used.
	}
	vTaskDelete(Semaphore_Handle);
}

void  vLED_4_Task( void *pvParameters )
{  
	TickType_t xLastWakeTime = xTaskGetTickCount();
	while(1) 
	{   
		led_turn(4);
		count ++;
		
		if(count >= 10)
		{
			count = 0;
			xSemaphoreGive(xSemaphore1);
		}
		
		vTaskDelay(500);       
	}  
}

void  vLED_8_Task( void *pvParameters )
{  
	while(1) 
	{   
		if(xSemaphoreTake(xSemaphore1,1) == pdTRUE)
		{			
			xSemaphoreGive(xSemaphore2);
			led_turn(8);
		}      
	}  
}

void vLED_1_Task(void *pvParameters)
{
	while(1)
	{
		if(xSemaphoreTake(xSemaphore2,1) == pdTRUE)
		{			
			led_turn(1);
		} 
	}
}

void vStartTask(void *pvParameters)
{
	taskENTER_CRITICAL();

	xTaskCreate(vATask,"Semphore",32,NULL,configMAX_PRIORITIES - 1,(TaskHandle_t*)&Semaphore_Handle);
	xTaskCreate( vLED_4_Task, "LED4",32,NULL,8 ,NULL);
	xTaskCreate( vLED_8_Task, "LED8",32,NULL,3 ,NULL);
	xTaskCreate( vLED_1_Task, "LED1",32,NULL,4 ,NULL);
	
	vTaskDelete(StartTask_Handle);
	taskEXIT_CRITICAL();
}

int main(void)
{
	int a = 0;
	
	led_init();
	
	//xSemaphore = xSemaphoreCreateBinary();
	xTaskCreate(vStartTask,"starttask",128,NULL,9,(TaskHandle_t*)&StartTask_Handle);
	
  vTaskStartScheduler();
	
	while(1)
	{
		
	}
}