pynq 中断 测试gpio (emio)中断

平台 PYNQ-Z2

实现功能

这里用pynq实现emio 接按钮按键中断IRQ

硬件上EMIO 54接btn0,通过输入,触发中断#52,到GIC

在这里插入图片描述
通过SPI,操作中断寄存器指定cpu等,触发IRQ

在这里插入图片描述

硬件设计

在这里插入图片描述

一位EMIO 的GPIO_0_0_tri_io引出管教到btn0

约束

set_property -dict { PACKAGE_PIN D19   IOSTANDARD LVCMOS33 } [get_ports { GPIO_0_0_tri_io }]; #IO_L4P_T0_35 Sch=btn[0]

软件设计



#include <stdio.h>
#include "platform.h"



#include "xgpiops.h"
#include "xgpiops_hw.h"

#include "XSCUGIC.H"
#include "XSCUGIC_HW.H"

#include "sleep.h"



#define ICCPMR   *(volatile unsigned int *) 0xf8f00104
//printf(" ICCPMR = %0X  @ line = %d \n", ICCPMR ,__LINE__  );
//(__FILE__, __LINE__);

#define GPIO_NO 54

static void GpioHandler(void *CallBackRef, int Bank, u32 Status)
{

	static int  i = 0;

	if (Status ==0 ) return ;
    XGpioPs* pGpioPs=(XGpioPs*)CallBackRef;

    XGpioPs_IntrDisablePin(pGpioPs,GPIO_NO);

    printf("Gpio Handler %d...\n\r",i++);

  //  while (1 == XGpioPs_ReadPin( pGpioPs  ,  GPIO_NO )) ;

    usleep(100*1000);
    XGpioPs_IntrClearPin(pGpioPs,GPIO_NO);
    XGpioPs_IntrEnablePin(pGpioPs,GPIO_NO);



}

int main()

{

    XGpioPs Gpio;

    XGpioPs_Config *ConfigPtr;

    printf(" ICCPMR = %0X  @ line = %d \n", ICCPMR ,__LINE__  );


    ConfigPtr = XGpioPs_LookupConfig(0);
    XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
 //初始化GPIO的输入以及中断。

    XGpioPs_SetDirectionPin(&Gpio,GPIO_NO,0x0);


     XGpioPs_SetIntrTypePin(&Gpio,GPIO_NO,XGPIOPS_IRQ_TYPE_EDGE_RISING);
     XGpioPs_SetCallbackHandler(&Gpio, (void *)&Gpio, GpioHandler);
     XGpioPs_IntrEnablePin(&Gpio,GPIO_NO);


     XScuGic ScuGic;
     XScuGic_Config* pScuGicCfg;
     pScuGicCfg=XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
     XScuGic_CfgInitialize(&ScuGic,pScuGicCfg,pScuGicCfg->CpuBaseAddress);

     XScuGic_Connect(&ScuGic, 52,
                    (Xil_ExceptionHandler)XGpioPs_IntrHandler,
                    (void *)&Gpio);

     XScuGic_SetPriorityTriggerType(&ScuGic,52,0xa0,0x01);//优先级阈值f0
     XScuGic_Enable(&ScuGic,52);


     Xil_ExceptionInit();
     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
     Xil_ExceptionEnable();

    printf("Intr test: \n\r");

    while(1)
    {

    }

}





结果

按键

在这里插入图片描述
ICCICR (IC CPU IC REG)->
ICDDC R( UC distributor C REG)->

GPIO中断库函数分析

void XGpioPs_SetCallbackHandler(XGpioPs *InstancePtr, void *CallBackRef,
				 XGpioPs_Handler FuncPointer)

 XGpioPs_SetCallbackHandler(&Gpio, (void *)&Gpio, GpioHandler);

XGpioPs_Handler是函数指针

中断

处理器的速度跟外围硬件设备的速度往往不在一个数量级上,因此,如果内核采取让处理器向硬件发出一个请求,然后专门等待回应的办法,显然降低内核效率。

因此,由我们来提供一种机制,让硬件在需要的时候再向内核发出信号(变内核主动为硬件主动),这就是中断机制。

不同的设备对应的中断不同,而每个中断都通过一个惟一的数字标识。
如,来自键盘的中断就有别于来自硬盘的中断,从而使得操作系统能够对中断进行区分,并知道哪个硬件设备产生了哪个中断。这样,操作系统才能给不同的中断提供不同的中断处理程序。

在它执行程序的时候,如果有另外的事件发生(比如用户又打开了一个程序)那么这时候就需要由计算机系统的中断机制来处理了。

中断机制包括硬件的中断装置和操作系统的中断处理服务程序

让硬件在需要的时候再向内核发出信号。

早期的微机系统中将由硬件产生的中断标识码(中断源的识别标志,可用来形成相应的中断服务程序的入口地址或存放中断服务程序的首地址)称为中断向量,中断的地址的变量

中断向量表:中断类型号与相应中断源的中断处理程序入口地址之间的连接表;

_vector_table:
	B	_boot
	B	Undefined
	B	SVCHandler
	B	PrefetchAbortHandler
	B	DataAbortHandler
	NOP	/* Placeholder for address exception vector*/
	B	IRQHandler
	B	FIQHandler

中断服务程序:发送中断时所执行的中断代码

汇编

IRQHandler:					/* IRQ vector handler */

	stmdb	sp!,{r0-r3,r12,lr}		/* state save from compiled code*/
#if FPU_HARD_FLOAT_ABI_ENABLED
	vpush {d0-d7}
	vpush {d16-d31}
	vmrs r1, FPSCR
	push {r1}
	vmrs r1, FPEXC
	push {r1}
#endif

#ifdef PROFILING
	ldr	r2, =prof_pc
	subs	r3, lr, #0
	str	r3, [r2]
#endif

	bl	IRQInterrupt			/* IRQ vector */

C

/*****************************************************************************/
/**
*
* This is the C level wrapper for the IRQ interrupt called from the vectors.s
* file.
*
* @param	None.
*
* @return	None.
*
* @note		None.
*
******************************************************************************/
void IRQInterrupt(void)
{
	XExc_VectorTable[XIL_EXCEPTION_ID_IRQ_INT].Handler(XExc_VectorTable[
					XIL_EXCEPTION_ID_IRQ_INT].Data);
}

#if !defined (__aarch64__)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ref
https://blog.csdn.net/qq_18077275/article/details/89304215?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

zynq 中断

来源分成三大类SPI,PPI,SGI总共96个ID号的中断

中断运行经过了多个 interrupt hander中断处理程序,有以下步骤

  • STEP 1,首先要中断向量要转跳到IRQ的服务程序。对应一下函数

  • STEP 2, 有几十方式可以产生IRQ (ID号96个),所以我们要知道具体是哪个发生了中断号发生了IRQ中断。找到后对应调用相应的处理程序。

  • STEP 3,找到具体是哪个ID号的中断,下面步骤就是要对应再处理,可能要进行再细分
    (比如要118个GPIO可以产生52号中断要判断出具体哪一位)。以及进行其他相应处理。

发布了452 篇原创文章 · 获赞 271 · 访问量 73万+

猜你喜欢

转载自blog.csdn.net/qq_35608277/article/details/105073908