STM32与Freertos入门(七)信号量

news2024/9/22 7:24:50

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1316309.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PAT 乙级 1019 数字黑洞

解法思路,我用c语言和python 做了这道题,这里面有一个小坑就是没说一定是4位整数,有可能是3位,2,1,位,用python排序时候需要注意,我c语言用的hash反而无所谓。。代码如下: c语言代码: #includ…

CTFHub | 反射型

0x00 前言 CTFHub 专注网络安全、信息安全、白帽子技术的在线学习,实训平台。提供优质的赛事及学习服务,拥有完善的题目环境及配套 writeup ,降低 CTF 学习入门门槛,快速帮助选手成长,跟随主流比赛潮流。 0x01 题目描述…

腾讯云服务器优惠活动大全页面_全站搜优惠合集

腾讯云推出优惠全站搜页面 https://curl.qcloud.com/PPrF9NFe 在这个页面可以一键查询所需云服务器、轻量应用服务器、数据库、存储、CDN、网络、安全、大数据等云产品优惠活动大全,活动打开如下图: 腾讯云优惠全站搜 腾讯云优惠全站搜页面 txybk.com/go…

STP笔记总结

STP --- 生成树协议 STP(Spanning Tree Protocol,生成树协议)是根据 IEEE802.1D标准建立的,用于在局域网中消除数据链路层环路的协议。运行STP协议的设备通过彼此交互信息发现网络中的环路,并有选择地对某些端口进行阻…

MyBatis原理解读

我们项目中多用MyBatis进行数据库的读写,开源的MyBatis-Plus框架对其进行了增强,使用上更加简单,我们之前的很多项目也是直接用的MyBatis-Plus。 数据库操作的时候,简单的单表读写,我们可以直接在方法里链式组装SQL,复杂的SQL或涉及多表联合join的,需要在xml手写SQL语句…

缓存的定义及重要知识点

文章目录 缓存的意义缓存的定义缓存原理缓存的基本思想缓存的优势缓存的代价 缓存的重要知识点 缓存的意义 在互联网高访问量的前提下,缓存的使用,是提升系统性能、改善用户体验的唯一解决之道。 缓存的定义 缓存最初的含义,是指用于加速 …

Python导入模块,Python import用法(超级详细)

对于一个真实的 Python 程序,我们不可能自己完成所有的工作,通常都需要借助于第三方类库。此外,也不可能在一个源文件中编写整个程序的源代码,这些都需要以模块化的方式来组织项目的源代码。 使用 import 导入模块的语法&#xf…

解决:TypeError: write() argument must be str, not tuple

解决:TypeError: write() argument must be str, not tuple 文章目录 解决:TypeError: write() argument must be str, not tuple背景报错问题报错翻译报错位置代码报错原因解决方法今天的分享就到此结束了 背景 在使用之前的代码时,报错&…

提供一个数据库的表,然后,分页显示表中所有信息,一页10个,此表130条信息。最后再以饼图显示男 女 未知 人数的情况。

运行之后显示的效果&#xff1a; 如果是新项目&#xff0c;建立项目后&#xff0c;把mysql驱动放到指定的目录下即&#xff1a; WebContent\WEB-INF-lib 我用的驱动是 mysql-connector-j-8.0.33.jar 展示页 listpage.jsp <%page import"java.util.Map.Entry"%&g…

DIY电脑装机机箱风扇安装方法

作为第一次自己diy一台电脑主机的我&#xff0c;在经历了众多的坑中今天来说一下如何安装机箱风扇的问题 一、风扇的数量 1、i3 xx50显卡 就用一个cpu散热风扇即可 2、i5 xx60 一个cpu散热风扇 一个风扇即可 3、i7 xx70 一个cpu散热 4个风扇即可 4、i9 xx80 就需要7个以…

设计模式详解---策略模式

1. 策略模式简介 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;用于在运行时根据不同的情境选择不同的算法或策略。该模式将算法封装成独立的类&#xff0c;使得它们可以相互替换&#xff0c;而且可以独立于客户端使用它们的方式。 1.1.…

拷贝的艺术:深拷贝与浅拷贝的区别与应用(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

轻量封装WebGPU渲染系统示例<50>- Json数据描述材质等场景信息

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/DataDrivenScene2.ts 当前示例运行效果: 此示例基于此渲染系统实现&#xff0c;当前示例TypeScript源码如下: json场景数据: {"renderer": {"mtplE…

设计模式——组合模式(结构型)

引言 组合模式是一种结构型设计模式&#xff0c; 你可以使用它将对象组合成树状结构&#xff0c; 并且能像使用独立对象一样使用它们。 问题 如果应用的核心模型能用树状结构表示&#xff0c; 在应用中使用组合模式才有价值。 例如&#xff0c; 你有两类对象&#xff1a; ​…

搞懂这6 个持续集成工具,领先80%测试人

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

太空旅行:计算机技术的崭新航程

太空旅行&#xff1a;计算机技术的崭新航程 一、引言 自古以来&#xff0c;人类就对浩渺的宇宙充满了无尽的好奇和渴望。随着科技的飞速发展&#xff0c;太空旅行已经从科幻小说中的构想变为现实。在这个过程中&#xff0c;计算机技术起到了不可或缺的作用。从阿波罗时代的初…

12V升18V4A同步升压恒压WT3210

12V升18V4A同步升压恒压WT3210 WT3210 是一款高功率密度的全集成同步升压转换器&#xff0c;内部集成的功率MOSFET管导通电阻为上管8mΩ和下管15mΩ。可为便携式系统提供空间小尺寸 解决方案。WT3210具有 2.7V 至 20V 的宽输入电压范围&#xff0c;应用在单节或两节锂电池的便携…

数据可视化?这些平台能处

图表在各行各业都起到举重若轻的作用&#xff0c;无论是项目汇报、业绩分析&#xff0c;亦或是数据挖掘、统计分析&#xff0c;良好的可视化可以为我们的阐述起到画龙点睛的效果。在一篇文章中&#xff0c;如果只有密密麻麻的文字堆积&#xff0c;无论是谁恐怕都无法长期保持注…

[Verilog] Verilog 简介

主页&#xff1a; 元存储的博客 全文 2100 字。 文章目录 前言1. Verilog 简介2. 主要特性3. 应用领域总结 前言 Verilog HDL&#xff08;简称 Verilog &#xff09;是一种硬件描述语言&#xff0c;用于数字电路的系统设计。可对算法级、门级、开关级等多种抽象设计层次进行建…

GZ015 机器人系统集成应用技术样题3-学生赛

2023年全国职业院校技能大赛 高职组“机器人系统集成应用技术”赛项 竞赛任务书&#xff08;学生赛&#xff09; 样题3 选手须知&#xff1a; 本任务书共 26页&#xff0c;如出现任务书缺页、字迹不清等问题&#xff0c;请及时向裁判示意&#xff0c;并进行任务书的更换。参赛队…