ZYNQ(八)定时器中断与URAT串口中断

上一章实现了PS端接收PL端的中断,本章主要在ZYNQ的PS端实现定时器中断:
(1)软件中断(SGI)
SGI通过写ICDSGIR寄存器产生SGI中断
(2)共享中断(SPI)
通过PS和PL内各种I/O和存储器控制器产生
(3)私有中断(PPI)
包含:全局定时器,私有看门狗定时器,私有定时器以及来自PL端的FIQ/IRQ
在这里插入图片描述
ZYNQ的每一个ARM core都有自己的私有定时器,私有定时器的工作频率是CPU的一半
私有定时器的特性如下:
(1)32位计数器,到达0产生一个中断
(2)8位预分频计数器,更好控制中断周期
(3)可配置一次性或自动重加载模式
所以,定时器记录时间=T*(预加载值+1)
前面的步骤与之前PL端中断是相同的,同样配置两个按键
在这里插入图片描述

/*
 * main.c
 *
 *  
 *      Author: Administrator
 */

#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 INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID
#define TIMER_IRPT_INTR     XPAR_SCUTIMER_INTR

#define TIMER_LOAD_VALUE    0x13D92D3F

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

static void TimerIntrHandler(void *CallBackRef)
{

    static int sec = 0;   //计数
    XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;
    XScuTimer_ClearInterruptStatus(TimerInstancePtr);
    sec++;
    printf(" %d Second\n\r",sec);  //每秒打印输出一次
}

void SetupInterruptSystem(XScuGic *GicInstancePtr,
        XScuTimer *TimerInstancePtr, u16 TimerIntrId)
{

        XScuGic_Config *IntcConfig; //GIC config
        Xil_ExceptionInit();
        //initialise the GIC
        IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
        XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
                        IntcConfig->CpuBaseAddress);

        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                    (Xil_ExceptionHandler)XScuGic_InterruptHandler,//connect to the hardware
                    GicInstancePtr);

        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
        XScuTimer_EnableInterrupt(TimerInstancePtr);//enable interrupt on the timer
        Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); //Enable interrupts in the Processor.
    }


int main()
{
     XScuTimer_Config *TMRConfigPtr;     //timer config
     printf("------------START-------------\n");
     //私有定时器初始化
     TMRConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);//通过查找配置这个程序可以获取参数
     XScuTimer_CfgInitialize(&Timer, TMRConfigPtr,TMRConfigPtr->BaseAddr);
     //XScuTimer_SelfTest(&Timer);
     //加载计数周期,私有定时器的时钟为CPU的一般,为333MHZ,如果计数1S,加载值为1sx(333x1000x1000)(1/s)-1=0x13D92D3F
     //程序的指针与测试程序(装载预加载值的寄存器)
     XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);
     //自动装载(将中断的预加载值设置为自动装载模式)
     XScuTimer_EnableAutoReload(&Timer);
     //启动定时器
     XScuTimer_Start(&Timer);
     //set up the interrupts 中断控制器/定时器/中断号
     SetupInterruptSystem(&Intc,&Timer,TIMER_IRPT_INTR);
     while(1);

     return 0;
}

对于初始化程序XScuTimer_CfgInitialize,在这个定时器被其他函数调用之前,这个函数必须先被调用(用了一个特定的函数来检测传递进来的参数是否是空的,如果是,则不能正常跳转到下一个语句)
在这里插入图片描述
在这里插入图片描述
(二)URAT中断
前面步骤同样相同,主要分析main.c程序

/*
 * main.c
 *
 *  Created on: 2016年6月26日
 *      Author: Administrator
 */

#include <stdio.h>
#include "xadcps.h"

#include "xil_types.h"
#include "Xscugic.h"
#include "Xil_exception.h"
#include "xuartps.h"

//timer info
#define UART_DEVICE_ID      XPAR_PS7_UART_1_DEVICE_ID //URAT的设备ID
#define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID //中断的设备ID
#define UART_IRPT_INTR      XPAR_XUARTPS_1_INTR //URAT的中断号(URAT1为82)

static XScuGic Intc; //GIC 结构体指针
static XUartPs Uart;// uart 结构体指针
 

static void UartIntrHandler(void *CallBackRef)
{

    XUartPs *InstancePtr = (XUartPs *) CallBackRef;
	u32 IsrStatus;

	u32 ReceivedCount=0;

	u32 CsrRegister;
	/*
	 * Read the interrupt ID register to determine which
	 * interrupt is active
	 */
	IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_IMR_OFFSET);//e0001000+10=regaddr=e0001010

	IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				   XUARTPS_ISR_OFFSET);//e0001000+14=regaddr=e0001014

	/* Dispatch an appropriate handler. */
	if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
			(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {

	CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,//判断FIFO触发标准位
					XUARTPS_SR_OFFSET);//e0001000+2c=regaddr=e000102c

	while((CsrRegister & XUARTPS_SR_RXEMPTY)== (u32)0){//读取FIFO中所有数据

			//InstancePtr->ReceiveBuffer.NextBytePtr[ReceivedCount] =//每次循环读取1byte
				;

			XUartPs_WriteReg(InstancePtr->Config.BaseAddress,//每次循环发送读取到的数据
					   XUARTPS_FIFO_OFFSET,
					   XUartPs_ReadReg(InstancePtr->Config.
					   					  BaseAddress,
					   					  XUARTPS_FIFO_OFFSET));

			ReceivedCount++;//计数
			CsrRegister = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
									XUARTPS_SR_OFFSET);
		}

	}
	printf("this time ReceivedCount=%d\r\n",ReceivedCount);
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
		IsrStatus);
}

void SetupInterruptSystem(XScuGic *GicInstancePtr,
		XUartPs *UartInstancePtr, u16 UartIntrId)
{


        XScuGic_Config *IntcConfig; //GIC config
        Xil_ExceptionInit();
        //initialise the GIC
        IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
        XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
                        IntcConfig->CpuBaseAddress);

        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                    (Xil_ExceptionHandler)XScuGic_InterruptHandler,//connect to the hardware
                    GicInstancePtr);
        Xil_ExceptionEnable();
        XScuGic_Connect(GicInstancePtr, UartIntrId,
                        (Xil_InterruptHandler)UartIntrHandler,//set up the timer interrupt
                        (void *)UartInstancePtr);

        XScuGic_Enable(GicInstancePtr, UartIntrId);//enable the interrupt for the Timer at GIC
        XUartPs_SetInterruptMask(UartInstancePtr, XUARTPS_IXR_RXOVR/* | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_TNFUL*/ );
       // XUartPs_EnableUart(UartInstancePtr);//enable interrupt on the timer
        Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ); //Enable interrupts in the Processor.
    }


int main()
{
	 XUartPs_Config *UartConfigPtr;     //timer config
 //    printf("------------START-------------\n");
     UartConfigPtr = XUartPs_LookupConfig(UART_DEVICE_ID);

     XUartPs_CfgInitialize(&Uart,UartConfigPtr,UartConfigPtr->BaseAddress);
     //set up the interrupts
     SetupInterruptSystem(&Intc,&Uart,UART_IRPT_INTR);
     while(1);

     return 0;
}

在这里插入图片描述
在XUartPs_Config中存放的是URAT的设备ID,基地址(在硬件工程中添加了中断后,系统自动生成的)

发布了54 篇原创文章 · 获赞 4 · 访问量 1030

猜你喜欢

转载自blog.csdn.net/buzhiquxiang/article/details/103604913
今日推荐