zynq7000系列PS端GPIO初始化函数XGpioPs_LookupConfig()和XGpioPs_CfgInitialize()详解

前言
   xilinx公司在设计这款芯片时就同步编写了ps端的函数库,我们在对zynq这款芯片进行开发,直接调用库函数就可以了。不过比较难过的是,官方虽然编写了函数驱动库,但并没有出版相应的类似于函数指导之类的文档,需要开发者自己去理解这个函数用法,但官方还是有相应的历程,我们可以学历历程来基本掌握这些函数的用法,但并不是很详细,也没有说明文档,需要结合datasheet和其他的文档进行综合理解分析。
首先
gpio有两个重要的数据结构:XGpioPs 和 XGpioPs_Config

typedef struct {
	XGpioPs_Config GpioConfig;	/**< Device configuration */
	u32 IsReady;			/**< Device is initialized and ready */
	XGpioPs_Handler Handler;	/**< Status handlers for all banks */
	void *CallBackRef; 		/**< Callback ref for bank handlers */
	u32 Platform;			/**< Platform data */
	u32 MaxPinNum;			/**< Max pins in the GPIO device */
	u8 MaxBanks;			/**< Max banks in a GPIO device */
} XGpioPs;

typedef struct {
	u16 DeviceId;		/**< Unique ID of device */
	u32 BaseAddr;		/**< Register base address */
} XGpioPs_Config;

XGpioPs 结构体里面各个成员变量的大致作用:
  1:GpioConfig 是XGpioPs_Config结构体的指针,指向内部成员DeviceId和BaseAddr;这两个成员作用是保存gpio这个设备的Id和基地址,在zynq中任何外设都有一个相应的id和基地址用来识别。
  解析一下为什么我们在所有历程中或者别人的工程中看到的id都是0,它只是被用来初始化,表示这个设备在vivado搭建工程环境时我们勾选了这个设备,没有勾选的设备你是在#include "xparameters_ps.h"中找不到相应的id和地址的。
  2:IsReady,当设备初始化完成,设备已经准备好
  3:Handler ,中断句柄,用于中断读取和写入
  4:CallBackRef 中断回调函数,没有用到中断时可不做关心
  5:Platform 这个是跟你的开发板硬件平台相关,不做关心
  6:MaxPinNum ps端能使用的最大的pin数量,在zynq中为118
  7:MaxBanks 在zynq中的io bank数目为4

1:查询函数XGpioPs_LookupConfig()

XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId)
{
	XGpioPs_Config *CfgPtr = NULL;
	u32 Index;
	for (Index = 0U; Index < (u32)XPAR_XGPIOPS_NUM_INSTANCES; Index++) {
		if (XGpioPs_ConfigTable[Index].DeviceId == DeviceId) {
			CfgPtr = &XGpioPs_ConfigTable[Index];
			break;
		}
	}
	return (XGpioPs_Config *)CfgPtr;
}

参数:设备id,我们可以在#include "xparameters_ps.h"找到id和地址

/* Definitions for peripheral PS7_GPIO_0 */
#define XPAR_PS7_GPIO_0_DEVICE_ID 0
#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000
#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF

每一个设备都有一个唯一的配置表:

XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] =
{
	{
		XPAR_PS7_GPIO_0_DEVICE_ID,
		XPAR_PS7_GPIO_0_BASEADDR
	}
};

XGpioPs_LookupConfig这个函数就是根据设备id,查找配置表,然后将设备的地址等信息,通过XGpioPs_Config 指针返回。

2:初始化函数XGpioPs_CfgInitialize()

s32 XGpioPs_CfgInitialize(XGpioPs *InstancePtr, XGpioPs_Config *ConfigPtr,
				u32 EffectiveAddr)
{
	s32 Status = XST_SUCCESS;
	u8 i;
	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(ConfigPtr != NULL);
	Xil_AssertNonvoid(EffectiveAddr != (u32)0);
	/*
	 * Set some default values for instance data, don't indicate the device
	 * is ready to use until everything has been initialized successfully.
	 */
	InstancePtr->IsReady = 0U;
	InstancePtr->GpioConfig.BaseAddr = EffectiveAddr;
	InstancePtr->GpioConfig.DeviceId = ConfigPtr->DeviceId;
	InstancePtr->Handler = StubHandler;
	InstancePtr->Platform = XGetPlatform_Info();

	/* Initialize the Bank data based on platform */
	if (InstancePtr->Platform == XPLAT_ZYNQ_ULTRA_MP) {
		/*
		 *	Max pins in the ZynqMP GPIO device
		 *	0 - 25,  Bank 0
		 *	26 - 51, Bank 1
		 *	52 - 77, Bank 2
		 *	78 - 109, Bank 3
		 *	110 - 141, Bank 4
		 *	142 - 173, Bank 5
		 */
		InstancePtr->MaxPinNum = (u32)174;
		InstancePtr->MaxBanks = (u8)6;
	} else {
		/*
		 *	Max pins in the GPIO device
		 *	0 - 31,  Bank 0
		 *	32 - 53, Bank 1
		 *	54 - 85, Bank 2
		 *	86 - 117, Bank 3
		 */
		InstancePtr->MaxPinNum = (u32)118;
		InstancePtr->MaxBanks = (u8)4;
	}

	/*
	 * By default, interrupts are not masked in GPIO. Disable
	 * interrupts for all pins in all the 4 banks.
	 */
	for (i=0;i<InstancePtr->MaxBanks;i++) {
		XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr,
					  ((u32)(i) * XGPIOPS_REG_MASK_OFFSET) +
					  XGPIOPS_INTDIS_OFFSET, 0xFFFFFFFFU);
	}

	/* Indicate the component is now ready to use. */
	InstancePtr->IsReady = XIL_COMPONENT_IS_READY;

	return Status;
}

  参数1:XGpioPs 结构体指针
  参数2:指向XGpioPs_Config 设备指针
  参数3:指向设备基地址
**函数功能:**设置一些初始默认值,如:设置io的最大值和bank数,默认关闭中断等等。

使用

	static XGpioPs   psGpioInstancePtr;
	XGpioPs_Config*  GpioConfigPtr;
	int xStatus;
	
    GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);
	if(GpioConfigPtr == NULL)
		return XST_FAILURE;
		
	xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr, GpioConfigPtr->BaseAddr);
	if(XST_SUCCESS != xStatus)
		print(" PS GPIO INIT FAILED \n\r");

你可能感兴趣的:(单片机,fpga,嵌入式,soc)