[LINUX] LED übers Motherboard steuern -gelöst-

  • Themenstarter Themenstarter Gelöschtes Mitglied 16444
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 16444

Guest
Hi!

Ich habe hier ein WAFER945GSE Board, auf dem ein IT8718F Chip verbaut ist. Das Board hat ein DIO Interface, das jeweils 4 Input und Output Pins bereitstellt. Diese Pins sind wiederum an die GPIO Pins des IT8718F angeschlossen.
An zwei der DIO Pins sind LEDs angeschlossen, die ich unter Debian nun gerne per Software ein- und ausschalten würde.
ich habe mir dazu die Datenblätter des Boards und des Chips besorgt und den unten stehenden Code geschrieben. Das funktioniert bis zum entscheidenden Punkt auch alles ganz gut und die Werte, die zu Beginn in den einzelnen Registern stehen machen Sinn wie ich denke.
Nur das schalten der LEDs will nicht funktionieren, ich denke ich mache da noch irgendwas falsch, kann aber nicht herausfinden was. Nach meinem Schreibvorgang steht in dem Register der gleiche Wert wie zuvor und bei den LEDs hat sich rein gar nichts getan.

Es gibt in dem Datenblatt des Chips einen kleinen Widerspruch. An einer Stelle schreiben sie, dass die base address bei 0x60 und 0x61 zu finden ist und an einer anderen Stelle 0x62 und 0x63. Da 0x60 und 0x61 aber komplett genullt sind, gehe ich mal davon aus, dass 0x62 und 0x63 korrekt ist.

Es geht um Output 0 und Output 1 auf dem Board, also GPIO Pin 20 und 21 auf dem Chip.

Hat jemand vielleicht einen Tipp, was ich falsch machen könnte?

General Purpose I/O

The IT8718F provides five sets of flexible I/O control and special functions for the system designers via a set of multi-functional General Purpose I/O pins (GPIO). The GPIO functions will not be performed unless the related enable bits of the GPIO Multi-function Pin Selection registers (Index 25h, 26h, 27h, 28h and 29h of the Global Configuration Registers) are set. The GPIO functions include the simple I/O function and alternate function, and the function selection is determined by the Simple I/O Enable Registers (LDN=07h, Index=C0h, C1h, C2h, C3h and C4h).

The Simple I/O function includes a set of registers, which correspond to the GPIO pins. All control bits are divided into five registers. The accessed I/O ports are programmable and are five consecutive I/O ports (Base Address+0, Base Address+1, Base Address+2, Base Address+3, Base Address+4). Base Address is programmed on the registers of GPIO Simple I/O Base Address LSB and MSB registers (LDN=07h, Index=60h and 61h).

Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/io.h>

#define ADDRREG 0x2e    /* The register to address read/write */
#define DATAREG 0x2f    /* The register to read/write */
#define LEDBITMASK 0x03 /* Bitmask corresponding to the LED pins */

int main(int argc, char **argv)
{
    if( ioperm(ADDRREG, 2, 1) )
    {
        printf("ioperm() failed\n");
        exit(1);
    }

    // Reset the device
    // Return to "Wait for Key" state
    outb(0x02, ADDRREG);
    outb(0x02, DATAREG);

    // Write the "Password" to enter
    // MB PnP Mode
    outb(0x87, ADDRREG);
    outb(0x01, ADDRREG);
    outb(0x55, ADDRREG);
    outb(0x55, ADDRREG);

    // Read DeviceID which should be
    // found at 0x20 and 0x21
    outb(0x20, ADDRREG);
    unsigned short deviceid = inb(DATAREG);
    outb(0x21, ADDRREG);
    deviceid = (deviceid << 8) | inb(DATAREG);

    if(deviceid != 0x8718)
    {
        printf("Device ID does not match! 0x%x != 0x8718\n", deviceid);
        exit(1);
    }

    printf("Found matching device!\n");

    // Switch to the GPIO Logical Device (0x07)
    outb(0x07, ADDRREG);
    outb(0x07, DATAREG);

    // These are multi-Function pins.
    // We reed the current setting and make sure
    // our LED pins are configured to perform
    // the GPIO functions
    outb(0x26, ADDRREG);
    unsigned char gpiostatus = inb(DATAREG);

    printf("Current GPIO status for set 2 is (1=on; 0=off): 0x%x!\n", gpiostatus);

    // Enable General Purpose I/O at
    // least for our LED pins
    gpiostatus |= LEDBITMASK;

    outb(0x26, ADDRREG);
    outb(gpiostatus, DATAREG);

    outb(0x26, ADDRREG);
    gpiostatus = inb(DATAREG);
    
    printf("New GPIO status for set 2 is (1=on; 0=off): 0x%x!\n", gpiostatus);

    // Each GPIO pin can either be used
    // for simple I/O or perform
    // "alternate functions".
    // We make sure we use simple I/O for
    // our LED pins
    outb(0xC1, ADDRREG);
    unsigned char gpiomode = inb(DATAREG);
    
    printf("Current GPIO mode for set 2 is (1=simple i/o; 0=alternate function): 0x%x!\n", gpiomode);
    
    // Enable simple I/O for
    // our LED pins
    gpiomode |= LEDBITMASK;
    
    outb(0xC1, ADDRREG);
    outb(gpiomode, DATAREG);
    
    outb(0xC1, ADDRREG);
    gpiomode = inb(DATAREG);
    
    printf("New GPIO mode for set 2 is (1=simple i/o; 0=alternate function): 0x%x!\n", gpiomode);

    // Each pin configured for simple I/O
    // can either be used for input or output.
    // We make sure our LED pins are configured
    // as output pins
    outb(0xC9, ADDRREG);
    unsigned char iomode = inb(DATAREG);
    
    printf("Current mode for set 2 is (1=output; 0=inout): 0x%x!\n", iomode);

    //Configure our LED pins as output
    iomode |= LEDBITMASK;
    
    outb(0xC9, ADDRREG);
    outb(iomode, DATAREG);
    
    outb(0xC9, ADDRREG);
    iomode = inb(DATAREG);
    
    printf("New mode for set 2 is (1=output; 0=inout): 0x%x!\n", iomode);

    // read Simple I/O base address
    outb(0x62, ADDRREG);
    unsigned short baseaddr = inb(DATAREG);
    outb(0x63, ADDRREG);
    baseaddr = (baseaddr << 8) | inb(DATAREG);

    printf("Simple I/O base address: 0x%x\n", baseaddr);

    // since our LED pins belong to set 2
    // we need to write to baseaddress+1
    outb(baseaddr+1, ADDRREG);
    unsigned char ledstatus = inb(DATAREG);

    printf("Current LED status:0x%x\n", ledstatus);

    // clear bit 0 to turn off
    // LED connected to GPIO 20
    ledstatus &= ~(0x01);

    outb(baseaddr+1, ADDRREG);
    outb(ledstatus, DATAREG);

    outb(baseaddr+1, ADDRREG);
    ledstatus = inb(DATAREG);
    
    printf("New LED status:0x%x\n", ledstatus);

    // Finish configuration by
    // returning to "Wait for Key" state
    outb(0x02, ADDRREG);
    outb(0x02, ADDRREG);

    if( ioperm(ADDRREG, 2, 0) )
    {
        printf("ioperm() failed\n");
        exit(2);
    }

    return 0;
}
 
Zuletzt bearbeitet von einem Moderator:
Ok, ich habe den Fehler gefunden. Die Basis Adresse, die man auslesen kann ist - wie ja auch im zitierten Abschnitt aus dem Datenblatt steht - die eines eigenen I/O Ports. Wer lesen kann ist klar im Vorteil... :rolleyes:

Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/io.h>

// REGISTERS

/* The register to address read/write */
static const short unsigned int ADDR_REG = 0x2e;

/* The register to read/write */
static const short unsigned int DATA_REG = 0x2f;

/* Register to configure Logical Device Number */
static const short unsigned int LDN_REG = 0x07;

/* Register for MSB of Chip ID */
static const short unsigned int CHIP_ID_MSB_REG = 0x20;

/* Register for MSB of Chip ID */
static const short unsigned int CHIP_ID_LSB_REG = 0x21;

/* Configure Control Register */
static const short unsigned int CONFIG_CTRL_REG = 0x02;

/* GPIO Set 2 Multi-Function Pin Selection Register */
static const short unsigned int GPIO_2_SEL_REG = 0x26;

/* Simple I/O Set 2 Enable Register */
static const short unsigned int SIMPLE_IO_2_ENABLE_REG = 0xC1;

/* Simple I/O Set 2 Output Enable Registers */
static const short unsigned int SIMPLE_IO_2_OUT_ENABLE_REG = 0xC9;

/* Register for Simple I/O Base Address MSB */
static const short unsigned int SIMPLE_IO_BASE_ADDR_MSB_REG = 0x62;

/* Register for Simple I/O Base Address LSB */
static const short unsigned int SIMPLE_IO_BASE_ADDR_LSB_REG = 0x63;


// SOME SPECIAL VALUES

/* The device ID of the ITE IT8718F */
static const unsigned short DEVICE_ID = 0x8718;

/* "Password" to enter Enter the MB PnP Mode */
static const unsigned char PASSWORD[] = {0x87, 0x01, 0x55, 0x55};

/* LDN for GPIO Configuration Registers */
static const unsigned char GPIO_LDN = 0x07;

/* Bitmask corresponding to the LED pins */
static const unsigned char LED_BITMASK = 0x03;

/* Value to write to Configure Control Register
to finish configuration procedure */
static const unsigned char CONFIG_COMPLETE = 0x02;

int main(int argc, char **argv)
{
    if( ioperm(ADDR_REG, 2, 1) )
    {
        printf("Couldn't get the ports\n");
        exit(1);
    }

    // Return to "Wait for Key" state
    outb(CONFIG_CTRL_REG, ADDR_REG);
    outb(CONFIG_COMPLETE, DATA_REG);

    // Write the "Password" to enter
    // MB PnP Mode
    outb(PASSWORD[0], ADDR_REG);
    outb(PASSWORD[1], ADDR_REG);
    outb(PASSWORD[2], ADDR_REG);
    outb(PASSWORD[3], ADDR_REG);

    // Read DeviceID
    outb(CHIP_ID_MSB_REG, ADDR_REG);
    unsigned short deviceid = inb(DATA_REG);
    outb(CHIP_ID_LSB_REG, ADDR_REG);
    deviceid = (deviceid << 8) | inb(DATA_REG);

    if(deviceid != DEVICE_ID)
    {
        printf("Device ID does not match! 0x%x != 0x8718\n", deviceid);
        exit(1);
    }

    printf("Found matching device!\n");

    // Switch to the GPIO Logical Device
    outb(LDN_REG, ADDR_REG);
    outb(GPIO_LDN, DATA_REG);

    // These are multi-Function pins.
    // We reed the current setting and make sure
    // our LED pins are configured to perform
    // the GPIO functions
    outb(GPIO_2_SEL_REG, ADDR_REG);
    unsigned char gpiostatus = inb(DATA_REG);

    printf("Current GPIO status for set 2 is (1=on; 0=off): 0x%x!\n", gpiostatus);

    // Enable General Purpose I/O at
    // least for our LED pins
    gpiostatus |= LED_BITMASK;

    outb(GPIO_2_SEL_REG, ADDR_REG);
    outb(gpiostatus, DATA_REG);

    outb(GPIO_2_SEL_REG, ADDR_REG);
    gpiostatus = inb(DATA_REG);
    
    printf("New GPIO status for set 2 is (1=on; 0=off): 0x%x!\n", gpiostatus);

    // Each GPIO pin can either be used
    // for simple I/O or perform
    // "alternate functions".
    // We make sure we use simple I/O for
    // our LED pins
    outb(SIMPLE_IO_2_ENABLE_REG, ADDR_REG);
    unsigned char gpiomode = inb(DATA_REG);

    printf("Current GPIO mode for set 2 is (1=simple i/o; 0=alternate function): 0x%x!\n", gpiomode);

    // Enable simple I/O for our LED pins
    gpiomode |= LED_BITMASK;

    outb(SIMPLE_IO_2_ENABLE_REG, ADDR_REG);
    outb(gpiomode, DATA_REG);

    outb(SIMPLE_IO_2_ENABLE_REG, ADDR_REG);
    gpiomode = inb(DATA_REG);

    printf("New GPIO mode for set 2 is (1=simple i/o; 0=alternate function): 0x%x!\n", gpiomode);

    // Each pin configured for simple I/O
    // can either be used for input or output.
    // We make sure our LED pins are configured
    // as output pins
    outb(SIMPLE_IO_2_OUT_ENABLE_REG, ADDR_REG);
    unsigned char iomode = inb(DATA_REG);

    printf("Current mode for set 2 is (1=output; 0=inout): 0x%x!\n", iomode);

    //Configure our LED pins as output
    iomode |= LED_BITMASK;

    outb(SIMPLE_IO_2_OUT_ENABLE_REG, ADDR_REG);
    outb(iomode, DATA_REG);

    outb(SIMPLE_IO_2_OUT_ENABLE_REG, ADDR_REG);
    iomode = inb(DATA_REG);

    printf("New mode for set 2 is (1=output; 0=inout): 0x%x!\n", iomode);

    // read Simple I/O base address
    outb(SIMPLE_IO_BASE_ADDR_MSB_REG, ADDR_REG);
    unsigned short baseaddr = inb(DATA_REG);
    outb(SIMPLE_IO_BASE_ADDR_LSB_REG, ADDR_REG);
    baseaddr = (baseaddr << 8) | inb(DATA_REG);

    printf("Simple I/O base address: 0x%x\n", baseaddr);

    const unsigned short set2address = baseaddr + 1;

    printf("Simple I/O Set 2 address: 0x%x\n", set2address);

    if( ioperm(set2address, 1, 1) )
    {
        printf("Couldn't get the Simple I/O port\n");
        exit(1);
    }

    unsigned char ledstatus = inb(set2address);

    printf("Current LED status:0x%x\n", ledstatus);

    ledstatus = atoi( argv[1] );

    outb(ledstatus, set2address);

    ledstatus = inb(set2address);

    printf("New LED status:0x%x\n", ledstatus);

    if( ioperm(set2address, 1, 0) )
    {
        printf("Couldn't return the Simple I/O port\n");
        exit(1);
    }

    // Finish configuration by
    // returning to "Wait for Key" state
    outb(CONFIG_CTRL_REG, ADDR_REG);
    outb(CONFIG_COMPLETE, ADDR_REG);

    if( ioperm(ADDR_REG, 2, 0) )
    {
        printf("Couldn't return the ports\n");
        exit(1);
    }

    return 0;
}
 
Zurück
Oben