1. 硬件 CONFREG 模块的设计
中断?简单来说就是 CPU 停下当前的工作任务,去处理其他事情,处理完后回来继 续执行刚才的任务,这一过程便是中断。中断是一个事件。这样的事件与 CPU 芯片 内外部硬件电路产生的电信号相对应。 中断分为同步中断和异步中断。
同步中断——同步中断是当指令执行时由控制单元产生的,之所以称为同步,是 因为只有在一条指令终止执行后 CPU 才会发出中断。由于信号来自 CPU 内 部,也称为内部中断。
异步中断——异步中断是由其他硬件设备依照 CPU 时钟信号随机产生的。由于 信号来自 CPU 外部,也称为外部中断。 通常我们所说的中断指的是异步中断,我们将同步中断称为异常(异常是由程序 的错误产生的,或者是由内核必须处理的异常条件产生的)。
中断处理的基本流程如下,
将寄存器值保存到 SRAM 中。
读取处理器 ESTAT寄存器,获取 IP11-IP0 的中断状态,结合 ECFG 寄存器中 的中断使能位,获知处理器中断源。
根据中断表继续查询中断控制器和模块相关寄存器,获知中断发生原因。
依据不同中断源进行相关处理,包括事件处理和清中断。
处理完成后恢复寄存器值。
返回正常执行流。
设计一个 CONFREG 模块,对应上述的 INTC 中断管理模块,中断号是 IP6 。一共汇总了 8 个中断,其中有我们常用的 Timer 和 Uart1 。
主要包括 7 个 8 位宽的寄存器,如下所示
INT_EN 中断使能寄存器
INT_EDGE 中断边沿寄存器
INT_POL 中断极性寄存器
INT_CLR 中断清除寄存器
INT_SET 中断置位寄存器
INT_OUT 中断输出寄存器
SRPROT 运行状态及保护寄存器
简单起见,第 7 个寄存器 SRPROT 可以忽略。 这个中断的中断源为电平型,并且默认配置为电平模式,所以只需要清除中断原因, 不需要清除中断控制寄存器的对应位。 我们可以将 CONFREG 模块作为一个 APB 外设,挂在 APB 总线上。那么就需要设 计一个 APB 接口来对寄存器进行读写操作。我们需要对每个 APB 接口分配一个地 址,这样才能通过译码电路区分开来不同的 APB 。在 config.h 文件中定了 9 路 APB 地址,默认使用 APB0 作为 GPIO ,现在我们为 CONFREG 模块分配 APB2 ,对应 地址为 0xbfed0000 ,如下所示,
CONFREG 模块通过子模块 one_int_gen 控制中断的边沿、极性、清除等。 CONFREG 将其他模块(Timer Uart1)产生的中断汇总起来,产生 int_o ,然后输入到 软核中。
最后实现的结构框图如下所示,
在顶层文件 godson_mcu_top.v 中例化我们设计的模块,如下所示,
CONFREG 模块没有需要连接到顶层的信号,也就不用添加新的约束。
2. 软件设计,基于 CONFREG 模块编写中断
既然已经设计好了硬件电路,我们就可以进行软件程序的编写了。在硬件 CONFREG 模块设计过程中我们为 APB 分配的地址是 0xbfea0000 ,所以软件上需 要对应好。一个不错的方法是用结构体指针来访问寄存器,如下所示,
以定时器中断为例,在配置好定时器后,进行 INTC 上的定时器中断使能,如下所 示,
因为 INTC 默认配置为电平模式,所以这里不需要清除中断控制寄存器的对应位。 在软件代码的 start.S 文件中通过汇编语言编写了中断向量表,对中断是否触发进行 判断,若触发则进入相应的中断服务函数中。