本节主要介绍了ZYNQ7020中的GPIO,并以按键电灯实例演示了GPIO之EMIO、中断、AXI的用法
ZYNQ与PYNQ的区别
- PYNQ是Xilinx的一个开源项目名称,ZYNQ是Xilinx的一个芯片系列。PYNQ-Z2平台用的芯片就是Xilinx的ZYNQ芯片。所以PYNQ的意思就是PYTHON Pruduct on ZYNQ
- PYNQ全称为Python Productivity for Zynq,即在Zynq全可编程ARM&FPGA融合处理架构的基础上,添加了对Python的支持
ZYNQ的基本组成
- Zynq-7000 SoC的主要组成部分:
- Processing System(PS):
- Application processor unit(APU)
- Memory interfaces
- I/O peripherals(IOP)
- Interconnect(通信互连)
- Programmable Logic(PL)
- Processing System(PS):
GPIO的简介
GPIO是一个外设,用来对器件的引脚作观测(input)以及控制(output)
MIO(Multisue I/O),将来自PS外设和静态存储器接口的访问多路复用到PS的引脚上,与外部器件访问
EMIO是PS和PL之间的一个接口,EMIO是扩展的MIO,当PS的引脚不够用时,可以通过EMIO来进行扩展,从而使用PL的引脚
GPIO可以独立且动态地编程,作为输入/输出以及中断模式
GPIO被分成了4个Bank,总共有118个pins
- Bank0的32位控制MIO引脚的[31:0]
- Bank1的22位控制MIO引脚的[53:32] (Bank1被限制为22位,是因为MIO总共只有54个pins)
- Bank2的32位控制EMIO信号的[31:0]
- Bank3的32位控制EMIO信号的[63:32]
软件通过一组存储映射的寄存器来控制GPIO,GPIO控制外设的本质都是读取寄存器
寄存器组(控制Bank0与Bank1):
- DATA_RO:用来反映器件引脚的状态
- DATA(32bit):在GPIO被配置成输出的时候,该寄存器可以控制输出的数值。如果用其来读取,只能读取到上一次的输入数据
- MASK_DATA_LSW:屏蔽DATA中低16位的某些位
- MASK_DATA_MSW:屏蔽DATA中高16位的某些位
- DIRM:Direction Mode,用于控制I/O引脚是作为输入还是输出。0:关闭输出驱动;1:使能输出驱动
- OEN:Output Enable,当I/O被配置成输出时,该寄存器用于打开/关闭输出使能
MIO[8:7]在系统复位过程中作为VMODE引脚(作为输入),用于配置MIO Bank的电压。复位结束后,MIO[8:7]只能作为输出引脚
GPIO之EMIO按键控制LED实验
1.Vivado配置
在hello world的实验基础上,添加EMIO的设置
给GPIO_0口添加引脚:单击GPIO_0,按快捷键ctrl+t即可实现
生成顶层文件
在IO引脚配置页面将EMIO链接到KEY和LED的端口
最后生成bit stream文件
在导出硬件时记得选上:
2.Vitis代码编写
1 |
|
3.实验结果
GPIO之EMIO中断按键控制LED实验
实验要求:按键按下LED亮,再按下LED熄灭
Vivado中的配置与EMIO按键控制LED实验一致
Vitis中代码的编写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
using namespace std;
/***********************参数声明**********************/
/*中断相关参数*/
XScuGic Intc;
/*普通GPIO相关参数*/
XGpioPs_Config * ConfigPtr;
XGpioPs Gpio;
/*其他过程变量*/
u32 key_press = 0;
u32 led_value = 0;
/***********************函数声明**********************/
/*中断相关函数*/
//配置中断函数
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,u16 GpioIntrId);
//中断服务函数
void IntrHandler();
/***********************主程序**********************/
int main(void)
{
//配置器件的ID,查找器件的配置信息
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
//初始化GPIO驱动
XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
//设置GPIO的方向(0:输入/1:输出)
XGpioPs_SetDirectionPin(&Gpio,EMIO54_KEY0, 0);
XGpioPs_SetDirectionPin(&Gpio,EMIO55_LED0, 1);
//设置输出使能(1:关闭/1:打开)
XGpioPs_SetOutputEnablePin(&Gpio, EMIO55_LED0, 1);
//设置中断系统
SetupInterruptSystem(&Intc, &Gpio,GPIO_INTERRUPT_ID);
while(1)
{
if(key_press)
{
led_value = ~led_value;
key_press = 0;
//清除之前的中断状态
XGpioPs_IntrClearPin(&Gpio, EMIO54_KEY0);
//将led_vaule的值写入LED
XGpioPs_WritePin(&Gpio, EMIO55_LED0, led_value);
//延时消抖200ms
usleep(200000);
//重新打开中断
XGpioPs_IntrEnablePin(&Gpio, EMIO54_KEY0);
}
}
return 0;
}
//配置中断
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpioPs *Gpio,u16 GpioIntrId)
{
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
//查找GIC器件配置信息,并进行初始化
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
//初始化ARM处理器异常句柄
Xil_ExceptionInit();
//来给IRQ异常注册处理程序
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
GicInstancePtr);
//使能处理器中断
Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
//关联中断处理函数
XScuGic_Connect(GicInstancePtr, GpioIntrId,
(Xil_ExceptionHandler)IntrHandler,
(void *)Gpio);
//设置引脚中断触发类型,下降沿触发
XGpioPs_SetIntrTypePin(Gpio, EMIO54_KEY0, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
//为GPIO器件使能中断
XScuGic_Enable(GicInstancePtr, GpioIntrId);
//打开中断使能信号
XGpioPs_IntrEnablePin(Gpio, EMIO54_KEY0);
}
//中断服务函数
void IntrHandler()
{
cout<<"Interrupt detected !\n"<<endl;
key_press = 1;
//关闭中断使能信号
XGpioPs_IntrDisablePin(&Gpio, EMIO54_KEY0);
}实验结果:虽然实现了按键控制LED的来回跳变,但总是在手松开时才开始跳变,原因依旧存疑
AXI_GPIO控制LED实验
- 实验要求:按键按下LED亮,再按下LED熄灭
1.AXI的简介
- AXI(高级可扩展接口)是一种高性能、低功耗的总线协议,用于在不同的硬件模块之间进行通信
- PS和PL之间的连接通常使用AXI接口,以实现数据传输和控制信号的交换。这种连接方式可以实现高速数据传输和灵活的系统集成,使得PS和PL之间可以进行有效的通信和协作
2.Vivado配置
选择axi gpio
用几个引脚GPIO width就选几个
zynq和EMIO实验那样配置好之后,再添加下面配置
选择自动连线时,gpio一定要选择custom
最终block设计如下:
引脚的配置如下:
3.Vitis代码编写
1 |
|
Reference
02.PYNQ入门_哔哩哔哩_bilibili(Jupyter notebook部分)
https://blog.csdn.net/www_haha__/category_12376091.html?spm=1001.2014.3001.5482(基于PYNQ-Z2学习的ZYNQ笔记)
vivado2020.1 vitis_vivado 2020 sdk_丁点的沙砾的博客-CSDN博客(用vitis实现hello word)
Vitis开发(一):Vivado启动vitis_vivado vitis_俩个圆的博客-CSDN博客(解决lanch vitis IDE报错的问题)