中断定义:中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。
zynq中断:由状态寄存器读取当前状态,判断当前的状态是否满足中断触发的条件,满足后开始中断的触发,进入到中断处理函数,中断处理完成后跳出函数继续执行其余操作。
1.uart的中断:zynq的共有两路uart,单个uart的fifo深度为64,如果想要发送或者接收大于64字节的数据,则需要使用uart的中断完成操作,具体的流程为:uart初始化完成后,开始中断的初始化,设置中断触发的条件,满足条件后进入到中断处理函数。
#include"stdio.h"
#include"xuartps.h"
#include "xparameters.h"
#include "xscugic.h"
#include "xplatform_info.h"
#include "xil_exception.h"
#include "sleep.h"
#define INTC XScuGic
#define DeviceId XPAR_XUARTPS_0_DEVICE_ID
#define UART_INT_IRQ_ID XPAR_XUARTPS_0_INTR
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define BAUDRATE 115200
XUartPs UartPs;
INTC InterruptController; /* Instance of the Interrupt Controller */
//function list
int SetupInterruptSystem(INTC *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId);
//void Handler(void *call_back);
void Handler(void *call_back_ref);
void UART_Init();
void XScuGic_ClearIntC(XUartPs * Uart_Ps,u32 IntrMASK);
u32 XScuGic_Getregstate(XUartPs * Uart_Ps);
int main()
{
//UART 初始化
UART_Init(&UartPs,BAUDRATE);
//设置中断系统
SetupInterruptSystem(&InterruptController, &UartPs, UART_INT_IRQ_ID);
printf("uart loop test action!\t\n");
while(1)
{
}
return 0;
}
void UART_Init(XUartPs *UartPs,u32 BaudRate)
{
/*
* 初始化UART 驱动
* Initialize the UART driver so that it's ready to use
* Look up the configuration in the config table, then initialize it.
*/
XUartPs_Config *Config;
Config = XUartPs_LookupConfig(DeviceId);
XUartPs_CfgInitialize(UartPs, Config, Config->BaseAddress);
//设置UART波特率
XUartPs_SetBaudRate(UartPs,BaudRate);
//设置UART的模式
XUartPs_SetOperMode(UartPs, XUARTPS_OPER_MODE_NORMAL);
//设置FIFO阈值 0位disable 1为接收一位就触发中断
XUartPs_SetFifoThreshold(UartPs, 1U);
printf("UART Initial finished!\n\t");
}
int SetupInterruptSystem(INTC *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId)
{
u32 IntrMask;
/* Config for interrupt controller */
XScuGic_Config *IntcConfig;
/* Initialize the interrupt controller driver */
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
// 中断必须要配置的函数
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler,
IntcInstancePtr);
Xil_ExceptionEnable();
//连接中断处理函数
XScuGic_Connect(IntcInstancePtr, UartIntrId,
(Xil_ExceptionHandler) Handler,
(void *) UartInstancePtr);
IntrMask =
XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
XUARTPS_IXR_RXOVR;
//设置中断触发方式
//IntrMask =XUARTPS_IXR_RXOVR;
XUartPs_SetInterruptMask(UartInstancePtr, XUARTPS_IXR_RXOVR);
/* Enable the interrupt for the device */
XScuGic_Enable(IntcInstancePtr, UartIntrId);
return 0;
}
/*
#define XUARTPS_IMR_OFFSET 0x0010U //< Interrupt Mask [12:0]
#define XUARTPS_ISR_OFFSET 0x0014U //< Interrupt Status [12:0]
*/
void XScuGic_ClearIntC(XUartPs * Uart_Ps,u32 IntrMASK)
{
XUartPs_WriteReg(Uart_Ps->Config.BaseAddress,XUARTPS_ISR_OFFSET, IntrMASK) ;
}
u32 XScuGic_Getregstate(XUartPs * Uart_Ps)
{
u32 int_state;
//第二个参数 表示基地址的偏移量
int_state = XUartPs_ReadReg(Uart_Ps->Config.BaseAddress,XUARTPS_IMR_OFFSET) ;
int_state &= XUartPs_ReadReg(Uart_Ps->Config.BaseAddress,XUARTPS_ISR_OFFSET) ;
return int_state;
}
void Handler(void *call_back_ref)
{
XUartPs *uart_instance_ptr = (XUartPs *) call_back_ref;
u32 rec_data = 0 ;
u32 isr_status ; //中断状态标志
printf("interrupt assert \n\t");
//读取中断 ID 寄存器,判断触发的是哪种中断
isr_status = XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
XUARTPS_IMR_OFFSET);
isr_status &= XUartPs_ReadReg(uart_instance_ptr->Config.BaseAddress,
XUARTPS_ISR_OFFSET);
//判断中断标志位 RxFIFO 是否触发
if (isr_status & (u32)XUARTPS_IXR_RXOVR){
rec_data = XUartPs_RecvByte(XPAR_PS7_UART_0_BASEADDR);
//清除中断标志
XUartPs_WriteReg(uart_instance_ptr->Config.BaseAddress,
XUARTPS_ISR_OFFSET, XUARTPS_IXR_RXOVR) ;
}
XUartPs_SendByte(XPAR_PS7_UART_0_BASEADDR,rec_data);
printf("interrupt end\t\n");
}
//简易版本
/*void Handler(void *call_back_ref)
{
u32 rec_data = 0 ;
XUartPs * Uart_PS = (XUartPs*)call_back_ref;
printf("interrupt assert \n\t");
rec_data = XUartPs_RecvByte(XPAR_PS7_UART_0_BASEADDR);
XUartPs_SendByte(XPAR_PS7_UART_0_BASEADDR,rec_data);
XScuGic_ClearIntC(Uart_PS,XUARTPS_IXR_RXOVR);
printf("interrupt end\t\n");
}*/