2 AXI-GPIO

前言

  • 主要记录的还是中断的使用,因为我认为中断在我后面的设计中将会发挥它的重要性,同时设计慢慢会倾向于PL端设计,使用的是AXI GPIO IP进行写一个小的demo,因为之前做了有将近几年记得FPGA设计(如果本科瞎搞的也算的话,吹个牛:本科的fpga实验课每次都是第一个提前下课的),

PL 对 PS中断

在这里插入图片描述

IRQ NAMEIRQ NumberBitsRequired TypeDescription
PL_PS_Group0121:1287,8rising edge/high levelPL to PS interrupt signals 0 to 7.(3)
PL_PS_Group1136:1438rising edge/high levelPL to PS interrupt signals 8 to 15.(3)
  • ZCU106开发版对应的SOC支持两组PL to PS中断(共16个中断)
    • group0: 中断号为121–128,8个中断
    • group1: 中断号为136–143,8个中断

如何使用

  • 如果使能了IRQ0:第一组PL to PS中断
    • PL端对PS端产生多个中断,默认从ID 121开始分配
    • 第一个中断的ID:121
    • 第一个中断的ID:122
    • …累加但第一组最大ID不超过128
  • 记录使用过一个中断的过程

设计流程

在这里插入图片描述

最后结果

  • zcu106开发版,sw15 pushbutton每按下一次,打印一次结果,LED也变换状态
    在这里插入图片描述

设计流程

BD设计

在这里插入图片描述

  • pl_ps_irq 的位宽是自动拓展的,可以单击以下 Validate Design 就会自动拓展。
  • 因为要对引脚进行约束,需要将GPIO和GPIO2端口导出
引脚约束

参考手册UG244,在这边日记中也有说明1 使用EMIO

set_property PACKAGE_PIN AL11 [get_ports LED_tri_io]
set_property PACKAGE_PIN AL10 [get_ports BUTTON_tri_io]

set_property IOSTANDARD LVCMOS18 [get_ports LED_tri_io]
set_property IOSTANDARD LVCMOS18 [get_ports BUTTON_tri_io]


# bit compress
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]

SDK 设计

初始
#include "xparameters.h"
#include "xgpio.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "xil_printf.h"
#include "sleep.h"

#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID            // define the General interrupt controller device ID
#define GPIO_DEVICE_ID		XPAR_AXI_GPIO_0_DEVICE_ID               // define the PL Slide GPIO device ID
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_GPIO_0_VEC_ID            // define the AXI GPIO interrupt ID

#define printf xil_printf

/* 对应的AXI GPIO 两个通道*/
#define LED_CHANNEL 1
#define BUTTON_CHANNEL 2

XGpio Gpio; // The instance of the GPIO Driver
XScuGic Intc; // The instance of the Interrupt Controller Driver
主函数
int main()
{
    int Status;
    Status = InitAxiGpio(&Gpio, GPIO_DEVICE_ID);  /* 初始化AXI GPIO */
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

    Status = InitIntrp(&Intc, &Gpio, INTC_DEVICE_ID, INTC_GPIO_INTERRUPT_ID);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
    return XST_SUCCESS;
}
AXI-GPIO初始化
  • AXI-GPIO属于PL端资源,使用的是XGpio函数
int InitAxiGpio(XGpio *GpioInstancePtr, u16 GpioDeviceId)
{
    int Status;
    Status = XGpio_Initialize(GpioInstancePtr, GPIO_DEVICE_ID);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
	/* Set channle 1 as led output */
    XGpio_SetDataDirection(GpioInstancePtr, LED_CHANNEL, 0x0); // Set the LED channel tristate buffer to be output
    XGpio_DiscreteWrite(GpioInstancePtr, LED_CHANNEL, 0x0); // Turn off the LEDs

	/* Set cahnnle 2 as button input and intr*/
    XGpio_SetDataDirection(GpioInstancePtr, BUTTON_CHANNEL, 0x1); // Set the push button channel tristate buffer to be input
    XGpio_InterruptEnable(GpioInstancePtr, BUTTON_CHANNEL); // Enable the interrupt for the push buttons
    XGpio_InterruptGlobalEnable(GpioInstancePtr); // Enable global interrupt

    return XST_SUCCESS;
}
中断初始化
  • 初始化中断
  • 初始化并注册中断异常
  • 建立中断
int InitIntrp(XScuGic *IntcInstancePtr, XGpio *GpioInstancePtr, u16 IntcDeviceId, u16 IntrId)
{
    int Status;
    XScuGic_Config *IntcConfig;

    IntcConfig = XScuGic_LookupConfig(IntcDeviceId);
    if (NULL == IntcConfig)
    {
        return XST_FAILURE;
    }

    Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }
	/* 初始化并注册中断异常 */
    Xil_ExceptionInit();
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstancePtr);
    Xil_ExceptionEnable();

	/* 设置中断优先级和中断触发方式 */
    XScuGic_SetPriorityTriggerType(IntcInstancePtr, IntrId, 0x10, 0x3);
	/* 建立中断 */
    Status = XScuGic_Connect(IntcInstancePtr, IntrId, (Xil_ExceptionHandler)IntrHandler, (void *)GpioInstancePtr);
    if (Status != XST_SUCCESS)
    {
        return XST_FAILURE;
    }

    XScuGic_Enable(IntcInstancePtr, IntrId);

    return XST_SUCCESS;
}

void IntrHandler(void *CallBackRef)
{
    XGpio *GpioInstancePtr = (XGpio *)CallBackRef;

    // Clear the interrupt status to allow future interrupts
    XGpio_InterruptClear(GpioInstancePtr, BUTTON_CHANNEL);

    // 去抖
    usleep(20000); 

    if (XGpio_DiscreteRead(GpioInstancePtr, BUTTON_CHANNEL) & 0x1)
    {
        led_status = ~led_status;
        XGpio_DiscreteWrite(GpioInstancePtr, LED_CHANNEL, led_status);
        printf("Button pressed, LED status: %d\r\n", led_status);
    }

    // Re-enable the interrupt
    XGpio_InterruptEnable(GpioInstancePtr, BUTTON_CHANNEL);
}
相关解释
  • 关与XScuGic_SetPriorityTriggerType()函数

    XScuGic_SetPriorityTriggerType(IntcInstancePtr, IntrId, 0x10, 0x3);
    
    • 第一个参数:中断实例化指针
    • 第二个参数:中断ID, 这里就是PL_KEY_INTR对应的宏定义ID号就是121
    • 第三个参数:中断优先级,只能值8的整数倍,越小优先级越高
    • 第三个参数:中断触发类型
      • 0x01: 高电平触发
      • 0x11: 上升沿触发
  • 关于关于XScuGic_Connect函数

    XScuGic_Connect(IntcInstancePtr, IntrId, (Xil_ExceptionHandler)IntrHandler, (void *)GpioInstancePtr);
    
    • 第一个参数:中断实例化指针
    • 第二个参数:中断ID, 这里就是PL_KEY_INTR对应的宏定义ID号就是121
    • 第三个参数:中断回调函数,这里的函数名就是IntrHandler,(Xil_InterruptHandler)是一个指针类型进行类型转换
    • 第三个参数:中断回调参考实例,可以是中断实例化指针,但一般是需要中断回调函数中使用的实例化指针
  • 关于回调函数IntrHandler

    
    void IntrHandler(void *CallBackRef)
    {
        XGpio *GpioInstancePtr = (XGpio *)CallBackRef;
    
        // Clear the interrupt status to allow future interrupts
        XGpio_InterruptClear(GpioInstancePtr, BUTTON_CHANNEL);
    
        // 去抖
        usleep(20000); 
    
        if (XGpio_DiscreteRead(GpioInstancePtr, BUTTON_CHANNEL) & 0x1)
        {
            led_status = ~led_status;
            XGpio_DiscreteWrite(GpioInstancePtr, LED_CHANNEL, led_status);
            printf("Button pressed, LED status: %d\r\n", led_status);
        }
    
        // Re-enable the interrupt
        XGpio_InterruptEnable(GpioInstancePtr, BUTTON_CHANNEL);
    }
    
    • 清除中断
    • 执行处理函数
      • 写LED通道控制LED状态
    • 使能中断
  • 关于异常

Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstancePtr);
Xil_ExceptionEnable();
  • ARM 处理器支持 7种异常情况:复位、未定义指令、软件中断、指令预取中止、数据中止、中断请求(IRQ)和快速中断请求(FIQ)。

  • ARM 处理器支持的每种异常也都有自己的 ID 标识,其中 XIL_EXCEPTION_ID_INT 用于标识中断请求(IRQ)异常。

  • 通 过 调 用 函 数 Xil_ExceptionRegisterHandler( )来给 IRQ 异常注册处理程序,它会将中断控制器 GIC 的中断处理程序与 ARM 处理器中的硬件中断处理逻辑连接起来。

    • XIL_EXCEPTION_ID_INT:异常中断ID,系统给出
    • XScuGic_InterruptHandler:要注册的异常处理函数
    • IntcInstancePtr : 中断实例化指针- 另外还要通过 Xil_ExceptionEnable()函数使能 IRQ 异常。
  • 使能异常中断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都不会的研究昇

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值