$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

【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开发教程

 

posted @ 2023-04-12 10:29  素衣叹风尘  阅读(691)  评论(0)    收藏  举报