什么时候该用裸机?什么时候该用RTOS?
今天在某QQ群里看到有人讨论这个问题,正巧我也仔细想了一下。以下是我对这个问题的看法
1.RTOS的RT这词就是实时的意思,网上很多归纳总结都说RTOS要用在实时性很高的项目,怎么才算是实时性高呢?
假设我们裸机有下面这个段程序
int main() { sys_init(); while(1) { 远程数据处理_proc(); //通讯模块接收的数据 10ms 485数据处理_proc(); // 10ms lcd_proc(); 5ms key_proc(); 5ms clock_proc(); 1ms 远程模块管理_proc(); //通讯模块连接服务器等 10ms 采集数据_proc(); //可以是采集电能或其它数据 20ms 处理采集数据_proc(); 30ms 喂狗_proc(); 1ms } }
假设每个函数的处理时间,不考虑中断,执行一轮循环的总共时间为92ms,我们知道裸机执行程序永远都是按顺序来的,不可能刚结束远程数据处理_proc(),就会去执行喂狗_proc();,想要执行到喂狗就必须乖乖地把其它任务按照顺序执行完,再去执行喂狗。
那么,裸机的问题就出来了,如果cpu当前执行到lcd_proc();,这时候远程数据来了,先触发接收中断,中断程序把数据给保存,但是有一个问题,就是cpu这时候没有办法去处理这段数据(如果有同学为什么不在中断程序处理,有这个疑问的可以去百度百度为什么不能在中断处理数据),为什么?因为你是裸机,cpu就得乖乖地把下面的程序都执行完后,才轮到远程数据处理_proc();。也就是说cpu从lcd_proc()到远程数据处理_proc(),需要至少72ms,72ms只是根据我们每个任务假设的时间得到的,在实际项目中,根据复杂程度或延时函数等等,说它是10秒也不过分,一切皆有可能。到这里,RTOS的实时到底是什么意思,我想大家应该能从这个例子看出一点头绪来。
我们把上面这段裸机程序移植到RTOS中,以FreeRTOS为例:
int main() { sys_init(); xTaskCreate(远程数据处理_task); 10ms 优先级最高,阻塞等待数据 xTaskCreate(485数据处理_task); 10ms xTaskCreate(lcd_task); 5ms xTaskCreate(key_task); 5ms xTaskCreate(clock_task); 1ms xTaskCreate(远程模块处理_task) 10ms xTaskCreate(采集数据_task); 20ms xTaskCreate(处理采集数据_task); 30ms xTaskCreate(喂狗_task); 1ms vTaskStartScheduler(); //调度开始 }
远程数据处理_task的优先级最高,而且是阻塞等待,为什么要阻塞,如果不阻塞,那么cpu会一直运行这个高优先级的任务,其它任务就执行不了。这里使用队列阻塞,即队列没有数据,该任务就会阻塞。其它任务的优先级是一样的,我们把按照裸机出现的问题放在FreeRTOS中,程序执行到lcd_task(相同优先级的任务采用时间片调度,cpu并不一定是连续5ms都在执行它,时间片大小根据configCPU_CLOCK_HZ,configTICK_RATE_HZ这两个值决定,这里我们假设1ms,即每个相同优先级的任务,执行1ms就会切换到下一个优先级相同的任务),这时候接收中断触发,接收到远程数据,注意,中断程序会往队列中发送数据。这时候,高优先级任务远程数据处理_task就从阻塞态变成了就绪态,由于它是高优先级的,该任务就会马上执行,不会像裸机一样等待72ms。
RTOS的实时性就是体现在这里的。