#include <stdio.h> #include "platform.h" #include "xgpiops.h" #include "sleep.h" #define LED_PinNumber 0 //LED D29 MIO管脚 //void print(char *str); int main() { int Status; XGpioPs_Config *p_gpio_config; XGpioPs Gpio; init_platform(); print("gpio mio test "); //初始化GPIO驱动 p_gpio_config = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID); Status = XGpioPs_CfgInitialize(&Gpio, p_gpio_config,p_gpio_config->BaseAddr); if (Status != XST_SUCCESS) { print("gpio_mio config error! "); return XST_FAILURE; } // LED_PinNumber gpio 设置 XGpioPs_SetDirectionPin(&Gpio, LED_PinNumber, 1); XGpioPs_SetOutputEnablePin(&Gpio, LED_PinNumber, 1); while (1) { XGpioPs_WritePin(&Gpio, LED_PinNumber, 0); sleep(1);//延时1s XGpioPs_WritePin(&Gpio, LED_PinNumber, 1); sleep(1);//延时1s } cleanup_platform(); }
封装函数位于bsp文件下xgpiops.h
void XGpioPs_SetDirection(XGpioPs *InstancePtr, u8 Bank, u32 Direction);// 设置IO的in/out方向 void XGpioPs_SetOutputEnable(XGpioPs *InstancePtr, u8 Bank, u32 OpEnable);// 设置out使能 void XGpioPs_WritePin(XGpioPs *InstancePtr, u32 Pin, u32 Data);//管脚置0/1
选XGpioPs_WritePin()函数分析(gpiops_v3_1srcxgpiops.c)
void XGpioPs_WritePin(XGpioPs *InstancePtr, u32 Pin, u32 Data) { u32 RegOffset; u32 Value; u8 Bank; u8 PinNumber; u32 DataVar = Data; Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(Pin < InstancePtr->MaxPinNum); /* Get the Bank number and Pin number within the bank. */ XGpioPs_GetBankPin((u8)Pin, &Bank, &PinNumber); if (PinNumber > 15U) { /* There are only 16 data bits in bit maskable register. */ PinNumber -= (u8)16; RegOffset = XGPIOPS_DATA_MSW_OFFSET; } else { RegOffset = XGPIOPS_DATA_LSW_OFFSET; } /* * Get the 32 bit value to be written to the Mask/Data register where * the upper 16 bits is the mask and lower 16 bits is the data. */ DataVar &= (u32)0x01;// 只取最后1bit Value = ~((u32)1 << (PinNumber + 16U)) & ((DataVar << PinNumber) | 0xFFFF0000U);// 修改设定的pin位 其他mask掉 XGpioPs_WriteReg(InstancePtr->GpioConfig.BaseAddr, ((u32)(Bank) * XGPIOPS_DATA_MASK_OFFSET) + RegOffset, Value);// 最终写入 MASK_DATA_0_LSW 寄存器 }
选XGpioPs_WriteReg()分析(xgpiops_hw.h)。Xil_Out32()是基础共享的,具体化成Gpio专用的。
#define XGpioPs_WriteReg(BaseAddr, RegOffset, Data) Xil_Out32((BaseAddr) + (u32)(RegOffset), (u32)(Data))// 带参宏把功能映射到底层函数上
分析Xil_Out32() (standalone_v5_5srcxil_io.c)
void Xil_Out32(UINTPTR Addr, u32 Value) { volatile u32 *LocalAddr = (u32 *)Addr;// 强制类型转换 映射到地址 *LocalAddr = Value;// 把数据写到该地址 }
//----------------------------------------------------------
//初始化分析
//----------------------------------------------------------
先定义结构体变量
// 定义struct变量 XGpioPs_Config *p_gpio_config; XGpioPs Gpio; //struct声明 typedef struct { u16 DeviceId; /**< Unique ID of device */ u32 BaseAddr; /**< Register base address */ } 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;
根据ID找到对应的结构体内容列表
// p_gpio_config = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID); // XGpioPs_Config *XGpioPs_LookupConfig(u16 DeviceId) { XGpioPs_Config *CfgPtr = NULL; u32 Index; //定义结构体数组,存储多组id信息,这里只有一组 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; } //导入外部定义好的结构体内容 extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES]; //该结构体下定义了一组信息。数组宽度1,即[0] XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES] = { { XPAR_PS7_GPIO_0_DEVICE_ID, XPAR_PS7_GPIO_0_BASEADDR } };
//
#define XPAR_XGPIOPS_NUM_INSTANCES 1
只要有config下的base信息,就能对其他内容进行定义,即initiaize
// Status = XGpioPs_CfgInitialize(&Gpio, p_gpio_config,p_gpio_config->BaseAddr); //实际传入参数只有p_gpio_config,以此对Gpio子变量进行定义 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; }