sdyxz123 2023-11-14 12:01 采纳率: 39%
浏览 2
已结题

WDM GPIO 如何控制

  1. 如何通过ACPI 的 asl 语言定义一个 GPIO (GPIO_A)引脚呢,比如该引脚 的基地址0x100, 具体的引脚偏移是1
  2. 然后在WDM 驱动中 如何获取 ACPI 中已经定义好的GPIO_A的 资源呢
  3. 在驱动中获取到GPIO_A的资源后(基地址,具体引脚) 如何使用 GpioClx DDI 框架来控制GPIO_A呢,比如输出高地平
  • 写回答

7条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-11-14 12:06
    关注

    引自强大而免费的微信小程序:皆我百晓生

    1. 使用 ASL 语言定义 GPIO

    在 ACPI 的 ASL 语言中,可以通过 Device 和 GPIO 元素来定义一个 GPIO。

    首先,在 Device 范围内定义一个 GPIO 控制器:

    Device (GPIOA) {
        Name (_HID, "ACPI000A")  // 定义设备的硬件 ID
        Name (_CRS, ResourceTemplate () { GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
                                            0x100, 0x1) }) // 定义 GPIO 资源
    }
    

    在上面的代码中,_HID 指定了 GPIO 控制器的硬件 ID,_CRS 定义了 GPIO 的资源,其中 GpioIo 定义了 GPIO 的 I/O 范围,具体的基地址是 0x100,引脚偏移是 0x1。

    2. 在 WDM 驱动中获取已定义的 GPIO 资源

    要在 WDM 驱动中获取 ACPI 中定义的 GPIO 资源,可以通过调用 WdfFdoQueryForInterface 方法查询 GPIO 控制器的接口。

    首先,在驱动的头文件中定义 GPIO 控制器的接口:

    #include <wdf.h>
    #include <gpio.h>
    
    EXTERN_C_START
    
    // GPIO 控制器的接口 GUID
    DEFINE_GUID(GUID_GPIO_CONTROLLER_INTERFACE_STANDARD, 
        0x1ed4460, 0xec47, 0x4a0b, 0x8b, 0x7e, 0x5b, 0x8f, 0x67, 0x8c, 0x94, 0x90);
    
    // GPIO 控制器接口定义
    typedef struct _GPIO_CONTROLLER_INTERFACE_STANDARD {
        INTERFACE                   Interface;
        WDFDEVICE                   GpioController;
        PVOID                       Context;
        PVOID                       InterfaceReference;
        PVOID                       InterfaceDereference;
        ULONG                       Size;
    } GPIO_CONTROLLER_INTERFACE_STANDARD, *PGPIO_CONTROLLER_INTERFACE_STANDARD;
    
    EXTERN_C_END
    

    然后,在驱动的初始化代码中查询 GPIO 接口:

    NTSTATUS InitializeDriver(
        _In_ WDFDRIVER Driver
    )
    {
        NTSTATUS status;
        PGPIO_CONTROLLER_INTERFACE_STANDARD gpioInterface;
    
        status = WdfFdoQueryForInterface(
            WdfDriverGetDevice(Driver),
            &GUID_GPIO_CONTROLLER_INTERFACE_STANDARD,
            (PINTERFACE)&gpioInterface,
            sizeof(GPIO_CONTROLLER_INTERFACE_STANDARD),
            1, // 需要 GPIO 控制器的第一个接口(可以根据实际情况调整)
            NULL
            );
    
        if (!NT_SUCCESS(status))
        {
            // 查询接口失败
            return status;
        }
    
        // 获取 GPIO 控制器的句柄
        WDFDEVICE gpioController = gpioInterface->GpioController;
    
        // 可以通过 gpioController 获取 GPIO 控制器的资源等信息
        // ...
    
        // 释放 GPIO 接口
        gpioInterface->InterfaceDereference(gpioInterface->Context);
    
        return STATUS_SUCCESS;
    }
    

    在上述代码中,通过调用 WdfFdoQueryForInterface 方法查询 GPIO 控制器的接口,并获取 GPIO 控制器的句柄 gpioController。可以根据需要使用 gpioController 获取 GPIO 控制器的其他信息。

    3. 使用 GpioClx DDI 框架控制 GPIO

    GpioClx 是一个 WDF 框架的扩展,用于简化 GPIO 控制的开发。可以通过 GpioClx 提供的 API 来控制 GPIO。

    首先,需要在驱动的 INF 文件中添加对 GpioClx 的依赖:

    [DDInstall.NT.Wdf]
    AddReg = Gpio_RegistrySettings
    
    [Gpio_RegistrySettings]
    ; 设置驱动的库路径
    "HKR,," = Gpio_Registry_InstallRootPath
    
    [Gpio_Registry_InstallRootPath]
    "LibraryPath"=hex(2):53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,47,\
    00,70,00,69,00,6f,00,43,00,6c,00,78,00,2e,00,64,00,6c,00,6c,00,00,00
    
    [Gpio_Registry_WdfframeworkSettings]
    ; 启用 GpioClx DDI 框架
    "GpioClxDdiEnabled"=dword:00000001
    

    然后,在驱动的初始化代码中使用 GpioClx 提供的 API 控制 GPIO:

    NTSTATUS InitializeDriver(
        _In_ WDFDRIVER Driver
    )
    {
        NTSTATUS status;
        PGPIO_CONTROLLER_INTERFACE_STANDARD gpioInterface;
    
        // 查询 GPIO 接口并获取 GPIO 控制器的句柄...
    
        // 创建 GPIO 线
        GPIO_CLIENT_CONTROLLER_HANDLE gpioClientController;
        GPIO_CONTROLLER_INIT_PARAMETERS initParams;
    
        GpioControllerInitParamsInit(&initParams);
        initParams.Size = sizeof(GPIO_CONTROLLER_INIT_PARAMETERS);
        initParams.ClientIdentificationDescription = L"GPIO_A";
    
        status = GpioClxCreateGpioController(
            &gpioClientController,
            gpioInterface->GpioController,
            &initParams
        );
    
        if (!NT_SUCCESS(status))
        {
            // 创建 GPIO 控制器失败
            return status;
        }
    
        // 控制 GPIO 输出高电平
        GPIO_CLIENT_PIN_HANDLE gpioPin;
        status = GpioClxAcquireGpioPinByIndex(
            gpioClientController,
            0x1, // 引脚偏移(根据实际情况调整)
            GPIO_PIN_IO_DIRECTION_OUTPUT,
            &gpioPin
        );
    
        if (!NT_SUCCESS(status))
        {
            // 获取 GPIO 引脚失败
            GpioClxDisposeGpioController(gpioClientController);
            return status;
        }
    
        GpioClxSetTargetState(gpioPin, GPIO_PIN_SET_HIGH);
    
        // 释放 GPIO 引脚和 GPIO 控制器
        GpioClxReleaseGpioPin(gpioPin);
        GpioClxDisposeGpioController(gpioClientController);
    
        return STATUS_SUCCESS;
    }
    

    在上述代码中,首先使用 GpioClxCreateGpioController 方法创建了 GPIO 控制器。然后使用 GpioClxAcquireGpioPinByIndex 方法获取了 GPIO_A 的引脚(根据实际情况调整引脚的偏移)。最后使用 GpioClxSetTargetState 方法将引脚设置为高电平。

    请注意,以上代码仅为示例,具体的实现可能因为硬件平台和驱动架构的不同而有所差异。建议参考相关硬件和驱动的文档、示例代码和调试工具,并根据实际需求进行适当调整。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月14日
  • 创建了问题 11月14日

悬赏问题

  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程
  • ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
  • ¥15 关于smbclient 库的使用