IT教程 ·

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试

用Docker部署自己的JupyterHub

一、媒介

Xlinx的ZYNQ系列SOC集成了APU、种种专用外设资本和传统的FPGA逻辑,为ARM+FPGA的运用供应助力,下降功耗和硬件设想难度的同时极大进步二者间传输的带宽。之前在研究生课题中运用过ZYNQ搭建环路体系对算法进行板级考证,但并没有深切运用和明白这个异构平台,本日算是对入门的总结。一款SOC的入门必定是GPIO的运用,而中断则是MCU能保证及时性的必杀兵器。硬件调试难度高一直是FPGA的痛点,集成ARM的FPGA更是如此,cross-trigger调试有效地处置惩罚了这一问题,所以它也作为入门ZYNQ的必要妙技。

二、硬件体系搭建

 ZYNQ的三种GPIO离别是MIO、EMIO和AXI-GPIO。PS部份直接衔接到芯片引脚的IO叫MIO,经由FPGA再衔接到引脚的是EMIO。EMIO能够经由过程硬件束缚指定差别的端口号和电压规范,进步了ARM IO的灵活性。而AXI-GPIO相称因而对ARM IO的补充,经由过程挪用AXI-GPIO IP核与外部通讯。以下经由过程一个实例来申明三种IO的运用体式格局。

体系功用:运用一个MIO使衔接其上的LED闪灼,运用8个EMIO一样与LED衔接组成流水灯结果,别的再挪用一个5bit位宽的AXI-GPIO IP核以终端形式响应电路板上5个按键。

平台:米联客 MIZ702N (ZYNQ-7020)

   设置ZYNQ IP,使能MIO和EMIO,设置EMIO位宽是8bit。

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第1张

使能Cross Trigger和同享中断。ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第2张

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第3张

以后增加AXI-GPIO IP Core,设置位宽并使能个中断功用:

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第4张

运转Run Automatic Connection终究block design体系构造:

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第5张

 

 这里运用ILA抓取AXI-GPIO的中断信号。

三、软件编程与AXI-GPIO中断形式剖析

Implementation,export hardware with bitstream, launch SDK. BSP中自带了硬件体系所运用到的IP的一些示例代码和文档,为入门供应了很好的协助。ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第6张

为了轻易复用,对Xilinx供应的API做进一步封装,生成gpiops.h gpiops.c gpio.h gpio.c和gic.h文件。接下来重点报告GIC相干的代码道理。若要运用中断体系,起首要初始化GIC,和其他IP一样包含查找设置和初始赋值两个步骤,离别由LookupConfig和CfgInitialize两个函数完成。后者实际上初始化了中断处置惩罚句柄使其指向了一个空构造。要明白内部道理,须要弄清楚XScuGic的数据构造。

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第7张

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第8张

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第9张

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第10张

个中Handler实际上是一个函数指针范例,用于定义中断发作时的回调函数。而CallBackRef用于传入InstancePtr,即Gic Instance Pointer。GIC初始化完,要将GIC与中断ID和自定义中断回调函数绑定。

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第11张

内部的中心代码依旧和初始化时一致,只不过换成了输入参数:

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第12张

下一步该使能中断了,一方面是运用GIC对GPIO中断ID的响应,另一方面是使能AXI-GPIO的中断信号。末了是体系对非常的处置惩罚函数,这里将其封装在exception_enable中:

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第13张

总结来看,中断体系竖立的步骤为:

1 初始化GIC

2 衔接GIC与中断ID和回调函数

3 使能中断

4 使能非常处置惩罚

  那末为何完成上述操纵后,中断事宜发作会马上实行自定义中断回调函数GpioHandler呢?CPU会将中断向量表存储在特定的寄存器中,读取该寄存器能够猎取中断向量表内容,里边存放着各个中断ID对应的中断函数进口地点。跳转指令则有中断掌握器完成。

接下来是各个文件的软件代码:

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第14张

  1 /*
  2  * main.c
  3  *
  4  *  Created on: 2020年2月22日
  5  *      Author: s
  6  */
  7 
  8 
  9 #include "xparameters.h"
 10 
 11 #include "xstatus.h"
 12 #include <xil_printf.h>
 13 #include "sleep.h"
 14 
 15 #include "gpiops.h"
 16 #include "gpio.h"
 17 #include "gic.h"
 18 
 19 
 20 XGpioPs GpioPs;    /* The driver instance for GPIO Device. */
 21 XGpio Gpio;
 22 XScuGic Intc; /* The Instance of the Interrupt Controller Driver */
 23 
 24 
 25 #define printf            xil_printf    /* Smalller foot-print printf */
 26 
 27 #define LOOP_NUM 8
 28 
 29 
 30 
 31 
 32 static u32 MIO_OUT_PIN_INDEX =7; /* LED button */
 33 static u32 EMIO_OUT_PIN_BASE_INDEX = 54;
 34 volatile u32 IntrFlag; /* Interrupt Handler Flag */
 35 
 36 void GpioHandler(void *CallbackRef);
 37 int setupIntSystem(XScuGic *IntcInstancePtr,XGpio *gpioInstancePtr
 38         ,u32 IntrId);
 39 
 40 int main()
 41 {
 42     int Status;
 43     u8 i=0;
 44     u32 sys_led_out=0x1;
 45 
 46     Status = gpiops_initialize(&GpioPs,GPIOPS_DEVICE_ID);
 47     if (Status != XST_SUCCESS) {
 48         return XST_FAILURE;
 49     }
 50 
 51     Status = gpio_initialize(&Gpio,GPIO_DEVICE_ID);
 52     if (Status != XST_SUCCESS) {
 53         return XST_FAILURE;
 54     }
 55 
 56 
 57     /*
 58      * Set the direction for the pin to be output and
 59     * Enable the Output enable for the LED Pin.
 60      */
 61     gpiops_setOutput(&GpioPs,MIO_OUT_PIN_INDEX);
 62 
 63     for(i=0;i<LOOP_NUM;i++){
 64         gpiops_setOutput(&GpioPs,EMIO_OUT_PIN_BASE_INDEX+i);
 65     }
 66 
 67     gpio_setDirect(&Gpio, 1,GPIO_CHANNEL1);
 68 
 69     Status = setupIntSystem(&Intc,&Gpio,INTC_GPIO_INTERRUPT_ID);
 70     if (Status != XST_SUCCESS) {
 71             return XST_FAILURE;
 72         }
 73 
 74     printf("Initialization finish.n");
 75 
 76     while(1){
 77 
 78         for(i=0;i<LOOP_NUM;i++){
 79             /* Set the GPIO output to be low. */
 80             gpiops_outputValue(&GpioPs, EMIO_OUT_PIN_BASE_INDEX+i, 0x1);
 81             usleep(200*1000);
 82             gpiops_outputValue(&GpioPs, EMIO_OUT_PIN_BASE_INDEX+i, 0x0);
 83         }
 84 
 85         gpiops_outputValue(&GpioPs, MIO_OUT_PIN_INDEX, sys_led_out);
 86         sys_led_out  = sys_led_out == 0x0 ? 0x1 : 0x0;
 87     }
 88     return 0;
 89 }
 90 
 91 int setupIntSystem(XScuGic *IntcInstancePtr,XGpio *gpioInstancePtr
 92         ,u32 IntrId)
 93 {
 94     int Result;
 95     /*
 96     * Initialize the interrupt controller driver so that it is ready to
 97     * use.
 98     */
 99 
100     Result = gic_initialize(&Intc,INTC_DEVICE_ID);
101     if (Result != XST_SUCCESS) {
102             return XST_FAILURE;
103         }
104 
105     XScuGic_SetPriorityTriggerType(IntcInstancePtr, IntrId,
106                         0xA0, 0x3);
107 
108     /*
109     * Connect the interrupt handler that will be called when an
110      * interrupt occurs for the device.
111      */
112     Result = XScuGic_Connect(IntcInstancePtr, IntrId,
113                 (Xil_ExceptionHandler)GpioHandler, gpioInstancePtr);
114     if (Result != XST_SUCCESS) {
115         return Result;
116     }
117 
118     /* Enable the interrupt for the GPIO device.*/
119     XScuGic_Enable(IntcInstancePtr, IntrId);
120 
121     /*
122      * Enable the GPIO channel interrupts so that push button can be
123     * detected and enable interrupts for the GPIO device
124     */
125     XGpio_InterruptEnable(gpioInstancePtr,GPIO_CHANNEL1);
126     XGpio_InterruptGlobalEnable(gpioInstancePtr);
127 
128     /*
129     * Initialize the exception table and register the interrupt
130     * controller handler with the exception table
131     */
132     exception_enable(&Intc);
133 
134     IntrFlag = 0;
135 
136     return XST_SUCCESS;
137 }
138 
139 void GpioHandler(void *CallbackRef)
140 {
141     XGpio *GpioPtr = (XGpio *)CallbackRef;
142     u32 gpio_inputValue;
143 
144 
145     /* Clear the Interrupt */
146     XGpio_InterruptClear(GpioPtr, GPIO_CHANNEL1);
147     printf("Input interrupt routine.n");
148 
149     //IntrFlag = 1;
150     gpio_inputValue = gpio_readValue(GpioPtr, 1);
151     switch(gpio_inputValue)
152     {
153     case 30:
154         printf("button upn");
155         break;
156     case 29:
157         printf("button centern");
158         break;
159     case 27:
160         printf("button leftn");
161         break;
162     case 23:
163         printf("button rightn");
164         break;
165     case 15:
166         print("button downn");
167         break;
168     }
169 
170 }

main.c
ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第14张

 1 /*
 2  * gpio.h
 3  *
 4  *  Created on: 2020年2月23日
 5  *      Author: s
 6  */
 7 
 8 #ifndef SRC_GPIO_H_
 9 #define SRC_GPIO_H_
10 
11 #include "xgpio.h"
12 
13 #define GPIO_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
14 #define INTC_GPIO_INTERRUPT_ID    XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR
15 #define GPIO_CHANNEL1        0x1F
16 
17 int gpio_initialize(XGpio * InstancePtr, u16 DeviceId);
18 void gpio_setDirect(XGpio *InstancePtr, unsigned Channel,
19         u32 DirectionMask);
20 void gpio_outputValue(XGpio * InstancePtr, unsigned Channel, u32 Data);
21 u32 gpio_readValue(XGpio * InstancePtr, unsigned Channel);
22 #endif /* SRC_GPIO_H_ */

gpio.h
ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第14张

/*
 * gpio.c
 *
 *  Created on: 2020年2月23日
 *      Author: s
 */


#include "gpio.h"

int gpio_initialize(XGpio * InstancePtr, u16 DeviceId)
{
    return XGpio_Initialize(InstancePtr,DeviceId);
}

void gpio_setDirect(XGpio *InstancePtr, unsigned Channel,
        u32 DirectionMask)
{
    XGpio_SetDataDirection(InstancePtr, Channel,
                     DirectionMask);
}

void gpio_outputValue(XGpio * InstancePtr, unsigned Channel, u32 Data)
{
    XGpio_DiscreteWrite(InstancePtr, Channel, Data);
}

u32 gpio_readValue(XGpio * InstancePtr, unsigned Channel)
{
    return XGpio_DiscreteRead(InstancePtr, Channel);
}

gpio.c
ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第14张

 1 /*
 2  * gpiops.c
 3  *
 4  *  Created on: 2020年2月23日
 5  *      Author: s
 6  */
 7 
 8 #include "gpiops.h"
 9 
10 int gpiops_initialize(XGpioPs *InstancePtr,u16 DeviceId)
11 {
12     XGpioPs_Config *ConfigPtr;
13 
14     ConfigPtr = XGpioPs_LookupConfig(DeviceId);
15     return XGpioPs_CfgInitialize(InstancePtr, ConfigPtr,
16                     ConfigPtr->BaseAddr);
17 }
18 
19 void gpiops_setOutput (XGpioPs *InstancePtr,u32 Pin)
20 {
21     XGpioPs_SetDirectionPin(InstancePtr, Pin, 1);
22     XGpioPs_SetOutputEnablePin(InstancePtr, Pin, 1);
23 }
24 
25 void gpiops_setInput(XGpioPs *InstancePtr,u32 Pin)
26 {
27     XGpioPs_SetDirectionPin(InstancePtr, Pin, 0);
28 }
29 
30 void gpiops_outputValue(XGpioPs *InstancePtr,u32 Pin,u32 Data)
31 {
32     XGpioPs_WritePin(InstancePtr, Pin, Data);
33 }
34 
35 
36 u32 gpiops_readValue(XGpioPs *InstancePtr,u32 Pin)
37 {
38     /* Read the state of the data so that it can be  verified. */
39     return XGpioPs_ReadPin(InstancePtr, Pin);
40 }

gpiops.c
ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第14张

 1 /*
 2  * gpio.h
 3  *
 4  *  Created on: 2020年2月23日
 5  *      Author: s
 6  */
 7 
 8 #ifndef SRC_GPIOPS_H_
 9 #define SRC_GPIOPS_H_
10 
11 #include "xgpiops.h"
12 
13 #define GPIOPS_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
14 
15 
16 
17 int gpiops_initialize(XGpioPs *InstancePtr,u16 DeviceId);
18 void gpiops_setOutput (XGpioPs *InstancePtr,u32 Pin);
19 void gpiops_setInput(XGpioPs *InstancePtr,u32 Pin);
20 void gpiops_outputValue(XGpioPs *InstancePtr,u32 Pin,u32 Data);
21 u32 gpiops_readValue(XGpioPs *InstancePtr,u32 Pin);
22 
23 
24 #endif /* SRC_GPIOPS_H_ */

gpiops.h
ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第14张

 1 /*
 2  * gic.h
 3  *
 4  *  Created on: 2020年2月23日
 5  *      Author: s
 6  */
 7 
 8 #ifndef SRC_GIC_H_
 9 #define SRC_GIC_H_
10 
11 #include "xscugic.h"
12 
13 #define INTC_DEVICE_ID    XPAR_SCUGIC_SINGLE_DEVICE_ID
14 
15 s32 gic_initialize(XScuGic *InstancePtr,u16 DeviceId)
16 {
17     XScuGic_Config *IntcConfig;
18 
19     IntcConfig = XScuGic_LookupConfig(DeviceId);
20     if (NULL == IntcConfig) {
21         return XST_FAILURE;
22     }
23 
24     return XScuGic_CfgInitialize(InstancePtr, IntcConfig,
25                         IntcConfig->CpuBaseAddress);
26 }
27 
28 void exception_enable(void *Data)
29 {
30     Xil_ExceptionInit();
31     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
32             (Xil_ExceptionHandler)XScuGic_InterruptHandler, Data);
33 
34     /* Enable non-critical exceptions */
35     Xil_ExceptionEnable();
36 }
37 
38 
39 #endif /* SRC_GIC_H_ */

gic.h

四、交织触发调试

   右键工程文件夹->Run As/Debug As离别用于代码下载和调试。SDK基于GDB供应了壮大的调试才能,支撑断点运转,可检察内部寄存器、地点数值以及汇编代码等。Debug As ->Debug Configuartion,双击System Debugger新建ELF文件。勾选Reset entire system和Program FPGA,由于ELF只是软件,硬件信息存储在bitstream中。最主要的是勾选enable cross-triggering。

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第26张

点击enable cross-triggering右边的按钮,根据以下操纵使能Processor to Fabric Trigger.

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第27张

再次create使能Fabric to Processor Trigger:

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第28张

末了点击Debug下载软硬件代码并进入调试界面。

  1 起首尝试PS触发PL调试:

  指定中断回调函数肇端位置一个断点。然后进入VIVADO,翻开Hardware Manager衔接硬件。注重此时触发形式挑选IN_ONLY。此时不必设置ILA抓取信号的触发前提,由于触发由PS端的PC掌握。点击Run Trigger守候触发前提。这时候回到SDK点击Resume按钮使代码入手下手运转。按下恣意按键发作中断,此时软件代码运转到断点处住手,ILA随即抓取中断信号。

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第29张

2 尝试PL触发PS调试:

   这回在VIVADO中设置触发形式为OR_TRIG_IN,并启动触发前提为上升沿触发。按下按键,C运转到满足ILA触发前提时C代码马上住手,故PL掌握了PS端的程序运转。

ZYNQ入门实例——三种GPIO运用、中断体系及软硬件交织触发调试 IT教程 第30张

能够看到此时程序进入IRQHandler。

 串口终端也打印进入中断函数的信息,准确响应中断。到此示例完毕。本文虽是对ZYNQ入门的整顿,但涉及到的东西许多,包含GPIO运用、中断体系竖立和响应机制、挪用AXI总线IP核、软件设想以及软硬件交织触发调试流程。

PBFT 算法 java实现(下)

参与评论