ARM的GPIO中断
一、实验目的
调用ZYNQ处理器,导出硬件到SDK 进行软件开发,使用GPIO输入的中断机制进行按键读取。
二、ZYNQ工程建立
三、新建bd以及ZYNQ处理器IP调用
1. 打开IP Catalog,Search输入GPIO,添加 AXI_GPIO:(添加IP也可以通过点击Diagram 上面的+号来添加):
2. 设置axi_gpio_0,勾选全部为输入,GPIO宽度1,其余不变,点击OK
3. 设置axi_gpio_1,勾选全部为输出,GPIO宽度4,其余不变,点击OK
4. 点击Diagram上方的Run Conection Automation自动连接信号:
弹出的界面,勾选所有的模块,表示全部都需要自动连接,点击OK:
5. 最后点击 Run Block Automation生成ZYNQ对外的管脚,包括DDR3和其他引脚:
6.默认勾选左边唯一一个IP,也就是ZYNQ IP还未连接,点击OK自动连接对外引脚:
7.重新布局
8.最后,手动连接axi_gpio_0智能高端输出接口和ZYNQ终端输入接口
9. 完成之后,按下ctrl+s保存设置,回到source窗口,生成输出文件和生成顶层文件。 生成输出,生成顶层
10.完成之后点击工程管理栏->RTL ANALYSIS->Open Elaborated Design,然后切换视图 到I/O Planing分配管脚视图,分配管脚。分配完成之后管脚如下,我们按ctrl+s保存管脚约束 文件,文件名为gpio_input_output。
11.工程管理栏直接点击生成比特文件。等待生成完成,生成完成之后,菜单栏File- >Export->Export Hardware导出硬件。我们的硬件部分设计到此结束。接下来我们开始软件 SDK开发,进行代码编写,debug。导出硬件需要勾选包含bit文件
四、SDK下的代码开发
1.. 我们启动SDK。在工具栏File ->Launch SDK启动。 启动SDK后,可以看到默认带的一个硬件描述工程。我们新建一个app工程。File->New- >Application Project,然后,工程名gpio_interrupt,点击NEXT:
2. 我们编辑gpio_interrupt工程中的helloword.c文件,写入如下代码:
#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xgpio.h"
#include <unistd.h>
#define INTC_DEVICE_ID XPAR_PS7_SCUGIC_0_DEVICE_ID
#define KEY_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define LED_DEVICE_ID XPAR_AXI_GPIO_1_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
#define KEY_INT_MASK XGPIO_IR_CH1_MASK
XGpio LEDInst;
XGpio KEYInst;
XScuGic INTCInst;
static void KeyIntrHandler(void * InstancePtr);
static int IntcInitFunction(u16 DeviceId, XGpio * GpioInstancePtr);
static int InterruptSystemSetup(XScuGic * XScuGicInstancePtr);
int main()
{
init_platform();
int status;
status = XGpio_Initialize(&KEYInst, KEY_DEVICE_ID); // initial KEY
if(status != XST_SUCCESS) return XST_FAILURE;
status = XGpio_Initialize(&LEDInst, LED_DEVICE_ID); // initial LED
if(status != XST_SUCCESS)return XST_FAILURE;
XGpio_SetDataDirection(&KEYInst, 1, 0xFF);
XGpio_SetDataDirection(&LEDInst, 1, 0); // set LED IO direction as out
XGpio_DiscreteWrite(&LEDInst, 1, 0x00);// at initial, all LED turn off
printf(">>Press PL KEY1, and check the PL LED1 \n");
status = IntcInitFunction(INTC_DEVICE_ID, &KEYInst);
if(status != XST_SUCCESS)return XST_FAILURE;
while(1)
{
;
}
cleanup_platform();
return 0;
}
static void KeyIntrHandler(void * InstancePtr)
{
u8 keyVal;
usleep(10000); // 0.1s sleep, to debounce, in common, the meta-state will sustain no more than 20ms
keyVal = XGpio_DiscreteRead(&KEYInst, 1) & 0x0f;
printf("PL KEY1 pressed,interrupt is generated!! key value=%d\n",keyVal);
XGpio_DiscreteWrite(&LEDInst, 1, 0X0F);//on led
usleep(500000);
XGpio_DiscreteWrite(&LEDInst, 1, 00);//reverse led
XGpio_InterruptClear(&KEYInst, KEY_INT_MASK);
XGpio_InterruptEnable(&KEYInst, KEY_INT_MASK); // Enable GPIO interrupts
}
static int IntcInitFunction(u16 DeviceId, XGpio * GpioInstancePtr)
{
XScuGic_Config * IntcConfig;
int status;
// Interrupt controller initialization
IntcConfig = XScuGic_LookupConfig(DeviceId);
status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
if(status != XST_SUCCESS)return XST_FAILURE;
// Call interrupt setup function
status = InterruptSystemSetup(&INTCInst);
if(status != XST_SUCCESS) return XST_FAILURE;
// Register GPIO interrupt handler
status = XScuGic_Connect(&INTCInst, INTC_GPIO_INTERRUPT_ID,
(Xil_ExceptionHandler)KeyIntrHandler, (void*)GpioInstancePtr);
if(status != XST_SUCCESS)return XST_FAILURE;
// Enable GPIO interrupts
XGpio_InterruptEnable(GpioInstancePtr, 1);
XGpio_InterruptGlobalEnable(GpioInstancePtr);
// Enable GPIO interrupts in the controller
XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);
return XST_SUCCESS;
}
//----------------------------------------------------------------------------
// Interrupt system setup
//----------------------------------------------------------------------------
static int InterruptSystemSetup(XScuGic * XScuGicInstancePtr)
{
// Register GIC interrupt handler
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler, XScuGicInstancePtr);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
3.然后,等待SDK自动编译完成。一定要等待编译结束。SDK在新建helloword模板代码工程结束它 就自动编译,不需要手动编译。每次修改完代码,按一下ctrl+s保存即可重新编译,编译进度在右下角 会显示,以及Console窗口也会打印便已结束信息。一般第一次新建工程自动编译会比较慢,后面修改 代码都是增量编译,只重新编译修改的代码文件,就很快。下图打印编译完成的信息。
4.完成之后,我们就可以进行上板调试。点击debug的小虫子符号,选择第一项,1 Launch On Hardware(System Debugger) 。注意,第一次debug不会成功,代码不能正常运行,因为我们还没 有配置烧写FPGA。当debug启动,代码已下载到芯片,可以看到菜单栏下的 符号可用。这个 时候,我们点击小虫子 右边的下拉选项,选择Debug Configuration,进入debug配置, 设置如下:
5.然后点击小虫子 重新DEBUG,弹出的对话框均选择OK,等待再次debug就绪。然后, 我们打开terminal配置模式serial,串口号,波特率,然后连接。点击 开始debug。我们 按下KEY1, 可以看到四个LED亮起约一秒熄灭,串口打印输出按钮按下,中断发生。
本文 zblog模板 原创,转载保留链接!网址:https://xn--zqqs03dbu6a.cn/?id=50
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。