来自: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.总结 
     互斥型信号量和二值型信号量使用方法相似,但二值型信号量用于同步而互斥型信号量用于资源保护。