我已经开始为OpenBSD
从NXP编写I2C设备PCF8574的驱动程序。
驱动程序可以很好地编译并在启动时加载,但是我得到了以下消息:
pcfgpio0 at iic0 addr 0x40
gpio at pcfgpio0 not configured
如何配置驱动程序以在用户区使用它?
这是我的司机:
/* 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;
}
我也试图将其添加到内核配置中:
gpio* at pcfgpio?
但是我得到这个错误:
$ config PCF8574
cd /usr/obj/sys/arch/arm64/compile/PCF8574 && config -s /usr/src/sys -b /usr/src/sys/arch/arm64/compile/PCF8574/obj /usr/src/sys/arch/arm64/conf/PCF8574
/usr/src/sys/arch/arm64/conf/PCF8574:11: gpio's cannot attach to pcfgpio's
*** Stop.
*** Error 1 in /usr/src/sys/arch/arm64/compile/PCF8574 (Makefile:1462 'config')
$
我该如何解决?缺少什么?
谢谢!
答案 0 :(得分:0)
好的,我已经解决了这个问题。
我忘记将标识符gpiobus
添加到文件/usr/src/sys/dev/i2c/files.i2c
:
# NXP PCF8574 I/O port expander
device pcfgpio: gpiobus
attach pcfgpio at i2c
file dev/i2c/pcf8574.c pcfgpio
现在,以下内核配置可以正常运行了:
gpio* at pcfgpio?
驱动程序现在在用户区工作。 对不起,浪费您的时间。