为了更好的浏览体验,请不要在本页面禁用 Javascript
2019-12-04
 Tags: 

Zynq7000私有定时器使用摘要

参考文章:
初始化私有定时器设备实例
XScuTimer_Config *XScuTimer_LookupConfig(u16 DeviceId);
Plain Text
通过设备ID查找设备配置 DeviceId,设备ID 返回XScuTimer_Config型指针,指向配置表中对应设备ID的配置,若未查找到相应设备返回NULL。
s32 XScuTimer_CfgInitialize(XScuTimer *InstancePtr, XScuTimer_Config *ConfigPtr, u32 EffectiveAddress)
Plain Text
初始化指定的定时器设备。 InstancePtr,指向XScuTimer的一个实例。 ConfigPtr,指向定时器实例的配置信息结构体 EffectiveAddress,设备的起始地址。 返回初始化的结果状态,初始化成功为XST_SUCCESS或者已被使用XST_DEVICE_IS_STARTED
#define XScuTimer_LoadTimer(InstancePtr, Value) \\ XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \\ XSCUTIMER_LOAD_OFFSET, (Value))
Plain Text
加载定时器的计数器中的值,其本质上只是操作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))
Plain Text
允许指定定时器设备实例能自动重载。
设置定时器中断
中断时基本过程:初始化中断控制器、设置中断异常、连接中断、使能中断。
1.初始化GIC中断控制器;
XScuGic_Config *XScuGic_LookupConfig(u16 DeviceId);
Plain Text
通过设备id查找设备的配置 DeviceID,设备ID的唯一标识符。 返回XScuGic_Config *型指针,指向指定设备的配置信息结构体中。
s32 XScuGic_CfgInitialize(XScuGic *InstancePtr, XScuGic_Config *ConfigPtr, u32 EffectiveAddr);
Plain Text
对指定的中断控制器实例进行初始化。 InstancePtr是指向XScuGic实例的指针。 ConfigPtr是指向所关联的特定设备的配置表的指针。 EffectiveAddr是所关联设备的有效地址。
2.设置中断异常
void Xil_ExceptionInit(void);
Plain Text
异常处理,在Coretex-A9中不做任何事,因为异常处理已被静态初始化。
void Xil_ExceptionRegisterHandler(u32 Exception_id, Xil_ExceptionHandler Handler, void *Data);
Plain Text
为特定的异常注册一个handler,当处理器发生特定异常后调用对应handler。 Exception_id异常源的id。 Handler是异常处理函数。 Data是异常发生时,传给对应handler的参数。
#define Xil_ExceptionEnable() \\ Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ)
Plain Text
允许中断的异常处理。
3.绑定中断服务函数
s32 XScuGic_Connect(XScuGic *InstancePtr, u32 Int_Id, Xil_InterruptHandler Handler, void *CallBackRef);
Plain Text
将指定中断服务函数绑定到指定中断号上。 InstancePtr是指向XScuGic实例的指针。 Int_Id是中断源的中断号。 Handler是中断处理函数。 CallBackRef是回调的一个引用,一般是所连接的设备的指针。
4.使能中断
void XScuGic_Enable(XScuGic *InstancePtr, u32 Int_Id);
Plain Text
中断使能,在该函数调用后,可使对应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))
Plain Text
允许定时器中断。 InstancePtr是指向私有定时器设备实例的指针。
启动私有定时器
void XScuTimer_Start(XScuTimer *InstancePtr);
Plain Text
启动定时器。 InstancePtr是指向私有定时器设备实例的指针。
#define XScuTimer_ClearInterruptStatus(InstancePtr) \\ XScuTimer_WriteReg((InstancePtr)->Config.BaseAddr, \\ XSCUTIMER_ISR_OFFSET, XSCUTIMER_ISR_EVENT_FLAG_MASK)
Plain Text
清除中断状态。 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); }
Plain Text
Modified based on gine-blog