Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programming GPIO pins on a FINTEK F81866A chipset

Tags:

c

gpio

I have a Cincoze DE-1000 industrial PC, that features a Fintek F81866A chipset. I have to manage the DIO pins to read the input from a phisical button and to set on/off a LED. I have experience in C++ programming, but not at low/hardware level.

On the documentation accompanying the PC, there is the following C code:

#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)

As far as I understood, the above code should read the value of the four input PINs (so it should read 1 for each PIN), but I am really struggling to understand how it actually works. I have understood the logic (selecting an address and reading/writing an hex value to it), but I cannot figure out what kind of C instructions WriteByte() and ReadByte() are. Also, I do not understand where Value in the line ReadByte(DataPort, Value) comes from. It should read the 4 PINs all together, so it should be some kind of "byte" type and it should contain 1 in its bits 4-7, but again I cannot really grasp the meaning of that line.

I have found an answer for a similar chip, but it did not help me in understanding.

Please advice me or point me to some relevant documentation.

like image 490
Giorgio R Avatar asked Jan 27 '23 08:01

Giorgio R


1 Answers

That chip looks like a fairly typical Super I/O controller, which is basically the hub where all of the "slow" peripherals are combined into a single chipset.

Coreboot has a wiki page that talks about how to access the super I/O.


On the PC architecture, Port I/O is accomplished using special CPU instructions, namely in and out. These are privileged instructions, which can only be used from a kernel-mode driver (Ring 0), or a userspace process which has been given I/O privileges.

Luckily, this is easy in Linux. Check out the man page for outb and friends.

You use ioperm(2) or alternatively iopl(2) to tell the kernel to allow the user space application to access the I/O ports in question. Failure to do this will cause the application to receive a segmentation fault.

So we could adapt your function into a Linux environment like this:

/* 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 */
}

Warning

You should be very careful when using this method to talk directly to the Super IO, because your operating system almost certainly has device drivers that are also talking to the chip.

The right way to accomplish this is to write a device driver that properly coordinates with other kernel code to avoid concurrent access to the device.

The Linux kernel provides GPIO access to at least some Super I/O devices; it should be straightforward to port one of these to your platform. See this pull request for the IT87xx chipset.

like image 164
Jonathon Reinhart Avatar answered Feb 07 '23 17:02

Jonathon Reinhart