来自:http://blog.csdn.net/xukai871105/article/details/43456985
0.前言
在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段。下面结合一个具体例子说明FreeRTOS中的互斥型信号量如何使用。
【相关博文】
【FreeRTOS STM32移植笔记
】 【FreeRTOS学习笔记——任务间使用队列同步数据】
【FreeRTOS学习笔记——二值型信号量】
【如何在FreeRTOS下实现低功耗——MSP430F5438平台】
【代码链接】——示例代码存于百度网盘
1.基本说明
互斥型信号量的使用方法如图1所示。在多数情况下,互斥型信号量和二值型信号非常相似,但是从功能上二值型信号量用于同步,而互斥型信号量用于资源保护。互斥型信号量和二值型信号量还有一个最大的区别,互斥型信号量可以有效解决优先级反转现象。
图1 互斥型信号量使用方法
2.参考代码
本例具有两个任务,两个任务都试图通过串口打印内容,此时串口就好比一个“资源”,某个任务使用串口资源时必须保护该资源,使用完串口之后在释放资源。保护和释放动作便对应互斥型信号量的两个基本操作,xSemaphoreTake和xSemaphoreGive。
【代码】
-
- #include <stdio.h>
- #include <string.h>
-
-
- #include "FreeRTOS.h"
- #include "task.h"
- #include "queue.h"
- #include "semphr.h"
-
-
- #include "stm32f10x.h"
-
- #define LED0_ON() GPIO_SetBits(GPIOB,GPIO_Pin_5);
- #define LED0_OFF() GPIO_ResetBits(GPIOB,GPIO_Pin_5);
-
- static void Setup(void);
- void TaskA( void *pvParameters );
- void TaskB( void *pvParameters );
-
- void LedInit(void);
- void UART1Init(void);
-
-
- SemaphoreHandle_t xSemaphore = NULL;
-
- int main(void)
- {
-
- Setup();
-
- xSemaphore = xSemaphoreCreateMutex();
-
- xTaskCreate( TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+3, NULL );
- xTaskCreate( TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+4, NULL );
-
- vTaskStartScheduler();
-
- return 0;
- }
-
- void TaskA( void *pvParameters )
- {
- for( ;; )
- {
- xSemaphoreTake( xSemaphore, portMAX_DELAY );
- {
- printf("Task A\r\n");
- }
- xSemaphoreGive( xSemaphore );
- vTaskDelay( 2000/portTICK_RATE_MS );
- }
- }
-
- void TaskB( void *pvParameters )
- {
- for( ;; )
- {
- xSemaphoreTake( xSemaphore, portMAX_DELAY );
- {
- printf("Task B\r\n");
- }
- xSemaphoreGive( xSemaphore );
- vTaskDelay( 1000/portTICK_RATE_MS );
- }
- }
-
- static void Setup( void )
- {
- LedInit();
- UART1Init();
- }
-
- void LedInit( void )
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_Init( GPIOB, &GPIO_InitStructure );
- }
-
- void UART1Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
-
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
-
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- 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);
-
-
- USART_ClearFlag(USART1, USART_FLAG_TC);
-
-
- NVIC_InitTypeDef NVIC_InitStructure;
-
-
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
-
-
- }
-
- int fputc(int ch, FILE *f)
- {
-
- USART_SendData(USART1, (uint8_t) ch);
-
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
- {}
- return ch;
- }
3.简单说明
SemaphoreHandle_t xSemaphore = NULL;
申明互斥型信号量,在FreeRTOS中二值型信号量和互斥型信号量类型完全相同。
xSemaphore = xSemaphoreCreateMutex();
创建互斥型信号量。
xSemaphoreTake( xSemaphore, portMAX_DELAY ); //Take:拿资源
获得资源的使用权,此处的等待时间为portMAX_DELAY(挂起最大时间),如果任务无法获得资源的使用权,任务会处于挂起状态。
xSemaphoreGive( xSemaphore ); //Give:给出资源
释放资源的使用权。
4.总结
互斥型信号量和二值型信号量使用方法相似,但二值型信号量用于同步而互斥型信号量用于资源保护。