米联客 ZYNQ/SOC精品教程 S02-CH04 PS MIO 实验

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

4.1 概述

        本课对ZYNQ芯片的GPIO进行介绍,通过设计PS端点亮LED的功能,讲解了PS端MIO使用方法。

4.2 GPIO简介

       Zynq7000系列芯片有54个MIO(multiuse I/O),它们分配在 GPIO 的Bank0 和Bank1隶属于PS部分,这些IO与PS直接相连。不需要添加引脚约束,MIO信号对PL部分是透明的,不可见。所以对MIO的操作可以看作是纯PS的操作。

        GPIO的控制和状态寄存器基地址为:0xE000_A000,SDK软件底层操作是对于内存地址空间的操作。

1e9c5bb992a062495b341c9e3f70466e165.jpg

Bank0:MIO [31:0]  GPIO PIN脚号:0~31

Bank1:MIO[32:53]  GPIO PIN脚号:32~53

以上描述和我们原理图中和VIVADO  ZYNQ IP中定义的有冲突,这个留给大家去讨论,下图中,是ZYNQ IP部分MIO电压分配,从这个软件上看,BANK0 IO 是0~15,BANK1 IO是16~53,这个是奇怪的事情,笔者现在还没搞懂。实际应用以软件设定和原理图为准。

a92be5b4010ce58d3439992abfb403f6b93.jpg

Bank2:EMIO [31 : 0] GPIO PIN脚号:54~85

Bank3:EMIO [63:32] GPIO PIN脚号:86~ 117

4.2.1 GPIO的控制寄存器地址空间

SDK软件下的底层操作是对这些寄存器的操作,具体的相关参数请参考技术手册ug585-Zynq-7000-TRM.pdf

113d8e1a3074375adc08e11ccb1dd24a668.jpg

3429651e10238d32bc34ea1d1559585d9c1.jpg071baa84ce399457c4c0b5023beb0cb5cff.jpg

e49ccd6c6be2e2340d742ed66cc41358910.jpg

4.2.2 MIO内部构造分析

82d9a183eb6ca4ae33cda683f9c6e534e93.jpg

DATA_RO: 此寄存器使能软件观察PIN脚,当GPIO被配置成输出的时候,这个寄存器的值会反应输出的PIN脚情况。

DATA:此寄存器控制输出到GPIO的值,读这个寄存器的值可以读到最后一次写入该寄存器的值。  

MASK_DATA_LSW:位操作寄存器,写入GPIO 低16bit 其他没有改变的位置保存原先的状态

MASK_DATA_MSW:位操作寄存器,写入GPIO 高16bit 其他没有改变的位置保存原先的状态

DIRM:此寄存器控制输出的开关,当DIRM[x]==0时候,禁止输出

OEN: 输出使能,当OEN[x]==0 的时候输出关闭,PIN脚处于三态

因此,如果要读IO状态就得读DATA_RO的值,如果是对某一位进行操作就是写MASK_DATA_LSW/MASK_DATA_MSW

具体的相关参数请参考技术手册ug585-Zynq-7000-TRM.pdf

4.2.3 EMIO的特性

与MIO大部分类似但是一下几点需要注意下

• EMIO在PL部分,输入与OEN寄存器无关,当DIRM设置为0的时候设置为输入可以读DATA_RO寄存器获取数据。

• 输出不能设置成三态,当DIRM设置为1的时候为输出,写入DATA寄存器或者MASK_DATA_LSW/MASK_DATA_MSW寄存器

• EMIOGPIOTN[x]=DIRM[x] & OEN[x],实现输出的控制。

具体的相关参数请参考技术手册ug585-Zynq-7000-TRM.pdf

4.3 电路分析及实验预期

        开发板上有一个MIO是与开发板上的一个LD9相连的,这个MIO就是MIO7。实验通过操作该MIO来实现LD9的闪烁。

原理图

5848126691fd3f51e20404d4db08fbd87d1.jpg

4.4 搭建BD工程

Step1:新建一个名为为Miz_sys的工程。

Step2:创建一个BD文件,并命名为system,添加并且配置好ZYNQ IP。读者需要根据自己的硬件类型配置好输入时钟频率、内存型号、串口,连接时钟等。新手不清楚这些内容个,请参考“CH01 HelloWold/DDR/网口测试及固化”这一节课。

3fe8fed4635d94d3454c244ea5498d6dd21.jpg

Step3:ZYNQ IP MIO配置

MIO部分其他功能的配置可以参考参考“CH01 HelloWold/DDR/网口测试及固化”这一节课

d9217cec0b389d9a0a16fca1045efebed05.jpg

757a0a3c0b9b3ceca9e5659ead046250a2e.jpg

3d755ebd814302b043eca6023aa4b3f8e39.jpg

Step2:建立一个空的工程

56cdff4c239f4c6a8ac41e8ef2a0c2ff61b.jpg

Step3: 在我们提供例程的文件夹中找到main.c文件,并进行复制。

b97a6e6fc2aca5eb6e815dca8a4fe48b038.jpg

Step4: 点击MIO_Test旁边的箭头使其展开,然后选中src,按下Ctrl+V快捷键,粘贴main.c文件

e264957e975b7deebc5d905d4834a2166ab.jpg

Step5:右击工程,选择Debug as ->Debug configurations。

d34cd5d5e1c7adf52854d80515a3cb91578.jpg

Step6:选中system Debugger,双击创建一个系统调试,点击Apply,点击Debug。

ed56e48eab86a2b4dde2cf4886b12e7de80.jpg

Step7:单击窗口上的运行按钮,运行程序

4.7 测试结果

可看到核心板LD9闪烁

4.8 程序分析

接下来对程序进行分析。

分析1

语句:static XGpioPs psGpioInstancePtr;

含义:这是一个指针实例,指向添加的GPIO端口。

具体分析:

XGpiops:绿色标识的一个结构体。SDK中结构体都用绿色标识。

将鼠标停留在XGpiops上或右键Open Declaration,查看这个结构体所包含的内容。

a5cd16121d7a2e7c0840118e297bec55a5d.jpg

分析2

语句:XGpioPs_Config* GpioConfigPtr

含义:这是一个指针实例。

具体分析

XGpioPs_Config:绿色标识的一个结构体。

将鼠标停留在XGpiops上或右键Open Declaration,查看这个结构体所包含的内容。

77510a589e90456adafa9b7644af4a9f9ce.jpg

          此结构体存放的是GPIO的设备地址和基地址。

分析3

语句:int iPinNumber= 7;

含义:参数

具体分析:iPinNumber这个参数,是告知程序,操作的MIO是哪一个,因为我们要操作的是MIO7,所以这里所以这里的iPinNumber等于7。(在第三章EMIO中也使用了这个参数,具体请参看下一节内容,这里仅作铺垫)

分析4

语句GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);

          if(GpioConfigPtr == NULL)

              return XST_FAILURE;

含义:查找GPIO配置程序。此处用到xparameters.h中XPAR_PS7_GPIO_0_DEVICE_ID。这段话的整体意思为查找GPIO的配置,判断其是否为空,若为空则返回查找失败。

具体分析

6e0ab603d7d83e697efda7d572ce15961c7.jpg

52153d733780f90935dbb3e4418b49527ec.jpg

eb01b44c7c5ecdc8ebd3e4e7cc3c2912888.jpg

分析5

语句:

       xStatus=XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr);

       if(XST_SUCCESS != xStatus)

       print(" PS GPIO INIT FAILED \n\r");

含义: 完成gpio配置的初始化工作,如果初始化不成功,将通过串口打印出初始化失败的信息。

分析6

语句:XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumber,uPinDirection)

含义:指定pin脚的方向设置。

具体分析:

e816ba2c8c432b1c0ac0edc2d9830927846.jpg

程序完成指定pin脚的方向设置。程序首先读取bank号,对应的子程序:

        /* Get the Bank number and Pin number within the bank. */

            XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber);

将鼠标停留在XGpioPs_GetBankPin函数上,按F3查看下其功能。

2b4d8d5023d89d59b96ca0baf7db67a9173.jpg

       图中画红框部分为程序查找bank号对应代码。程序首先判断ZYNQ的类型,本课第一节GPIO简介介绍7010和7020有四个bank,因此当程序执行后,程序首先执行else部分的程序。此时看else部分程序。程序给出了四个bank的bank号的最大值,初始化bank号为0,while语句限制了bank的最大数量为4。然后用pin的序号从bank0到bank3逐个比对,若是此时pin的序号小于或等于当前bank的最大值,则可以判断出pin是属于这个bank的,跳出while语句,否则bank号进行自加操作直到得出符合的bank号。接下来if语句,判断bank号是否为bank0,若是则将PinNumber直接赋值,否则经过计算一段公式得出PinNumber。

接下来回到XGpioPs_SetDirectionPin函数分析其他的子程序。获取了bank号后,开始读取寄存器,程序如下:

              DirModeReg = XGpioPs_ReadReg(InstancePtr->GpioConfig.BaseAddr,

                          ((u32)(Bank) * XGPIOPS_REG_MASK_OFFSET) +

                                XGPIOPS_DIRM_OFFSET);

      这里重点观察第二个参数,这是一个任务寄存器偏移+DIRM_OFFSET的参数。此时打开xilinx的编程手册ug585-zynq-7000-TRM(接下来的内容中我们将将其简称为ug585),来具体看看这个参数含义。

      复制DIRM,在ug585中查找到这么一段话:

4252fc725fd3c92275f83963fa121ea7ff0.jpg

      此时得知这是一个方向寄存器,当它等于0的时候输出被禁止,只有输入进行,即此时为输入功能。等于1时做输出使用。在GPIO的通道示意图中也能发现有这个部分构成。

44f4b842c24317d90f759046f85053a0136.jpg

       回到XGpioPs_SetDirectionPin的分析,再得到了bank号与要写哪个寄存器的地址后,接下来的if else语句就是对这对pinbumer这一位单独做一些操作,最后把方向寄存器的值写入到读出的那个寄存器当中。

分析7

语句:XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumber,1);

含义:配置输出

分析8

语句:XGpioPs_WritePin(&psGpioInstancePtr, iPinNumber, 1)

含义:写数据到pin脚

具体分析:

XGpioPs_WritePin的参数分别为gpio的基地址、要操作的MIO号和写入的数据。定义如下:

abfd2e1bd3af899b2f525f3a303eff492d9.jpg

观察图中方框圈起来部分,此处观测到有两个陌生的偏移,此时可在ug585中查看其具体含义。

cb2a0f90dd8393157247808da99c17482bc.jpg

f754ce833b48dd5fe46d20d5b831a272900.jpg

       此时可以得知,语句是要写入数据的高16位偏移量和低16位偏移量。程序是通过判断PinNumber的值来决定寄存器偏移量是用高16位偏移量还是低16位偏移量。

       此时再看XGpioPs_WritePin函数的接下来的这段程序:

be3df1990d9d45a1059f50e7f216dac684f.jpg

       这段程序完成向指定MIO写入某个值的操作。分析这段程序,如果要向MIO7写入1,程序一开始已经把要写入的值赋值给了DataVar,此段程序又将DataVar与0x01与操作,操作后DataVar的值还是为1。

       接下来的value就是要写入寄存器的值。~ ((u32)1 << (u32)PinNumber):表示把PinNumber加上16(也就是把pinNumber移到高16位)赋值为1,然后再取反,执行完后这一段的值为~(80000)h,也就是(FFF7FFFF)h。

       ((DataVar << PinNumber) | 0xFFFF0000U):已经得到DataVar的值为1,因此这里的意思为把pinNumber位赋值为1,再与FFFF0000或操作,执行完这一段的值为(80)h | (FFFF0000)h,也就是(FFFF0080)h,整句执行完之后就是(FFF7FFF)h & (FFFF0080)h=(FFF70080)h。也就是此时Value的值为FFF70080。

       XGpioPs_WriteReg这个函数功能是往寄存器中写入数据。

c968137ed776d073b9414c3390e7b4fe494.jpg

从图上可知,第一个参数为设备的基地址 第二个参数为偏移量,此处为0,第三个参数为要写入寄存器的数据。另外程序还可直接使用寄存器函数对MIO进行操作,其用法参照之前的分析,寄存器函数操作如下所示:

XGpioPs_WriteReg(0xE000A000,0x00000000, 0xFF7FFFFF&0xFFFF0080);

usleep(500000); //延时

XGpioPs_WriteReg(0xE000A000,0x00000000, 0xFF7FFFFF&0xFFFF0000);

usleep(500000); //

按照之前讲解的方法,开发人员可自行对库函数进行学习分析。

转载于:https://my.oschina.net/msxbo/blog/3098330

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值