【FPGA学习】- SDK实验篇(定时器中断实验)
中断,英文名为"Interrupt"。中断从概念上来讲就是指CPU暂时停止当前的工作,转而去处理其它的事情,处理结束之后回来继续执行当前的工作。中断产生的意义是为了在高速处理器和低速的外部设备交互数据时,提升处理器的利用率。
中断提高处理器利用率的方式。
1). 外部设备开始启动。
2). 外设产生一个信号,请求正在运行的高速处理器。
3). 处理器接收到信号后,处理器暂时停止高速计算,转而执行为外设服务的中断服务程序。
4). 中断服务程序结束之后,处理器返回执行原来的任务。
依据中断信号的来源,可以将中断分为内中断和外中断。内中断,又称异常/例外,内中断信号来自于处理器内部。外中断,又称中断,外中断信号来自于处理器外部。

在ZYNQ-7000之中,PS基于Arm架构,采用两个Cortex-A9处理器(cpu)和GIC pl390中断控制器。ZYNQ中断可以分为三个部分,Software Generated Interrupts (SGI),CPU Private Peripheral Interrupts (PPI),Shared Peripheral Interrupts (SPI)。
Software Generated Interrupts (SGI):软中断,一个SGI是通过将SGI中断号写入ICDSGIR寄存器并指定目标CPU来生成的。
CPU Private Peripheral Interrupts(PPI):CPU私有外设中断,每个CPU都有一组私有外设中断集(PPIs),使用存储寄存器进行私有访问。PPIs包括全局定时器、私有看门狗定时器、私有定时器和来自PL的FIQ/IRQ。
Shared Peripheral Interrupts (SPI):共享外设中断,共享外设中断(SPI)由PS和PL中的各种I/O和内存控制器生成。

实验:每秒中断一次,然后打印信息,30s结束。
硬件工作
与《SDK实验篇("Hello World")》中硬件工作相同,不再叙述。
软件工作
点击“launch SDK”,新建一个模板为“hello world”的C语言工程。参考官方给出的模板代码,进行编码工作。
在“system.mss”中导入参考代码scutimer。文件包含使用Cortex A9 Scu专用定时器和使用中断的驱动程序 (XScuTimer 的设计示例。


我们可以在代码中学习到中断控制器的使用。步骤如下,初始化中断控制器 GIC ->初始化中断异常 -> 中断服务函数注册 -> 在中断控制器中使能中断 -> 使能外设中断 -> 使能中断异常。


在UG585文档可以知道,定时器的时钟频率为CPU频率的一半,首先要修改计数器最大值,修改为CPU频率的一半,以便每秒中断一次。

将计数器修改为30。

添加打印信息。

使用PuTTy进行调试,可以看到每隔一秒输出信息。

/************************************** 中 断 **************************************/
从上述部分知道,中断的流程为中断初始化 -> 中断异常初始化及异常函数注册 -> 中断服务函数注册 -> 中断使能 -> 外设使能 -> 使能中断异常。
中断初始化。
/* * Initialize the interrupt controller driver so that it is ready to * use. */ IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); if (NULL == IntcConfig) { return XST_FAILURE; } Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; }
中断异常初始化及异常服务函数注册。
Xil_ExceptionInit(); /* * 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_InterruptHandler, IntcInstancePtr);
中断服务函数注册。
/* * 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. */ Status = XScuGic_Connect(IntcInstancePtr, TimerIntrId, (Xil_ExceptionHandler)TimerIntrHandler, (void *)TimerInstancePtr); if (Status != XST_SUCCESS) { return Status; }
中断使能。
/* * Enable the interrupt for the device. */ XScuGic_Enable(IntcInstancePtr, TimerIntrId);
外设使能
/* * Enable the timer interrupts for timer mode. */ XScuTimer_EnableInterrupt(TimerInstancePtr);
中断异常使能
/* * Enable interrupts in the Processor. */ Xil_ExceptionEnable();
中端服务函数。确定中断之后CPU要做的事情。
static void TimerIntrHandler(void *CallBackRef) { XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef; /* * Check if the timer counter has expired, checking is not necessary * since that's the reason this function is executed, this just shows * how the callback reference can be used as a pointer to the instance * of the timer counter that expired, increment a shared variable so * the main thread of execution can see the timer expired. */ if (XScuTimer_IsExpired(TimerInstancePtr)) { XScuTimer_ClearInterruptStatus(TimerInstancePtr); TimerExpired++; if (TimerExpired == 3) { XScuTimer_DisableAutoReload(TimerInstancePtr); } } }
参考资料
[1] Zynq-7000 SoC Technical Reference Manual (UG585),https://docs.xilinx.com/v/u/en-US/ug585-Zynq-7000-TRM
[2] 黑金FPGA开发教程
[3] 正点原子FPGA开发教程

浙公网安备 33010602011771号