目前多数人熟知的操作系统有windows linux,macos等,然而在MCU中也可以运行操作系统,因为MCU运行内存较PC小且应用场景的需要及时的响应外部设备的操作,所以嵌入式实时操作系统(RTOS)就经常应用在MCU的程序设计中。在使用MCU的工程中,一般程序设计为:
1、前后台系统
在主函数中会有一个超级循环即前台处理程序,用于判断标志位flag,并执行对于的处理函数;对判断标志位flag进行置1的操作函数一般为所使用的外设中断注册的中断服务函数即后台程序。
unsigned char flag;
void interrupt_handle(void)
{
flag=1;
}
void func()
{
/*操作代码*/
}
void main(void)
{
while(1) {
if(flag==1) {
func();
flag=1;
}
}
}
2、协程
Protothreads 是极其轻量级的无堆栈 为内存受限严重的系统设计的线程,例如 小型嵌入式系统或无线传感器网络节点。原型线程 为在以下环境中实现的事件驱动系统提供线性代码执行 C. Protothreads 可以在有或没有底层操作的情况下使用 系统提供阻塞事件处理程序。Protothreads 提供 顺序控制流,无需复杂状态机或完整状态机 多线程。
#include "pt.h"
struct pt pt;
struct timer timer;
PT_THREAD(example(struct pt *pt))
{
PT_BEGIN(pt);
while(1) {
if(initiate_io()) {
timer_start(&timer);
PT_WAIT_UNTIL(pt,
io_completed() ||
timer_expired(&timer));
read_data();
}
}
PT_END(pt);
}
上述协程代码与原理引用于此网址。
3、RTOS
在程序中会提供一套任务调度的管理器函数接口,设计时使用api函数接口注册到管理器中,每个任务函数中都设计了一个死循环,也可以不设计这样这个任务只会被执行一次就退出。当调用启动任务调度的函数,注册的任务函数就会被调度器调用,具体的调度逻辑与使用的rtos有关。
#include "task_kernal.h"
void task_1()
{
while(1) {
printf("task_1");
}
}
void task_2()
{
while(1) {
printf("task_2");
}
}
void main()
{
init();
//开启任务调度
task_start();
//程序一般不会执行到这里
while(1) {
}
}
这两种程序设计中各自的优点和缺点:
优点 | 缺点 | |
前后台系统 | 程序设计简单,开发占用的Ram资源较少 | 当处理的任务变多时,会导致处理不及时, |
协程 | 程序设计功能精简,不依赖任何库函数,且占用内存极小。 | 编写和管理协程代码需要充分考虑代码的运行效率,且不适用于多核场景。 |
rtos | 提高了CPU的利用率,适合处理任务多且多人同时开发的工程 | 会占用部分资源,上手难度较大 |
在实际的使用过程中,使用前后台系统时可以参考RTOS和协程的代码设计与结构也可以提高程序的可读性与维护性,使用RTOS和协程可以减轻设计者设计调度的难度,同时增加了代码的可读性。