【SDK】控制PS侧GPIO ( 操作地址强制转换为指针 )

#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;
}

  

原文地址:https://www.cnblogs.com/kevinchase/p/7099215.html