来自:http://blog.csdn.net/xukai871105/article/details/43456985

0.前言

在嵌入式操作系统中互斥型信号量是任务间资源保护的重要手段。下面结合一个具体例子说明FreeRTOS中的互斥型信号量如何使用。

【相关博文】

    【FreeRTOS STM32移植笔记】

【FreeRTOS学习笔记——任务间使用队列同步数据】
【FreeRTOS学习笔记——二值型信号量】
【如何在FreeRTOS下实现低功耗——MSP430F5438平台】

【代码链接】——示例代码存于百度网盘

1.基本说明

互斥型信号量的使用方法如图1所示。在多数情况下,互斥型信号量和二值型信号非常相似,但是从功能上二值型信号量用于同步,而互斥型信号量用于资源保护。互斥型信号量和二值型信号量还有一个最大的区别,互斥型信号量可以有效解决优先级反转现象。
图1 互斥型信号量使用方法

2.参考代码

    本例具有两个任务,两个任务都试图通过串口打印内容,此时串口就好比一个“资源”,某个任务使用串口资源时必须保护该资源,使用完串口之后在释放资源。保护和释放动作便对应互斥型信号量的两个基本操作,xSemaphoreTake和xSemaphoreGive。
【代码】
[cpp] view plaincopy
  1. /* Standard includes. */
  2. #include <stdio.h>
  3. #include <string.h>
  4. /* Scheduler includes. */
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "queue.h"
  8. #include "semphr.h"
  9. /* Library includes. */
  10. #include "stm32f10x.h"
  11. #define LED0_ON()   GPIO_SetBits(GPIOB,GPIO_Pin_5);
  12. #define LED0_OFF()  GPIO_ResetBits(GPIOB,GPIO_Pin_5);
  13. static void Setup(void);
  14. void TaskA( void *pvParameters );
  15. void TaskB( void *pvParameters );
  16. void LedInit(void);
  17. void UART1Init(void);
  18. /* 互斥信号量句柄 */
  19. SemaphoreHandle_t xSemaphore = NULL;
  20. int main(void)
  21. {
  22. /* 初始化硬件平台 */
  23. Setup();
  24. /* 创建互斥信号量 */
  25. xSemaphore = xSemaphoreCreateMutex();
  26. /* 建立任务 */
  27. xTaskCreate( TaskA, "TaskA", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+3, NULL );
  28. xTaskCreate( TaskB, "TaskB", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+4, NULL );
  29. /* 启动OS */
  30. vTaskStartScheduler();
  31. return 0;
  32. }
  33. void TaskA( void *pvParameters )
  34. {
  35. for( ;; )
  36. {
  37. xSemaphoreTake( xSemaphore, portMAX_DELAY );
  38. {
  39. printf("Task A\r\n");
  40. }
  41. xSemaphoreGive( xSemaphore );
  42. vTaskDelay( 2000/portTICK_RATE_MS );
  43. }
  44. }
  45. void TaskB( void *pvParameters )
  46. {
  47. for( ;; )
  48. {
  49. xSemaphoreTake( xSemaphore, portMAX_DELAY );
  50. {
  51. printf("Task B\r\n");
  52. }
  53. xSemaphoreGive( xSemaphore );
  54. vTaskDelay( 1000/portTICK_RATE_MS );
  55. }
  56. }
  57. static void Setup( void )
  58. {
  59. LedInit();
  60. UART1Init();
  61. }
  62. void LedInit( void )
  63. {
  64. GPIO_InitTypeDef GPIO_InitStructure;
  65. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  66. /*LED0 @ GPIOB.5*/
  67. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  68. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  69. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  70. GPIO_Init( GPIOB, &GPIO_InitStructure );
  71. }
  72. void UART1Init(void)
  73. {
  74. GPIO_InitTypeDef GPIO_InitStructure;
  75. USART_InitTypeDef USART_InitStructure;
  76. /* 第1步:打开GPIO和USART时钟 */
  77. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);
  78. /* 第2步:将USART1 Tx@PA9的GPIO配置为推挽复用模式 */
  79. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  80. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  81. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  82. GPIO_Init(GPIOA, &GPIO_InitStructure);
  83. /* 第3步:将USART1 Rx@PA10的GPIO配置为浮空输入模式 */
  84. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  85. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  86. GPIO_Init(GPIOA, &GPIO_InitStructure);
  87. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  88. GPIO_Init(GPIOA, &GPIO_InitStructure);
  89. /* 第4步:配置USART1参数
  90. 波特率   = 9600
  91. 数据长度 = 8
  92. 停止位   = 1
  93. 校验位   = No
  94. 禁止硬件流控(即禁止RTS和CTS)
  95. 使能接收和发送
  96. */
  97. USART_InitStructure.USART_BaudRate = 9600;
  98. USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  99. USART_InitStructure.USART_StopBits = USART_StopBits_1;
  100. USART_InitStructure.USART_Parity = USART_Parity_No;
  101. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  102. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  103. USART_Init(USART1, &USART_InitStructure);
  104. /* 第5步:使能 USART1, 配置完毕 */
  105. USART_Cmd(USART1, ENABLE);
  106. /* 清除发送完成标志 */
  107. USART_ClearFlag(USART1, USART_FLAG_TC);
  108. /* 使能USART1发送中断和接收中断,并设置优先级 */
  109. NVIC_InitTypeDef NVIC_InitStructure;
  110. // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  111. /* 设定USART1 中断优先级 */
  112. NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  113. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
  114. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  115. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  116. NVIC_Init(&NVIC_InitStructure);
  117. /* 使能接收中断 */
  118. // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  119. }
  120. int fputc(int ch, FILE *f)
  121. {
  122. /* 写一个字节到USART1 */
  123. USART_SendData(USART1, (uint8_t) ch);
  124. /* 等待发送结束 */
  125. while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
  126. {}
  127. return ch;
  128. }

3.简单说明

SemaphoreHandle_t xSemaphore = NULL;
申明互斥型信号量,在FreeRTOS中二值型信号量和互斥型信号量类型完全相同。

xSemaphore = xSemaphoreCreateMutex();

创建互斥型信号量。

xSemaphoreTake( xSemaphore, portMAX_DELAY ); //Take:拿资源

获得资源的使用权,此处的等待时间为portMAX_DELAY(挂起最大时间),如果任务无法获得资源的使用权,任务会处于挂起状态。

xSemaphoreGive( xSemaphore ); //Give:给出资源

    释放资源的使用权。

4.总结

    互斥型信号量和二值型信号量使用方法相似,但二值型信号量用于同步而互斥型信号量用于资源保护。

FreeRTOS学习笔记——互斥型信号量相关推荐

  1. 5.FreeRTOS学习笔记- 互斥量

    基本概念 互斥量又称互斥信号量(本质是信号量),是一种特殊的二值信号量 互斥量 支持互斥量所有权.递归访问以及防止优先级翻转的特性,用于实现对临界资源(如显示器.打印机)的独占式访问. 任意时刻互斥量 ...

  2. freeRtos学习笔记 (7)信号量

    freeRtos学习笔记 freeRtos信号量 信号量种类 信号量分为四种:二值信号量,互斥信号量,计数信号量和递归互斥信号量,其中计数信号量用于管理系统多个共享资源,用计数值表示可用资源数目;二值 ...

  3. FreeRTOS学习笔记

    FreeRTOS学习笔记 (这是我自己学习FreeRTOS整理的笔记,仅供参考) 第一部分:实现FreeRTOS内核 变量名: 定义变量时往往会把变量的类型当作前缀加在变量上 变量类型 前缀 char ...

  4. 1、野火freertos学习笔记

    野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...

  5. FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析

    FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析 怎么查找就绪任务中优先级最高的? tasks.c中声明了一个全局变量 uxTopReadyPriority,任务从其他状态进入就绪 ...

  6. freeRtos学习笔记 (8) 任务通知

    freeRtos学习笔记 freeRtos任务通知 任务通知的优缺点 freeRtos任务控制块中包含两个32位的变量,用于任务通知,在一些情况下,任务通知可以替代信号量和事件组,并且比信号量和事件组 ...

  7. freeRtos学习笔记 (5)事件组

    freeRtos学习笔记 freeRtos事件组 为什么要用事件组? 多任务环境下, 任务.中断之间往往需要同步操作,一个事件发生会告知等待中的任 务,即形成一个任务与任务.中断与任务间的同步.事件可 ...

  8. FreeRTOS学习笔记20200526

    FreeRTOS学习笔记-Day1-20200526 nFlag = TRUE; 先立个Flag,是时候点亮嵌入式实时操作系统这个技能了.座右铭:坚持.认真.沉静.笃行. FreeRTOS优势 总结F ...

  9. freeRtos学习笔记 (9) 移植和CPU利用率统计

    freeRtos学习笔记 (9) 移植和CPU利用率统计 使用官方固件移植 首先准备一个能跑的裸机工程 注意,freertos需要使用systick定时器,而stm32HAL库默认使用systick作 ...

最新文章

  1. 几经沉浮,人工智能前路何方?
  2. php修改新闻分类代码,新闻分类录入、显示系统_php
  3. 递归算法学习系列之八皇后问题
  4. linux怎么安装python包_linux下安装python软件包pymssql
  5. Android典型界面设计(3)——访网易新闻实现双导航tab切换
  6. honeywell新风系统控制面板说明_如何选择新风系统中的新风设备万家舒适家
  7. [react] React的isMounted有什么作用?
  8. JavaScript中九九乘法表制作
  9. java矩阵类_151-矩阵类
  10. C#实现DataTable按天分组并计数
  11. Linux 服务器安全加固 10条建议
  12. PASCAL VOC2012数据集介绍
  13. MCU_segger-JLINK批处理脚本烧录工具-JFlash
  14. 惠普笔记本安装Linux 7及NVIDIA Quandro P600显卡驱动
  15. Codeforces 1013 A. Piles With Stones
  16. 七牛云php回调,回调通知_开发指南_对象存储 - 七牛开发者中心
  17. pion-example-webrtc-applications示例学习
  18. 电商平台快递物流解决方案
  19. html的细节优化,网站图片优化细节放送(seo技巧)
  20. HTTP协议漫谈 C#实现图(Graph) C#实现二叉查找树 浅谈进程同步和互斥的概念 C#实现平衡多路查找树(B树)...

热门文章

  1. Linux网卡命名规则
  2. 爬虫中的关于字符串的一些理解
  3. python ==》 元组
  4. PHP 错误与异常 笔记与总结(12 )异常
  5. 写文章最难写的是标题
  6. CodeSmith终极玩法
  7. const指针和指向常量的指针
  8. Jetty - Container源码分析
  9. openssl、ssh
  10. 她说程序员不懂浪漫,生日宴上惨变单身狗,其实,程序员的浪漫你不懂!