ESP-IDF是个筐,啥OS都可以往里面装!
ESP32基于一款Xtensa指令集架构的核心,虽然这款IP核知道的人不多,但是提到音频领域鼎鼎大名的HIFI系列DSP,可能很多人不会陌生,事实上,HIFI系列和ESP32基于的LX6核心使用的是相同的指令集架构(ISA).ISA架构。xtensa架构的ISA定义比较晦涩,而且使用了比较难于理解的寄存器窗的概念,也就是在汇编指令用的EABI寄存器和微架构上实现的物理寄存器中间做了一层抽象,为了的是节省caller/callee 之间堆栈save/restore的花销,为了防止新的寄存器窗口覆盖老的,又设计了windowoverflow exception机制,整个逻辑理解起来非常复杂。根据google到的xtensa dsp ISA手册,里面建议用户不要手搓汇编,而是用cadence提供的 FreeRTOS 移植版本或者自家的 xrtos系统,esp-idf虽然基于裸机和rtos的版本,但是经过仔细分析,发现它的arch porting层实现完全基于cadence提供的汇编层实现。
熊大的rt-thread支持运行ESP-IDF框架,我们看一下它是怎么做到,该不会是手搓汇编的把?带着疑问把代码下载下来:
下载代码:
在熊大的github个人主页,找到rtthread-esp-idf项目,根据项目readme,下载代码:
分析:
先找分析突破口,由于每个RTOS都需要提供一个tick中断函数,而我很清楚rtt的tick函数叫做 "rt_tick_increase", 所以,顶层目录执行 "grep rt_tick_increase -nR",看哪里调用了它,就一定可以找到xtensa架构层实现的线索。
搜索到的第一个文件./esp-idf-port/stubs/libcpu.c 264行就是调用它的地方,打开它:
xTaskIncrementTick是FreeRTOS上tick中断的实现,所以看起来像是给RTT穿了一层FreeRTOS的马甲。
浏览了一遍libcpu.c实现,发现它几乎实现了所有的FreeRTOS一级系统接口,也就是说它不仅仅换了FreeRTOS的马甲,还易了容,让自己看起来完全是freeRTOS.,这样就可以复用ESP-IDF框架的现有设施,运行起来。
调度器的封装:
调度器也需要重新封装,以使RTT看起来像FreeRTOS,它的封装也在./esp-idf-port/stubs/libcpu.c文件里面:
看看这些封装,真是委屈了RTT。
所以整个系统看起来是这个样子:
FreeRTOS皮肤就像是一个壳,把Xtensa对FreeRTOS的支持转化为对RT-Thread的支持,实际上,这里可能会有两个方向的工作,面向应用和面向处理器核心,后者在前面已经说了,前者则是把内核对RT-Thread系统API的支持转化为对FreeRTOS的支持,看起来似乎对称且相反.
通过两层抽象,实现了不为rtt增加新的arch porting层支持rtt的功能.
经典金庸武侠天龙八部中有一个片段,吐番国师大轮明王上少林单挑少林寺各位方丈,表面上使用的是少林寺的七十二绝技,方丈和各位长老均不是对手,幸好被虚竹看穿,揭穿他使用的绝技是用小无相功催动出的,使用的是道家内力,并非真正的少林寺七十二绝技,保住了少林的名声.跟套马甲的方法很像.
从商业角度出发,我们研究操作系统的目的并不是操作系统本身,而是它的一种能力,这种能力就是加载并执行用户方案的能力,只是到了RTOS这里,体量小,规模小,方案小,场景固定,通常把方案和操作系统本身合在一起开发,编译,这样构造出来的系统只是使用于固定场景的.
这种方式与普通家用pc,工作站,服务器等的主要不同在,在这些硬件上,操作系统是独立的,虽然操作系统负责的主要任务仍然是加载并执行程序,但这些被执行的程序可以被任意定义和开发,不局限与RTOS场景中的一两种场景,如下图:
实际跑了一下,做了airkiss配网的测试,发现蛮稳定的,这样难怪,RTT本身就是一个非常优秀的RTOS(个人认为,在支持大型RTOS方案方面,他远远优于FreeRTOS).
所以看起来虚拟化也分两种,一种硬件类的虚拟化,比如qemu,可以虚拟出不同的ISA架构,并在之上运行对应架构的程序,另一种软件类的虚拟化,通过对软件加层,让一种功能的软件以一种新的面目呈现.
所以开头的问题有了答案,RTT的ESP32支持方式仍然使用了Cadence提供的arch porting层,这种做法工作量做小,而且可行性没问题,这也应了软件开发中的一条格言“软件中所有的问题,都可以通过加层来解决"