本帖最后由 松山归人 于 2021-7-10 11:57 编辑
讲完了基本的外设接口,我们今天看一下这个开发板的中断系统。中断系统可以说是单片机能够响应任务需求的核心机制,对于一个固定的单片机而言,计算资源只有那么多,如何高效地利用这些计算资源,是单片机设计者必须回答的问题。目前主流的方案,就是我们今天要讲的中断系统。我们可以人为给不同的中断请求设定不同的级别,这样单片机系统就知道执行任务的轻重缓急了,系统的实时性提高了,计算资源就相当于被高效地利用了。 那么,在嵌入式实时操作系统中,任务又是一个什么概念呢?我们知道,任务也是有优先级的,不同的任务优先级是不同的,那任务的优先级和中断的优先级是什么关系?我觉得,可以把任务理解成一种不靠硬件抢占执行的中断,应该归入大中断的概念中去,本质上是进一步提升了单片机响应任务的实时性。我们知道,一般中断程序的执行时间都不宜太长,只是负责变量打标,然后快速退出就可以了。一个高中断优先级的中断程序,执行得太长的话,那么所有相应的低优先级的中断程序是不是就完全无法执行了。所以程序开发的时候,才尽可能地让中断程序只是负责对变量打标而已。中断程序对相应的变量打标以后,实际工作的执行,还主要是任务的调度来实现的。这样的设计,相比而言能够让计算资源的实时性得到最大程序的发挥。这个也是嵌入式实时操作系统被设计出来的一个关键的原因。 鸿蒙系统外部中断,到底是怎么样被初始化的呢?
上图中,第一个红框里面代码的意思就是开中断,这样单片机的各种硬件中断就可以进行响应了。这段代码执行以后,使用鸿蒙系统的中断创建函数创建外部中断。 我们先不看外部中断内部是怎么实现的,先看一下这个中断创建函数是怎么工作的。在STM32中,中断函数能够被执行,是因为中断函数的地址或者叫做向量被放在中断向量表这个地方。当有外部中断请求发生的时候,单片机的硬件电路就会自动寻址到相应的中断函数,进而进入到函数里面去执行相应的代码。当然这中间肯定伴随着各种环境参数的保存,环境参数的保存,主要是为了解决从中断中恢复的时候,程序找到回去的路。
鸿蒙系统的中断创建函数,所做的主要事情,如下图所示,就是把一个数组g_hwiForm里面的数值初始化了。
这个数组里面的每一个数值存放了相应中断函数的地址以及相关的参数值。我们可以暂且认为这个数组存放的就是中断向量表,那这些个函数是怎么执行起来的,或者说是如何被调用的呢?
我们看一下,我们这款单片机的中断执行机制。RISC-V单片机中断向量表的起始地址,是由CSR寄存器mtvt来指定的,具体说明,如下图。那也就是说当有外部中断触发的时候,单片机硬件查询的首先是这个寄存器的地址,然后执行这个寄存器中的地址所指向的代码。那么我们的鸿蒙系统中,有没有对这个寄存器进行初始化呢?
大家可以看一下,实际上在操作系统启动的汇编代码部分,这个向量是被初始化了的。如下图,操作系统把TrapVector函数地址放入了t0,然后把t0放入了mtvec这个寄存器中。那TrapVector到底是什么呢? 篇幅长,完整内容见附件:
|