STM32与Freertos入门(七)信号量

发布时间:2023年12月20日

1、简介

FreeRTOS提供了二值信号(Binary Semaphore)作为一种同步机制,用于在任务之间进行简单的通信和同步操作。二值信号是一种特殊类型的信号量,只能有两种状态:0(未触发)和1(已触发)。

以下是关于FreeRTOS二值信号的一些详细介绍和用法:

  1. 信号创建:可以使用FreeRTOS提供的API函数创建二值信号。在创建信号时,需要指定初始状态。可以选择将信号初始化为未触发(0)或已触发(1)。

  2. 信号等待:任务可以使用xSemaphoreTake()函数等待二值信号。如果信号的状态为未触发(0),任务将被阻塞等待,直到信号状态为已触发(1)。

  3. 信号释放:任务可以使用xSemaphoreGive()函数释放二值信号。这将使信号状态从未触发(0)变为已触发(1)。如果有多个任务等待此信号,只会有一个任务被唤醒。

  4. 优先级反转:在使用二值信号时要注意优先级反转问题。如果一个高优先级任务等待一个由低优先级任务触发的信号,而低优先级任务又被一个中优先级任务抢占,那么高优先级任务将一直等待,因为低优先级任务无法通过抢占释放信号。使用优先级继承技术或二值信号的特殊类型(递归二值信号)可以解决这个问题。

  5. 递归二值信号:FreeRTOS还提供了一种特殊类型的二值信号,称为递归二值信号(Recursive Binary Semaphore)。这种信号可以在同一个任务中多次获取和释放。它对于某些特定的应用场景非常有用,例如递归函数的同步。

使用FreeRTOS二值信号时,需要注意以下几点:

  • 确保在正确的时间和位置上获取和释放信号,避免信号的不一致状态。
  • 调度策略要合理,以避免优先级反转问题。
  • 在设计多任务应用程序时,考虑任务间的依赖关系和同步需求,以选择适当的同步机制。

总的来说,FreeRTOS二值信号是一种简单而有效的任务同步和通信机制,可用于控制任务的执行顺序和互斥访问共享资源。它是FreeRTOS提供的强大功能之一,帮助开发人员构建可靠的实时系统。

2、CubeMX配置

?2.1 任务配置

?2.2 信号配置

?3、KEIL 5代码设计

/* 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 */

文章来源:https://blog.csdn.net/weixin_44597885/article/details/135033199
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。