freeRTOS总结(四)

1.与队列一样任务每一次循环未得到信号量时就会进入阻塞态,以此来进行任务同步 ,当阻塞时间无限大时就会进入完全阻塞态(portMAX_DELAY)若不死等,则在阻塞时间过后就会执行该任务的下一步

二值信号量即为队列项为1的队列,不为空则可以使任务获得信号量,即可解除阻塞态和执行任务其余部分代码。
在使用前也需要创建二值信号量句柄
SemaphoreHandle_t my_Semaphorehandle;
并在开始任务中my_Semaphorehandle = xSemaphoreCreateBinary(); if(my_Semaphorehandle == NULL) printf("Semaphr creat faild!");
创建二值信号量
2.信号量用的时队列实现的

void task1_task(void *pvParameters)
{
    u8 ui = 0;
    u8 key = 0;
    while(1)
    {
        key = KEY_Scan(0);
        if(my_Semaphorehandle!=NULL && key)
        {
            if(xSemaphoreGive(my_Semaphorehandle))
            {
                printf("信号值释放成功!\r\n");
            }
        }
        
        LED0 = !LED0;
//        printf("task1 running");
        vTaskDelay(7);
        
        
    }
}
以上是发送,
以下是接收函数

```c

        if(my_Semaphorehandle!=NULL)
        {
            xSemaphoreTake( my_Semaphorehandle, portMAX_DELAY ); 
放在另一个任务函数中。

 3.也与队列一样,有中断释放信号量,释放完后得判断是否切换任务

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
	u8 Res;
    BaseType_t pxHigherPriorityTaskWoken;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
		{
			if(USART_RX_STA&0x4000)//接收到了0x0d
			{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
			}
			else //还没收到0X0D
			{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
				}		 
			}
		}   		 
	} 
    //释放二值信号量
	if((USART_RX_STA&0x8000)&&(my_Semaphorehandle!=NULL))//接收到数据,并且二值信号量有效
	{
		xSemaphoreGiveFromISR(my_Semaphorehandle,&pxHigherPriorityTaskWoken);	//释放二值信号量
		portYIELD_FROM_ISR(pxHigherPriorityTaskWoken);//如果需要的话进行一次任务切换
	}
} 
#endif	

 中断中使用发送,任务中接收
 
4.计数信号量就是多个队列项的队列,和二值信号量一样只在乎有没有释放信号和多少个信号(二值信号量只有一个),不在乎信号内容

5.semphr这个h文件为什么可以定义函数,因为他都是用define和typedef来调用queue.c中的函数,来形成自己的函数,基于queue.c

6.与二值信号量一样
需要先定义
SemaphoreHandle_t counting_Semaphorehandle;
开始任务中初始化

```c
//counting_Semaphorehandle = xSemaphoreCreateCounting( 20, 0 );   inite vaule is 0
counting_Semaphorehandle = xSemaphoreCreateCounting( 20, 10 );    //init vaule is 10
    if(counting_Semaphorehandle == NULL)
        printf("Semaphr creat faild!");

7.释放信号量,则项数加一

void task1_task(void *pvParameters)
{

    u8 key = 0;
    while(1)
    {
        key = KEY_Scan(0);
        if(counting_Semaphorehandle!=NULL && key)
        {
            if(xSemaphoreGive(counting_Semaphorehandle))
            {
                printf("信号值释放成功!\r\n");
            }
        }
        
        LED0 = !LED0;
//        printf("task1 running");
        vTaskDelay(7);
        
        
    }
}

8.获取信号量,则项数减一


void task2_task(void *pvParameters)
{
    UBaseType_t a = 0;
    while(1)
    {
        if(counting_Semaphorehandle!=NULL)
        {
            xSemaphoreTake( counting_Semaphorehandle, portMAX_DELAY );  
            {
                a = uxSemaphoreGetCount(counting_Semaphorehandle);
                printf("num = %d",a);
            }
        }
        LED1 = !LED1;
        printf("task2 running\r\n");
        vTaskDelay(1000);     //一秒获取一次,那在一秒内释放的信号量就得累积
    }
}


9.优先级反转
这个现象是由于等待信号量造成的,比如:当一个低级任务获取到信号量并处于运行状态,此时高优先级也需要获取信号量才能运行,但是他会由于信号量被低级任务占用而处于阻塞态,此时如果有一个中级任务出现,则会打断低级任务的执行,这将导致效果:中级任务优先级高于高级任务,非常危险!!(以上针对二值信号量)
所以需要互斥信号量,在某些情况下代替二值信号量。可以避免中级任务优先于高级任务

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值