xzy610030

一起探讨,一起进步,一起分享!

zynq裸机中断(一)

0
阅读(7801)

学习了zynq的中断系统后,这里做一个简单的中断实验,第一个中断的实验是一个简单的按键中断实验。
开发环境:XPS14.6+SDK14.6
一:硬件配置
1. 启动xps,创建工程,选择好平台。



2.移除外设


3.进入工程,已经配置好了(PlanAhead的话好像是不是自动配置好的)


注:建议自己手动添加一次zedboard配置文件,我这前面没添加后面不行,后面添加后就可以了。

 

4.添加axi  GPIOIP核,注意这里勾上GPIO  Support Interrupts  和设置好为1位。


 

5.点击ok



6.这里需要连接中断,如下图



7.然后就是添加约束了,生成bit流文件了,在导入到SDK就可以了。硬件配置就结束了。



.应用软件

和以前一样,新建一个helloworld工程。

这里我对比了一下又添加中断后的axi gpio和没有添加中的gpio的区别

这是添加中断后的工程(这是在xparameter.h中找到的信息)



这是以前博客zedboard--zynq使用自带外设IPARM PS访问FPGA(八)



也就是在这里查找中断的ID号了,因为我们在应用程序中要使用ID号了。

软件代码:

#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xil_exception.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "xil_printf.h"

#include "xscugic.h"
#include "xgpio.h"
#include "xgpiops.h"

#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID				//设备ID
#define INTC_DEVICE_INT_ID	XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR   //中断号

int ScuGicExample(u16 DeviceId);
void DeviceDriverHandler(void *CallbackRef);

unsigned int led_state;
volatile static int InterruptProcessed = FALSE;
static int iPinNumber = 7; /*Led LD9 is connected to MIO pin 7*/

XScuGic InterruptController; 	     /* Instance of the Interrupt Controller */
static XScuGic_Config *GicConfig;    /* The configuration parameters of the controller */

static XGpioPs psGpioInstancePtr;
XGpioPs_Config *GpioConfigPtr;

static XGpio GPIOInstance_Ptr;

int main(void)
{
	int Status;
	int xStatus;

	u32 uPinDirection = 0x1;
	led_state = 0;
	init_platform();
	print("GIC Example Test\r\n");
	//axi gpio的初始化,这里比之前的GPIO多了中断的使能
	xStatus = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
	if(XST_SUCCESS != xStatus)
		print("GPIO INIT FAILED\n\r");
	XGpio_SetDataDirection(&GPIOInstance_Ptr, 1,1);
	XGpio_InterruptGlobalEnable(&GPIOInstance_Ptr);
	XGpio_InterruptEnable(&GPIOInstance_Ptr, XGPIO_IR_CH1_MASK);
	//LD9,即MIO7的初始化
	  GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	  if(GpioConfigPtr == NULL)
	    return XST_FAILURE;
	  xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,
	      GpioConfigPtr,
	      GpioConfigPtr->BaseAddr);
	  if(XST_SUCCESS != xStatus)
	    print(" PS GPIO INIT FAILED \n\r");
	  XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection);
	  XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);
	  print("LED 'LD9' Turned OFF \r\n");
	  XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,0);
	  //调用中断控制器的初始化
	Status = ScuGicExample(INTC_DEVICE_ID);
	if (Status != XST_SUCCESS) {
		print("GIC Example Test Failed\r\n");
		return XST_FAILURE;
	}
	print("Successfully ran GIC Example Test\r\n");
	while(1)
	{
		usleep(1);
		if(TRUE == InterruptProcessed)
		{
			InterruptProcessed = FALSE;
			sleep(1);
			XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID);
		}
	}
	cleanup_platform();
	return XST_SUCCESS;
}
//中断初始化,
int ScuGicExample(u16 DeviceId)
{
	int Status;
	print("1 \r\n");
	GicConfig = XScuGic_LookupConfig(DeviceId);
	if (NULL == GicConfig) {
		return XST_FAILURE;
	}
	print("2 \r\n");
	Status = XScuGic_CfgInitialize(&InterruptController, GicConfig,
					GicConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	print("3 \r\n");

	XScuGic_SetPriorityTriggerType(&InterruptController, INTC_DEVICE_INT_ID,
						0x05, 0x01);

	Status = XScuGic_SelfTest(&InterruptController);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	print("4 \r\n");

	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler) XScuGic_InterruptHandler,
			&InterruptController);

	print("5 \r\n");

	Status = XScuGic_Connect(&InterruptController, INTC_DEVICE_INT_ID,
			   (Xil_ExceptionHandler)DeviceDriverHandler,
			   (void *)&InterruptController);
	Xil_ExceptionEnable();
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	print("6 \r\n");

	XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID);
	print("7 \r\n");
	return XST_SUCCESS;
}

void DeviceDriverHandler(void *CallbackRef)
{
	 print("LED 'LD9' Turned ON \r\n");
	 XScuGic_Disable(&InterruptController, INTC_DEVICE_INT_ID);
	 led_state = (0 == led_state)?1:0;
	 XGpioPs_WritePin(&psGpioInstancePtr,iPinNumber,led_state);
	 XGpio_InterruptClear(&GPIOInstance_Ptr, XGPIO_IR_CH1_MASK);
	 XScuGic_Enable(&InterruptController, INTC_DEVICE_INT_ID);
	 InterruptProcessed = TRUE;
}

实验结果:板子的图就不贴了,没多大的意思,看串口的信息吧。



代码中其实是按一下就亮,再按一下就熄灭,但是这里存在边沿触发中断的情况(似乎与实际的不一样,这个还有待查证),但不妨碍本实验了练习zedboard的中断,下次继续学习zynq的中断。

PS:中途出现的问题,之前其实就可以了的,但是后面自己新建一个xps工程后又不可以了,之前的工程是用PlanAhead来弄的,是自己添加的配置文件,这次xps工程一开始没有添加配置文件,后面添加配置文件后重新生成bit文件,导入到sdk中,就可以了。还有就是ucf文件这里(不知道有没有编写ucf比较好的方法,反正我是很害怕这里了。),这里真的是要非常当心。