中断分为中断系统和中断源系统,因此两个系统都需要一定的配置。并且需要把中断源系统挂载到中断系统上去。
pl向ps发出中断请求
1.获取配置和初始化中断,此时初始化的是arm cpu的中断系统SGI,然后需要注册中断处理进程,注册完之后,相当于中断系统完成。
使能中断处理进程,然后把具体的中断设备绑定到中断系统中去,并且,制定了中断处理进程需要调用的中断处理函数。
设置中断触发的类型是电平触发还是上升沿触发。
最后所有配置配置好后,使能整个中断系统。
2 定时器中断
定时器是一个arm里面的一个小系统,需要额外配置定时器,因为是arm内部的,所以arm本身对定时器就有配置函数。
初始化配置
使能定时器的中断,而pl-ps的按键中断实验不需要,因为终中断系统是人,人给按键信号,信号作为中断信号,给cpu。
启动定时器。
在这里插入图片描述
不论什么中断系统,中断源有自己的ID号,
为什么要初始化Xil_ExceptionInit() ???这里把Exception相关的放一起了,ScuGic的函数。
会在中断向量表里面查询有哪些子中断,然后回调子中断的中断处理函数
串口中断也初始化了中断系统呀!
把定时器的中断回调函数关联到系统的中断函数里面。
cnnect有四个参数,中断系统,定时器系统(回调函数),定时器中断ID,定时器中断处理函数
uart中断:
uart中断也分为 uart系统和中断系统,不仅要配置中断系统,还要配置好uart系统以及使能配置好uart的中断
初始化配置uart系统
配置uart中断系统
int Init_UartPsIntr(XUartPs *UartInstPtr,u16 DeviceId )
{
int Status;
XUartPs_Config *Config;
u32 IntrMask;
if (XGetPlatform_Info() == XPLAT_ZYNQ_ULTRA_MP) {
#ifdef XPAR_XUARTPS_1_DEVICE_ID
DeviceId = XPAR_XUARTPS_1_DEVICE_ID;
#endif
}
Config = XUartPs_LookupConfig(DeviceId);
if (NULL == Config) {
return XST_FAILURE;
}
Status = XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handlers for the UART that will be called from the
* interrupt context when data has been sent and received, specify
* a pointer to the UART driver instance as the callback reference
* so the handlers are able to access the instance data
*/
XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)UartPs_Intr_Handler, UartInstPtr);
/*
* Enable the interrupt of the UART so interrupts will occur, setup
* a local loopback so data that is sent will be received.
*/
IntrMask =
XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
XUARTPS_IXR_RXOVR;
if (UartInstPtr->Platform == XPLAT_ZYNQ_ULTRA_MP) {
IntrMask |= XUARTPS_IXR_RBRK;
}
XUartPs_SetInterruptMask(UartInstPtr, IntrMask);
XUartPs_SetRecvTimeout(UartInstPtr, 8);
return XST_SUCCESS;
}
void UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
int i = 0;
/* All of the data has been sent */
if (Event == XUARTPS_EVENT_SENT_DATA) {
TotalSentCount = EventData;
}
/* All of the data has been received */
if (Event == XUARTPS_EVENT_RECV_DATA) {
TotalReceivedCount = EventData;
if(TotalReceivedCount == TEST_BUFFER_SIZE) {
for(i=0;i<TotalReceivedCount;i++)
SendBuffer[i] = RecvBuffer[i];
XUartPs_Send(&UartPs, SendBuffer, TotalReceivedCount);
XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
TotalReceivedCount=0;
}
}
/*
* Data was received, but not the expected number of bytes, a
* timeout just indicates the data stopped for 8 character times
*/
if (Event == XUARTPS_EVENT_RECV_TOUT) {
TotalReceivedCount = EventData;
for(i=0;i<TotalReceivedCount;i++)
SendBuffer[i] = RecvBuffer[i];
XUartPs_Send(&UartPs, SendBuffer, TotalReceivedCount);
XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
TotalReceivedCount=0;
}
/*
* Data was received with an error, keep the data but determine
* what kind of errors occurred
*/
if (Event == XUARTPS_EVENT_RECV_ERROR) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
/*
* Data was received with an parity or frame or break error, keep the data
* but determine what kind of errors occurred. Specific to Zynq Ultrascale+
* MP.
*/
if (Event == XUARTPS_EVENT_PARE_FRAME_BRKE) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
/*
* Data was received with an overrun error, keep the data but determine
* what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
*/
if (Event == XUARTPS_EVENT_RECV_ORERR) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
}
配置中断系统,注册异常处理进程
void Setup_Intr_Exception(XScuGic * IntcInstancePtr)
{
/* Enable interrupts from the hardware */
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)IntcInstancePtr);
Xil_ExceptionEnable();
}
int Init_Intr_System(XScuGic * IntcInstancePtr)
{
int Status;
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
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;
}
return XST_SUCCESS;
}
把uart的中断挂载到中断系统中去,然后设置中断处理函数
int UartPs_Setup_IntrSystem(XScuGic *IntcInstancePtr,XUartPs *UartInstancePtr,u16 UartIntrId)
{
int Status;
//XScuGic_Config *IntcConfig; /* Config for interrupt controller */
/* Initialize the interrupt controller driver */
/*
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;
}
*/
/*
* interrupt for the device occurs, the device driver handler
* performs the specific interrupt processing for the device
*/
Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,
(Xil_ExceptionHandler) XUartPs_InterruptHandler,
(void *) UartInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/* Enable the interrupt for the device */
XScuGic_Enable(IntcInstancePtr, UartIntrId);
return XST_SUCCESS;
}
/****************************************************************************/
/**
*
* This function is the interrupt handler for the driver.
* It must be connected to an interrupt system by the application such that it
* can be called when an interrupt occurs.
*
* @param InstancePtr contains a pointer to the driver instance
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XUartPs_InterruptHandler(XUartPs *InstancePtr)
{
u32 IsrStatus;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Read the interrupt ID register to determine which
* interrupt is active
*/
IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_IMR_OFFSET);
IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_ISR_OFFSET);
/* Dispatch an appropriate handler. */
if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
/* Received data interrupt */
ReceiveDataHandler(InstancePtr);
}
if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))
!= (u32)0) {
/* Transmit data interrupt */
SendDataHandler(InstancePtr, IsrStatus);
}
/* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */
if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
(u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) {
/* Received Error Status interrupt */
ReceiveErrorHandler(InstancePtr, IsrStatus);
}
if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
/* Received Timeout interrupt */
ReceiveTimeoutHandler(InstancePtr);
}
if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
/* Modem status interrupt */
ModemHandler(InstancePtr);
}
/* Clear the interrupt status. */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
IsrStatus);
}
注意有两个中断处理函数,一个是中断系统去处理的,一个是uart中断去处理的。
Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,
(Xil_ExceptionHandler) XUartPs_InterruptHandler,
(void *) UartInstancePtr);
* This function is the interrupt handler for the driver.
* It must be connected to an interrupt system by the application such that it
* can be called when an interrupt occurs.
*
* @param InstancePtr contains a pointer to the driver instance
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XUartPs_InterruptHandler(XUartPs *InstancePtr)
{
u32 IsrStatus;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Read the interrupt ID register to determine which
* interrupt is active
*/
IsrStatus = XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_IMR_OFFSET);
IsrStatus &= XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
XUARTPS_ISR_OFFSET);
/* Dispatch an appropriate handler. */
if((IsrStatus & ((u32)XUARTPS_IXR_RXOVR | (u32)XUARTPS_IXR_RXEMPTY |
(u32)XUARTPS_IXR_RXFULL)) != (u32)0) {
/* Received data interrupt */
ReceiveDataHandler(InstancePtr);
}
if((IsrStatus & ((u32)XUARTPS_IXR_TXEMPTY | (u32)XUARTPS_IXR_TXFULL))
!= (u32)0) {
/* Transmit data interrupt */
SendDataHandler(InstancePtr, IsrStatus);
}
/* XUARTPS_IXR_RBRK is applicable only for Zynq Ultrascale+ MP */
if ((IsrStatus & ((u32)XUARTPS_IXR_OVER | (u32)XUARTPS_IXR_FRAMING |
(u32)XUARTPS_IXR_PARITY | (u32)XUARTPS_IXR_RBRK)) != (u32)0) {
/* Received Error Status interrupt */
ReceiveErrorHandler(InstancePtr, IsrStatus);
}
if((IsrStatus & ((u32)XUARTPS_IXR_TOUT)) != (u32)0) {
/* Received Timeout interrupt */
ReceiveTimeoutHandler(InstancePtr);
}
if((IsrStatus & ((u32)XUARTPS_IXR_DMS)) != (u32)0) {
/* Modem status interrupt */
ModemHandler(InstancePtr);
}
/* Clear the interrupt status. */
XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_ISR_OFFSET,
IsrStatus);
}
XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)UartPs_Intr_Handler, UartInstPtr);`
void UartPs_Intr_Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
int i = 0;
/* All of the data has been sent */
if (Event == XUARTPS_EVENT_SENT_DATA) {
TotalSentCount = EventData;
}
/* All of the data has been received */
if (Event == XUARTPS_EVENT_RECV_DATA) {
TotalReceivedCount = EventData;
if(TotalReceivedCount == TEST_BUFFER_SIZE) {
for(i=0;i<TotalReceivedCount;i++)
SendBuffer[i] = RecvBuffer[i];
XUartPs_Send(&UartPs, SendBuffer, TotalReceivedCount);
XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
TotalReceivedCount=0;
}
}
/*
* Data was received, but not the expected number of bytes, a
* timeout just indicates the data stopped for 8 character times
*/
if (Event == XUARTPS_EVENT_RECV_TOUT) {
TotalReceivedCount = EventData;
for(i=0;i<TotalReceivedCount;i++)
SendBuffer[i] = RecvBuffer[i];
XUartPs_Send(&UartPs, SendBuffer, TotalReceivedCount);
XUartPs_Recv(&UartPs, RecvBuffer, TEST_BUFFER_SIZE);
TotalReceivedCount=0;
}
/*
* Data was received with an error, keep the data but determine
* what kind of errors occurred
*/
if (Event == XUARTPS_EVENT_RECV_ERROR) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
/*
* Data was received with an parity or frame or break error, keep the data
* but determine what kind of errors occurred. Specific to Zynq Ultrascale+
* MP.
*/
if (Event == XUARTPS_EVENT_PARE_FRAME_BRKE) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
/*
* Data was received with an overrun error, keep the data but determine
* what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
*/
if (Event == XUARTPS_EVENT_RECV_ORERR) {
TotalReceivedCount = EventData;
TotalErrorCount++;
}
}
这两个的关系是:系统中断调用了connect里面的中断调用函数,函数功能是判断了来自uart的中断的类型,并将类型赋值给了中断列表里的event。
uart系统根据event判断中断类型,调用合适的处理函数,来实现具体的功能。