单片机学习小组
直播中

陈敏

7年用户 1282经验值
私信 关注

怎样去使用FreeRTOS二值信号量呢

怎样去使用FreeRTOS二值信号量呢?
怎样通过按键中断来控制LED灯的亮灭从而实现任务与中断之间的同步呢?

回帖(1)

杨秀兰

2022-2-28 16:47:47
1.FreeRTOS 二值信号量

1.1二值信号量简介

信号量实际上就是一个值,这个值被用来解决临界区问题以及实现进程在多处理器环境下的进程同步。
其中,两个最重要的信号量为二进制信号量和计数信号量,计数信号量可以表示为非负的整数而二进制信号量只存在0和1两个值。

二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号量更适合用于同步(任务与任务或任务与中断的同步),

1.2二值信号量函数

1.2.1 创建信号量

对于二值信号量,若想使用,必须先创建二值信号量,在新版FreeRTOS中,一般使用xSemaphoreCreateBinary()函数动态创建二值信号量。此函数是个宏,具体创建工程是由函数xQueueGenericCreate()完成。其函数原型如下:

SemaphoreHandle_t xSemaphoreCreateBinary(void)

参数: 无

返回值:

NULL:二值信号量创建失败

其他值:创建成功的二值信号量的句柄

1.2.2 释放信号量

释放信号量的函数有两个,分别如下:

任务级信号量释放函数 xSemaphoreGive(),此函数是个宏,可以用于释放二值信号量、计数型信号量或互斥信号量,其函数原型如下:

BaseType_t xSemaphoreGive(xSemaphore)

参数:

xSemaphore:要释放的信号量句柄

返回值:

PdPASS:释放信号量成功

PdQUEUE_FULL:释放信号量失败

中断级信号量释放函数 xSemaphoreGiveFromISR(),此函数也是个宏,只能用来释放二值信号量和计数型信号量,其函数原型如下:

BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore,

BaseType_t* pxHigherPriorityTaskWoken)

参数:

xSemaphore:要释放的信号量句柄

pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换

返回值:

PdPASS:释放信号量成功

PdQUEUE_FULL:释放信号量失败

1.2.3 获取信号量


获取信号量的函数也有两个,分别如下:

任务级信号量获取函数xSemaphoreTake(),此函数也是个宏,可以获取二值信号量、计数型信号量和互斥信号量,其函数原型如下:

BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,

TickType_t xBlockTime)

参数:

xSemaphore:要获取的信号量句柄

xBlockTime:阻塞时间

返回值:

pdTRUE:获取信号量成功

pdFALSE:超时,获取信号量失败

中断级信号量获取函数 xSemaphoreTakeFromISR(),此函数也是个宏,只能获取二值信号量和计数型信号量,其函数原型如下:

BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,

BaseType_t* pxHigherPriorityTaskWoken)

参数:

xSemaphore:要获取的信号量句柄

pxHigherPriorityTaskWoken:标记退出此函数以后是否进行任务切换

返回值:

PdPASS:获取信号量成功

pdFALSE:获取信号量失败

1.3操作实验

1.3.1实验设计

二值信号量可以实现任务与任务之间或者任务与中断之间的同步,在本节实验中,通过按键中断来控制LED灯的亮灭来实现任务与中断之间的同步。

在本实验中,共创建了两个任务,其中一个任务每隔一秒让LED3电平翻转,来表示程序可以正常运行,另外一个任务根据中断中传来的指令来控制不同LED灯的亮灭。

当按键按下时,进入中断,在中断中同时同时释放二值信号量,任务StartTask02()会一直尝试获取二值信号量,当获取到信号量后就会根据中断中的指令进而控制不同的LED灯发生亮灭。

任务及其功能如下:

StartDefaultTask():控制LED3闪烁,提示系统正在运行。

StartTask02():进行指令处理,根据接收的指令控制不同的LED灯。

1.3.2实验过程与分析

首先,根据之前几章内容配置好KEY、UART4、LED灯,切换到中间件“Middleware”的“FREERTOS”,默认自动勾选给M4了,然后接口“Interface”选择“CMSIS_V2”。初次接触,下面的参数大部分默认即可,为了运行其它任务,这里需要切换到“Tasks and Queues”标签,可以看到默认有个“defaultTask”任务,我们再点击“Add”再新增一个任务,如所示。




随后生成初始化代码,会弹出Systick被FreeRTOS占用,建议HAL库时钟基准源换成其它。之后FreeRTOS实验默认为此配置。

上述为新建工程配置过程,可参考12.3.2章节进行导入已有工程,工程存放路径【华清远见-FS-MP1A开发资料2-程序源码ARM体系结构与接口技术FreeRTOS1_FS-MP1A-FreeRTOS】

生成代码后,找到“main.c”,结尾部分会有两个任务函数,分别是“StartDefaultTask()”和“StartTask02()”。两个任务宏观看同时、独立运行,互不干扰。在“StartDefaultTask()”实现LED3每隔一秒闪烁,在“StartTask02()”中实现根据不同的指令控制不同LED灯亮灭。







在本次实验中,释放信号量在中断中进行,每进行一次按键按下,就释放一次信号量。在StartTask02任务中循环检测信号量,当在中断中释放信号量以后,便可以获取到信号量,然后根据指令进行控制,按键1或按键2按下时,分别控制LED1或LED2点亮,按键3按下时,控制LED1和LED2熄灭。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分