FreeRTOS--队列

在讲队列前,先思考一下这个问题:
下面这个程序,如果用RTOS实现会出问题吗?

c:
int a = 0;
void fun_a(){
 a++;
}
void fun_b(){
 a++;
}
int main(){
	while(1){
	fun_a();
	fun_b();
	}

}
RTOS:
int a = 0;
void fun_a(){
 a++;
}
void fun_b(){
 a++;
}
int main()
{
	creat_Task(fun_a);
	creat_Task(fun_b);

}

对RTOS代码分析:
我们的期望是运行一次fun_a后a++运行1次,运行1次fun_b后a++运行1次,a = 2
fun_a和fun_b的a++:
1)读a: R0寄存器,读RAM的a的地址,得到a的值
2)修改:R0 自加 1
3)写a:R0寄存器,写RAM的a的地址,修改a的值
接下来模拟一下 RTOS运行
t0:
fun_a:
1)R0寄存器,读RAM的a的地址,得到a的值,R0 = 0,
2)此时到下一个tick,保存现场R0 = 0.
t1:
fun_b:
1)读a: R0寄存器,读RAM的a的地址,得到a的值,R0 = 0;
2)修改:R0 自加 1,R0 += 1,R0 = 1;
3)写a:R0寄存器,写RAM的a的地址,修改a的值;a = 1
t2:
fun_a:
1)恢复现场 R0 = 0
2)修改:R0 自加 1 R0 += 1,R0 = 1;
3)写a:R0寄存器,写RAM的a的地址,修改a的值;a = 1

由上面可知,不符合我们的期望,运行结果为 a = 1
根本问题在于,多个任务一起修改没有互斥机制保护数据。

队列提供了解决的方法,使用QueueSend可以将任务的tick中断关闭,实现裸机运行,修改完数据后再打开中断

接下来再举个栗子

void fun_a(){
 while(1){
 ...
 	达成某条件后
	flag = 1;
 ...
	}
}
void fun_b(){
 ...
	if(flag = 1){
	}
 ...
}

如果运行100w次就要判断100w次太过于浪费CPU

void fun_a(){
 while(1){
 ...
 	达成某条件后
	写队列:{
	1)写Data
	2)唤醒Queue.list里的任务,并将DelayList里的任务放进ReadyList

}
 ...
	}
}
void fun_b(){
 ...
	读队列:{
	1)有Data,返回做事
	2)无Data,休眠:
				  a.将该任务放进DelayList链表
				  b.将该任务插入Queue.List队列
	}
	
 ...
}

FreeRTOS--队列_第1张图片
fun_a可以全速运行
fun_b可以不浪费CPU资源

通过链表队列实现唤醒休眠

环形缓冲区

FreeRTOS--队列_第2张图片
FreeRTOS--队列_第3张图片
这里很简单,就直接贴一下韦老师的图了

读队列

a.关中断
b.
有数据:
1)copy数据
2)唤醒Queue.list里的任务,移除Queue.list第一个任务
3)将DelayList里的任务放进ReadyList
无数据:
1.返回ERR
2.休眠:
1)将该任务放进DelayList链表
2)将该任务插入Queue.List队列

写队列

a.关中断
b.
有空间:
1)写数据
2)唤醒Queue.list里的任务,移除Queue.list第一个任务
3)将DelayList里的任务放进ReadyList
无空间:
1.返回ERR
2.休眠:
1)将该任务放进DelayList链表
2)将该任务插入Queue.List队列

超时唤醒

任务休眠,对于休眠的任务,每次tick中断都会累加计数,然后对DelayList的任务检查是否超时,超时则会移到ReadyList

你可能感兴趣的:(RTOS,arm,单片机,arm开发,驱动开发,硬件架构)