信号量:信号量(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)
{
}
}