FreeRTOS操作系统优先级翻转问题(八)

FreeRTOS总结


前言

在使用二值信号量的时候会遇到很常见的一个问题——优先级翻转,优先级翻转在可剥夺
内核中是非常常见的,在实时系统中不允许出现这种现象,这样会破坏任务的预期顺序,可能
会导致严重的后果。

提示:以下是本篇文章正文内容,下面案例可供参考

一、浅浅了解优先级翻转

在这里插入图片描述
例如:三个不同优先级的任务——低任务、中任务、高任务
创建二值信号量,然后释放一次信号量。
低任务获取信号量,长时间不释放,占住了高任务的资源。
高任务获取信号量,但是此时信号量被低任务占用着,高任务只能等待。但是等待过程中,中任务是一直运行的。出现了优先级反转。

二、模拟 优先级翻转实验

1.代码

在这里插入图片描述
在这里插入图片描述
**注意:**低优先级和高优先级均要获取二值信号,并且低优先级要长时间获取信号量,模拟占取高优先级的二值信号量。

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "lcd.h"
#include "key.h"
#include "beep.h"
#include "malloc.h"
#include "string.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/************************************************
 ALIENTEK ¾«Ó¢STM32F103¿ª·¢°å FreeRTOSʵÑé14-3
 FreeRTOSÓÅÏȼ¶·­×ªÊµÑé-¿âº¯Êý°æ±¾
 ¼¼ÊõÖ§³Ö£ºwww.openedv.com
 ÌÔ±¦µêÆÌ£ºhttp://eboard.taobao.com 
 ¹Øע΢ÐŹ«ÖÚƽ̨΢Ðźţº"ÕýµãÔ­×Ó"£¬Ãâ·Ñ»ñÈ¡STM32×ÊÁÏ¡£
 ¹ãÖÝÊÐÐÇÒíµç×ӿƼ¼ÓÐÏÞ¹«Ë¾  
 ×÷ÕߣºÕýµãÔ­×Ó @ALIENTEK
************************************************/

//ÈÎÎñÓÅÏȼ¶
#define START_TASK_PRIO			1
//ÈÎÎñ¶ÑÕ»´óС	
#define START_STK_SIZE 			256  
//ÈÎÎñ¾ä±ú
TaskHandle_t StartTask_Handler;
//ÈÎÎñº¯Êý
void start_task(void *pvParameters);

//ÈÎÎñÓÅÏȼ¶
#define LOW_TASK_PRIO			2
//ÈÎÎñ¶ÑÕ»´óС	
#define LOW_STK_SIZE 			256  
//ÈÎÎñ¾ä±ú
TaskHandle_t LowTask_Handler;
//ÈÎÎñº¯Êý
void low_task(void *pvParameters);

//ÈÎÎñÓÅÏȼ¶
#define MIDDLE_TASK_PRIO 		3
//ÈÎÎñ¶ÑÕ»´óС	
#define MIDDLE_STK_SIZE  		256 
//ÈÎÎñ¾ä±ú
TaskHandle_t MiddleTask_Handler;
//ÈÎÎñº¯Êý
void middle_task(void *pvParameters);

//ÈÎÎñÓÅÏȼ¶
#define HIGH_TASK_PRIO 			4
//ÈÎÎñ¶ÑÕ»´óС	
#define HIGH_STK_SIZE  			256 
//ÈÎÎñ¾ä±ú
TaskHandle_t HighTask_Handler;
//ÈÎÎñº¯Êý
void high_task(void *pvParameters);

//¶þÖµÐźÅÁ¿¾ä±ú
SemaphoreHandle_t BinarySemaphore;	//¶þÖµÐźÅÁ¿

//LCDË¢ÆÁʱʹÓõÄÑÕÉ«
int lcd_discolor[14]={	WHITE, BLACK, BLUE,  BRED,      
						GRED,  GBLUE, RED,   MAGENTA,       	 
						GREEN, CYAN,  YELLOW,BROWN, 			
						BRRED, GRAY };

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é4	 
	delay_init();	    				//ÑÓʱº¯Êý³õʼ»¯	 
	uart_init(115200);					//³õʼ»¯´®¿Ú
	LED_Init();		  					//³õʼ»¯LED
	KEY_Init();							//³õʼ»¯°´¼ü
	BEEP_Init();						//³õʼ»¯·äÃùÆ÷
	LCD_Init();							//³õʼ»¯LCD
	my_mem_init(SRAMIN);            	//³õʼ»¯ÄÚ²¿ÄÚ´æ³Ø

    POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"ATK STM32F103/407");	
	LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 14-3");
	LCD_ShowString(30,50,200,16,16,"Priority Overturn");
	LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,90,200,16,16,"2016/11/25");
	
	//´´½¨¿ªÊ¼ÈÎÎñ
    xTaskCreate((TaskFunction_t )start_task,            //ÈÎÎñº¯Êý
                (const char*    )"start_task",          //ÈÎÎñÃû³Æ
                (uint16_t       )START_STK_SIZE,        //ÈÎÎñ¶ÑÕ»´óС
                (void*          )NULL,                  //´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
                (UBaseType_t    )START_TASK_PRIO,       //ÈÎÎñÓÅÏȼ¶
                (TaskHandle_t*  )&StartTask_Handler);   //ÈÎÎñ¾ä±ú              
    vTaskStartScheduler();          //¿ªÆôÈÎÎñµ÷¶È
}

//¿ªÊ¼ÈÎÎñÈÎÎñº¯Êý
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //½øÈëÁÙ½çÇø
	
	//´´½¨¶þÖµÐźÅÁ¿
	BinarySemaphore=xSemaphoreCreateBinary();
	//¶þÖµÐźÅÁ¿´´½¨³É¹¦ÒÔºóÒªÏÈÊÍ·ÅÒ»ÏÂ
	if(BinarySemaphore!=NULL)xSemaphoreGive(BinarySemaphore);	
	
    //´´½¨¸ßÓÅÏȼ¶ÈÎÎñ
    xTaskCreate((TaskFunction_t )high_task,             
                (const char*    )"high_task",           
                (uint16_t       )HIGH_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )HIGH_TASK_PRIO,        
                (TaskHandle_t*  )&HighTask_Handler);   
    //´´½¨ÖеÈÓÅÏȼ¶ÈÎÎñ
    xTaskCreate((TaskFunction_t )middle_task,     
                (const char*    )"middle_task",   
                (uint16_t       )MIDDLE_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )MIDDLE_TASK_PRIO,
                (TaskHandle_t*  )&MiddleTask_Handler); 
	//´´½¨µÍÓÅÏȼ¶ÈÎÎñ
    xTaskCreate((TaskFunction_t )low_task,     
                (const char*    )"low_task",   
                (uint16_t       )LOW_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )LOW_TASK_PRIO,
                (TaskHandle_t*  )&LowTask_Handler);
    vTaskDelete(StartTask_Handler); //ɾ³ý¿ªÊ¼ÈÎÎñ
    taskEXIT_CRITICAL();            //Í˳öÁÙ½çÇø
}

//¸ßÓÅÏȼ¶ÈÎÎñµÄÈÎÎñº¯Êý
void high_task(void *pvParameters)
{
	u8 num;
	
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(5,110,115,314); 	//»­Ò»¸ö¾ØÐÎ	
	LCD_DrawLine(5,130,115,130);		//»­Ïß
	POINT_COLOR = BLUE;
	LCD_ShowString(6,111,110,16,16,"High Task");
	
	while(1)
	{
		vTaskDelay(500);	//ÑÓʱ500ms£¬Ò²¾ÍÊÇ500¸öʱÖÓ½ÚÅÄ	
		num++;
		printf("high task Pend Sem\r\n");
		xSemaphoreTake(BinarySemaphore,portMAX_DELAY);	//»ñÈ¡¶þÖµÐźÅÁ¿
		printf("high task Running!\r\n");
		LCD_Fill(6,131,114,313,lcd_discolor[num%14]); 	//Ìî³äÇøÓò
		LED1=!LED1;
		xSemaphoreGive(BinarySemaphore);				//ÊÍ·ÅÐźÅÁ¿
		vTaskDelay(500);	//ÑÓʱ500ms£¬Ò²¾ÍÊÇ500¸öʱÖÓ½ÚÅÄ  
	}
}

//ÖеÈÓÅÏȼ¶ÈÎÎñµÄÈÎÎñº¯Êý
void middle_task(void *pvParameters)
{
	u8 num;
	
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(125,110,234,314); //»­Ò»¸ö¾ØÐÎ	
	LCD_DrawLine(125,130,234,130);		//»­Ïß
	POINT_COLOR = BLUE;
	LCD_ShowString(126,111,110,16,16,"Middle Task");
	while(1)
	{
		num++;
		printf("middle task Running!\r\n");
		LCD_Fill(126,131,233,313,lcd_discolor[13-num%14]); //Ìî³äÇøÓò
		LED0=!LED0;
        vTaskDelay(1000);	//ÑÓʱ1s£¬Ò²¾ÍÊÇ1000¸öʱÖÓ½ÚÅÄ	
	}
}

//µÍÓÅÏȼ¶ÈÎÎñµÄÈÎÎñº¯Êý
void low_task(void *pvParameters)
{
	static u32 times;

	while(1)
	{
		xSemaphoreTake(BinarySemaphore,portMAX_DELAY);	//»ñÈ¡¶þÖµÐźÅÁ¿
		printf("low task Running!\r\n");
		for(times=0;times<5000000;times++)				//Ä£ÄâµÍÓÅÏȼ¶ÈÎÎñÕ¼ÓöþÖµÐźÅÁ¿
		{
			taskYIELD();								//·¢ÆðÈÎÎñµ÷¶È
		}
		xSemaphoreGive(BinarySemaphore);				//ÊͷŶþÖµÐźÅÁ¿
		vTaskDelay(1000);	//ÑÓʱ1s£¬Ò²¾ÍÊÇ1000¸öʱÖÓ½ÚÅÄ	
	}
}




总结

今天就大概了解了什么是优先级翻转的现象。
当一个低优先级任务和一个高优先级任务同时使用同一个信号量,而系统中还有其他中等优先级任务时。如果低优先级任务获得了信号量,那么高优先级的任务就会处于等待状态,但是,中等优先级的任务可以打断低优先级任务而先于高优先级任务运行(此时高优先级的任务在等待信号量,所以不能运行),这是就出现了优先级翻转的现象。
那如何解决这个问题呢?下篇的博客会告诉你。
继续加油!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值