ZYNQ中ARM架构简析(2)——中断

ZYNQ中ARM架构简析(2)——中断_第1张图片
ZYNQ中的中断与传统ARM架构中基本一致,包括软件中断(SGI)、CPU私有外设中断(PPI)以及共享外设中断(SPI)。区别在于私有外设中断和共享外设中断中含有PL侧引入的中断。
中断的概念在本文中不再陈述,如果不了解的话,可以直接搜索一下即可。
ZYNQ7000的中断控制器是基于ARM GIC 1.0版本,
ZYNQ中ARM架构简析(2)——中断_第2张图片

  1. 软中断
    软中断包含16个中断信号,都可以分配给任意一个或多个CPU。
    ZYNQ中ARM架构简析(2)——中断_第3张图片
    ZYNQ中ARM架构简析(2)——中断_第4张图片

  2. 私有中断
    私有中断包括global timer,private timer,watch dog以及PL侧中断。这其中包含了FIQ(快中断),属于ARM架构的独有特性。
    ZYNQ中ARM架构简析(2)——中断_第5张图片
    ZYNQ中ARM架构简析(2)——中断_第6张图片

  3. 共享中断
    共享中断主要包含各个外设的中断,以及PL侧的常规中断。
    在这里插入图片描述
    三种中断的优先级可以在寄存器中进行配置,每一个中断都会对应一个ID,对每个ID配置相应的优先级,如果两个中断的优先级相同,则同时发生时,选择ID小的先执行。

下面代码是初始化timer的中断函数,为lwip例程中的代码片段。

void platform_setup_interrupts(void)
{
	Xil_ExceptionInit();

	XScuGic_DeviceInitialize(INTC_DEVICE_ID);

	/*
	 * Connect the interrupt controller interrupt handler to the hardware
	 * interrupt handling logic in the processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
			(Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler,
			(void *)INTC_DEVICE_ID);
	/*
	 * Connect the device driver handler that will be called when an
	 * interrupt for the device occurs, the handler defined above performs
	 * the specific interrupt processing for the device.
	 */
	XScuGic_RegisterHandler(INTC_BASE_ADDR, TIMER_IRPT_INTR,
					(Xil_ExceptionHandler)timer_callback,
					(void *)&TimerInstance);
	/*
	 * Enable the interrupt for scu timer.
	 */
	XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, TIMER_IRPT_INTR);

	return;
}
void platform_enable_interrupts()
{
	/*
	 * Enable non-critical exceptions.
	 */
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
	XScuTimer_EnableInterrupt(&TimerInstance);
	return;
}

Xil_ExceptionInit 用于初始化异常向量表;
Xil_ExceptionRegisterHandler 在异常向量表中配置中断的回调函数;
XScuGic_RegisterHandler 在中断向量表中配置相应中断的回调函数;
XScuGic_EnableIntr 使能timer中断;
Xil_ExceptionEnableMask 使能异常中的中断;

有人会弄混异常和中断的关系。中断是属于异常的子集的,也就是说中断其实是异常其中的一种。
异常向量其实是一张表格,每个格子里存放的是一个地址,或者是一个跳转命令,不管是哪个,其目的都是让PC跳转到真正处理异常的代码的地方。
中断也含有一张表格,被称为中断向量表,每个格子中存放相应中断ID的跳转地址。

当发生中断时,会触发异常,根据异常向量表中中断的地址跳转到中断的向量表中去,再根据中断向量表中中断的ID去跳转到相应ID的执行地址。

再回过头来,看上面的代码就可以理解了,Xil_ExceptionRegisterHandler是将中断的回调函数地址写入异常向量表中,XScuGic_RegisterHandler则是将timer中断的回调函数写入中断向量表中。之后再分步进行使能,确保可以正常工作。

小问题:为什么FIQ比IRQ快?
两个原因。
一、如下图所示,FIQ的回调函数是紧挨着中断向量表存放的,在读取中断向量表时,已经将相应的指令读入到I-Cache中,因此节省了读取时间,具体可参见上一篇文章中关于cache的内容。
ZYNQ中ARM架构简析(2)——中断_第7张图片
二、FIQ包含独立的r8-r12寄存器,在进行模式切换的过程中,比IRQ需要压栈的内容要少,因此更快一些。
ZYNQ中ARM架构简析(2)——中断_第8张图片

你可能感兴趣的:(ZYNQ,ARM,中断)