Free RTOS的优先级翻转

优先级翻转简介:就是高优先级的任务运行起来的效果好像成了低优先级,而低优先级比高优先级先运行;
举个栗子:假如有三个高、中、低优先级不同的任务,中优先级任务正常跑,假如高、低优先级任务它们两个都在等待同一个二值信号量,但是较低优先级的那个任务有点特别,就是它在获取到信号量后有很长一段很长的延迟(如delay_100s),再释放信号量,因为较低优先级任务没有释放信号量,这就导致高优先级的任务在这段时间是在死等,正常都是高优先级的任务会抢占低优先级任务,而这个刚好违背了常理导致出现优先级翻转;如何解决这个问题呢,请看下一篇推文!
用个小实验看看具体效果
#include stm32f10x.h#include #include freertos.h#include task.h#include semphr.h//毫秒级的延时void delay_ms(u16 time){ u16 i=0; while(time--) { i=12000; //自己定义 while(i--) ; }}void led_init(void){ gpio_inittypedef gpio_initstructure; //定义结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioc,enable); //开启时钟 gpio_initstructure.gpio_pin=gpio_pin_0; //选择你要设置的io口 gpio_initstructure.gpio_mode=gpio_mode_out_pp; //设置推挽输出模式 gpio_initstructure.gpio_speed=gpio_speed_50mhz; //设置传输速率 gpio_init(gpioc,&gpio_initstructure); //初始化gpio gpio_setbits(gpioc,gpio_pin_0); //将led端口拉高,熄灭led}void key_init(void){ gpio_inittypedef gpio_initstructure; //定义结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioa|rcc_apb2periph_gpioe,enable); gpio_initstructure.gpio_pin=gpio_pin_0; //选择你要设置的io口 gpio_initstructure.gpio_mode=gpio_mode_ipd;//下拉输入 gpio_initstructure.gpio_speed=gpio_speed_50mhz; //设置传输速率 gpio_init(gpioa,&gpio_initstructure); /* 初始化gpio */ gpio_initstructure.gpio_pin=gpio_pin_3|gpio_pin_2|gpio_pin_4; gpio_initstructure.gpio_mode=gpio_mode_ipu; //上拉输入 gpio_initstructure.gpio_speed=gpio_speed_50mhz; gpio_init(gpioe,&gpio_initstructure);}void usart_init(uint32_t bound){ gpio_inittypedef gpio_initstruct; //定义gpio结构体变量 usart_inittypedef usart_initstruct; //定义串口结构体变量 rcc_apb2periphclockcmd(rcc_apb2periph_gpioa|rcc_apb2periph_usart1,enable); //使能gpioc的时钟 gpio_initstruct.gpio_pin=gpio_pin_9; //配置tx引脚 gpio_initstruct.gpio_mode=gpio_mode_af_pp; //配置pa9为复用推挽输出 gpio_initstruct.gpio_speed=gpio_speed_50mhz; //配置pa9速率 gpio_init(gpioa,&gpio_initstruct); //gpio初始化函数 gpio_initstruct.gpio_pin=gpio_pin_10; //配置rx引脚 gpio_initstruct.gpio_mode=gpio_mode_in_floating; //配置pa10为浮空输入 gpio_initstruct.gpio_speed=gpio_speed_50mhz; //配置pa10速率 gpio_init(gpioa,&gpio_initstruct); //gpio初始化函数 usart_initstruct.usart_mode=usart_mode_tx|usart_mode_rx; //发送接收模式 usart_initstruct.usart_parity=usart_parity_no; //无奇偶校验 usart_initstruct.usart_baudrate=bound; //波特率 usart_initstruct.usart_stopbits=usart_stopbits_1; //停止位1位 usart_initstruct.usart_wordlength=usart_wordlength_8b; //字长8位 usart_initstruct.usart_hardwareflowcontrol=usart_hardwareflowcontrol_none; //无硬件数据流控制 usart_init(usart1,&usart_initstruct); //串口初始化函数 usart_cmd(usart1,enable); //使能usart1}int fputc(int ch,file *f) //printf重定向函数{ usart_senddata(usart1,(uint8_t)ch); //发送一字节数据 while(usart_getflagstatus(usart1,usart_flag_txe) == reset); //等待发送完成 return ch;}#define start_task_prio 5 //任务优先级#define start_stk_size 128 //任务堆栈大小taskhandle_t starttask_handler; //任务句柄void start_task(void *pvparameters);//任务函数#define low_task_prio 2 //任务优先级#define low_stk_size 50 //任务堆栈大小taskhandle_t lowtask_handler; //任务句柄void low_task(void *p_arg); //任务函数#define med_task_prio 3 //任务优先级#define med_stk_size 50 //任务堆栈大小taskhandle_t medtask_handler; //任务句柄void med_task(void *p_arg); //任务函数#define high_task_prio 4 //任务优先级#define high_stk_size 50 //任务堆栈大小taskhandle_t hightask_handler; //任务句柄void high_task(void *p_arg); //任务函数semaphorehandle_t binary_handle =null; //二值信号量句柄int main( void ) { nvic_prioritygroupconfig(nvic_prioritygroup_4);//设置系统中断优先级分组 4 led_init(); //初始化 led key_init(); usart_init(9600); //创建开始任务 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(); //进入临界区 /* 创建test_queue */ binary_handle = xsemaphorecreatebinary(); if(binary_handle != null) { xsemaphoregive(binary_handle);//释放信号量 } //创建 low 任务 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 ); //创建 med 任务 xtaskcreate( (taskfunction_t )med_task, (const char* )med_task, (uint16_t )med_stk_size, (void* )null, (ubasetype_t )med_task_prio, (taskhandle_t* )&medtask_handler ); //创建 high 任务 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 ); vtaskdelete(starttask_handler); //删除开始任务 taskexit_critical(); //退出临界区}void low_task(void *pvparameters){ int count = 0; while(1) { printf(low正在等待n); xsemaphoretake(binary_handle,portmax_delay); printf(low获取成功%d次n,++count); delay_ms(5000); xsemaphoregive(binary_handle);//释放信号量 vtaskdelay(50); }}void med_task(void *pvparameters){ //basetype_t xreturn = null; while(1) { printf(正在运行n); vtaskdelay(1000); }}void high_task(void *pvparameters){ int count = 0; while(1) { printf(high正在等待n); xsemaphoretake(binary_handle,portmax_delay); printf(high获取成功%d次n,++count); xsemaphoregive(binary_handle);//释放信号量 vtaskdelay(50); }}  
实验效果
--end--

超二代微光像增强器性能随工作时间的变化规律研究
魅族Pro7、魅族Max2最新消息:魅蓝E2才推出,魅族全年的产品规划全曝光!魅族Pro7、魅族Max2都在这
激光雷达“3.0时代”来临了吗?
盘点RISC-V MCU厂商,爱普特为何能在市场占有率拔得头筹?
透过华为军团看科技之变(六):智慧公路
Free RTOS的优先级翻转
电池的容量
LM1875功率放大器制作,LM1875 POWER AMPLIFIER
使用Analog Discovery 2 分析云端测量数据
降低PLC高速计数器计数误差的方法
PCBA加工电路板短路检查方法
Allegro PCB编辑器添加连接的智能层行为是怎么一回事
led灯具的高压测试标准及原因
R40工业路由器海康摄像头监控地址接入平台
深度学习开源框架,AI从业者的选择之路
三星Galaxy A70曝光采用了一个被称作为Infinity-U水滴屏的设计
阿玛尼推出全触控智能手表,搭载了NFC模块支持移动支付
从台湾吸引高科技人才,已成为大陆积极发展芯片行业的一部分
场效应管厂商:上海双岭电子有限公司简介
问答|iphone6s耗电快, 充电慢自动关机……这可咋办?