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 }

測試驗證結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM