PS端定时器学习记录

所用板:zedbroad

针对于定时器,Cortex-A9 processor 有一个32位私有定时器和一个32位的看门狗,并且与其他处理器公用一个64位的定时器;

对于我对看门狗的理解就是,对于系统看门狗,当过一定时刻要喂狗,不然就默认系统没有正常运行,会对系统进行复位。

对于系统级来说的话,有一个24位看门狗和二个16位的triple定时器;这个看门狗的时钟频率是CPU时钟的四分之一或者六分之一,也可以由外部时钟来提供(从MIO或者PL端)。对于两个triple timer的时钟频率通常是CPU时钟的四分之一或者六分之一,一般用来计算来自MIO或者PL端的脉冲宽度。

下图是系统定时器之间的关系:

对于CPU私有定时器和看门狗

1.32位计数器自减到0时,产生一个中断。

2.8位预分频可以更好的控制中断周期。(预分频置x,就代表着要分频2^x)

3.可以设置自动装载模式和单次(这里的自动装载可以这样理解,当计数结束时,产生中断后,我为了多次进行,我将计数器值再次装载,这样就可以继续中断)

4.可以设定计数器开始的数值

5.对于所有的私有定时器和看门狗时钟频率一般都设定CPU频率的二分之一

CPU私有中断ID是29

这两个图是定时器和看门狗中寄存器功能

对于triple 定时器、全局定时器和系统定时器不一一赘述,后面我再补充

此次学习针对实现ScuTimer(也就是基于 ARM Cortex-A9 的私有系统控制器(SCU)定时器)

对于此次定时器的实践操作

打开vivado,建立BD文件

之后生成输出文件,产生HDL wrapper文件,导入硬件打开SDK

建新工程新建c文件和H文件

这里我分别用两个c文件来初始化系统中断和定时器中断。h文件用来声明

一般调用资源,例如GPIO,定时器,中断这些,都需要先初始化,根据设备ID查找配置,用来初始化端口。

对于系统中断初始化如下

#ifndef SYS_INTR_H_
#define SYS_INTR_H_

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

#define INTC_DEVICE_ID 		XPAR_SCUGIC_SINGLE_DEVICE_ID

int Init_Intr_System(XScuGic * IntrInstancePtr);


#endif
//h文件
int Init_Intr_System(XScuGic * IntcInstancePtr)

{
	int status;

	XScuGic_Config *IntcConfig;

	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;
		}

		/* Enable interrupts from the hardware */
		Xil_ExceptionInit();
		Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				(void *)IntcInstancePtr);
		Xil_ExceptionEnable();


		return XST_SUCCESS;
	}

定时器中断初始化如下,此处的中断响应函数功能打印出秒数,当定时器递减到0,进入中断,sec++,并清除中断


#include "timer_intr.h"

volatile int sec = 0 ;

static void TimerIntrHandler(void *CallBackRef)
{
    XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
    XScuTimer_ClearInterruptStatus(TimerInstancePtr);

    printf("seconds is %d \n",sec++);

}

int Timer_init(XScuTimer *TimerPtr, u8 PrescalerValue , u32 Load_Value,u32 DeviceId)
{
     XScuTimer_Config *TMRConfigPtr;     //timer config
     TMRConfigPtr = XScuTimer_LookupConfig(DeviceId);
     XScuTimer_CfgInitialize(TimerPtr, TMRConfigPtr,TMRConfigPtr->BaseAddr);

     XScuTimer_SetPrescaler(TimerPtr,  PrescalerValue) ;

     XScuTimer_LoadTimer(TimerPtr, Load_Value);

     XScuTimer_EnableAutoReload(TimerPtr);

     return 1;
}


void Timer_Setup_Intr_System(XScuGic *GicInstancePtr,XScuTimer *TimerInstancePtr, u16 TimerIntrId)
{
        XScuGic_Connect(GicInstancePtr, TimerIntrId,
                        (Xil_ExceptionHandler)TimerIntrHandler,//set up the timer interrupt
                        (void *)TimerInstancePtr);

        XScuGic_Enable(GicInstancePtr, TimerIntrId);//enable the interrupt for the Timer at GIC
        XScuGic_SetPriorityTriggerType(GicInstancePtr,  TimerIntrId, 0XA0 , 3 ) ;
        XScuTimer_EnableInterrupt(TimerInstancePtr);//enable interrupt on the timer
 }


void Timer_start(XScuTimer *TimerPtr)
{
	 XScuTimer_Start(TimerPtr);
}

void Timer_stop(XScuTimer *TimerPtr)
{
	 XScuTimer_Stop(TimerPtr);
}


#ifndef TIMER_INTR_H_

#define TIMER_INTR_H_



#include <stdio.h>
#include "xadcps.h"
#include "xil_types.h"
#include "Xscugic.h"
#include "Xil_exception.h"
#include "xscutimer.h"

//timer info
#define TIMER_DEVICE_ID     XPAR_XSCUTIMER_0_DEVICE_ID
#define TIMER_IRPT_INTR     XPAR_SCUTIMER_INTR

void Timer_start(XScuTimer *TimerPtr);
void Timer_stop(XScuTimer *TimerPtr) ;
void Timer_Setup_Intr_System(XScuGic *GicInstancePtr,XScuTimer *TimerInstancePtr, u16 TimerIntrId);

int Timer_init(XScuTimer *TimerPtr, u8   PrescalerValue , u32 Load_Value,u32 DeviceId) ;


#endif /* TIMER_INTR_H_ */
//h文件

主函数文件

定义一个装载值,定时器设定的自动装载模式,当定时器溢出时,装载值会写入寄存器,重新进行新的计数周期,这样可以用来多次中断。还有一个比较重要的预分频器(PSC),比方说我们要一秒产生一个中断,有两种方式,一个是通过计算装载值与定时器时钟频率的倍数之比来算,还有一种就是通过预分频,将定时器的时钟频率降低,例如:zynq cpu的系统频率为666.66MHz,定时器的频率是CPU的一半,即333.33MHz,原定667*1000*1000 / 2-1装载值,运行产生中断是一秒一次,当设置预分频,为二分频时,装载值不变的话,2秒才能产生一个中断。


#include "timer_intr.h"
#include "timer_intr.h"
#include "sys_intr.h"



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

int main(void)
{


	unsigned int TIMER_LOAD_VALUE ;

	TIMER_LOAD_VALUE =  667*1000*1000 / 2 ;
	TIMER_LOAD_VALUE -= 1 ;

	Init_Intr_System(&GIC);

	Timer_init(&Timer,0 ,TIMER_LOAD_VALUE,0);
	Timer_Setup_Intr_System(&GIC,&Timer,TIMER_IRPT_INTR);
	Timer_start(&Timer);

	while(1) ;

}


运行结果我们下载到板子上之后,会在串口显示:

秒数会不断增加。至此实验结束。

                                                                                                                                        24.10.22

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值