最近在用实验室的zedboard学习zynq,在网上找到了一个叫Harald's Embedded Electronics 的网站,里面有关于zedboard的一些教学。
在做完第一个实验时,打算把PS部分的程序学习和注释并记录下来,于是有了这个帖子。
Block Design部分
原贴中的Block Design还是比较简单,结构如下:
PS程序部分
PS部分的程序主要用来实现八个LED中的0,2,4,6与1,3,5,7闪烁,内容如下:
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"
int main()
{
init_platform();
print("Hello World\r\n");
XGpio gpio; //PL 端AXI GPIO 器件ID
int xStatus = XGpio_Initialize(&gpio,XPAR_AXI_GPIO_0_DEVICE_ID);
if(XST_SUCCESS != xStatus) {
print("Failed to initialize GPIO");
}
for(;;) {
for(volatile int i=0;i<0x1000000;++i) {}
XGpio_DiscreteWrite(&gpio,1,0x55);
for(volatile int i=0;i<0x1000000;++i) {}
XGpio_DiscreteWrite(&gpio,1,0xAA);
}
cleanup_platform();
return 0;
}
代码第14行,XGpio gpio;
功能为PL 端AXI GPIO 驱动实例。可以看作定义了一个XGpio驱动实例,实例的名字叫做gpio。
代码第16行,int xStatus = XGpio_Initialize(&gpio,XPAR_AXI_GPIO_0_DEVICE_ID);
打开函数 XGpio_Initialize,内容如下:
int XGpio_Initialize(XGpio * InstancePtr, u16 DeviceId)
{
XGpio_Config *ConfigPtr;
/*
* Assert arguments
*/
Xil_AssertNonvoid(InstancePtr != NULL);
/*
* Lookup configuration data in the device configuration table.
* Use this configuration info down below when initializing this
* driver.
*/
ConfigPtr = XGpio_LookupConfig(DeviceId);
if (ConfigPtr == (XGpio_Config *) NULL) {
InstancePtr->IsReady = 0;
return (XST_DEVICE_NOT_FOUND);
}
return XGpio_CfgInitialize(InstancePtr, ConfigPtr,
ConfigPtr->BaseAddress);
}
这个函数的第一个输入形参:InstancePtr 为XGpio实例的指针。
第二个输入形参:DeviceId 为被这个驱动实例控制的设备的ID,可以在xparameters.h这个文件中找到。对于本实验而言,输入的参数叫XPAR_AXI_GPIO_0_DEVICE_ID,命名是由图一右上角的AXI GPIO模块的名字决定的。如果有多个AXI GPIO,那么每个的ID都不一样,直接在xparameters.h里找自己想要的设备就好了。
这个函数的功能为:根据给的DeviceId,初始化InstancePtr。
在本实验中就是根据XPAR_AXI_GPIO_0_DEVICE_ID,初始化gpio这个实例驱动。
代码第24行:XGpio_DiscreteWrite(&gpio,1,0x55);
打开函数XGpio_DiscreteWrite,内容如下:
void XGpio_DiscreteWrite(XGpio * InstancePtr, unsigned Channel, u32 Data)
{
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid((Channel == 1) ||
((Channel == 2) && (InstancePtr->IsDual == TRUE)));
XGpio_WriteReg(InstancePtr->BaseAddress,
((Channel - 1) * XGPIO_CHAN_OFFSET) + XGPIO_DATA_OFFSET,
Data);
}
这个函数的功能:把数据写入特定的discretes register
- 第一个参数:InstancePtr,为XGpio实例的指针。
- 第二个参数:Channel,是图一右上角的AXI GPIO模块的通道数,只能为1或2。AXI GPIO模块可以设置为双通道,本实验只有通道一。
- 第三个参数:Data,就是写进去的数据呗。
所以这句代码的含义为:把0x55写入实例gpio相对应的IO口,可以实现LED灯0,2,4,6灯的点亮。