IGNORANT

Zynq7000私有定时器使用摘要

参考文章:

学会Zynq(9)定时器使用示例(PPI)
米联客 ZYNQ/SOC精品教程 S02-CH08 定时器中断实验

初始化私有定时器设备实例

XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId);

通过设备ID查找设备配置
DeviceId,设备ID
返回XScuTimer_Config型指针,指向配置表中对应设备ID的配置,若未查找到相应设备返回NULL。

s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr,
             XScuTimer_Config *ConfigPtr, u32 EffectiveAddress)

初始化指定的定时器设备。
InstancePtr,指向XScuTimer的一个实例。
ConfigPtr,指向定时器实例的配置信息结构体
EffectiveAddress,设备的起始地址。
返回初始化的结果状态,初始化成功为XST_SUCCESS或者已被使用XST_DEVICE_IS_STARTED

#define XScuTimer_LoadTimer(InstancePtr, Value)                \
    XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr,        \
            XSCUTIMER_LOAD_OFFSET, (Value))

加载定时器的计数器中的值,其本质上只是操作Timer Load寄存器。
InstancePtr,指向XScuTimer的一个实例。
Value,计数的预加载值。
私有定时器是从装载值递减到0时发出中断。私有定时器的工作时钟为333MHz,每1/333M秒减1。因此若想定时1s,则装载值为1/(1/333M)-1,

#define XScuTimer_EnableAutoReload(InstancePtr)                \
    XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr,        \
            XSCUTIMER_CONTROL_OFFSET,            \
            (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \
                XSCUTIMER_CONTROL_OFFSET) |         \
                XSCUTIMER_CONTROL_AUTO_RELOAD_MASK))

允许指定定时器设备实例能自动重载。

设置定时器中断

中断时基本过程:初始化中断控制器、设置中断异常、连接中断、使能中断。

1.初始化GIC中断控制器;

XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId);

通过设备id查找设备的配置
DeviceID,设备ID的唯一标识符。
返回XScuGic_Config *型指针,指向指定设备的配置信息结构体中。

s32  XScuGic_CfgInitialize(XScuGic *InstancePtr,
                XScuGic_Config *ConfigPtr,
                u32 EffectiveAddr);

对指定的中断控制器实例进行初始化。
InstancePtr是指向XScuGic实例的指针。
ConfigPtr是指向所关联的特定设备的配置表的指针。
EffectiveAddr是所关联设备的有效地址。

2.设置中断异常

void Xil_ExceptionInit(void);

异常处理,在Coretex-A9中不做任何事,因为异常处理已被静态初始化。

void Xil_ExceptionRegisterHandler(u32 Exception_id,
                    Xil_ExceptionHandler Handler,
                    void *Data);

为特定的异常注册一个handler,当处理器发生特定异常后调用对应handler。
Exception_id异常源的id。
Handler是异常处理函数。
Data是异常发生时,传给对应handler的参数。

#define Xil_ExceptionEnable() \
        Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ)

允许中断的异常处理。

3.绑定中断服务函数

s32  XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id,
                      Xil_InterruptHandler Handler, void *CallBackRef);

将指定中断服务函数绑定到指定中断号上。
InstancePtr是指向XScuGic实例的指针。
Int_Id是中断源的中断号。
Handler是中断处理函数。
CallBackRef是回调的一个引用,一般是所连接的设备的指针。

4.使能中断

void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id);

中断使能,在该函数调用后,可使对应id的pending的中断能够发生。
InstancePtr是指向XScuGic实例的指针。
Int_Id是中断源的中断号。

#define XScuTimer_EnableInterrupt(InstancePtr)                \
    XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr,        \
            XSCUTIMER_CONTROL_OFFSET,            \
            (XScuTimer_ReadReg((InstancePtr)->Config.BaseAddr, \
                    XSCUTIMER_CONTROL_OFFSET) |    \
                    XSCUTIMER_CONTROL_IRQ_ENABLE_MASK))

允许定时器中断。
InstancePtr是指向私有定时器设备实例的指针。

启动私有定时器

void XScuTimer_Start(XScuTimer *InstancePtr);

启动定时器。
InstancePtr是指向私有定时器设备实例的指针。

#define XScuTimer_ClearInterruptStatus(InstancePtr)            \
    XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr,        \
        XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK)

清除中断状态。
InstancePtr是指向私有定时器设备实例的指针。

在定时器中断处理程序中,我们必须清除中断标志,因此XscuGic_Connect的第三个参数设置为定时器的控制设备实例的指针,在调用中断状态清除函数时会用到该参数。

实例参考

搬运米联客文章中的案例,完成私有定时器计秒。


/*
 *
 * www.osrc.cn
 * www.milinker.com
 * copyright by nan jin mi lian dian zi www.osrc.cn
 * axi dma test
 *
*/

#include "xscugic.h"
#include "xil_exception.h"
#include "xscutimer.h"
#include "xparameters.h"

#define INTC_DEVICE_ID          XPAR_SCUGIC_SINGLE_DEVICE_ID
extern volatile int usec;
//timer info
#define TIMER_DEVICE_ID     XPAR_XSCUTIMER_0_DEVICE_ID
#define TIMER_IRPT_INTR     XPAR_SCUTIMER_INTR

static XScuGic Intc; //GIC
static  XScuTimer Timer;//timer


#define TIMER_LOAD_VALUE    0x13D92D3F //1S

static void TimerIntrHandler(void *CallBackRef)
{

    XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
    XScuTimer_ClearInterruptStatus(TimerInstancePtr);
    usec++;
    xil_printf(" %d Second\n\r",usec);  //每秒打印输出一次
}

int init_timer(void)
{
    XScuTimer_Config *TMRConfigPtr;     //timer config
    //私有定时器初始化
    TMRConfigPtr = XScuTimer_LookupConfig(0);
    XScuTimer_CfgInitialize(&Timer, TMRConfigPtr,TMRConfigPtr->BaseAddr);
    //XScuTimer_SelfTest(&Timer);
    //加载计数周期,私有定时器的时钟为CPU的一半,为333MHZ,如果计数1S,加载值为1sx(333x1000x1000)(1/s)-1=0x13D92D3F
    XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);//F8F00600+0=reg=F8F00600
    //自动装载
    XScuTimer_EnableAutoReload(&Timer);//F8F00600+8=reg=F8F00608
    XScuGic_Config *IntcConfig;
    IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
    if (NULL == IntcConfig) {
        return XST_FAILURE;
    }
    int Status = XScuGic_CfgInitialize(&Intc, IntcConfig,
                    IntcConfig->CpuBaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    /* Enable interrupts from the hardware */
    Xil_ExceptionInit();
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
            (Xil_ExceptionHandler)XScuGic_InterruptHandler,
            (void *)&Intc);
    Xil_ExceptionEnable();
    XScuGic_Connect(&Intc, TIMER_IRPT_INTR,
                    (Xil_ExceptionHandler)TimerIntrHandler,//set up the timer interrupt
                    (void *)&Timer);

    XScuGic_Enable(&Intc, TIMER_IRPT_INTR);//enable the interrupt for the Timer at GIC
    XScuTimer_EnableInterrupt(&Timer);//enable interrupt on the timer
    XScuTimer_Start(&Timer);
    return XST_SUCCESS;
}

int main(void)
{
    xil_printf("------------START-------------\n");
    int Status=init_timer();
    if(Status!=XST_SUCCESS){
        xil_printf("Failed to initialize Timer!\n\r");
        return 0;
    }

    while(1);
}

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »