赞
踩
目录
刚入手ZYNQ,对SDK的编程风格真的是不太习惯,不过适应一段时间后,会发现SDK还是挺好用的。这篇文章,主要是将最近学的中断系统进行一次整理,让自己的遗忘速度稍微变慢一点。
想要完全认识ZYNQ的中断,下面这张图真的要非常熟悉。主干是通用中断控制器(GIC)。GIC的左边包含三部分,分别是软中断(SGI)、私有中断(PPI)以及共享中断(SPI)。最常用的就是共享中断,只要把其中一种中断的初始化步骤弄清楚,那么其它理解起来就会变很简单。
每个中断都对应有自己的ID,这里ID的作用主要是在初始化中断的时候,作为某些中断初始化的入口参数。目的是告诉中断系统我用的哪一个中断,名字告诉你了,你别搞错了。
中断的程序流程如下图所示,其中前四步为固定流程,因为这四步主要是用来初始化通用中断控制器,也就是第一张图的主干部分的初始化。因为无论是SGI、PPI还是SPI,这三个中断类型都连接着GIC,因此前四步初始化的便可以固定下来。
前四步的配置代码如下:
- /*step1、初始化异常处理*/
- Xil_ExceptionInit();
- /*step2、初始化中断控制器*/
- ScuGicCfgPtr = XScuGic_LookupConfig(GIC_DEV_ID);
- status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- if(status != XST_SUCCESS)
- {
- printf("Initial Gic Failed!");
- return status;
- }
- /*step3、注册异常处理回调函数*/
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
- /*step4、异常处理使能*/
- Xil_ExceptionEnable();
Zynq内的串口一共有四种工作模式,分别是普通模式、自动回声模式、本地回环模式和远程回环模式。
用于标准的UART操作模式。正常情况下都是用的这个模式。
这个模式下RXD引脚接收的数据,会自动路由到TXD引脚上。一边接收数据一边发送数据。
1.1.3、Local Loopback Mode模式
本地回环模式,相当于自发自收,数据不经过TXD和RXD这两个管脚。
这个模式下,CPU在TXD上不能发送任何内容,在RXD上不能接收任何内容。
配置串口中断之前,必须要对串口进行初始化,然后再去配置串口中断。初始化步骤包括:连接串口的ID、设置波特率、设置串口工作模式、设置中断间隔时间、启动中断监听。代码如下:
- //串口初始化函数
- void Uart0_Init()
- {
- int state = 0;
- //寻找ID,初始化设备
- UartPsCfgPtr = XUartPs_LookupConfig(XPAR_PS7_UART_0_DEVICE_ID);//Device id
- state = XUartPs_CfgInitialize(&Uart0,UartPsCfgPtr,UartPsCfgPtr->BaseAddress);
- if(state != XST_SUCCESS)
- {
- printf("Uart initial failed");
- return state;
- }
- //设置波特率(应该与硬件相关,在设置硬件的时候就设置串口为115200)
- XUartPs_SetBaudRate(&Uart0,115200);
- //设置串口的工作模式
- XUartPs_SetOperMode(&Uart0,XUARTPS_OPER_MODE_NORMAL);//设置为普通模式
- //设置中断间隔时间(由于初始化中断时,设置为时间间隔中断)
- XUartPs_SetRecvTimeout(&Uart0,8);//8*4*1/115200 间隔这么久没有数据,就算中断
- //启动监听
- XUartPs_Recv(&Uart0,uart_rx_data,32);// 启动监听,设置接收buf的预计的字节数
- }
需要注意的就是串口中断触发方式,串口的触发方式有多种,本次实验选用的是接收时间间隔中断,当超过一段时间RXD没有接收到数据,便产生中断。具体参照xuartps_hw.h头文件。
- #define XUARTPS_IXR_RBRK 0x00002000U /**< Rx FIFO break detect interrupt */
- #define XUARTPS_IXR_TOVR 0x00001000U /**< Tx FIFO Overflow interrupt */
- #define XUARTPS_IXR_TNFUL 0x00000800U /**< Tx FIFO Nearly Full interrupt */
- #define XUARTPS_IXR_TTRIG 0x00000400U /**< Tx Trig interrupt */
- #define XUARTPS_IXR_DMS 0x00000200U /**< Modem status change interrupt */
- #define XUARTPS_IXR_TOUT 0x00000100U /**< Timeout error interrupt */
- #define XUARTPS_IXR_PARITY 0x00000080U /**< Parity error interrupt */
- #define XUARTPS_IXR_FRAMING 0x00000040U /**< Framing error interrupt */
- #define XUARTPS_IXR_OVER 0x00000020U /**< Overrun error interrupt */
- #define XUARTPS_IXR_TXFULL 0x00000010U /**< TX FIFO full interrupt. */
- #define XUARTPS_IXR_TXEMPTY 0x00000008U /**< TX FIFO empty interrupt. */
- #define XUARTPS_IXR_RXFULL 0x00000004U /**< RX FIFO full interrupt. */
- #define XUARTPS_IXR_RXEMPTY 0x00000002U /**< RX FIFO empty interrupt. */
- #define XUARTPS_IXR_RXOVR 0x00000001U /**< RX FIFO trigger interrupt. */
- #define XUARTPS_IXR_MASK 0x00003FFFU /**< Valid bit mask */
串口中断初始化剩下的步骤如下
main.c代码如下,需要注意的是串口初始化要放在中断初始化之前,不然程序会卡死,原因:串口的初始化中,包含了寻找串口的设备ID,和初始化变量赋值的过程。
- #include <stdio.h> //printf函数
- #include "xparameters.h"
- #include "xil_printf.h" //printf打印函数文件
- #include "sleep.h" //延迟头文件
- #include "xscugic.h" //通用中断控制器头文件
- #include "xuartps.h" //串口中断的处理函数
- #include "xuartps_hw.h" //串口中断模式设置
-
-
- /*重定义*/
- #define GIC_DEV_ID XPAR_PS7_SCUGIC_0_DEVICE_ID//gic device id
- #define UART0_INTR_ID XPAR_XUARTPS_0_INTR //UART0 interrupt id,not device id,the id from "xparameters_ps.h"
-
- /*必要变量定义*/
- static XScuGic ScuGic;//初始化中断控制器变量
- static XScuGic_Config * ScuGicCfgPtr;
-
- static XUartPs Uart0;//串口初始化中断控制器
- static XUartPs_Config * UartPsCfgPtr;
-
- /*全局变量*/
- unsigned char uart_rx_data[32];//存储串口接收的数据
-
- //函数初始化
- int Init_Gic(void);//通用中断控制器初始化
- void Uart0_Handler(void *CallBackRef, u32 Event,u32 EventData);//串口中断处理函数
- void Uart0_Init();//串口初始化函数(包含中断模式)
-
-
- int main()
- {
- int status = 0;
- Uart0_Init();//串口初始化放到中断控制器前面
- status = Init_Gic();
- if(status != XST_SUCCESS){
- return status;
- }
-
- while(1)
- {
-
- }
- return 0;
- }
-
-
- //串口中断处理函数
- void Uart0_Handler(void *CallBackRef, u32 Event,u32 EventData)
- {
- u32 revcnt = 0;
- if(Event = XUARTPS_IXR_TOUT)//判断触发中断的事件是哪一个
- {
- revcnt = EventData;
- if(revcnt == 8 && uart_rx_data[0] == 0x55 && uart_rx_data[1] == 0x55)
- {
- printf("frame1\n\r");
- }
- printf("串口中断成功,frame1\n\r");
- XUartPs_Recv(&Uart0,uart_rx_data,32);// 启动监听,设置接收buf的预计的字节数
- }
-
- }
-
-
- //串口初始化函数
- void Uart0_Init()
- {
- int state = 0;
- //寻找ID,初始化设备
- UartPsCfgPtr = XUartPs_LookupConfig(XPAR_PS7_UART_0_DEVICE_ID);//Device id
- state = XUartPs_CfgInitialize(&Uart0,UartPsCfgPtr,UartPsCfgPtr->BaseAddress);
- if(state != XST_SUCCESS)
- {
- printf("Uart initial failed");
- return state;
- }
- //设置波特率(应该与硬件相关,在设置硬件的时候就设置串口为115200)
- XUartPs_SetBaudRate(&Uart0,115200);
- //设置串口的工作模式
- XUartPs_SetOperMode(&Uart0,XUARTPS_OPER_MODE_NORMAL);//设置为普通模式
- //设置中断间隔时间
- XUartPs_SetRecvTimeout(&Uart0,8);//8*4*1/115200 间隔这么久没有数据,就算中断
- //启动监听
- XUartPs_Recv(&Uart0,uart_rx_data,32);// 启动监听,设置接收buf的预计的字节数
- }
- //初始化通用中断控制器
- int Init_Gic(void)
- {
- int status;
- //step1、初始化异常处理
- Xil_ExceptionInit();
- //step2、初始化中断控制器
- ScuGicCfgPtr = XScuGic_LookupConfig(GIC_DEV_ID);
- status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- if(status != XST_SUCCESS)
- {
- printf("Initial Gic Failed!");
- return status;
- }
-
- //step3、注册异常处理回调函数
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
- //step4、异常处理使能
- Xil_ExceptionEnable();
-
- /******配置区域*******/
- //step5、在gic中使能uart0中断
- XScuGic_Enable(&ScuGic,UART0_INTR_ID);
- //step6、在gic中连接uart0对应的中断ID
- status = XScuGic_Connect(&ScuGic,UART0_INTR_ID,(Xil_ExceptionHandler)XUartPs_InterruptHandler,&Uart0);
- if(status != XST_SUCCESS)
- {
- printf("Connect Gic Failed!");
- return status;
- }
- //step7、设置uart0中断处理函数
- XUartPs_SetHandler(&Uart0,(XUartPs_Handler)Uart0_Handler,&Uart0);
- //step8、设置uart0中断触发方式(这里为间隔时间中断)
- XUartPs_SetInterruptMask(&Uart0,XUARTPS_IXR_TOUT);//多事件相或
-
- return XST_SUCCESS;
- }
PL到PS的中断,也属于共享中断,一般都称做硬中断。硬中断一共有16个ID分别是61-68和84-91,系统默认从61开始分配ID号。如下图IRQ_F2P[0] = 61,IRQ_F2P[1] = 62,依次类推,需要注意的是:IRQ_F2P的数据位宽是自动分配,不要自己去分配。
其次,由上面可知,硬中断的触发方式可分为上升沿触发和高电平触发,因此在配置时,需要说明清楚,我一般使用都配置为边沿触发。
注意:高电平触表示在高电平期间触发中断,但并不是说在高电平期间的每一个时刻都会触发中断。
本次实验,由FPGA给CPU0产生一个1s中断,FPGA每次计数到1s就产生一个1us的中断信号给CPU0。
Verilog代码如下:
- // -----------------------------------------------------------------------------
- // Copyright (c) 2014-2023 All rights reserved
- // -----------------------------------------------------------------------------
- // Author : BigFartPeach
- // CSDN : 大屁桃
- // E-mail : 2624507313@qq.com
- // File : intr1s.v
- // Create : 2023-11-04 14:33:39
- // -----------------------------------------------------------------------------
- module intr1s(
- input wire clk, //50MHz
- input wire rst,
- output wire intr1sflag
- );
-
- //常量定义
- parameter CNT_END = 49999999;//50,000,000 - 1
- parameter CNT_1US_END = 49;
-
- //1s计数器
- reg [25:0] cnt_1s;
- reg flag_1s;
- assign intr1sflag = flag_1s;
-
- //1s计数器
- always @(posedge clk) begin
- if (rst == 1'b1) begin
- cnt_1s <= 'd0;
- end
- else if (cnt_1s == CNT_END) begin
- cnt_1s <= 'd0;
- end
- else begin
- cnt_1s <= cnt_1s + 1'b1;
- end
- end
-
- //1us的标志信号
- always @(posedge clk) begin
- if (rst == 1'b1) begin
- flag_1s <= 1'b0;
- end
- else if (cnt_1s == CNT_1US_END) begin
- flag_1s <= 1'b0;
- end
- else if(cnt_1s == CNT_END) begin
- flag_1s <= 1'b1;
- end
- end
-
- endmodule
注意:
1、AMP模式下,需要对硬中断的ID进行绑定CPU。
2、AMP模式下,对CPU0和CPU1同时初始化时,要有先后顺序,一般情况下先给CPU0初始化,再给CPU1初始化。
- #include <stdio.h>
- #include "platform.h"
- #include "xil_printf.h"
- #include "xscugic.h" //中断头文件
- #include "xparameters.h"//设备ID
-
- /*step1 重定义*/
- #define GIC_DEV_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
- #define GIC_BASEADDR XPAR_PS7_SCUGIC_0_DIST_BASEADDR
- #define F2P_DEV_INTR0 61 //1s中断源对应的ID
- #define INTR_PORI 32 //F2P中断优先级
- #define TRIG_TYPE 3 //F2P中断触发类型 2'b01 高电平触发,2'b11 = 3为上升沿触发
-
-
- /*step2 变量定义*/
- XScuGic ScuGic;
- XScuGic_Config *ScuGicCfgPtr;
-
- /*step3 函数声明*/
- int Init_Gic(void);
- void F2P0_Handler(void *data);//1s中断处理函数
-
- int main()
- {
- Init_Gic();
- while(1)
- {
-
- }
- return 0;
- }
-
-
- int Init_Gic(void)
- {
- int status = 0;
- /*step1、初始化异常处理*/
- Xil_ExceptionInit();
- /*step2、初始化中断控制器*/
- ScuGicCfgPtr = XScuGic_LookupConfig(GIC_DEV_ID);
- status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- if(status != XST_SUCCESS)
- {
- printf("Initial Gic Failed!");
- return status;
- }
- /*step3、注册异常处理回调函数*/
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
- /*step4.异常处理使能*/
- Xil_ExceptionEnable();
-
- /******配置区域*******/
- /*step5、在gic中使能(被中断的设备ID)*/
- XScuGic_Enable(&ScuGic,F2P_DEV_INTR0);
- /*step6、在gic中连接被中断的设备ID,并注册回调函数*/
- status = XScuGic_Connect(&ScuGic,F2P_DEV_INTR0,(Xil_ExceptionHandler)F2P0_Handler,&ScuGic);
- if(status != XST_SUCCESS)
- {
- printf("Connect Gic Failed!");
- return status;
- }
- /*step7、设置F2P中断源优先级和触发类型*///设置触发类型是因为F2P有两种触发方式让你选
- XScuGic_SetPriTrigTypeByDistAddr(GIC_BASEADDR,F2P_DEV_INTR0,INTR_PORI,TRIG_TYPE);
- /*step8、在双核架构下需要,将硬件ID与对应的CPU相连接*/
- // XScuGic_InterruptMaptoCpu(&ScuGic,0,F2P_DEV_INTR0);
-
- return XST_SUCCESS;
- }
-
- void F2P0_Handler(void *data)
- {
- printf("come from PL 1s 999!\n\r");
- }
GPIO和串口中断比较类似,在中断初始化之前首先要对GPIO进行初始化,只有在GPIO初始化结束后再去配置GPIO的中断。
需要注意的是:要区分开设备ID和中断号ID这两者的区别。同时关于MIO和EMIO的设备ID如下图。MIO和EMIO的ID顺序都是按照初始化时数组的低位到高位排列,对应于不同bank的低位到高位。
具体代码如下:
- #include <stdio.h>
- #include "platform.h"
- #include "xil_printf.h"
- #include "xparameters.h" //设备ID号
- #include "xgpiops.h" //GPIO设置头文件
- #include "xscugic.h" //通用中断控制器头文件
- #include "sleep.h" //延时函数头文件
- //全局变量
- u32 led_value = 1;
-
- /*1.重定义*/
- #define GPIO_DEV_ID XPAR_PS7_GPIO_0_DEVICE_ID //GPIO device ID
- #define GIC_DEV_ID XPAR_PS7_SCUGIC_0_DEVICE_ID //GIC devive ID
-
- #define LED0 54
- #define LED1 55
- #define SW0 56
-
- #define GPIO_INTR_ID 52//GPIO的中断ID,来源于表格
-
- #define SW_BANK_ID 2 //连接按键的管脚属于EMIO,属于GPIO BANK 2
- /*2.变量定义*/
- XScuGic ScuGic;
- XScuGic_Config * ScuGicCfgPtr;
-
- XGpioPs GpioPs;
- XGpioPs_Config * GpioPsCfPtr;
-
- /*3.函数初始化*/
- int Init_GPIO(void);
- int Init_Gic(void);
- void GPIO_Handler(void *CallBackRef, u32 Bank, u32 Status);
-
- int main()
- {
- int status = 0;
- // printf("GPIO interrupt !\r\n");
- Init_GPIO();
- status = Init_Gic();
- if(status != XST_SUCCESS)
- {
- return status;
- }
- while(1)
- {
- printf("GPIO interrupt ! led_value = %d\r\n",led_value);
- sleep(1);
- }
- return 0;
- }
-
- int Init_GPIO(void)
- {
- int status = 0;
- GpioPsCfPtr = XGpioPs_LookupConfig(GPIO_DEV_ID);
- status = XGpioPs_CfgInitialize(&GpioPs,GpioPsCfPtr,GpioPsCfPtr->BaseAddr);
- if(status != XST_SUCCESS){
- return status;
- }
- //设置GPIO的方向
- XGpioPs_SetDirectionPin(&GpioPs,LED0,0x01);
- XGpioPs_SetDirectionPin(&GpioPs,LED1,0x01);
- XGpioPs_SetDirectionPin(&GpioPs,SW0,0x00);//input for button
- //设置输出使能
- XGpioPs_SetOutputEnablePin(&GpioPs,LED0,0x01);
- XGpioPs_SetOutputEnablePin(&GpioPs,LED1,0x01);
-
- return XST_SUCCESS;
- }
-
- int Init_Gic(void)
- {
- int status = 0;
- /*step1、初始化异常处理*/
- Xil_ExceptionInit();
- /*step2、初始化中断控制器*/
- ScuGicCfgPtr = XScuGic_LookupConfig(GIC_DEV_ID);
- status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- if(status != XST_SUCCESS)
- {
- printf("Initial Gic Failed!");
- return status;
- }
- /*step3、注册异常处理回调函数*/
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
- /*step4、使能异常处理*/
- Xil_ExceptionEnable();
-
- /***********配置区域***********/
- //step5、在GIC中使能GPIO中断
- XScuGic_Enable(&ScuGic,GPIO_INTR_ID);
- //step6、在GIC中连接GPIO对应的中断ID
- status = XScuGic_Connect(&ScuGic,GPIO_INTR_ID,(Xil_InterruptHandler)XGpioPs_IntrHandler,&GpioPs);
- if(status != XST_SUCCESS){
- return status;
- }
- //step7、设置GPIO中断处理函数
- XGpioPs_SetCallbackHandler(&GpioPs,(void*) &GpioPs,(XGpioPs_Handler)GPIO_Handler);
- //step8、使能GPIO对应的bank上的具体地址
- XGpioPs_IntrEnable(&GpioPs,SW_BANK_ID,1<<(SW0-54));
-
- return XST_SUCCESS;
- }
-
-
- void GPIO_Handler(void *CallBackRef, u32 Bank, u32 Status)
- {
- XGpioPs *GpioPtr;
- GpioPtr = (XGpioPs *)CallBackRef;
- //读取中断是否被触发
- u32 intrstatus;
- intrstatus = XGpioPs_IntrGetStatusPin(GpioPtr,SW0);
- if(intrstatus == 1)
- {
- //清除按键中断使能
- XGpioPs_IntrClearPin(GpioPtr,SW0);
- XGpioPs_IntrDisablePin(GpioPtr,SW0);
- //等待按键抖动结束,100ms高电平
- u32 readSW=0;
- int cnt;
- while(cnt <100)
- {
- readSW= XGpioPs_ReadPin(GpioPtr,SW0);
- if(readSW == 1)
- {
- cnt ++;
- }
- else
- {
- cnt =0;
- }
- usleep(1000);
- }
- //打开对应GPIO的中断使能
- XGpioPs_IntrEnablePin(GpioPtr,SW0);
-
- }
- /*中断处理*/
- led_value = ~led_value;
- XGpioPs_WritePin(GpioPtr,LED1,led_value);
- XGpioPs_WritePin(GpioPtr,LED0,led_value);
-
- }
软中断的中断ID为0~15,并且全部是上升沿触发,主要用于核间中断或者CPU自己中断自己。关于AMP模式下的工程构建,请参考博客:
CPU0和CPU1的中断ID固定如下
- #define CPU0_INTR_DEV_ID 0x0D//CPU0 interrupt ID
- #define CPU1_INTR_DEV_ID 0x0E//CPU1 interrupt ID
触发中断的方式:在中断配置完成后,CP0可以自己中断自己,也可以中断CPU1
- //XSCUGIC_SPI_CPU0_MASK和XSCUGIC_SPI_CPU1_MASK为系统自带
- status = XScuGic_SoftwareIntr(&ScuGic,CPU0_INTR_DEV_ID,XSCUGIC_SPI_CPU0_MASK);//CPU0自己中断自己
- status = XScuGic_SoftwareIntr(&ScuGic,CPU1_INTR_DEV_ID,XSCUGIC_SPI_CPU1_MASK);//CPU0中断CPU1
CPU0的配置代码如下:
- //cpu0 main.c
- #include <stdio.h>
- #include "sleep.h"
- #include "xparameters.h"
- #include "xscugic.h" //通用中断控制器头文件
-
- /*1.重定义*/
- #define GIC_DEV_ID XPAR_PS7_SCUGIC_0_DEVICE_ID //GIC devive ID
- #define CPU0_INTR_DEV_ID 0x0D//CPU0 interrupt ID(被中断的设备ID)
- #define CPU1_INTR_DEV_ID 0x0E//CPU1 interrupt ID(被中断的设备ID)
-
- /*2.变量定义*/
- XScuGic ScuGic;
- XScuGic_Config * ScuGicCfgPtr;
-
- /*3.函数初始化*/
- int Init_GIC_SGI(void);
- void CPU0_Handler(void * CallBackRef);
-
- int main()
- {
- int status = 0;
- status = Init_GIC_SGI();
- if(status != XST_SUCCESS)
- {
- printf("Initial GIC and SGI Failed!");
- return status;
- }
- while(1)
- {
- status = XScuGic_SoftwareIntr(&ScuGic,CPU0_INTR_DEV_ID,XSCUGIC_SPI_CPU0_MASK);//自己中断自己
- if (status != XST_SUCCESS) {
- return XST_FAILURE;
- }
- sleep(5);
- }
- return 0;
- }
-
- int Init_GIC_SGI(void)
- {
- int status = 0;
- /******中断控制器初始化*******/
- //step1.初始化异常处理
- Xil_ExceptionInit();
- //step2.初始化中断控制器
- ScuGicCfgPtr = XScuGic_LookupConfig(GIC_DEV_ID);
- status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- if(status != XST_SUCCESS)
- {
- printf("Initial Gic Failed!");
- return status;
- }
- //step3.注册异常处理回调函数
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
- //step4.异常处理使能
- Xil_ExceptionEnable();
-
- /******SGI配置区域*******/
- //step5.在gic中使能(被中断的设备ID)
- XScuGic_Enable(&ScuGic,CPU0_INTR_DEV_ID);
- //step6.在gic中连接被中断的设备ID,并注册回调函数
- status = XScuGic_Connect(&ScuGic,CPU0_INTR_DEV_ID,(Xil_ExceptionHandler)CPU0_Handler,&ScuGic);
- if(status != XST_SUCCESS)
- {
- printf("Connect Gic Failed!");
- return status;
- }
- return XST_SUCCESS;
- }
-
- void CPU0_Handler(void * CallBackRef)
- {
- printf("i am cpu000 intr !\n\r");
- }
CPU1的配置代码如下:
- //cpu1 main.c
- #include <stdio.h>
- #include "sleep.h"
- #include "xparameters.h"
- #include "xscugic.h" //通用中断控制器头文件
-
- /*1.重定义*/
- #define GIC_DEV_ID XPAR_PS7_SCUGIC_0_DEVICE_ID //GIC devive ID
- #define CPU0_INTR_DEV_ID 0x0D//CPU0 interrupt ID(被中断的设备ID)
- #define CPU1_INTR_DEV_ID 0x0E//CPU1 interrupt ID(被中断的设备ID)
-
- /*2.变量定义*/
- XScuGic ScuGic;
- XScuGic_Config * ScuGicCfgPtr;
-
- /*3.函数初始化*/
- int Init_GIC_SGI(void);
- void CPU1_Handler(void * CallBackRef);
-
- int main()
- {
- int status = 0;
- sleep(2);//让cpu0先初始化
- status = Init_GIC_SGI();
- if(status != XST_SUCCESS)
- {
- printf("Initial GIC and SGI Failed!");
- return status;
- }
- while(1)
- {
- // sleep(3);
- // printf("this is cpu1 main\n\r");
- sleep(2);
- status = XScuGic_SoftwareIntr(&ScuGic,CPU0_INTR_DEV_ID,XSCUGIC_SPI_CPU0_MASK);//中断CPU0
- if (status != XST_SUCCESS) {
- return XST_FAILURE;
- }
-
- }
- return 0;
- }
-
- int Init_GIC_SGI(void)
- {
- int status = 0;
- /******中断控制器初始化*******/
- //step1.初始化异常处理
- Xil_ExceptionInit();
- //step2.初始化中断控制器
- ScuGicCfgPtr = XScuGic_LookupConfig(GIC_DEV_ID);
- status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
- if(status != XST_SUCCESS)
- {
- printf("Initial Gic Failed!");
- return status;
- }
- //step3.注册异常处理回调函数
- Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
- //step4.异常处理使能
- Xil_ExceptionEnable();
-
- /******SGI配置区域*******/
- //step5.在gic中使能(被中断的设备ID)
- XScuGic_Enable(&ScuGic,CPU1_INTR_DEV_ID);
- //step6.在gic中连接被中断的设备ID,并注册回调函数
- status = XScuGic_Connect(&ScuGic,CPU1_INTR_DEV_ID,(Xil_ExceptionHandler)CPU1_Handler,&ScuGic);
- if(status != XST_SUCCESS)
- {
- printf("Connect Gic Failed!");
- return status;
- }
- return XST_SUCCESS;
- }
-
- void CPU1_Handler(void * CallBackRef)
- {
- printf("i am cpu1 intr !\n\r");
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。