裸机和rtos两种开发方式的区别

您所在的位置:网站首页 rtos和裸机哪个难 裸机和rtos两种开发方式的区别

裸机和rtos两种开发方式的区别

2023-07-30 08:19| 来源: 网络整理| 查看: 265

一、裸机开发 1.轮询方式

轮询,顾名思义就是事情一件件按顺序来,同一时间只能做一件事情。举个例子,一个妈妈要做两件事情,喂饭和回信息,只能先喂好饭,然后再回信息,两件事情不能同时做有先后顺序。

void main() { while (1) { 喂一口饭(); 回一个信息(); } } 2.事件驱动

事件是一个宽泛的概念,什么叫事件?可以是:按下了按键、串口接收到了数据、模块产生了中断、某个全局变量被设置了。

什么叫事件驱动?当某个事件发生时,才调用对应函数,这就叫事件驱动。放到MCU来讲,我们可以理解为来了一个按键中断,这时就要调用中断处理函数处理中断信息。

再以上个例子为例,妈妈一直给小孩喂饭,就做这件事情,某个时间点同事发来一条信息,这时就需要妈妈去处理这个信息,处理完成后继续喂饭。

void main() { while (1) { 喂饭(); } } void message_isr() /* 同事发来信息触发中断 */ { 回一个信息(); }

对于中断的处理,原则是"尽快"。否则会影响到其他中断,导致其他中断的处理被延迟、甚至丢失,所以中断处理的事情要尽量的精简。

3.定时器方式

上述例子中只有两个任务,如果有更多的任务,很多有经验的工程师会使用定时器来驱动:

设置一个定时器,比如每1ms产生一次中断,以此为时间基准

对于函数A,可以设置它的执行周期,比如每1ms执行一次

对于函数B,可以设置它的执行周期,比如每2ms执行一次

对于函数C,可以设置它的执行周期,比如每3ms执行一次

注意:1ms、2ms、3ms只是假设,你可根据实际情况调整。

typedef struct soft_timer { int remain; int period; void (*function)(void); }soft_timer, *p_soft_timer; static soft_timer timers[] = { {1, 1, A}, {2, 2, B}, {3, 3, C}, }; void main() { while (1) { } } void timer_isr() { int i; /* timers数组里每个成员的expire都减一 */ for (i = 0; i < 3; i++) timers[i].remain--; /* 如果timers数组里某个成员的expire等于0: * 1. 调用它的函数 * 2. 恢复expire为period */ for (i = 0; i < 3; i++) { if (timers[i].remain == 0) { timer[i].function(); timers[i].remain = timers[i].period; } } }

但这时又出现个问题,如果某个函数处理的时间过长,这又会影响其他函数,或者时间基准。当然也可以把函数分得更精简,一件事情拆成多个步骤完成,这样可以解决这个问题。

也可以可以做以下改进,将任务放回主函数中,这样做就退回轮询方式。

typedef struct soft_timer { int remain; int period; void (*function)(void); }soft_timer, *p_soft_timer; static soft_timer timers[] = { {1, 1, A}, {2, 2, B}, {3, 3, C}, }; void main() { int i; while (1) { /* 如果timers数组里某个成员的expire等于0: * 1. 调用它的函数 * 2. 恢复expire为period */ for (i = 0; i < 3; i++) { if (timers[i].remain == 0) { timer[i].function(); timers[i].remain = timers[i].period; } } } } void timer_isr() { int i; /* timers数组里每个成员的expire都减一 */ for (i = 0; i < 3; i++) if (timers[i].remain) timers[i].remain--; } 4.状态机方式

假设要调用两个函数AB,AB执行的时间都很长,又要AB任务都可以及时得到响应,裸机就很难处理这种场景,这时就需要使用状态机方式,将一个任务拆多个任务处理。

void feed_kid(void) { static int state = 0; switch (state) { case 0: /* 开始 */ { /* 盛饭 */ state++; return; } case 1: /* 盛菜 */ { /* 盛菜 */ state++; return; } case 2: { /* 拿勺子 */ state++; return; } } } void send_msg(void) { static int state = 0; switch (state) { case 0: /* 开始 */ { /* 打开电脑 */ state++; return; } case 1: { /* 观看信息 */ state++; return; } case 2: { /* 打字 */ state++; return; } } } void main() { while (1) { feed_kid(); send_msg(); } } 二、rtos开发

由以上裸机开发方式可见,在处理多任务方面,裸机开发或多或少都存在缺陷,这时就急需引入一种多任务并行运行的方式,实时处理信息。rtos的开发方式就由此而来。

有人可能会说,我使用状态机也可以实现同样的效果呀,为啥那么麻烦学习rtos。使用rtos的关键就是在于可以多任务并行,遇到执行时间长的任务,也不需要像状态机那样将任务分拆,而且每个任务之间的资源和栈都是独立的,程序的耦合性大大降低,可移植性和可读性大大增强。

举例如下:

// RTOS程序 喂饭() { while (1) { 喂一口饭(); } } 回信息() { while (1) { 回一个信息(); } } void main() { create_task(喂饭); create_task(回信息); start_scheduler(); while (1) { sleep(); } }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3