英特尔芯片组 - GPIO编程

时间:2015-12-03 06:02:46

标签: x86 embedded-linux intel gpio

根据规范,我知道以下信息:

JGPIO1 PIN# :10

SoC GPIO # : 71 

USE select: IO 0x532[7] ( 0 = native function, 1 = GPIO )

IO select: IO 0x536[7] (0 = output, 1 = input )

Level: IO 0x540[7] ( 0 = low, 1= high )

在这种情况下,我想编写GPIO引脚#10。我可以参考任何示例或示例代码吗?

我可以通过RW-everything [1]做到这一点。但是,这是在Windows中。

我想在C和Linux环境中这样做。

请指教。

=============================================== ================

例如,如果我想设置

0x532的第7位到1

第0x536位的第7位为0

0x540处的第7位到1位。

2 个答案:

答案 0 :(得分:2)

在Linux用户空间中,用于访问GPIO的典型方法是通过 / sys 伪文件系统(也称为sysfs)。这提供了一个有点便携的接口,试图最小化硬件依赖性并避免与设备驱动程序冲突。

要确定要在电路板上访问的GPIO编号,您必须查阅SoC文档。 / sys / class / gpio / 中的目录名称需要使用其硬件寄存器对应项进行标识。这些目录名称的格式为 gpiochip N,其中N表示该寄存器中的基本GPIO号。文件 gpiochipN / label 应该有助于识别寄存器,例如通过其(内存或端口)地址。

请注意,N可能不会以0开头。英特尔BayTrail系统可能将 gpiochip82 作为其第一个目录,因此编号最小的GPIO将为82.应添加寄存器的位数到基数以获得GPIO号。

有关正式文件,请参阅Documentation/gpio/sysfs.txt

  

我可以通过RW-everything 1做到这一点。但是,这是在Windows中。

可能会编写类似的程序以在Linux下执行。然而,Linux程序(不同于以x86为中心的Windows)应该可以移植到其他架构,因此这种需要了解低级硬件细节的程序几乎不可能编写/维护。设备驱动程序的一个目的是隔离/模块化这些硬件细节,这样的程序试图绕过这些驱动程序!

此外,使用此类程序可能会导致系统不稳定或出现故障。在运行的系统上使用内存和/或设备寄存器是不安全的。 FWIW我编写了一个实用程序,报告一个特定SoC的引脚配置,但只有读取寄存器,从不修改任何设置。

请注意,大多数SoC文档(以及Linux)将引脚控制/配置视为与GPIO分离(但密切相关,如果不重叠)的子系统。引脚控制/配置通常包括:

  • 将引脚复用为不同的外设/功能,
  • 方向性(即输入或输出),
  • 连接上拉或下拉电阻,
  • 输入过滤(即去毛刺),
  • 输出驱动(例如开漏)和
  • 中断控制。

GPIO子系统通常处理:

  • 方向性,
  • 引脚状态,
  • 中断控制。

请参阅Documentation/pinctrl.txtDocumentation/gpio/gpio.txt

答案 1 :(得分:0)

许多嵌入式板都支持EAPI库-“嵌入式应用程序编程接口”。基本规范是由PICMG开发的。 Here's the doc.

如果您想通过用户空间程序控制和/或检测GPIO引脚,此API可能会为您提供最简单,最快的解决方案。

下面是使用EAPI打开/关闭任意GPO引脚的代码片段。 (设备本身的引脚号通常与板上接头连接器上的引脚号不匹配,因此您需要转换“外部”与“内部”引脚号。

bool
DvmA44I2CGPI::setOutput(int pinNum, bool pinOn)
{
    if (pinNum > NUMPINS)
        return false;

    bool     pinPhyVal = (mReversePolarity) ? !pinOn : pinOn;
    uint32_t       val = (pinPhyVal) ? EAPI_GPIO_HIGH : EAPI_GPIO_LOW;

    uint32_t inputs, outputs;
    EApiStatus_t rc;

    if ((rc = EApiGPIOGetDirectionCaps(EAPI_ID_GPIO_BANK00, &inputs, &outputs)) != EAPI_STATUS_SUCCESS)
    {
        fprintf(stderr, "EApiGPIOGetDirectionCaps() Get Direction Failed: ");
        printStatus(rc);
        return false;
    }


    if ((rc = EApiGPIOSetLevel(mPinMap[pinNum-1], outputs, val)) != EAPI_STATUS_SUCCESS)
    {
        fprintf(stderr, "EApiGPIOSetLevel() Set Level Failed: ");
        printStatus(rc);
        return false;
    }

    return true;
}