ZYNQ 定时器中断

1. 建立软硬件工程

建立HelloWorld工程,具体方法参照ZYNQ Vivado环境实现Helloworld,并启用DDR,启用DDR方式见ZYNQ AMP模式 双裸核CPU同时运行

2. 验证HelloWorld工程正确

3. 修改HelloWorld.c

3.1 包含相关头文件

#include <stdio.h>
#include "platform.h"
#include "xil_types.h"
#include "xscugic.h"
#include "xscutimer.h"
#include "xil_exception.h"
#include "xil_printf.h"

3.2 添加中断系统建立函数

// 中断系统建立函数 SetupTimerInterruptSystem,完成中断控制模块 GIC 的初始化,中断处理函数的 Register, Enable 等功能
static void SetupTimerInterruptSystem(XScuGic * GicInstPtr, XScuTimer * TimerInstPtr, u32 TimerInterruptId)
{
    //---------------------------------------------------------------------------
    // Interrupt Controller initialization     中断控制器初始化
    //---------------------------------------------------------------------------
    // Looks up the GIC device configuration based on the unique device ID     根据唯一的设备ID查找GIC设备配置
    XScuGic_Config * XScuGic_Config_ptr;
    XScuGic_Config_ptr = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
    // CfgInitialize a specific interrupt controller instance/driver      CfgInitialize特定的中断控制器实例/驱动程序
    XScuGic_CfgInitialize(GicInstPtr, XScuGic_Config_ptr, XScuGic_Config_ptr->CpuBaseAddress);

    //---------------------------------------------------------------------------
    // Interrupt system setup      中断系统设置
    //---------------------------------------------------------------------------
    // Makes the connection between the Id of the exception source and the associated Handler
    // 在异常源的Id和相关的Handler之间建立连接
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, GicInstPtr);
    // Enable Exceptions     启用例外
    Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

    //---------------------------------------------------------------------------
    // Register Interrupt Handler    寄存器中断处理程序
    //---------------------------------------------------------------------------
    // Makes the connection between the Int_Id of the interrupt source and the associated handler
    // 在中断源的Int_Id和关联的处理程序之间建立连接
    XScuGic_Connect(GicInstPtr, TimerInterruptId, (Xil_ExceptionHandler)TimerInterruptHandler, (void*)TimerInstPtr);

    //---------------------------------------------------------------------------
    // Enable Timer interrupt in the controller    在控制器中启用定时器中断
    //---------------------------------------------------------------------------
    // Enable the Timer interrupt      启用定时器中断
    XScuTimer_EnableInterrupt(TimerInstPtr);
    // Enables the interrupt source provided as the argument Int_Id   启用作为参数Int_Id提供的中断源
    XScuGic_Enable(GicInstPtr, TimerInterruptId);
}

3.3 添加中断服务函数

// 中断服务程序 TimerInterruptHandler,当中断发生时进行信息打印并 Clear 中断状态
static void TimerInterruptHandler(void * CallBackRef)
{
    static int sec = 0;
    printf("Seconds Count: %d\r\n", sec++);

    // Clears the interrupt status
    XScuTimer * TimerInstPtr = (XScuTimer *) CallBackRef;
    XScuTimer_ClearInterruptStatus(TimerInstPtr);
}

3.4 在main函数前添加函数声明

// 函数声明
// 中断系统建立函数 SetupTimerInterruptSystem,完成中断控制模块 GIC 的初始化,中断处理函数的 Register, Enable 等功能
static void SetupTimerInterruptSystem(XScuGic * GicInstPtr, XScuTimer * TimerInstPtr, u32 TimerInterruptId);
// 中断服务程序 TimerInterruptHandler,当中断发生时进行信息打印并 Clear 中断状态
static void TimerInterruptHandler(void * CallBackRef);

3.5 修改main函数为

int main()
{
    init_platform();

    //---------------------------------------------------------------------------
    // Timer initialization   定时器初始化
    // Zynq 中每一个模块都要查找硬件信息表,之后配置相应的软件驱动后才可以使用。
    //---------------------------------------------------------------------------
    // Lookup the Timer configuration based on the unique device ID
    // 基于唯一设备ID查找定时器配置
    XScuTimer_Config * TimerConfigPtr;
    TimerConfigPtr = XScuTimer_LookupConfig(XPAR_XSCUTIMER_0_DEVICE_ID);
    // Initialize a specific timer instance/driver
    // 初始化一个特定的定时器实例/驱动程序
    XScuTimer XScuTimerInst;
    XScuTimer_CfgInitialize(&XScuTimerInst, TimerConfigPtr, TimerConfigPtr->BaseAddr);
    // Run a self-test on the timer  在定时器上运行自检
    XScuTimer_SelfTest(&XScuTimerInst);

    //---------------------------------------------------------------------------
    // Timer configure     定时器配置
    //---------------------------------------------------------------------------
    // Write to the timer load register       写入定时器加载寄存器
    // From ARM DDI0407I_cortex_a9_mpcore_r4p1_trm.pdf reference, timers are always
    // clocked at 1/2 of the CPU frequency (CPU_3x2x), now CPU frequency now is 666MHz, so the timer is 333MHz
    // 333_000_000 * 1(s) - 1 = 332_999_999 = 0x13D92D3F
    XScuTimer_LoadTimer(&XScuTimerInst, 0x13D92D3F);
    // Enable auto-reload mode    启用自动重新加载模式
    XScuTimer_EnableAutoReload(&XScuTimerInst);
    // Start timer    启动计时器
    XScuTimer_Start(&XScuTimerInst);

    //---------------------------------------------------------------------------
    // Interrupt System setup     中断系统设置
    //---------------------------------------------------------------------------
    XScuGic XScuGicInst;
    SetupTimerInterruptSystem(&XScuGicInst, &XScuTimerInst, XPAR_SCUTIMER_INTR);

    printf(">>> START...\n");
    while(1)
    {;}

    cleanup_platform();
    return 0;
}

3.6 保存编译下载验证。

发表评论

电子邮件地址不会被公开。 必填项已用*标注