Freertos 二元信号量
来源:互联网 发布:解除端口占用的命令 编辑:程序博客网 时间:2024/06/07 08:08
Freertos 二元信号量
信号量是任务与任务之间,任务与中断之间同步的重要方式,二元信号量与互斥锁十分相像,两者之间的差别在于优先级的继承机制,当另外一个具有更高优先级的任务试图获取同一个互斥锁时,已经获得互斥锁的任务将继承试图获取同一互斥锁的任务的优先级。而信号量没有这种机制,所以二元信号量更适合实现同步,互斥锁更适合实现简单的互斥。需要注意的是互斥锁在使用完资源后必须返还,否则高优先级的任务永远也无法获取互斥锁,低优先级的任务将不会放弃优先级的继承。二元信号量并不需要在得到后立即释放,因此同步操作一般可以通过一个任务或中断持续释放信号量,另一个任务持续获取信号量来实现。
一、简单例程
同样实现间隔一秒按顺序打印A/B/C的测试,这里用信号量来实现。
/* includes. */#include <stdio.h>#include "FreeRTOS.h"#include "task.h"#include "queue.h"#include "stm32f10x.h"#include "semphr.h"#include "portmacro.h"static void prvSetupHardware( void );static void vLEDTask( void *pvParameters );void vPrintTask(void *pvParameters);void vTask1(void *pvparameters);void vTask2(void *pvparameters);void vTask3(void *pvparameters);void vLedInit(void);void UartInit(void);#define LED1_ON() GPIO_SetBits(GPIOB,GPIO_Pin_0)#define LED1_OFF() GPIO_ResetBits(GPIOB,GPIO_Pin_0)SemaphoreHandle_t xSemaphore_1;SemaphoreHandle_t xSemaphore_2;SemaphoreHandle_t xSemaphore_3;int main( void ){ prvSetupHardware(); xSemaphore_1 = xSemaphoreCreateBinary(); xSemaphore_2 = xSemaphoreCreateBinary(); xSemaphore_3 = xSemaphoreCreateBinary(); xTaskCreate( vTask1, "vTask1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+7, NULL ); xTaskCreate( vTask2, "vTask2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+6, NULL ); xTaskCreate( vTask3, "vTask3", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+5, NULL ); xTaskCreate( vLEDTask, "LED", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+3, NULL ); vTaskStartScheduler(); return 0;}void vTask1(void *pvparameters){ TickType_t xLastWakeTime; while(1) { if(xSemaphoreTake( xSemaphore_1, portMAX_DELAY ) == pdTRUE) { xLastWakeTime = xTaskGetTickCount(); vTaskDelayUntil( &xLastWakeTime, 1000/portTICK_RATE_MS );// vTaskDelay(1000/portTICK_RATE_MS ); printf("Task1:A\r\n"); xSemaphoreGive( xSemaphore_2); } }}void vTask2(void *pvparameters){ TickType_t xLastWakeTime; while(1) { if( xSemaphoreTake( xSemaphore_2, portMAX_DELAY ) == pdTRUE ) { xLastWakeTime = xTaskGetTickCount(); vTaskDelayUntil( &xLastWakeTime, 1000/portTICK_RATE_MS );// vTaskDelay(1000/portTICK_RATE_MS ); printf("Task2:B\r\n"); xSemaphoreGive( xSemaphore_3); } }}void vTask3(void *pvparameters){ xSemaphoreGive( xSemaphore_1); while(1) { TickType_t xLastWakeTime; if( xSemaphoreTake( xSemaphore_3, portMAX_DELAY ) == pdTRUE ) { xLastWakeTime = xTaskGetTickCount(); vTaskDelayUntil( &xLastWakeTime, 1000/portTICK_RATE_MS );// vTaskDelay(1000/portTICK_RATE_MS ); printf("Task3:C\r\n"); xSemaphoreGive( xSemaphore_1); } }}void vLEDTask( void *pvParameters ){ TickType_t xLastWakeTime; for( ;; ) { LED1_ON(); xLastWakeTime = xTaskGetTickCount(); vTaskDelayUntil( &xLastWakeTime, 1000/portTICK_RATE_MS ); LED1_OFF(); xLastWakeTime = xTaskGetTickCount(); vTaskDelayUntil( &xLastWakeTime, 1000/portTICK_RATE_MS ); }}static void prvSetupHardware( void ){ vLedInit(); UartInit();}void vLedInit( void ){ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_Init(GPIOB, &GPIO_InitStructure);}void UartInit(void){ USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 ,ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE);}
结果:
二、分析
SemaphoreHandle_t xSemaphore_1;
创建信号量句柄。
xSemaphore_1 = xSemaphoreCreateBinary();
xSemaphore_2 = xSemaphoreCreateBinary();
xSemaphore_3 = xSemaphoreCreateBinary();
创建三个信号量,用于三个任务间的同步。
xSemaphoreGive( xSemaphore_1);
在任务3中先发送信号量给任务1,启动打印过程。
xSemaphoreTake( xSemaphore_1, portMAX_DELAY )
接收信号量,第一个参数为信号量句柄,大二个参数为最大等待时间,接收到则返回pdTRUE,失败则返回pdFALSE。
创建三个信号量,任务3先发送信号量给任务1,任务1接收到信号量过1秒后打印'A',并发送信号量给任务2,以此类推来实现间隔一秒依次打印A/B/C的操作。
三、其他
在V8.0之后的版本,创建信号量时初值为空,在函数中实现了判断,如果为满则清空操作。
在中断中发送信号量时使用xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );函数,以FromISR结尾的函数具有保护功能,任务中接收信号量使用xSemaphoreTake( xSemaphore_1, portMAX_DELAY )。
0 0
- Freertos 二元信号量
- FreeRTOS 信号量
- FreeRTOS 信号量
- FreeRTOS 信号量
- FreeRTOS内核详解----信号量
- FreeRTOS-二值信号量
- FreeRTOS-互斥信号量
- FreeRTOS系列第19篇---FreeRTOS信号量
- FreeRTOS高级篇6---FreeRTOS信号量分析
- FreeRTOS系列第19篇---FreeRTOS信号量
- FreeRTOS高级篇6---FreeRTOS信号量分析
- FreeRTOS系列第19篇---FreeRTOS信号量
- FreeRTOS学习------信号量(实践)
- 二元信号量一个小例子
- FreeRTOS系列第20篇---FreeRTOS信号量API函数
- FreeRTOS系列第20篇---FreeRTOS信号量API函数
- FreeRTOS学习笔记——二值型信号量
- FreeRTOS学习笔记——互斥型信号量
- java实现约瑟夫环问题
- 数据结构:有向图的十字链表存储表示(c实现)
- Cygwin下编译MySQL后启动遇到的问题
- Count The Carries - HDU 4588 水题
- C语言数组名与指针
- Freertos 二元信号量
- Android 实现borderless的Button并设置分界线
- 黑马程序员—java基础_IO流—字节流
- java不定参数列表---乔老师没讲,但是传智有讲
- js去掉空格回车换行
- JAVA中的流学习
- JavaScript常用记录(2)
- C语言 二叉树按层打印、深度优先遍历、二叉树是否对称
- 北斗卫星导航产业重大应用示范项目落户哈市