在FINTEK F81866A芯片组上编程GPIO引脚

时间:2018-10-05 17:17:01

标签: c gpio

我有一台Cincoze DE-1000工业PC,它具有Fintek F81866A芯片组。我必须管理DIO引脚以从一个物理按钮读取输入并设置LED的开/关。我有C ++编程经验,但没有较低/硬件级别的经验。

在PC随附的文档中,有以下C代码:

User.aggregate([{
  "$lookup":{
    "from":"projects",
    "let":{"projects":"$projects","user":"$_id"},
    "pipeline":[
      {"$match":{
        "$expr":{
          "$and":[
            {"$in":["$_id","$$projects"]},
            {"$in":["$$user","$user"]}
          ]
        }}
      },
      {"$lookup":{
        "from":"tasks",
        "localField":"tasks",
        "foreignField":"_id",
        "as":"tasks"
      }}
    ],
    "as":"project-tasks"
  }
}])

据我了解,上面的代码应该读取四个输入PIN的值(因此每个PIN应该读取1),但是我真的很难理解它的实际工作原理。我已经了解了逻辑(选择地址并向其读取/写入十六进制值),但是我无法弄清楚#define AddrPort 0x4E #define DataPort 0x4F //<Enter the Extended Function Mode> WriteByte(AddrPort, 0x87) WriteByte(AddrPort, 0x87) //Must write twice to entering Extended mode //<Select Logic Device> WriteByte(AddrPort, 0x07) WriteByte(DataPort, 0x06) //Select logic device 06h //<Input Mode Selection> //Set GP74 to GP77 input mode WriteByte(AddrPort, 0x80) //Select configuration register 80h WriteByte(DataPort, 0x0X) //Set (bit 4~7) = 0 to select GP 74~77 as Input mode. //<input Value> WriteByte(AddrPort, 0x82) // Select configuration register 82h ReadByte(DataPort, Value) // Read bit 4~7(0xFx)= GP74 ~77 as High. //<Leave the Extended Function Mode> WriteByte(AddrPort, 0xAA) WriteByte()是哪种C指令。另外,我不知道ReadByte()行中Value的来源。它应该一起读取4个PIN,因此应该是某种“字节”类型,并且在其4-7位中应包含1,但是我仍然无法真正理解该行的含义。

我找到了answer for a similar chip,但是它对我的理解没有帮助。

请给我建议或指向一些相关文档。

2 个答案:

答案 0 :(得分:4)

该芯片看起来像一个非常典型的Super I/O controller,基本上是所有“慢速”外围设备都组合成单个芯片组的枢纽。

Coreboot的Wiki页面谈论how to access the super I/O


在PC架构上,端口I / O 使用特殊的CPU指令inout完成。这些是特权指令,只能从内核模式驱动程序(Ring 0)或已获得I / O特权的用户空间进程中使用。

幸运的是,在Linux中这很容易。签出man page for outb and friends

  

您使用ioperm(2)或iopl(2)告诉内核允许用户空间应用程序访问有问题的I / O端口。否则,将导致应用程序收到分段错误。

因此我们可以将您的功能调整为这样的Linux环境:

/* Untested: Use at your own risk! */
#include <sys/io.h>
#include <stdio.h>

#define ReadByte(port)          inb(port)
#define WriteByte(port, val)    outb(val, port)

int main(void)
{
    if (iopl(3) < 0) {
        fprintf(stderr, "Failed to get I/O privileges (are you root?)\n");
        return 2;
    }


    /* Your code using ReadByte / WriteByte here */
}

警告

使用这种方法直接与Super IO对话时应非常小心,因为您的操作系统几乎可以肯定也有与晶片对话的设备驱动程序。

正确的实现方法是编写一个设备驱动程序,该设备驱动程序应与其他内核代码正确协调,以避免并发访问设备。

Linux内核提供了对至少某些超级I / O设备的GPIO访问;将其中之一移植到您的平台应该很简单。参见this pull request for the IT87xx chipset

答案 1 :(得分:2)

WriteByte()ReadByte()不是C语言的一部分。从外观上看,它们是用作OS内核端口IO的某种形式的系统调用的占位符的函数(不是按照此答案的先前版本直接执行内存映射IO的宏)。

这些函数的原型可能类似于:

#include <stdint.h>
void WriteByte(unsigned port, uint8_t value);
void ReadByte(unsigned port, uint8_t *value);

因此Value变量将是一个指向8位无符号整数的指针(也可以使用unsigned char),例如:

uint8_t realValue;
uint8_t *Value = &realValue;

当然,让Value成为uint8_t并拥有ReadByte(DataPort, &Value)会更有意义。但是然后示例代码也没有任何分号,因此可能从未真正运行过任何分号。无论哪种方式,Value都将包含您要查找的数据。

我还在这里找到了更多有关寄存器的文档-https://www.electronicsdatasheets.com/download/534cf560e34e2406135f469d.pdf?format=pdf

希望这会有所帮助。