FreeRTOS学习笔记 ——二值信号量
Posted haoaoooooo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FreeRTOS学习笔记 ——二值信号量相关的知识,希望对你有一定的参考价值。
前言
上一个笔记学习完了FreeRTOS的消息队列,以及如何创建与使用,在本篇文章中,继续基于上一个工程来学习FreeRTOS的信号量,其中二值信号量是尤其重要的一点,比较常用,所以本篇会着重介绍二值信号量作用与使用。
FreeRTOS信号量简介
- 二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一 些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号 另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问。
- 二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空 的,这不正好就是二值的吗? 任务和中断使用这个特殊队列不用在乎队列中存的是什么消息,只需要知道这个队列是满的还是空的。可以利用这个机制来完成任务与中断之间的同步或是任务与任务之间的同步。
下面进入工程创建。
CubeMx配置
MCU: STM32F103C8T6
CubeMX: STM32CubeMX 5.3.0
在上篇文章的CubeMx配置基础上,增加内容,如果有基本工程不会创建的小伙伴可以点击传送门进行学习。
在Timers and Semaphores栏里在Binary Semaphores点击add,新增一个二值信号量。
接下来就像往常那样创建并打开工程就可以了
填写项目名
配置项目生成单独的.c/.h文件
接着生成代码就ok了~ (点击后会出现警告,直接点yes即可)
打开工程,freertos.c中会发现多出这段代码
osSemaphoreDef(myBinarySem01);
myBinarySem01Handle = osSemaphoreCreate(osSemaphore(myBinarySem01), 1);
也就是创建二值信号量的代码。
下面的测试demo与上篇文章差不多,在原有基础上,增加二值信号量,使得两个任务可以同步起来,第一个任务把信息放入队列里后并产生一个随机的延时数(用于测试),然后将二值信号量释放出去;任务二无限时长等待信号量,如果获取信号量成功,则将队列里的信息出队,并打印出来。
下面为演示代码。
=加入头文件以及变量=
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <stdlib.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct{
uint8_t mid;
char mDate[20];
}MSG;
MSG myDate;
uint16_t cnt=1;
uint16_t d_time=0;
/* USER CODE END PTD */
再编写task里的代码
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN StartDefaultTask */
MSG *TXMSG;
uint8_t i;
TXMSG = &myDate;
/* Infinite loop */
for(;;)
{
TXMSG->mid = cnt++;
for(i=0; i<20; i++){
TXMSG->mDate[i] = rand()%255;
}
if(xQueueSend(myQueue02Handle,&TXMSG,10) ==errQUEUE_FULL)
{
printf("myQueue01Handle errQUEUE_FULL\\r\\n");
}
d_time = rand()%500;
osDelay(d_time);
xSemaphoreGive(myBinarySem01Handle);//释放信号量
printf("\\r\\nTX-Task1 Done!\\r\\n");
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void const * argument)
{
/* USER CODE BEGIN StartTask02 */
MSG *RXMSG;
uint8_t i;
/* Infinite loop */
for(;;)
{
xSemaphoreTake(myBinarySem01Handle,osWaitForever);//获取信号量
if(xQueueReceive( myQueue02Handle,&RXMSG, 10) == pdPASS)
{
printf("\\r\\nRXMSG->ucMessageID = %d \\r",RXMSG->mid);
printf("RXMSG->ucData[0] = ");
for(i=0;i<20;i++)
printf(" %03d",RXMSG->mDate[i]);
printf("\\r\\n");
}
printf("delay time: %d RX-Task2 Done!\\r\\n",d_time);
}
/* USER CODE END StartTask02 */
}
打开串口工具进行测试
可以发现首先Task1先进行信息推进队列里,并随机产生几百毫秒的延时,随后Task2才开始工作,说明二值信号量使得它们同步了。
关于信号量的内容还有计数信号量、互斥信号量和递归互斥信号量,这里就不做解释与实验了。
以上内容记录下来,希望能帮助到有需要的伙伴。
该文章如有不对地地方,欢迎指出。
以上是关于FreeRTOS学习笔记 ——二值信号量的主要内容,如果未能解决你的问题,请参考以下文章