ZYNQ的MIO与EMIO中断设置流程——Vivado2018.3

MIO与EMIO在各bank的分布

image
根据官方手册可以看到MIO分布在BANK0与BANK1有54个,而EMIO分布在BANK2与BANK3有64个。

中断系统的介绍

image

根据官方手册的GIC中断控制器的系统级块图可以看出中断源有:软件中断SGI、两个CPU的私有中断PPI、共享外设中断SPI(包括PS端的IOP和PL端)。

image
根据这张图就更清晰的看出各中断源如何与GIC连接的。

一、MIO和EMIO的设置

1.初始化MIO与EMIO

	XGpioPs_Config *ConfigPtr; /*为GPIO的设备信息创建一个指针*/
	ConfigPtr = XGpioPs_LookupConfig(XPAR_AXI_GPIO_0_DEVICE_ID);/*根据设备ID查找到GPIO的配置信息*/
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);/*根据查找到的GPIO的配置信息进行初始化*/

2.MIO与EMIO的输入输出设置

	//设置IO方向函数
	XGpioPs_SetDirectionPin(&Gpio, PL_LED, 1);/*(函数指针,IO管脚编号,0设置为输入 1设置为输出)*/
	XGpioPs_SetDirectionPin(&Gpio, PL_KEY, 0x0);
	//设置IO输出使能函数
	XGpioPs_SetOutputEnablePin(&Gpio, PL_LED, 1);/*(函数指针,IO管脚编号,0设置为禁止 1设置为使能)*/
	//设置IO输出数据函数
	XGpioPs_WritePin(&Gpio, PL_LED, 0x0);/*(函数指针,IO管脚编号,0设置为输出为0 1设置输出为1)*/

二、中断的设置

1.初始化Scugic驱动

	XScuGic_Config *IntcConfig; /* 为中断设置配置一个实例指针 */
	//根据设备ID查找到Scugic的配置信息,并进行初始化,这里只需要注意填下ID号,其他的不需要关心
	IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
	XScuGic_CfgInitialize(&GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);

2.配置中断服务

    //注册异常处理函数(不需要关心)
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                    (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                    &GicInstancePtr);
    //注册/绑定具体外设的中断服务函数(需要用户去关心)
    XScuGic_Connect(&GicInstancePtr, XPS_GPIO_INT_ID,
                            (Xil_ExceptionHandler)XGpioPs_IntrHandler,
                            &Gpio);
							//(指针,中断ID号,中断函数地址,回调参考指针)

    //设置具体外设的中断相关的寄存器(使能、禁止、中断检测类型)(需要用户去关心)
    XGpioPs_SetIntrType(&Gpio, XGPIOPS_BANK2 , 0xFFFFFFFF, 0x00000000, 0x00);/*(实例指针,bank号,中断触发类型_0电平触发_1边沿触发,
			中断触发极性_0低电平或下降沿_1高电平或上升沿,中断触发敏感度_0单边缘触发_1双边缘触发)*/

    /* 设置回调函数. */
    XGpioPs_SetCallbackHandler(&Gpio, &Gpio, IntrHandler);//(实例指针,回调指针,中断函数指针)

    //设置某位的中断使能(需要用户去关心)
    XGpioPs_IntrEnable(&Gpio, XGPIOPS_BANK2, (1 << (PL_KEY - 54)));//(实例指针,BANK号,32位_位1为使能_位0为禁止)
	
    //在GIC中允许该外设的中断源向Cpu发出中断
    XScuGic_Enable(&GicInstancePtr, XPS_GPIO_INT_ID);

    //开启总中断
    Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

3.中断处理函数的设置

static void IntrHandler(void *CallBackRef, u32 Bank, u32 Status)
{
	XGpioPs *Gpio = (XGpioPs *)CallBackRef;
	u32 DataRead;

	/* Push the switch button */
	if(Status)
	{
		DataRead = XGpioPs_ReadPin(Gpio , PL_KEY);
		if (DataRead == 0) {
			flag ++;
		}
	}
}

三、整体代码

#include "stdio.h"
#include "xgpiops.h"
#include "xparameters.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "unistd.h"


static XGpioPs Gpio; /* The Instance of the GPIO Driver */
static XScuGic GicInstancePtr; /* The Instance of the Interrupt Controller Driver */

#define PS_LED      7       //MIO_LED为MIO7,对应的GPIO编号为7
#define PS_KEY      47      //MIO_KEY为MIO47,对应的GPIO编号为47
#define PL_KEY      (54 + 1)      //EMIO_KEY为EMIO1,对应的GPIO编号为55
#define PL_LED      (54 + 0)      //EMIO_LED为EMIO0,对应的GPIO编号为54

int flag;

static void IntrHandler(void *CallBackRef, u32 Bank, u32 Status)
{
	XGpioPs *Gpio = (XGpioPs *)CallBackRef;
	u32 DataRead;

	/* Push the switch button */
	if(Status)
	{
		DataRead = XGpioPs_ReadPin(Gpio , PL_KEY);
		if (DataRead == 0) {
			flag ++;
		}
	}
}


int main (void)
{

    //MIO初始化
    XGpioPs_Config *ConfigPtr; /*为GPIO的设备信息创建一个指针*/
	ConfigPtr = XGpioPs_LookupConfig(XPAR_AXI_GPIO_0_DEVICE_ID);/*根据设备ID查找到GPIO的配置信息*/
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);

	//设置本例中用到的GPIO的基本工作模式(输入(MIO47)、输出(MIO7)、初始值)
	XGpioPs_SetDirectionPin(&Gpio, PL_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, PL_LED, 1);
	XGpioPs_WritePin(&Gpio, PL_LED, 0x0);

	/* Set the direction for the specified pin to be input */
	XGpioPs_SetDirectionPin(&Gpio, PL_KEY, 0x0);

    //初始化SCUGIO驱动
    XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
    	IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
    	XScuGic_CfgInitialize(&GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
	
    	//注册异常处理函数
    	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
    	                                (Xil_ExceptionHandler)XScuGic_InterruptHandler,
    	                                &GicInstancePtr);
    	//注册/绑定具体外设的中断服务函数(需要用户去关心)
    	XScuGic_Connect(&GicInstancePtr, XPS_GPIO_INT_ID,
    	                        (Xil_ExceptionHandler)XGpioPs_IntrHandler,
    	                        &Gpio);
	
    	//设置具体外设的中断相关的寄存器(使能、禁止、中断检测类型)(需要用户去关心)
    	/* Enable falling edge interrupts for all the pins in bank 0. */
    	XGpioPs_SetIntrType(&Gpio, XGPIOPS_BANK2 , 0xFFFFFFFF, 0x00000000, 0x00);
	
    	/* Set the handler for gpio interrupts. */
    	XGpioPs_SetCallbackHandler(&Gpio, &Gpio, IntrHandler);
	
    	//设置某位的中断使能(需要用户去关心)
    	XGpioPs_IntrEnable(&Gpio, XGPIOPS_BANK2, (1 << (PL_KEY - 54)));
	
    	//在GIC中允许该外设的中断源向Cpu发出中断
    	XScuGic_Enable(&GicInstancePtr, XPS_GPIO_INT_ID);
	
    	//开启总中断
    	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

    while(1)
    {
        if(flag > 0)
        {
            flag--;
            XGpioPs_WritePin(&Gpio, PL_LED, 0x1);
            usleep(500000);
            XGpioPs_WritePin(&Gpio, PL_LED, 0x0);
            usleep(500000);
        }
    }
}


posted @ 2022-11-29 10:31  Lclone  阅读(499)  评论(0编辑  收藏  举报