引言
在嵌入式开发中,只要你使用实时操作系统,那么使用信号量可以说必不可少。我们常使用信号量进行同步或互斥。
信号量介绍
信号量(semaphore)是一种用于提供不同进程之间或者一个给定的不同线程间同步手段的原语。信号量多用于任务间的同步与互斥。 信号量在FreeRTOS中分为三种:计数型信号量、二值信号量和互斥信号量。
- 同步:处理竞争就是同步,安排进程执行的先后顺序就是同步,每个进程都有一定的个先后执行顺序。
- 互斥:互斥访问不可共享的临界资源,同时会引发两个新的控制问题(互斥可以说是特殊的同步)。
- 竞争:当并发进程竞争使用同一个资源的时候,我们就称为竞争进程。
二值信号量顾名思义就是信号量取值只有0和1的信号量,但他与互斥信号量不同,他没有优先级继承机制,也不是获取和释放均只能在同一个任务里进行。在实现任务间同步中,使用的非常广泛。
准备
硬件
- STM32F103开发板
- LED灯
软件
- Keil 5
- STM32CubeMX
- 串口调试助手
功能设计
需求设计
设置两个任务和一个信号量。 任务1运行时会令LED1闪烁,并串口发送01,当运行4次任务1后,任务1会释放二值信号量。 任务2首先获取二值信号量,如果获取失败任务进行调度。当获取到信号量时,任务2会执行LED2闪烁,并串口发送02。 实现任务1 每运行四次,任务2运行一次。
软件实现
- 信号量定义 下面的程序目的是创建了一个二值信号量。
#include "Semaphore.h"SemaphoreHandle_t LED_Semaphore;void initSemaphore(void){
LED_Semaphore =xSemaphoreCreateBinary();
configASSERT(LED_Semaphore != NULL);}
- 任务1 任务1主要是每次执行一次闪烁和串口发送01,当执行第四次的时候,释放信号量。
void LED1ToggleTesk(void const * argument){
BaseType_t xReturn=pdTRUE;
int ledtime1=4;
for(;;)
{
usart_send[0]=0x1;
ledtime1--;
if(ledtime1==0){
xSemaphoreGive(LED_Semaphore);
ledtime1=4;
}
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
HAL_UART_Transmit(&huart3,usart_send,1,portMAX_DELAY);
vTaskDelay(1000);
}}
- 任务2 任务2主要执行的是,当获取的信号量时,LED2翻转,并串口发送02。
void LED2ToggleTesk(void const *argument){
BaseType_t xReturn=pdTRUE;
for(;;)
{
usart_send[0]=0x2;
xReturn =xSemaphoreTake(LED_Semaphore,0);
if(xReturn==pdTRUE)
{
HAL_UART_Transmit(&huart3,usart_send,1,portMAX_DELAY);
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
}
vTaskDelay(1000);
}
}
现象
实现的现象是LED1始终在翻转,串口始终发送01,当执行四次上述现象的时候。LED2翻转并串口发送02.