Intel 芯片组 - GPIO 编程
Intel chipset - GPIO programming
从规范中,我了解到以下信息:
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 pin #10 进行编程。有没有我可以参考的示例或示例代码?
我可以通过 RW 完成所有事情 [1]。然而,这是在 Windows.
我想在 C 和 linux 环境中执行此操作。
请指教。
============================================= ==================
例如,如果我想设置
0x532处第7位为1
第7位0x536处为0
第 7 位在 0x540 处为 1。
在 Linux 用户空间中,用于访问 GPIO 的典型方法是通过 /sys 伪文件系统(又名 sysfs)。这提供了一个有点便携的接口,试图最小化硬件依赖性并避免与设备驱动程序发生冲突。
要确定您要在开发板上访问的 GPIO 编号,您必须查阅 SoC 文档。 /sys/class/gpio/ 中的目录名称需要与其对应的硬件寄存器标识。这些目录名称的格式为 gpiochipN,其中 N 表示该寄存器中的基本 GPIO 编号。文件 gpiochipN/label 应该有助于识别寄存器,例如按其(内存或端口)地址。
请注意,N 可能不以 0 开头。Intel BayTrail 系统可能将 gpiochip82 作为其第一个目录,因此最低编号的 GPIO 将为 82。位数寄存器应该添加到基数以获得GPIO编号。
参考Sysfs Interface for Userspace获取正式文档。
I can do this thorugh RW-everything 1. However, this is in Windows.
可能会编写类似的程序在 Linux 下执行。然而 Linux 程序(不像 Windows 以 x86 为中心)应该可以移植到其他架构,所以这样一个需要了解低级硬件细节的程序几乎不可能 write/maintain .设备驱动程序的目的之一是 isolate/modularize 这样的硬件细节,而这样的程序正试图绕过这些驱动程序!
此外,使用此类程序可能会使系统不稳定或发生故障。在 运行 系统上,绕过内存 and/or 设备寄存器是不安全的。 FWIW 我已经编写了一个实用程序来报告一个特定 SoC 的引脚配置,但它只 读取 寄存器并且从不修改任何设置。
请注意,大多数 SoC 文档(以及 Linux)都将引脚控制和
配置为 GPIO 的独立(但如果不重叠则密切相关)子系统。 Pin control and configuration 通常包括:
- 为不同的 peripherals/functionality、
多路复用引脚
- 方向性(即输入或输出),
- 连接上拉或下拉电阻,
- 输入过滤(即去毛刺),
- 输出驱动(例如漏极开路),以及
- 中断控制。
GPIO subsystem 通常处理:
- 方向性,
- 管脚状态,
- 中断控制。
许多嵌入式板都支持 EAPI 库 - "Embedded Application Programming Interface"。基本规范由 PICMG 制定。 Here's the doc.
如果您想通过 user-space 程序控制 and/or 检测 GPIO 引脚,此 API 可能为您提供最简单、最快捷的解决方案。
这是使用 EAPI 将 on/off 任意 GPO 引脚转换的代码片段。 (设备本身的引脚编号通常与电路板上接头连接器上的引脚编号不匹配,因此您需要转换 "external" 与 "internal" 引脚编号。
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;
}
从规范中,我了解到以下信息:
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 pin #10 进行编程。有没有我可以参考的示例或示例代码?
我可以通过 RW 完成所有事情 [1]。然而,这是在 Windows.
我想在 C 和 linux 环境中执行此操作。
请指教。
============================================= ==================
例如,如果我想设置
0x532处第7位为1
第7位0x536处为0
第 7 位在 0x540 处为 1。
在 Linux 用户空间中,用于访问 GPIO 的典型方法是通过 /sys 伪文件系统(又名 sysfs)。这提供了一个有点便携的接口,试图最小化硬件依赖性并避免与设备驱动程序发生冲突。
要确定您要在开发板上访问的 GPIO 编号,您必须查阅 SoC 文档。 /sys/class/gpio/ 中的目录名称需要与其对应的硬件寄存器标识。这些目录名称的格式为 gpiochipN,其中 N 表示该寄存器中的基本 GPIO 编号。文件 gpiochipN/label 应该有助于识别寄存器,例如按其(内存或端口)地址。
请注意,N 可能不以 0 开头。Intel BayTrail 系统可能将 gpiochip82 作为其第一个目录,因此最低编号的 GPIO 将为 82。位数寄存器应该添加到基数以获得GPIO编号。
参考Sysfs Interface for Userspace获取正式文档。
I can do this thorugh RW-everything 1. However, this is in Windows.
可能会编写类似的程序在 Linux 下执行。然而 Linux 程序(不像 Windows 以 x86 为中心)应该可以移植到其他架构,所以这样一个需要了解低级硬件细节的程序几乎不可能 write/maintain .设备驱动程序的目的之一是 isolate/modularize 这样的硬件细节,而这样的程序正试图绕过这些驱动程序!
此外,使用此类程序可能会使系统不稳定或发生故障。在 运行 系统上,绕过内存 and/or 设备寄存器是不安全的。 FWIW 我已经编写了一个实用程序来报告一个特定 SoC 的引脚配置,但它只 读取 寄存器并且从不修改任何设置。
请注意,大多数 SoC 文档(以及 Linux)都将引脚控制和 配置为 GPIO 的独立(但如果不重叠则密切相关)子系统。 Pin control and configuration 通常包括:
- 为不同的 peripherals/functionality、 多路复用引脚
- 方向性(即输入或输出),
- 连接上拉或下拉电阻,
- 输入过滤(即去毛刺),
- 输出驱动(例如漏极开路),以及
- 中断控制。
GPIO subsystem 通常处理:
- 方向性,
- 管脚状态,
- 中断控制。
许多嵌入式板都支持 EAPI 库 - "Embedded Application Programming Interface"。基本规范由 PICMG 制定。 Here's the doc.
如果您想通过 user-space 程序控制 and/or 检测 GPIO 引脚,此 API 可能为您提供最简单、最快捷的解决方案。
这是使用 EAPI 将 on/off 任意 GPO 引脚转换的代码片段。 (设备本身的引脚编号通常与电路板上接头连接器上的引脚编号不匹配,因此您需要转换 "external" 与 "internal" 引脚编号。
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;
}