本文包含了Vitis使用LED灯示例笔记,FPGA端参考官方例程
7020板子的DDR3 MT41J256M16 RE-125
其中256M是,16指数据位宽,板子由2个16位DDR3拼成。
256162=8192Mbit = 8Gbit
所以选择的Effective DRAM Bus With是32bit
7010板子 MT41J128M16 HA125
I/O口是PS内部的输入输出口,通过MIO与PL侧进行连接,MIO有54个,
一个功能比如UART0有多组MIO接口可选,通过原理图确定选择那一组接口。
也可以在MIO Configuration中的I/O配置。
同样在MIO Configuration中的I/O中,根据原理图,配置Bank0和Bank1的电平值。
DDR与UART接口属于模块DDR和FIXED_IO接口
1.PS-PL 中GP Master AXI Interface 中 GP Master AXI Interface 中 M AXI GP0 interface
2.Clock 配置中 可以根据原理图更改Processor/Memory Clocks中CPU 和DDR 的时钟频率
去掉PL Fabric Clocks 中 FCLK_CLK0。这是PS提供给PL的时钟接口。
3.PL-PS配置中,General中 Enable Clock Reset中 FCLK_RESETT0_N,这是PS提供给PL的复位接口。
Run Block Automation,出现了端口引脚。
PS配置结束。选择对勾Validate,自动进行验证是否配置正确。
在DesignSource 中对bd文件右击,选择Generate Output Product,
对bd文件右键,选择create HDL warpper,选择默认的Let vivado manage…当底层改变时,顶层文件自动更新。
理解:
BD文件generate output product用于生成bd下一层的顶层(里面包含了你调用的所有核)
create HDL warpper用于生成bd上一层的顶层(让这个bd可综合)弄好后,先generate output products,大概意思就是根据BD文件输出生成一个产品,然后create HDL wrapper,意思就是将刚才生成的产品生成一个硬件封装。
生成了warpper文件,用verilog语言编写的,这就是顶层的封装文件。
通用I/O (GPIO)外围设备通过MIO模块提供多达54个设备引脚的观察和控制软件。它还提供来自可编程逻辑(PL)的64个输入和通过EMIO接口到PL的128个输出。
GPIO被组织成四组寄存器,用来分组相关的接口信号。
每个GPIO都被独立地动态编程为输入、输出或中断感知
(7000系列中,banks 500 and banks 501 contains the PS MIO pins
bank 502 contains the PS DDR pins.)
MIO实现了多路复用的功能。EMIO是连接到PL的拓展。
GPIO分为四个bank,四组。前两组通过MIO连接至PS的54个引脚(32pin+22pin),后两组EMIO。
GPIO由软件通过一系列内存映射寄存器来控制。每个bank的控制都是相同的
寄存器组:
DATA_RO:起到观测功能,外部器件引脚的电平通过MIO读入了进来。DATA_RO寄存器总是返回GPIO引脚的状态,而不管GPIO是设置为输入还是输出
如果MIO没有配置为使该引脚成为GPIO引脚,(就是指没有连接GPIO引脚,可能连了USB引脚)那么DATA_RO不再是观测功能的,因为软件不能通过GPIO寄存器观察非GPIO引脚上的值
DATA:(可以控制外设的LED灯)当GPIO信号被配置为输出时,这个寄存器控制要输出的值。这个寄存器的所有32位都是一次写入的。从这个寄存器读取将返回之前写入DATA或MASK_DATA_{LSW,MSW}的值;它不返回设备引脚上的当前值。
MASK_DATA_LSW:灵活的改变DATA数据中的某些位,使用一种掩码的方式。该寄存器支持对所需输出值进行更有选择性的更改。
可以写入最多16位的任何组合。那些没有被写入的比特是不变的,并保持它们之前的值
MASK_DATA_LSW:用于屏蔽DATA的低16位,MASK_DATA_MSW用于屏蔽DATA的高16位
DIRM:方向模式,控制I/O引脚是作为输入还是输出,0为关闭输出驱动,1打开输出驱动。
OEN:输出使能,当I/O被配置为输出时,它将控制是否启用输出,0关闭输出使能,1打开输出使能。
由原理图可知,DIRM和OEN经过与门,就是说都是1,才表示打开输出。
Bank0, Bits[8:7] are Outputs:
(这两个信号MIO7,8在系统复位过程中,作为VMODE引脚,用于配置MIO bank的电压,复位结束后,只作为输出引脚)
GPIO分成了4个bank,MIO也进行了分组,bank0为MIO[0:15],bank1为MIO[16:53]
所以这里GPIO的bank0的bits[7:8]等同与MIO的bank0的bits[7:8]???
MIO的bank0 bank1的电压分别由MIO[7] MIO[8]控制,在7010中对应bank500,bank501
Example: Configure MIO pin 10 as an output
打开.c文件,This file contains an example for using GPIO hardware and driver
这是一个关于gpio如何使用的示例
进入main函数,查看第一个函数,跳转到第一个函数,一般会跳出main,顺序来到第一个自定义函数
GpioPolledExample(GPIO_DEVICE_ID, &InputData)
->int GpioPolledExample(u16 DeviceId, u32 *DataRead)
这个代表了一个gpio示例,现在查看该函数内部。
ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
根据器件ID,查找器件配置信息的函数,进入内部
XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
…
return (XGpioPs_Config *)CfgPtr;
返回值是一个指针类型,所以查看到示例程序中,对ConfigPtr 有如下定义
XGpioPs_Config *ConfigPtr
接着一步一步寻找示例中传入的参数GPIO_DEVICE_ID
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
跳转到了一个xparameters.h头文件
#define XPAR_XGPIOPS_0_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID
/* Definitions for peripheral PS7_GPIO_0 /选择gpio_0
#define XPAR_PS7_GPIO_0_DEVICE_ID 0
/ Definitions for driver GPIOPS */定义gpio个数
#define XPAR_XGPIOPS_NUM_INSTANCES 1
所以示例文件引用了头文件 #include “xparameters.h”
示例文件下一个函数
Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
This function initializes a XGpioPs instance/driver,初始化GPIO的驱动
进入函数内部,跳转至xgpiops.c文件
s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, const XGpioPs_Config
*ConfigPtr, u32 EffectiveAddr)
返回值类型用来判断是否成功,忽略。
查看传入参数类型
@param InstancePtr is a pointer to the XGpioPs instance.
第一个参数是一个指针,指向XGpioPs,这是一个gpio实例,
xgpiops.h文件包含了这个自定义结构体,命名为XGpioPs
所以示例程序定义了变量Gpio,同时引用了xgpiops.h头文件
XGpioPs Gpio
同时传入参数&Gpio
@param ConfigPtr points to the XGpioPs device configuration structure.
第二个参数是一个指针,指向GPIO的配置信息,跳转至头文件
typedef struct {
u16 DeviceId; /< Unique ID of device */
UINTPTR BaseAddr; /< Register base address */
} XGpioPs_Config;
找到了自定义结构体XGpioPs_Config
就到这吧,差不多了。