• 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
    ",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!!!!!
    ");
     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
    ",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
    ", sum);
    129   printf("the consumer exit!
    ");
    130 
    131   osThreadSuspend(vTaks2Handle);
    132   /* USER CODE END consumer_task */
    133 }

    测试验证结果:

  • 相关阅读:
    git version info & svn version info map(七)
    /proc/pid/statm content analysis
    git log filter(六)
    git create remote branch (五)
    learning svn diff --summarize
    learning scala akka ask_pattern
    learning scala akka tell pattern(二)
    learning scala akka actorySystem create and close
    hibernate 自动生成数据库
    STRICT_TRANS_TABLES STRICT_ALL_TABLES
  • 原文地址:https://www.cnblogs.com/mickey-double/p/11457667.html
Copyright © 2020-2023  润新知