FreeRTOS--计数信号量

时间:2019-09-04
本文章向大家介绍FreeRTOS--计数信号量,主要包括FreeRTOS--计数信号量使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

计数信号量有两种典型的用法:

1.事件计数:

每次事件发生时,中断ISR会释放(Give)信号量,信号量的计数值加1 。事件处理任务每次处理一个事件会获取(Take)一次信号量,计数值减1. 信号量的值就是已发生事件数目与已处理事件数目之间的差值。用于事件的计数的计数信号量,在被创建时其计数值被初始化为0。

2.资源管理:

信号量的计数值表示可用资源的数目,一个任务获取资源的控制权,必须先获取(Take)信号量,使信号的计数值减1。当资源总数为0,表示没有资源可用。当任务利用资源完成工作后,归还信号量,信号量的计数值加1.用于资源管理的信号量,在被创建时其计数值为可用的最大资源数。

典型的生产者与消费者问题如下图示:

这里对生产者与消费者问题,进行验证:

 

资源:生产线上有5个箱子(共享资源),一开始都是空的。

生产者:先判断在5个箱子(共享资源)中有木有空箱子,若有空箱子则向空箱子放入数字(依次放入1,2,…10);若无空箱子则需要等待。

消费者:先判断在5个箱子(共享资源)中有木有已放入数字的箱子,若有则取出箱子的数字,进行累加处理,若无则需要等待。

  1 #define BOX_NUM         5       
  2 uint32_t box[BOX_NUM];      
  3 uint32_t put = 0,get = 0;       
  4 
  5 
  6 void MX_FREERTOS_Init(void) {
  7   /* USER CODE BEGIN Init */
  8        
  9   /* USER CODE END Init */
 10 
 11 
 12   /* Create the semaphores(s) */
 13   /* definition and creation of lockSem */
 14   osSemaphoreDef(lockSem);
 15 //lockSem用于对共享资源的互斥访问
 16   lockSemHandle = osSemaphoreCreate(osSemaphore(lockSem), 1);
 17 
 18   /* definition and creation of emptySem */
 19   osSemaphoreDef(emptySem);
 20 //emptySem代表空箱子的资源数,初始计数值5
 21   emptySemHandle = osSemaphoreCreate(osSemaphore(emptySem), 5);
 22 
 23   /* definition and creation of fullsem */
 24 //fullSem代表装有数字箱子的资源数,初始计数值0
 25   fullsemHandle = xSemaphoreCreateCounting(5, 0);
 26 
 27   /* USER CODE BEGIN RTOS_TIMERS */
 28   /* start timers, add new ones, ... */
 29   /* USER CODE END RTOS_TIMERS */
 30 
 31   /* Create the thread(s) */
 32   /* definition and creation of vTask1 */
 33   osThreadDef(vTask1, producer_task, osPriorityNormal, 0, 256);
 34   vTask1Handle = osThreadCreate(osThread(vTask1), NULL);
 35 
 36   /* definition and creation of vTaks2 */
 37   osThreadDef(vTaks2, consumer_task, osPriorityHigh, 0, 256);
 38   vTaks2Handle = osThreadCreate(osThread(vTaks2), NULL);
 39 
 40   /* USER CODE BEGIN RTOS_THREADS */
 41   /* add threads, ... */
 42   /* USER CODE END RTOS_THREADS */
 43 
 44   /* USER CODE BEGIN RTOS_QUEUES */
 45   /* add queues, ... */
 46   /* USER CODE END RTOS_QUEUES */
 47 }
 48 
 49 /* producer_task function */
 50 void producer_task(void const * argument)
 51 {
 52 
 53   /* USER CODE BEGIN producer_task */
 54   static int Count = 0;
 55   /* Infinite loop */
 56   while(Count < 10)
 57   {
 58       //尝试获取一个空箱子
 59       osSemaphoreWait(emptySemHandle,osWaitForever);
 60 
 61       //互斥访问共享资源
 62       osSemaphoreWait(lockSemHandle,osWaitForever);
 63 
 64      //向空箱子放入数字
 65       box[put % BOX_NUM] = Count + 1;
 66 
 67       printf("the producer package box[%d] which content is : %d\n",put % BOX_NUM,box[put % BOX_NUM]);
 68 
 69       //放入数字次数
 70       put++;
 71 
 72       //当对共享资源访问完毕,解锁。
 73       osSemaphoreRelease(lockSemHandle);
 74 
 75       //释放一个“满”信号量,代表已完成对一个box的加工
 76       osSemaphoreRelease(fullsemHandle);
 77 
 78       //循环执行次数
 79       Count++;
 80 
 81       //生产者休息一会
 82       osDelay(20);
 83   }
 84 
 85   printf("producer finish!!!!!\n");
 86 
 87   osThreadSuspend(vTask1Handle);
 88   /* USER CODE END producer_task */
 89 }
 90 
 91 /* consumer_task function */
 92 void consumer_task(void const * argument)
 93 {
 94   /* USER CODE BEGIN consumer_task */
 95   static int sum = 0;
 96   /* Infinite loop */
 97   while(1)
 98   {
 99       //尝试获取一个已放入数字箱子
100       osSemaphoreWait(fullsemHandle,osWaitForever);
101 
102       //互斥访问共享资源
103       osSemaphoreWait(lockSemHandle,osWaitForever);
104 
105      //获取箱子里数字进行累加计算
106       sum = sum + box[get % BOX_NUM];
107 
108       printf("the consumer : box[%d] get a num %d\n",get%BOX_NUM, box[get%BOX_NUM]);
109 
110      //获取数字的次数
111       get++;
112 
113       //当对共享资源访问完毕,解锁。
114       osSemaphoreRelease(lockSemHandle);
115 
116       //释放一个空箱子资源
117       osSemaphoreRelease(emptySemHandle);
118 
119      //获取10次数字后退出
120       if(get == 10)
121       {
122         break;
123       }
124 
125       osDelay(120);
126   }
127 
128   printf("the consumer sum is: %d\n", sum);
129   printf("the consumer exit!\n");
130 
131   osThreadSuspend(vTaks2Handle);
132   /* USER CODE END consumer_task */
133 }

测试验证结果:

原文地址:https://www.cnblogs.com/mickey-double/p/11457667.html