FreeRTOS学习------信号量(实践)

来源:互联网 发布:淘宝的微淘怎么弄2016 编辑:程序博客网 时间:2024/05/29 21:34

硬件:STM32F107

软件:keil4


1.信号量和计数信号量的概念

    这里有关这两个概念的介绍的博文很多,如果你刚入门连这两个概念你都不清楚,这时候你就需要多去看些有关的文章或者资料。当然也可以参考我上传的《FreeRTOS入门手册》里面的有关介绍,里面还是介绍的很详细的。这里我就不累述这些理解性的概念,这里我直接给出两幅图,在文章结尾帮助大家理解。


2.代码编程实现

   (1)应用场景

    这里我们既然要应用到实际代码中,自然也要谈到我们在实际应用中对于信号量和计数信号量的使用场景。信号量这里大多数应 

    用都是应用在任务同步中。特别对于中断同步来说,对于有芯片编程的经验的朋友应该都知道,中断函数中我们尽可能是少做事

    情,这样CPU的工作效率以及整体的性能都会得到提升。信号量在系统应用中就多用在中断函数的同步中,当然任务同步也可

    以,这些都是根据你个人的项目需求而定。下面我直接给出我测试实现中断函数同步功能的代码,这里有关函数的使用和解释,

    大家也可以参考我的博客资源里面的 《FreeRTOS入门手册》。

   (2)相关理论知识

     这里我们在系统中用到中断,自然要了解系统的优先级的结构有所了解。FreeRTOS是一个高度可剪裁的操作系统,这里有关整

     个系统的优先级涉及的有关宏定义这里我也参考了几篇网友的博文,感谢这几位网友。下面我会给出他们的文章链接,建议大家

     一定要去阅读和理解清楚,无论对现在的学习,还是今后的项目需要来说都是必须的。这里在结合FreeRTOS使用之前,我们也

     必须对CotexM-3的内核有一定了解,以及使用这个内核的芯片的优先级的设置相关知识。这些知识也是你理解这两篇博文的前 

     提:

      相关博文链接http://blog.csdn.net/xukai871105/article/details/43153177

                           http://blog.csdn.net/zhzht19861011/article/details/50135449         

   (3)代码实现

SemaphoreHandle_t  xSemaphore;             //定义一个二值信号量或者计数信号量的句柄int main(void) {   NVIC_Configuration();    #if DEBUG>0  Usart_IO();   Debug_Usart_Init(115200);  #endif           //xSemaphore=xSemaphoreCreateBinary();       //创建一个二值信号量          
           //参数1:可以缓存的最大数值,参数2;信号量的初始值   xSemaphore=xSemaphoreCreateCounting(10,2);   //创建一个计数信号量    xTaskCreate(vBEBUG_Task, "DEBUG",configMINIMAL_STACK_SIZE,NULL, tskIDLE_PRIORITY+1,NULL);    xTaskCreate(vBEBUG_Task2,"DEBUG2",configMINIMAL_STACK_SIZE,NULL,tskIDLE_PRIORITY+10,NULL);          vTaskStartScheduler();                                //Æô¶¯OS           return 0;}void  vBEBUG_Task( void *pvParameters ){   while(1)           {        if( xSemaphoreTake(xSemaphore,portMAX_DELAY )==pdTRUE )                 {   printf("666666 \r\n");               }       vTaskDelay( 700 / portTICK_RATE_MS );    } }void  vBEBUG_Task2( void *pvParameters ){   while(1)            {  printf("vBEBUG_Task2 \r\n"); vTaskDelay( 600 / portTICK_RATE_MS );      } }void NVIC_Configuration(void){   NVIC_InitTypeDef NVIC_InitStructure;  /* Set the Vector Table base location at 0x08000000 */   NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    NVIC_Init(&NVIC_InitStructure);}void USART1_IRQHandler(void){  static BaseType_t xHigherPriorityTaskWoken;    if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)  {           xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );        USART_ClearFlag(USART1, USART_FLAG_RXNE);  }    }


3.学习总结

 (1)中断函数是每接收一个字节数据就进入一次中断,这里我们在中断函数中应该有相关数据判断确认我们接收到一个完整的数   

          据包之后我们再经行一次相关二值信号量的函数操作。

(2)这里实际测试发现,我们利用二值量使得与中断几乎同步执行的函数这里建议优先级尽量高于其他任务函数的优先级,用来保

         证同步函数可以得到执行。这里如果其他任务函数优先级高于同步函数的优先级并且这个函数中没有 vTaskDel( 700 /            

          portTICK_RATE_MS ); 相关的任务调度函数,同步函数将永远得不到执行,这是非常危险的事情。

(3) 计数信号量作为一个可以锁存多个同步事件的变量,当我们执行了多少次xSemaphoreGiveFromISR这个函数,同步函数就

          会执行多少次,当然我们的数值不能超过创建计数信号量函数中的第一个参数的值。

(4)使用计数信号量的相关函数,需要打开这个宏定义#define configUSE_COUNTING_SEMAPHORES  1FreeRTOSConfig.h

         文件中这个宏定义系统默认是0在FreeRTOS.h文件中。




 信号量的任务同步图解(最多锁存一个同步事件)                   计数信号量任务同步图解(可锁存多个同步事件)


                                                                         

                                                                      这里本人始终相信交流就是力量,欢迎大家加入本人的交流群一起学习:469602418

               

                   

                   







0 0