zynq中断之gpio中断,emio按键中断详解(解决重复中断)

一.概要
    zynq有三种中断:软中断(software interrtpts),私有外设中断(private peripheral)和共享外设中断(shared perlpherals)。区别在于私有外设中断和共享外设中断含有PL测引入的中断。*每个中断都有自己ID号。*有一个中断控制器(generic interrupt controller)管理着这些中断的使能,分类,分配和优先级。框图如下图所示:
图一
①软中断:
在这里插入图片描述
②私有外设中断:
    私有外设中断包括global timer,private time,watchdog。

③共享外设中断

在这里插入图片描述
在这里插入图片描述
二.emio按键中断
    中断初始化有两种格式,第一种是按照sdk给出的例程的格式,第二种是做了一点小的修改,个人觉得第二种更好用。
1)根据sdk例程的中断初始化

	//初始化异常管理
	Xil_ExceptionInit();
//初始化中断控制器
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	XScuGic_CfgInitialize(&GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);
//连接中断控制器到CPU
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				&GicInstancePtr);
//连接中断控制器到中断服务函数(这个很重要,下面要用到)
	XScuGic_Connect(&GicInstancePtr, GpioIntrId,
				(Xil_ExceptionHandler)XGpioPs_IntrHandler,
				&Gpio);
//设置中断类型
	XGpioPs_SetIntrType(&Gpio, GPIO_BANK, 0x00, 0x00000000, 0x00);
//设置中断服务函数地址到gpio实例数据中
	XGpioPs_SetCallbackHandler(&Gpio, (void *)&Gpio, IntrHandler);
//使能gpio的中断
	XGpioPs_IntrEnable(&Gpio, GPIO_BANK, (1 << 0));

//使能中断控制器中的gpio中断
	XScuGic_Enable(&GicInstancePtr, GpioIntrId);
//使能异常处理
	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);

中断服务函数的地址是通过上面的XGpioPs_SetCallbackHandler()函数添加到GPIO的实例数据的,当经过emio的一个按键按下触发中断时,CPU会转到下面的函数中参数的Xil_ExceptionHandler)XGpioPs_IntrHandler中去(经过单步调试可以知道)

XScuGic_Connect(&GicInstancePtr, GpioIntrId,
				(Xil_ExceptionHandler)XGpioPs_IntrHandler,
				&Gpio);

XGpioPs_IntrHandler函数是塞琳思已经写好的,内部如下所示
在这里插入图片描述
进入XGpioPs_IntrHandler函数以后,又会通过上图红色框中的语句跳到中断服务函数去,中断服务函数就是这样被调用的。但是从XGpioPs_IntrHandler函数进入中断服务函数会有一些小问题,就是中断服务函数会重复执行好几次。原因是因为:
在这里插入图片描述
如上图所示,XGpioPs_IntrHandler函数中有有个for 循坏会检测GPIO的4个bank的中断状态,不知道为什么他这里的bank0和1的中断状态不是0的,所以他就会连续进入好几次中断服务函数。为了解决这个问题,我们需要在中断服务函数中读取gpio中断pin的中断状态,只有在对应中断pinc触发了才会执行if里面的语句,示例代码如下图所示:
在这里插入图片描述
注意:上面if里面程序我用usleep()代替了按键消抖,这里我想说的是必须要先消抖才能执行下面的中断清0和屏蔽函数,反过来的话可能会导致中断清0失败。
2)第二种中断初始化格式
    第二种中断初始化是把第一种中断初始化中的XGpioPs_SetCallbackHandler(&Gpio, (void *)&Gpio, IntrHandler)删去,然后把XScuGic_Connect(&GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)XGpioPs_IntrHandler,
&Gpio)中的XGpioPs_IntrHandler改为自定义的中断服务函数的地址。如下图所示:
在这里插入图片描述
这样中断触发的时候,就会直接调用中断服务函数IntrHandler(),避免了第一种触发中断后进入XGpioPs_IntrHandler()中去检测GPIO的4个bank的中断状态,从而导致连续进入中断服务函数好几次。😎

<think>好的,我现在需要帮助用户了解如何在Zynq平台上将EMIO映射到PS串口的配置或实现方法。用户的问题是关于Zynq EMIO映射到PS UART的配置教程或实现方案。我需要结合之前提供的引用信息来构建一个清晰的步骤指南,并确保符合用户的需求。 首先,我应该回顾用户提供的引用内容。引用1提到了配置ZYNQEMIO GPIO时遇到的一些错误,引用2详细描述了如何通过EMIO扩展UART1,包括代码示例,引用3讨论了EMIO中断的问题。这些信息都是关于EMIO的使用,特别是UART的扩展,所以用户可能是在尝试通过EMIO将UART连接到PL端的引脚,但遇到了配置上的问题。 接下来,我需要确定EMIO映射到PS UART的具体步骤。根据引用2,用户需要配置ZYNQ的PS部分,启用UART并通过EMIO连接到PL的引脚。这可能涉及Vivado中的IP配置,生成比特流,然后在SDK中编写驱动程序。 我应该分步骤来写,首先在Vivado中设置ZYNQ IP,启用UART1并将TX和RX通过EMIO引出。然后进行管脚约束,生成比特流。接着在SDK中初始化UART,发送数据,如引用2中的代码示例所示。同时,还需要注意中断处理的问题,如引用3提到的,可能需要处理EMIO中断共享情况。 用户可能需要详细的代码示例,特别是初始化UART的部分,以及如何正确设置波特率等参数。此外,硬件配置的正确性很重要,比如确保PL的引脚正确分配到EMIO接口。 还需要考虑用户可能的疑问,比如在Vivado中如何具体配置EMIO,如何将UART1的引脚连接到外部,如何处理可能出现的错误如APB事务错误(引用1中的问题)。这时候可能需要提醒用户检查配置步骤,确保EMIO的正确分配和管脚约束。 最后,生成相关的问题,帮助用户深入理解,例如EMIO与其他扩展方式的区别,调试方法,中断处理等。确保问题与主题相关,并覆盖用户可能感兴趣的扩展内容。 总结起来,回答的结构应该是步骤式的,包括硬件配置、软件实现、注意事项和相关问题。确保每个步骤都清晰,引用对应的参考资料,并指出可能的问题点。</think>在Zynq平台上通过EMIO实现PS端UART外设的PL引脚映射,需通过以下步骤实现: ### 一、硬件平台配置(Vivado部分) 1. **添加Zynq Processing System IP** - 双击IP打开配置界面,在**PS-PL Configuration**选项卡中展开**GPIO EMIO**,启用至少2位GPIO(对应UART的TX/RX) - 在**MIO Configuration**中找到**UART 1**,将其**IO Type**改为**EMIO**模式[^2] 2. **管脚约束生成** ```tcl set_property PACKAGE_PIN T14 [get_ports UART1_TX_0] set_property IOSTANDARD LVCMOS33 [get_ports UART1_TX_0] ``` 需根据开发板原理图指定实际物理引脚[^2] 3. **生成硬件平台** - 通过**Generate Output Products**生成HDL包装 - 导出硬件包含.xsa文件(含EMIO映射配置) ### 二、软件驱动实现(SDK部分) 1. **UART初始化函数** ```c XUartPs_Config *Config = XUartPs_LookupConfig(XPAR_XUARTPS_1_DEVICE_ID); XUartPs_CfgInitialize(&UartPs1, Config, Config->BaseAddress); XUartPs_SetBaudRate(&UartPs1, 115200); // 设置波特率[^2] ``` 2. **数据收发示例** ```c u8 buffer[] = "EMIO_UART_Test"; XUartPs_Send(&UartPs1, buffer, strlen(buffer)); // 发送数据 XUartPs_Recv(&UartPs1, recv_buffer, sizeof(recv_buffer)); // 接收数据 ``` ### 三、关键注意事项 1. **中断共享问题** - EMIOGPIO BANK2/BANK3共用中断控制器,需在中断服务程序中添加BankID判断[^3] ```c if(XGpio_InterruptGetStatus(&Gpio, BANK2_ID)){ // 处理BANK2中断 } ``` 2. **硬件验证** - 使用ILA核抓取EMIO信号波形 - 通过TCL命令验证EMIO连接: ```tcl connect_bd_net [get_bd_pins processing_system7_0/UART1_TX] [get_bd_pins axi_uartlite_0/rx] ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值