Danke Danke:  0
Dislikes Dislikes:  0
Ergebnis 1 bis 4 von 4

Thema: OpenBSD: Kernel: Nur einzelnes Modul bzw. einzelne Datei kompilieren und linken

  1. #1

    Registriert seit
    03.07.15
    Danke (erhalten)
    2
    Gefällt mir (erhalten)
    7

    Standard OpenBSD: Kernel: Nur einzelnes Modul bzw. einzelne Datei kompilieren und linken

    Anzeige
    Hallo,

    Schreibe gerade einen Treiber (für den I/O Port Expander PCF8574 von NXP) für OpenBSD.
    Es bestehen noch Probleme. Und zwar bekomme ich immer "device is not configured".
    Diese Probleme möchte ich noch gerne beseitigen.

    Kann man beim OpenBSD Kernel nur einzelne Module bzw. Dateien kompilieren und anschließend linken?
    Müsste ja irgendwie gehen. Denn wenn ich den Code vom Treiber ändere und nochmal make eingebe kompiliert
    er der den Kernel komplett, was er eigentlich nicht bräuchte und deswegen so lange dauert.

    Vorweg vielen Dank!

    Edit:
    Eigentlich sollte ja make dafür sorgen, dass nicht jedes mal alles nochmal kompiliert wird. Aber irgendie
    klappt das nicht. Das Testsystem ist ein PINE64 ROCK64 (Arch: arm64) Board.
    Geändert von fork(Agent Smith) (06.08.18 um 03:03 Uhr)
    /* Beware of bugs in the above code;
    I have only proved it correct, not tried it. */


    Original quote by Donald E. Knuth

  2. #2
    Moderator Avatar von Chromatin
    Registriert seit
    30.06.08
    Danke (erhalten)
    32
    Gefällt mir (erhalten)
    846

    Standard

    Check mal das Datum deiner Sourcen.

    *scnr*
    Wenn ein Gesetz nicht gerecht ist, dann geht die Gerechtigkeit vor dem Gesetz!

    Habo Blog - http://blog.hackerboard.de/

  3. Gefällt mir fork(Agent Smith), bitmuncher liked this post
  4. #3

    Registriert seit
    03.07.15
    Danke (erhalten)
    2
    Gefällt mir (erhalten)
    7

    Standard

    Zitat Zitat von Chromatin Beitrag anzeigen
    Check mal das Datum deiner Sourcen.

    *scnr*
    OMG! Ja, dass war das Problem. Die Systemzeit war nicht korrekt.
    Jetzt verhält sich make richtig.

    Edit:
    Das Problem mit "Device is not configured" habe ich hinbekommen. Der Treiber
    funktioniert jetzt. Getestet mit einer Testschaltung und gpioctl.
    Geändert von fork(Agent Smith) (07.08.18 um 06:12 Uhr)
    /* Beware of bugs in the above code;
    I have only proved it correct, not tried it. */


    Original quote by Donald E. Knuth

  5. Gefällt mir bitmuncher liked this post
  6. #4

    Registriert seit
    03.07.15
    Danke (erhalten)
    2
    Gefällt mir (erhalten)
    7

    Standard

    Anzeige
    Falls wer den Treiber benötigt. Hier der Quellcode:
    Code:
    /* Driver for the NXP PCF8574(A) Remote 8-bit I/O expander */
    
    #include <sys/param.h>
    #include <sys/systm.h>
    #include <sys/device.h>
    #include <sys/gpio.h>
    
    #include <dev/i2c/i2cvar.h>
    #include <dev/gpio/gpiovar.h>
    
    #define PCFGPIO_NPINS        8
    
    struct pcfgpio_softc {
        struct device             sc_dev;
        i2c_tag_t                sc_tag;
        i2c_addr_t                sc_addr;
        int                        sc_node;
    
        u_int8_t                sc_npins;
    
        struct gpio_chipset_tag    sc_gpio_gc;
        gpio_pin_t                sc_gpio_pins[PCFGPIO_NPINS];
    };
    
    int pcfgpio_match(struct device *, void *, void *);
    void pcfgpio_attach(struct device *, struct device *, void *);
    uint8_t pcfgpio_read(struct pcfgpio_softc *);
    void pcfgpio_write(struct pcfgpio_softc *, uint8_t);
    int pcfgpio_pin_read(void *, int);
    void pcfgpio_pin_write(void *, int, int);
    void pcfgpio_pin_ctl(void *, int, int);
    
    struct cfattach pcfgpio_ca = {
        sizeof(struct pcfgpio_softc), pcfgpio_match, pcfgpio_attach
    };
    
    struct cfdriver pcfgpio_cd = {
        NULL, "pcfgpio", DV_DULL
    };
    
    int
    pcfgpio_match(struct device *parent, void *match, void *aux)
    {
        struct i2c_attach_args *ia = aux;
    
        if ((strcmp(ia->ia_name, "nxp,pcf8574") == 0) ||
            (strcmp(ia->ia_name, "nxp,pcf8574a") == 0))
            return (1);
        return (0);
    }
    
    void
    pcfgpio_attach(struct device *parent, struct device *self, void *aux)
    {
        struct pcfgpio_softc *sc = (struct pcfgpio_softc *)self;
        struct i2c_attach_args *ia = aux;
        struct gpiobus_attach_args gba;
        int i;
    
        sc->sc_tag = ia->ia_tag;
        sc->sc_addr = ia->ia_addr;
        sc->sc_npins = PCFGPIO_NPINS;
        sc->sc_node = *(int *)ia->ia_cookie;
    
        printf("\n");
    
        for (i = 0; i < sc->sc_npins; i++) {
            sc->sc_gpio_pins[i].pin_num = i;
            sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INOUT | 
                GPIO_PIN_OPENDRAIN | GPIO_PIN_INVOUT;
    
            sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT;
            sc->sc_gpio_pins[i].pin_state = 0;
        }
    
        pcfgpio_write(sc, 0xFF);
    
        sc->sc_gpio_gc.gp_cookie = sc;
        sc->sc_gpio_gc.gp_pin_read = pcfgpio_pin_read;
        sc->sc_gpio_gc.gp_pin_write = pcfgpio_pin_write;
        sc->sc_gpio_gc.gp_pin_ctl = pcfgpio_pin_ctl;
    
        gba.gba_name = "gpio";
        gba.gba_gc = &sc->sc_gpio_gc;
        gba.gba_pins = sc->sc_gpio_pins;
        gba.gba_npins = sc->sc_npins;
        config_found(&sc->sc_dev, &gba, gpiobus_print);
    }
    
    uint8_t
    pcfgpio_read(struct pcfgpio_softc *sc)
    {
        uint8_t val;
    
        iic_acquire_bus(sc->sc_tag, 0);
        if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
            NULL, 0, &val, sizeof(val), 0)) {
            printf("%s: pcfgpio_read: failed to read\n",
                sc->sc_dev.dv_xname);
            iic_release_bus(sc->sc_tag, 0);
            return (0);
        }
        iic_release_bus(sc->sc_tag, 0);
        return val;
    }
    
    void
    pcfgpio_write(struct pcfgpio_softc *sc, uint8_t val)
    {
        iic_acquire_bus(sc->sc_tag, 0);
        if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr,
            &val, sizeof val, NULL, 0, 0)) {
            printf("%s: pcfgpio_write: failed to write\n",
                sc->sc_dev.dv_xname);
            iic_release_bus(sc->sc_tag, 0);
            return;
        }
        iic_release_bus(sc->sc_tag, 0);
    }
    
    int
    pcfgpio_pin_read(void *arg, int pin)
    {
        struct pcfgpio_softc *sc = arg;
        uint8_t tmp;
    
        if (pin >= sc->sc_npins)
            return 0;
        if (!ISSET(sc->sc_gpio_pins[pin].pin_flags, GPIO_PIN_INPUT))
            pcfgpio_pin_write(sc, pin, GPIO_PIN_HIGH);
        tmp = pcfgpio_read(sc);
        if (tmp & (1 << pin))
            sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
        else
            sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
        return sc->sc_gpio_pins[pin].pin_state;
    }
    
    void
    pcfgpio_pin_write(void *arg, int pin, int val)
    {
        struct pcfgpio_softc *sc = arg;
        int i;
        uint8_t tmp = 0x00;
    
        if (pin >= sc->sc_npins)
            return;
        for (i = 0; i < sc->sc_npins; i++)
            if (sc->sc_gpio_pins[i].pin_state == GPIO_PIN_LOW)
                tmp |= (1 << i);
        if (val == GPIO_PIN_HIGH) {
            tmp &= ~(1 << pin);
            pcfgpio_write(sc, tmp);
            sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_HIGH;
        } else {
            tmp |= 1 << pin;
            pcfgpio_write(sc, tmp);
            sc->sc_gpio_pins[pin].pin_state = GPIO_PIN_LOW;
        }
    }
    
    void
    pcfgpio_pin_ctl(void *arg, int pin, int flags)
    {
        struct pcfgpio_softc *sc = arg;
    
        if (ISSET(flags, GPIO_PIN_INPUT)) {
            pcfgpio_pin_write(sc, pin, GPIO_PIN_HIGH);
            sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_INPUT;
        } else
            sc->sc_gpio_pins[pin].pin_flags = GPIO_PIN_OUTPUT;
    }
    Folgendes in der Datei /usr/src/sys/dev/i2c/files.i2c hinzufügen:
    Code:
    # NXP PCF8574 I/O port expander
    device    pcfgpio: gpiobus
    attach    pcfgpio at i2c
    file    dev/i2c/pcf8574.c            pcfgpio
    Denn Quellcode vom Treiber natürlich unter /usr/src/sys/dev/i2c/ plazieren. Hier im Beispiel habe ich die Datei pcf8574.c benannt.
    Und danach vor dem Kompilieren die Kernel Konfiguration anpassen, also folgendes hinzufügen:
    Code:
    pcfgpio* at i2c?
    gpio* at pcfgpio?
    Viel Spaß damit!

    Edit:
    Natürlich noch den Device tree anpassen:
    Code:
    &i2c0 {
    	status = "okay";
    
    	pcf8574: gpio@20 {
    		compatible = "nxp,pcf8574";
            status = "okay";
            reg = <0x20>;
            #gpio-cells = <2>;
            gpio-controller;
    	};
    };
    Adresse des Bausteins und i2c interface ggf. anpassen.
    Geändert von fork(Agent Smith) (08.08.18 um 12:58 Uhr)
    /* Beware of bugs in the above code;
    I have only proved it correct, not tried it. */


    Original quote by Donald E. Knuth

  7. Gefällt mir Chromatin liked this post

Ähnliche Themen

  1. Linux Kernel Modul
    Von Fluffy im Forum Code Kitchen
    Antworten: 13
    Letzter Beitrag: 27.06.16, 11:37
  2. Einzelne Datei immer mit bestimmtem Programm öffnen
    Von devildire im Forum Windows 7
    Antworten: 5
    Letzter Beitrag: 03.06.13, 10:25
  3. Antworten: 2
    Letzter Beitrag: 06.05.09, 11:35
  4. einzelne zeilen einer datei löschen
    Von Nimda05 im Forum Linux/UNIX
    Antworten: 3
    Letzter Beitrag: 23.05.07, 20:55
  5. Kernel Kompilieren AMD64
    Von Hephaistos im Forum Linux/UNIX
    Antworten: 2
    Letzter Beitrag: 11.03.05, 12:33

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •