FreeRTOS提供了二值信号(Binary Semaphore)作为一种同步机制,用于在任务之间进行简单的通信和同步操作。二值信号是一种特殊类型的信号量,只能有两种状态:0(未触发)和1(已触发)。
以下是关于FreeRTOS二值信号的一些详细介绍和用法:
信号创建:可以使用FreeRTOS提供的API函数创建二值信号。在创建信号时,需要指定初始状态。可以选择将信号初始化为未触发(0)或已触发(1)。
信号等待:任务可以使用xSemaphoreTake()
函数等待二值信号。如果信号的状态为未触发(0),任务将被阻塞等待,直到信号状态为已触发(1)。
信号释放:任务可以使用xSemaphoreGive()
函数释放二值信号。这将使信号状态从未触发(0)变为已触发(1)。如果有多个任务等待此信号,只会有一个任务被唤醒。
优先级反转:在使用二值信号时要注意优先级反转问题。如果一个高优先级任务等待一个由低优先级任务触发的信号,而低优先级任务又被一个中优先级任务抢占,那么高优先级任务将一直等待,因为低优先级任务无法通过抢占释放信号。使用优先级继承技术或二值信号的特殊类型(递归二值信号)可以解决这个问题。
递归二值信号:FreeRTOS还提供了一种特殊类型的二值信号,称为递归二值信号(Recursive Binary Semaphore)。这种信号可以在同一个任务中多次获取和释放。它对于某些特定的应用场景非常有用,例如递归函数的同步。
使用FreeRTOS二值信号时,需要注意以下几点:
总的来说,FreeRTOS二值信号是一种简单而有效的任务同步和通信机制,可用于控制任务的执行顺序和互斥访问共享资源。它是FreeRTOS提供的强大功能之一,帮助开发人员构建可靠的实时系统。
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
osThreadId Task_giveHandle;
osThreadId Task_takeHandle;
osSemaphoreId myBinarySemHandle;
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartTask_give(void const * argument);
void StartTask_Task_take(void const * argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/* GetIdleTaskMemory prototype (linked to static allocation support) */
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
/* USER CODE BEGIN GET_IDLE_TASK_MEMORY */
static StaticTask_t xIdleTaskTCBBuffer;
static StackType_t xIdleStack[configMINIMAL_STACK_SIZE];
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCBBuffer;
*ppxIdleTaskStackBuffer = &xIdleStack[0];
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
/* place for user code */
}
/* USER CODE END GET_IDLE_TASK_MEMORY */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* Create the semaphores(s) */
/* definition and creation of myBinarySem */
osSemaphoreDef(myBinarySem);
//myBinarySemHandle = osSemaphoreCreate(osSemaphore(myBinarySem), 1);
myBinarySemHandle = xSemaphoreCreateBinary();
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of Task_give */
osThreadDef(Task_give, StartTask_give, osPriorityNormal, 0, 128);
Task_giveHandle = osThreadCreate(osThread(Task_give), NULL);
/* definition and creation of Task_take */
osThreadDef(Task_take, StartTask_Task_take, osPriorityBelowNormal, 0, 128);
Task_takeHandle = osThreadCreate(osThread(Task_take), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
}
/* USER CODE BEGIN Header_StartTask_give */
/**
* @brief Function implementing the Task_give thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask_give */
void StartTask_give(void const * argument)
{
/* USER CODE BEGIN StartTask_give */
/* Infinite loop */
for(;;)
{
if(key==0){
osDelay(20);
if(key==0){
printf("key按下\r\n");
if(xSemaphoreGive(myBinarySemHandle) == pdTRUE){
printf("二值信号放入成功\r\n");
}
else{
printf("二值信号放入失败\r\n");
}
}
while(key==0);
}
osDelay(10);
}
/* USER CODE END StartTask_give */
}
/* USER CODE BEGIN Header_StartTask_Task_take */
/**
* @brief Function implementing the Task_take thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask_Task_take */
void StartTask_Task_take(void const * argument)
{
/* USER CODE BEGIN StartTask_Task_take */
/* Infinite loop */
for(;;)
{
if(key2==0){
osDelay(20);
if(key2==0){
printf("key按下\r\n");
if(xSemaphoreTake(myBinarySemHandle,portMAX_DELAY) == pdTRUE){
printf("二值信号放入成功\r\n");
}
else{
printf("二值信号放入失败\r\n");
}
}
while(key2==0);
}
osDelay(10);
}
/* USER CODE END StartTask_Task_take */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */