摘要:嵌入式系统不仅局限于 ARM+Linux,也不仅仅是安卓系统。事实上,任何电子产品都可以被称为嵌入式系统。而随着物联网行业的崛起,FreeRTOS 在市场上的份额也得到了提升。
一、为什么学习实时操作系统(RTOS)
在大学中,电子信息专业的大部分学生最终都会进入嵌入式系统领域。在刚开始接触时,我们通常会学习单片机编程,特别是针对 C51 单片机的编程。通常情况下,我们会进行裸机编程,即不采用任何实时操作系统(RTOS)。在这方面,常见的选择包括国外的 FreeRTOS、μC/OS、RTX,以及国内的 RT-thread、Huawei LiteOS 和 AliOS-Things 等。在其中,开源且免费的 FreeRTOS 在市场上占据了极高的份额。在工作中,我们经常使用 FreeRTOS,因为它是免费的,并且没有版权限制,这无疑是一个受人喜爱的选择。
二、裸机系统
1、轮询系统
轮询系统即是在裸机编程的时候,先初始化好相关的硬件,然后让主程序在一个死循环里面不断循环,顺序地做各种事情。裸机系统通常分成轮询系统和前后台系统。
int main(void)
{
/* 硬件相关初始化 */
HardWareInit();
/* 无限循环 */
for (;;) {
/* 处理事情 1 */
DoSomething1();
/* 处理事情 2 */
DoSomethingg2();
/* 处理事情 3 */
DoSomethingg3();
}
}
轮询系统是一种非常简单的软件结构,通常只适用于那些只需要顺序执行代码且不需要外部事件来驱动的就能完成的事情。在代码清单中,如果只是实现LED翻转,串口输出,液晶显示等这些操作,那么使用轮询系统将会非常完美。但是,如果加入了按键操作等需要检测外部信号的事件,用来模拟紧急报警,那么整个系统的实时响应能力就不会那么好了。
假设DoSomethingg3
是按键扫描,当外部按键被按下,相当于一个警报,这个时候,需要立马响应 , 并做紧急处理 , 而这个时候程序刚好执行到DoSomethingg1
, 要命的是DoSomethingg1
需要执行的时间比较久,久到按键释放之后都没有执行完毕,那么当执行到DoSomethingg3
的时候就会丢失掉一次事件。足见,轮询系统只适合顺序执行的功能代码,当有外部事件驱动时,实时性就会降低。
2、前后台系统
在裸机系统中,所有的操作都是在一个无限的大循环里面实现,支持中断检测。外部中断紧急事件在中断里面标记或者响应,中断服务称为前台,main 函数里面的while(1)无限循环称为后台,按顺序处理业务功能,以及中断标记的可执行的事件。小型的电子产品用的都是裸机系统,而且也能够满足需求。
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int main(void)
{
/* 硬件相关初始化 */
HardWareInit();
/* 无限循环 */
for (;;) {
if (flag1) {
/* 处理事情 1 */
DoSomething1();
}
if (flag2) {
/* 处理事情 2 */
DoSomethingg2();
}
if (flag3) {
/* 处理事情 3 */
DoSomethingg3();
}
}
}
void ISR1(void)
{
/* 置位标志位 */
flag1 = 1;
/* 如果事件处理时间很短,则在中断里面处理
如果事件处理时间比较长,在回到后台处理 */
DoSomething1();
}
void ISR2(void)
{
/* 置位标志位 */
flag2 = 2;
/* 如果事件处理时间很短,则在中断里面处理
如果事件处理时间比较长,在回到后台处理 */
DoSomething2();
}
void ISR3(void)
{
/* 置位标志位 */
flag3 = 1;
/* 如果事件处理时间很短,则在中断里面处理
如果事件处理时间比较长,在回到后台处理 */
DoSomething3();
}
在顺序执行后台程序的时候,如果有中断来临,那么中断会打断后台程序的正常执行流,转而去执行中断服务程序,在中断服务程序里面标记事件,如果事件要处理的事情很简短,则可在中断服务程序里面处理,如果事件要处理的事情比较多,则返回到后台程序里面处理。
虽然事件的响应和处理是分开了,但是事件的处理还是在后台里面顺序执行的,但相比轮询系统,前后台系统确保了事件不会丢失,再加上中断具有可嵌套的功能,这可以大大的提高程序的实时响应能力。在大多数的中小型项目中,前后台系统运用的好,堪称有操作系统的效果。
一般来说:如果的项目里面没有使用RTOS,则一般使用的都是这种前后台系统。
三、多线程系统
相比前后台系统,多线程系统的事件响应也是在中断中完成的,但是事件的处理是在线程中完成的。在多线程系统中,线程跟中断一样,也具有优先级,优先级高的线程会被优先执行。
当一个紧急的事件在中断被标记之后,如果事件对应的线程的优先级足够高,就会立马得到响应。相比前后台系统,多线程系统的实时性又被提高了。
多线程系统大概的伪代码具体见代码清单所示:
int flag1 = 0;
int flag2 = 0;
int flag3 = 0;
int main(void)
{
/* 硬件相关初始化 */
HardWareInit();
/* OS 初始化 */
RTOSInit();
/* OS 启动,开始多线程调度,不再返回 */
RTOSStart();
while(1);/* 程序不会执行到这里 */
}
void ISR1(void)
{
/* 置位标志位 */
flag1 = 1;
}
void ISR2(void)
{
/* 置位标志位 */
flag2 = 2;
}
void ISR3(void)
{
/* 置位标志位 */
flag3 = 1;
}
void DoSomething1(void)
{
/* 无限循环,不能返回 */
for (;;) {
/* 线程实体 */
if (flag1) {
}
}
}
void DoSomething2(void)
{
/* 无限循环,不能返回 */
for (;;) {
/* 线程实体 */
if (flag2) {
}
}
}
void DoSomething3(void)
{
/* 无限循环,不能返回 */
for (;;) {
/* 线程实体 */
if (flag3) {
}
}
}
相比前后台系统中后台顺序执行的程序主体,在多线程系统中,根据程序的功能,我们把这个程序主体分割成一个个独立的,无限循环且不能返回的小程序,这个小程序我们称之为线程。
每个线程都是独立的,互不干扰的,且具备自身的优先级,它由操作系统调度管理。加入操作系统后,我们在编程的时候不需要精心地去设计程序的执行流,不用担心每个功能模块之间是否存在干扰。
加入了操作系统,我们的编程反而变得简单了。整个系统随之带来的额外开销就是操作系统占据的那一丁点的FLASH
和RAM
。现如今,单片机的 FLASH和RAM是越来越大,完全足以抵挡RTOS那点开销。
学习RTOS的意义到底是什么?
学习RTOS,一是项目需要,随着产品要实现的功能越来越多,单纯的裸机系统已经不能完美地解决问题,反而会使编程变得更加复杂,如果想降低编程的难度,就必须引入RTOS实现多任务管理。二是技能需要,掌握操作系统,和基于RTOS的编程,实现更好的职业规划,对个人发展尤其是“钱途”是必不可少的。
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !