diff --git a/components/atx_psu/atx_psu.c b/components/atx_psu/atx_psu.c index 196d2342..1d98f26e 100644 --- a/components/atx_psu/atx_psu.c +++ b/components/atx_psu/atx_psu.c @@ -8,34 +8,93 @@ #include -#define ATX_PSU_STATE_CLEAR_BIT (1 << 0) -#define ATX_PSU_STATE_BIT(bit) (1 << (bit + 1)) -#define ATX_PSU_STATE_BITS ((1 << ATX_PSU_BIT_COUNT) - 1 - 1) // all bits, but not the clear bit +#define ATX_PSU_BIT(bit) (1 << (bit)) +#define ATX_PSU_BITS ((1 << ATX_PSU_BIT_COUNT) - 1) + +#define ATX_PSU_EVENTS_SET_BIT (1 << 0) +#define ATX_PSU_EVENTS_CLEAR_BIT (1 << 1) +#define ATX_PSU_EVENTS_INTR_BIT (1 << 2) #define ATX_PSU_STATUS_POWER_ENABLE_BIT (1 << 0) #define ATX_PSU_STATUS_POWER_GOOD_BIT (1 << 1) -#define ATX_PSU_POWER_GOOD_TICKS (100 / portTICK_PERIOD_MS) +// polling for PG +#define ATX_PSU_INACTIVE_TICKS (10000 / portTICK_PERIOD_MS) +#define ATX_PSU_ACTIVATE_TICKS (100 / portTICK_PERIOD_MS) +#define ATX_PSU_ACTIVE_TICKS (1000 / portTICK_PERIOD_MS) enum atx_psu_state { - INACTIVE, - ACTIVATE, - ACTIVE, - DEACTIVATE, + INACTIVE, // waiting for any bit set + ACTIVATE, // waiting for power-good, or bits cleared + ACTIVE, // waiting for bits cleared, checking for power-bad + DEACTIVATE, // waiting for delayed power-off, or any bit set }; +static const char *atx_psu_state_str(enum atx_psu_state state) +{ + switch (state) { + case INACTIVE: return "INACTIVE"; + case ACTIVATE: return "ACTIVATE"; + case ACTIVE: return "ACTIVE"; + case DEACTIVATE: return "DEACTIVATE"; + default: return "?"; + } +} + struct atx_psu { struct atx_psu_options options; + enum atx_psu_state state; + TickType_t tick; + + EventGroupHandle_t events; - EventGroupHandle_t state, status; + // XXX: these are just atomic bitmasks + EventGroupHandle_t bits, status; } atx_psu; -static int atx_psu_init(struct atx_psu *atx_psu, struct atx_psu_options options) +static IRAM_ATTR void atx_psu_gpio_interrupt(gpio_pins_t pins, void *arg) +{ + struct atx_psu *atx_psu = arg; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + LOG_ISR_DEBUG("pins=" GPIO_PINS_FMT, GPIO_PINS_ARGS(pins)); + + if (!xEventGroupSetBitsFromISR(atx_psu->events, ATX_PSU_EVENTS_INTR_BIT, &xHigherPriorityTaskWoken)) { + LOG_ISR_WARN("xEventGroupSetBitsFromISR"); + } + +#if CONFIG_IDF_TARGET_ESP8266 + if (xHigherPriorityTaskWoken == pdTRUE) { + portYIELD_FROM_ISR(); + } +#else + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +#endif +} + +static int atx_psu_init(struct atx_psu *atx_psu, const struct atx_psu_options *options) { - atx_psu->options = options; + int err; + + atx_psu->options = *options; + + // use interrupts for power_good input pins + atx_psu->options.gpio_options.interrupt_pins = atx_psu->options.gpio_options.in_pins; + atx_psu->options.gpio_options.interrupt_func = atx_psu_gpio_interrupt; + atx_psu->options.gpio_options.interrupt_arg = atx_psu; + + if ((err = gpio_setup(&atx_psu->options.gpio_options))) { + LOG_ERROR("gpio_setup"); + return err; + } + + if (!(atx_psu->events = xEventGroupCreate())) { + LOG_ERROR("xEventGroupCreate"); + return -1; + } - if (!(atx_psu->state = xEventGroupCreate())) { + if (!(atx_psu->bits = xEventGroupCreate())) { LOG_ERROR("xEventGroupCreate"); return -1; } @@ -48,7 +107,7 @@ static int atx_psu_init(struct atx_psu *atx_psu, struct atx_psu_options options) return 0; } -int atx_psu_new(struct atx_psu **atx_psup, struct atx_psu_options options) +int atx_psu_new(struct atx_psu **atx_psup, const struct atx_psu_options *options) { struct atx_psu *atx_psu; int err = 0; @@ -75,22 +134,22 @@ int atx_psu_new(struct atx_psu **atx_psup, struct atx_psu_options options) static void set_power_enable(struct atx_psu *atx_psu) { - LOG_DEBUG("pins=" GPIO_PINS_FMT " -> high", GPIO_PINS_ARGS(atx_psu->options.gpio_options->out_pins)); + LOG_DEBUG("pins=" GPIO_PINS_FMT " -> high", GPIO_PINS_ARGS(atx_psu->options.gpio_options.out_pins)); xEventGroupSetBits(atx_psu->status, ATX_PSU_STATUS_POWER_ENABLE_BIT); - if (gpio_out_set_all(atx_psu->options.gpio_options)) { + if (gpio_out_set_all(&atx_psu->options.gpio_options)) { LOG_WARN("gpio_out_set_all"); } } static void clear_power_enable(struct atx_psu *atx_psu) { - LOG_DEBUG("pins=" GPIO_PINS_FMT " -> low", GPIO_PINS_ARGS(atx_psu->options.gpio_options->out_pins)); + LOG_DEBUG("pins=" GPIO_PINS_FMT " -> low", GPIO_PINS_ARGS(atx_psu->options.gpio_options.out_pins)); xEventGroupClearBits(atx_psu->status, ATX_PSU_STATUS_POWER_ENABLE_BIT | ATX_PSU_STATUS_POWER_GOOD_BIT); - if (gpio_out_clear(atx_psu->options.gpio_options)) { + if (gpio_out_clear(&atx_psu->options.gpio_options)) { LOG_WARN("gpio_out_clear"); } } @@ -100,11 +159,11 @@ static bool get_power_good(struct atx_psu *atx_psu) gpio_pins_t pins; int err; - if (!atx_psu->options.gpio_options->in_pins) { + if (!atx_psu->options.gpio_options.in_pins) { LOG_DEBUG("pins=" GPIO_PINS_FMT " unknown -> true", GPIO_PINS_ARGS(pins)); xEventGroupSetBits(atx_psu->status, ATX_PSU_STATUS_POWER_GOOD_BIT); return true; - } else if ((err = gpio_in_get(atx_psu->options.gpio_options, &pins))) { + } else if ((err = gpio_in_get(&atx_psu->options.gpio_options, &pins))) { LOG_DEBUG("pins=" GPIO_PINS_FMT " error -> true", GPIO_PINS_ARGS(pins)); return true; } else if (pins) { @@ -118,116 +177,186 @@ static bool get_power_good(struct atx_psu *atx_psu) } } -static EventBits_t atx_psu_wait(struct atx_psu *atx_psu, TickType_t ticks) +static void next_state(struct atx_psu *atx_psu, enum atx_psu_state state, TickType_t ticks) { - LOG_DEBUG("ticks=%d", ticks); + EventBits_t bits = xEventGroupGetBits(atx_psu->bits); + + LOG_DEBUG("%s -> %s<%08x> @ %d", atx_psu_state_str(atx_psu->state), atx_psu_state_str(state), bits, ticks); - // wait for any bit except clear, do not clear - return xEventGroupWaitBits(atx_psu->state, ATX_PSU_STATE_BITS, pdFALSE, pdFALSE, ticks) & ATX_PSU_STATE_BITS; + atx_psu->state = state; + atx_psu->tick = (ticks == portMAX_DELAY) ? 0 : xTaskGetTickCount() + ticks; } -static EventBits_t atx_psu_wait_clear(struct atx_psu *atx_psu, TickType_t ticks) +static EventBits_t atx_psu_wait(struct atx_psu *atx_psu) { - LOG_DEBUG("ticks=%d", ticks); + EventBits_t events = 0; + + // always follow input interrupts + events |= ATX_PSU_EVENTS_INTR_BIT; + + switch(atx_psu->state) { + case INACTIVE: + // indefinite wait for any bit to be set + events |= ATX_PSU_EVENTS_SET_BIT; + break; + + case ACTIVATE: + // fast wait for power-good + events |= ATX_PSU_EVENTS_CLEAR_BIT; + break; + + case ACTIVE: + // slow wait for power-bad + events |= ATX_PSU_EVENTS_CLEAR_BIT; + break; + + case DEACTIVATE: + // configurable wait for bits to remain cleared + events |= ATX_PSU_EVENTS_SET_BIT; + break; + + default: + LOG_FATAL("state=%d", atx_psu->state); + } + + // schedule + TickType_t ticks, tick = xTaskGetTickCount(); - // wait for clear bit and clear it - return xEventGroupWaitBits(atx_psu->state, ATX_PSU_STATE_CLEAR_BIT, pdTRUE, pdTRUE, ticks) & ATX_PSU_STATE_BITS; + if (!atx_psu->tick) { + ticks = portMAX_DELAY; // indefinite + } else if (atx_psu->tick > tick) { + ticks = atx_psu->tick - tick; + } else { + ticks = 0; // immediate + } + + LOG_DEBUG("state=%s events=%04x ticks=%d", atx_psu_state_str(atx_psu->state), events, ticks); + + // wait for any bit and clear + const BaseType_t xClearOnExit = pdTRUE; + const BaseType_t xWaitForAllBits = pdFALSE; + + events = xEventGroupWaitBits(atx_psu->events, events, xClearOnExit, xWaitForAllBits, ticks); + + // check state tick timeout + if (!atx_psu->tick) { + return false; + } else if (xTaskGetTickCount() >= atx_psu->tick) { + return true; + } else { + return false; + } } void atx_psu_main(void *arg) { struct atx_psu *atx_psu = arg; - enum atx_psu_state state = INACTIVE; for (;;) { - EventBits_t bits; + bool timeout = atx_psu_wait(atx_psu); + EventBits_t bits = xEventGroupGetBits(atx_psu->bits); + bool power_good = get_power_good(atx_psu); + + LOG_DEBUG("state=%s bits=%04x power_good=%d timeout=%d", atx_psu_state_str(atx_psu->state), bits, power_good, timeout); - switch(state) { + switch(atx_psu->state) { case INACTIVE: - LOG_DEBUG("INACTIVE..."); + if (bits) { + next_state(atx_psu, ACTIVATE, ATX_PSU_ACTIVATE_TICKS); - // indefinite wait for any bit - if ((bits = atx_psu_wait(atx_psu, portMAX_DELAY))) { - LOG_DEBUG("INACTIVE -> ACTIVE<%08x>", bits); + LOG_INFO("power-on"); set_power_enable(atx_psu); - state = ACTIVATE; + } else { - LOG_DEBUG("INACTIVE -> ACTIVATE"); + next_state(atx_psu, INACTIVE, ATX_PSU_INACTIVE_TICKS); } break; case ACTIVATE: - LOG_DEBUG("ACTIVATE..."); - - // indefinite wait for clear bit - if (get_power_good(atx_psu)) { - LOG_DEBUG("ACTIVATE -> ACTIVE"); - state = ACTIVE; - } else if ((bits = atx_psu_wait_clear(atx_psu, ATX_PSU_POWER_GOOD_TICKS))) { - // test power_good - } else { - LOG_DEBUG("ACTIVE -> DEACTIVATE"); + // poll for PG + if (!bits) { // delay deactivation - state = DEACTIVATE; + next_state(atx_psu, DEACTIVATE, atx_psu->options.timeout); + + } else if (power_good) { + LOG_INFO("power-good"); + + next_state(atx_psu, ACTIVE, ATX_PSU_ACTIVE_TICKS); + + } else if (timeout) { + // re-ACTIVATE to test power_good + next_state(atx_psu, ACTIVATE, ATX_PSU_ACTIVATE_TICKS); } break; case ACTIVE: - LOG_DEBUG("ACTIVE..."); - - // indefinite wait for clear bit - if ((bits = atx_psu_wait_clear(atx_psu, portMAX_DELAY))) { - LOG_DEBUG("ACTIVE -> ACTIVE<%08x>", bits); - } else { - LOG_DEBUG("ACTIVE -> DEACTIVATE"); + // wait for clear bit, poll for PG + if (!bits) { // delay deactivation - state = DEACTIVATE; + next_state(atx_psu, DEACTIVATE, atx_psu->options.timeout); + + } else if (!power_good) { + LOG_WARN("power-bad"); + + // re-ACTIVATE to test power_good + next_state(atx_psu, ACTIVATE, ATX_PSU_ACTIVATE_TICKS); + + } else if (timeout) { + next_state(atx_psu, ACTIVE, ATX_PSU_ACTIVE_TICKS); } break; case DEACTIVATE: - LOG_DEBUG("DEACTIVATE..."); - // wait for any bit or deactivate on timeout - if ((bits = atx_psu_wait(atx_psu, atx_psu->options.timeout))) { - LOG_DEBUG("DEACTIVATE -> ACTIVE<%08x>", bits); - state = ACTIVE; - } else { - LOG_DEBUG("DEACTIVATE -> INACTIVE"); + if (bits && power_good) { + // remain active + next_state(atx_psu, ACTIVE, ATX_PSU_ACTIVE_TICKS); + } else if (bits) { + // re-ACTIVATE to test power_good + next_state(atx_psu, ACTIVATE, ATX_PSU_ACTIVATE_TICKS); + } else if (timeout) { + LOG_INFO("power-off"); clear_power_enable(atx_psu); - state = INACTIVE; + + next_state(atx_psu, INACTIVE, ATX_PSU_INACTIVE_TICKS); + } else { + // remain in DEACTIVATE state } break; default: - abort(); + LOG_FATAL("state=%d", atx_psu->state); } } } void atx_psu_power_enable(struct atx_psu *atx_psu, enum atx_psu_bit bit) { - xEventGroupSetBits(atx_psu->state, ATX_PSU_STATE_BIT(bit)); + LOG_DEBUG("bit=%08x", ATX_PSU_BIT(bit)); + + xEventGroupSetBits(atx_psu->bits, ATX_PSU_BIT(bit)); + xEventGroupSetBits(atx_psu->events, ATX_PSU_EVENTS_SET_BIT); } int atx_psu_power_good(struct atx_psu *atx_psu, enum atx_psu_bit bit, TickType_t timeout) { - EventBits_t bits; + LOG_DEBUG("bit=%08x", ATX_PSU_BIT(bit)); - xEventGroupSetBits(atx_psu->state, ATX_PSU_STATE_BIT(bit)); + xEventGroupSetBits(atx_psu->bits, ATX_PSU_BIT(bit)); + xEventGroupSetBits(atx_psu->events, ATX_PSU_EVENTS_SET_BIT); - if (!atx_psu->options.gpio_options->in_pins) { + if (!atx_psu->options.gpio_options.in_pins) { LOG_DEBUG("power_good_gpio disabled"); return ATX_PSU_STATUS_POWER_GOOD_BIT; } else { - bits = xEventGroupWaitBits(atx_psu->status, ATX_PSU_STATUS_POWER_ENABLE_BIT | ATX_PSU_STATUS_POWER_GOOD_BIT, pdFALSE, pdTRUE, timeout); + EventBits_t bits = xEventGroupWaitBits(atx_psu->status, ATX_PSU_STATUS_POWER_ENABLE_BIT | ATX_PSU_STATUS_POWER_GOOD_BIT, pdFALSE, pdTRUE, timeout); - LOG_DEBUG("bits=%08x", bits); + //LOG_DEBUG("bits=%08x", bits); return (bits & ATX_PSU_STATUS_POWER_GOOD_BIT); } @@ -235,6 +364,8 @@ int atx_psu_power_good(struct atx_psu *atx_psu, enum atx_psu_bit bit, TickType_t void atx_psu_standby(struct atx_psu *atx_psu, enum atx_psu_bit bit) { - xEventGroupClearBits(atx_psu->state, ATX_PSU_STATE_BIT(bit)); - xEventGroupSetBits(atx_psu->state, ATX_PSU_STATE_CLEAR_BIT); + LOG_DEBUG("bit=%08x", ATX_PSU_BIT(bit)); + + xEventGroupClearBits(atx_psu->bits, ATX_PSU_BIT(bit)); + xEventGroupSetBits(atx_psu->events, ATX_PSU_EVENTS_CLEAR_BIT); } diff --git a/components/atx_psu/include/atx_psu.h b/components/atx_psu/include/atx_psu.h index 10fa3dbf..7ef56f29 100644 --- a/components/atx_psu/include/atx_psu.h +++ b/components/atx_psu/include/atx_psu.h @@ -37,7 +37,7 @@ struct atx_psu_options { * * Use <0 to disable. */ - const struct gpio_options *gpio_options; + struct gpio_options gpio_options; /* * Return ATX PSU into standby mode once all bits are inactive, and the timeout has passed. @@ -45,7 +45,7 @@ struct atx_psu_options { TickType_t timeout; }; -int atx_psu_new(struct atx_psu **atx_psup, struct atx_psu_options options); +int atx_psu_new(struct atx_psu **atx_psup, const struct atx_psu_options *options); /* Run as a separate task */ void atx_psu_main(void *arg); diff --git a/components/gpio/esp32/gpio_host.c b/components/gpio/esp32/gpio_host.c index 7b71ffa2..97e78e54 100644 --- a/components/gpio/esp32/gpio_host.c +++ b/components/gpio/esp32/gpio_host.c @@ -145,7 +145,7 @@ int gpio_host_setup(const struct gpio_options *options) gpio_host_setup_rtc(gpio, inverted, !inverted); } if (interrupt) { - gpio_intr_setup_pin(options, gpio); + gpio_intr_setup_host_pin(gpio, options); } } diff --git a/components/gpio/esp32/gpio_intr.c b/components/gpio/esp32/gpio_intr.c index 5573ec09..2a3fa432 100644 --- a/components/gpio/esp32/gpio_intr.c +++ b/components/gpio/esp32/gpio_intr.c @@ -11,7 +11,18 @@ intr_handle_t gpio_intr_handle; -const struct gpio_options *gpio_intr_options[GPIO_HOST_PIN_COUNT] = {}; +struct gpio_intr_options { + enum gpio_intr_type { + GPIO_INTR_TYPE_NONE = 0, + GPIO_INTR_TYPE_HOST, + GPIO_INTR_TYPE_I2C, + } type; + + union { + const struct gpio_options *host; + const struct gpio_i2c_dev *i2c_dev; + }; +} gpio_intr_options[GPIO_HOST_PIN_COUNT] = {}; static IRAM_ATTR void gpio_isr (void *arg) { @@ -21,16 +32,23 @@ static IRAM_ATTR void gpio_isr (void *arg) LOG_ISR_DEBUG("core=%d pins=" GPIO_PINS_FMT, core, GPIO_PINS_ARGS(pins)); for (gpio_pin_t gpio = 0; gpio < GPIO_HOST_PIN_COUNT; gpio++) { - const struct gpio_options *options; + if ((pins & GPIO_PINS(gpio))) { + const struct gpio_intr_options *options = &gpio_intr_options[gpio]; - if ((pins & GPIO_PINS(gpio)) && (options = gpio_intr_options[gpio])) { switch(options->type) { - case GPIO_TYPE_HOST: - gpio_host_intr_handler(options, pins); + case GPIO_INTR_TYPE_NONE: break; - case GPIO_TYPE_I2C: - gpio_i2c_intr_handler(options, pins); + case GPIO_INTR_TYPE_HOST: + LOG_ISR_DEBUG("pin=%d host options=%p", gpio, options->host); + gpio_host_intr_handler(options->host, pins); + break; + + case GPIO_INTR_TYPE_I2C: + for (const struct gpio_i2c_dev *i2c_dev = options->i2c_dev; i2c_dev; i2c_dev = i2c_dev->intr_link) { + LOG_ISR_DEBUG("pin=%d i2c dev=%p", gpio, i2c_dev); + gpio_i2c_intr_handler(i2c_dev, pins); + } break; } } @@ -53,16 +71,49 @@ int gpio_intr_init() return 0; } -void gpio_intr_setup_pin(const struct gpio_options *options, gpio_pin_t gpio) +void gpio_intr_setup_host_pin(gpio_pin_t gpio, const struct gpio_options *options) +{ + if (gpio >= GPIO_HOST_PIN_COUNT) { + LOG_FATAL("[%d] invalid gpio_pin_t", gpio); + } + + if (gpio_intr_options[gpio].type) { + LOG_WARN("[%d] intr pin conflict type=%u", gpio, gpio_intr_options[gpio].type); + } + + LOG_DEBUG("[%d] host options=%p", gpio, options); + + gpio_intr_options[gpio] = (struct gpio_intr_options) { + .type = GPIO_INTR_TYPE_HOST, + .host = options, + }; +} + +void gpio_intr_setup_i2c_pin(gpio_pin_t gpio, struct gpio_i2c_dev *i2c_dev) { if (gpio >= GPIO_HOST_PIN_COUNT) { - LOG_WARN("[%d] -> %p: invalid gpio_pin_t", gpio, options); - return; + LOG_FATAL("[%d] invalid gpio_pin_t", gpio); } - LOG_DEBUG("[%d] -> %p", gpio, options); + switch (gpio_intr_options[gpio].type) { + case GPIO_INTR_TYPE_NONE: + LOG_DEBUG("[%d] i2c dev=%p", gpio, i2c_dev); + break; + + case GPIO_INTR_TYPE_HOST: + LOG_WARN("[%d] intr pin conflict type=%u", gpio, gpio_intr_options[gpio].type); + break; + + case GPIO_INTR_TYPE_I2C: + LOG_DEBUG("[%d] i2c dev=%p link=%p", gpio, i2c_dev, gpio_intr_options[gpio].i2c_dev); + i2c_dev->intr_link = gpio_intr_options[gpio].i2c_dev; + break; + } - gpio_intr_options[gpio] = options; + gpio_intr_options[gpio] = (struct gpio_intr_options) { + .type = GPIO_INTR_TYPE_I2C, + .i2c_dev = i2c_dev, + }; } int gpio_intr_core() diff --git a/components/gpio/esp8266/gpio_host.c b/components/gpio/esp8266/gpio_host.c index ed472471..264c0b74 100644 --- a/components/gpio/esp8266/gpio_host.c +++ b/components/gpio/esp8266/gpio_host.c @@ -171,7 +171,7 @@ int gpio_host_setup(const struct gpio_options *options) } if (interrupt) { if (GPIO_HOST_PINS_HOST & GPIO_PINS(gpio)) { - gpio_intr_setup_pin(options, gpio); + gpio_intr_setup_host_pin(gpio, options); } } } diff --git a/components/gpio/esp8266/gpio_intr.c b/components/gpio/esp8266/gpio_intr.c index 3c05802d..72a58524 100644 --- a/components/gpio/esp8266/gpio_intr.c +++ b/components/gpio/esp8266/gpio_intr.c @@ -26,7 +26,8 @@ static IRAM_ATTR void gpio_isr (void *arg) #if GPIO_I2C_ENABLED case GPIO_TYPE_I2C: - gpio_i2c_intr_handler(options, pins); + // TODO: + gpio_i2c_intr_handler(i2c_dev, pins); break; #endif } @@ -44,7 +45,7 @@ int gpio_intr_init() return 0; } -void gpio_intr_setup_pin(const struct gpio_options *options, gpio_pin_t gpio) +void gpio_intr_setup_host_pin(gpio_pin_t gpio, const struct gpio_options *options) { if (gpio >= 16) { LOG_WARN("[%d] -> %p: invalid gpio_pin_t", gpio, options); diff --git a/components/gpio/gpio.h b/components/gpio/gpio.h index 27c59843..74cec041 100644 --- a/components/gpio/gpio.h +++ b/components/gpio/gpio.h @@ -27,6 +27,8 @@ struct gpio_i2c_options options; SemaphoreHandle_t mutex; union gpio_i2c_state state; + + const struct gpio_i2c_dev *intr_link; // multiple i2c devs sharing the same host intr pin const struct gpio_options *intr_pins[GPIO_I2C_PINS_MAX]; }; #endif @@ -45,7 +47,10 @@ int gpio_host_set_all(const struct gpio_options *options); /* gpio_intr.c */ int gpio_intr_init(); -void gpio_intr_setup_pin(const struct gpio_options *options, gpio_pin_t gpio); +void gpio_intr_setup_host_pin(gpio_pin_t gpio, const struct gpio_options *options); +#if GPIO_I2C_ENABLED + void gpio_intr_setup_i2c_pin(gpio_pin_t gpio, struct gpio_i2c_dev *i2c_dev); +#endif #if !CONFIG_IDF_TARGET_ESP8266 int gpio_intr_core(); @@ -53,7 +58,7 @@ void gpio_intr_setup_pin(const struct gpio_options *options, gpio_pin_t gpio); #if GPIO_I2C_ENABLED /* i2c.cc */ - void gpio_i2c_intr_handler (const struct gpio_options *options, gpio_pins_t pins); + void gpio_i2c_intr_handler (const struct gpio_i2c_dev *i2c_dev, gpio_pins_t pins); int gpio_i2c_setup(const struct gpio_options *options); int gpio_i2c_setup_input(const struct gpio_options *options, gpio_pins_t pins); @@ -62,7 +67,7 @@ void gpio_intr_setup_pin(const struct gpio_options *options, gpio_pin_t gpio); int gpio_i2c_set(const struct gpio_options *options, gpio_pins_t pins); /* gpio_i2c_pca54xx.c */ - int gpio_i2c_pca54xx_init(struct gpio_i2c_pca54xx_state *state); + int gpio_i2c_pca54xx_init(struct gpio_i2c_dev *i2c_dev); int gpio_i2c_pca54xx_setup(const struct gpio_options *options); int gpio_i2c_pca54xx_setup_input(const struct gpio_options *options, gpio_pins_t pins); int gpio_i2c_pca54xx_get(const struct gpio_options *options, gpio_pins_t *pins); diff --git a/components/gpio/i2c.c b/components/gpio/i2c.c index 17b217dd..4fbf0c7d 100644 --- a/components/gpio/i2c.c +++ b/components/gpio/i2c.c @@ -6,9 +6,9 @@ #if GPIO_I2C_ENABLED #include - IRAM_ATTR void gpio_i2c_intr_handler (const struct gpio_options *options, gpio_pins_t pins) + IRAM_ATTR void gpio_i2c_intr_handler (const struct gpio_i2c_dev *dev, gpio_pins_t pins) { - struct gpio_i2c_dev *dev = options->i2c_dev; + const struct gpio_options *options; for (unsigned i = 0; i < GPIO_I2C_PINS_MAX; i++) { if (!(options = dev->intr_pins[i])) { @@ -38,6 +38,8 @@ } if (options->int_pin > 0) { + gpio_intr_setup_i2c_pin(options->int_pin, dev); + if ((err = gpio_host_setup_intr_pin(options->int_pin, GPIO_INTR_NEGEDGE))) { LOG_ERROR("gpio_host_setup_intr_pin"); return err; @@ -47,7 +49,7 @@ switch(options->type) { case GPIO_I2C_TYPE_PCA9534: case GPIO_I2C_TYPE_PCA9554: - return gpio_i2c_pca54xx_init(&dev->state.pca54xx); + return gpio_i2c_pca54xx_init(dev); default: LOG_FATAL("unsupported type=%d", options->type); @@ -110,12 +112,8 @@ } if (options->interrupt_pins) { - if (options->i2c_dev->options.int_pin > 0) { - // XXX: multiple gpio_i2c_dev sharing the same int_pin? - gpio_intr_setup_pin(options, options->i2c_dev->options.int_pin); - } else { - LOG_ERROR("interrupt_pins without i2c_dev int_pin"); - return -1; + if (!options->i2c_dev->options.int_pin) { + LOG_WARN("interrupt_pins without i2c_dev int_pin"); } for (gpio_pin_t pin = 0; pin < GPIO_I2C_PINS_MAX; pin++) { diff --git a/components/gpio/i2c_pca55xx.c b/components/gpio/i2c_pca55xx.c index 943a419e..51714656 100644 --- a/components/gpio/i2c_pca55xx.c +++ b/components/gpio/i2c_pca55xx.c @@ -19,12 +19,12 @@ return (pins) & GPIO_I2C_PCA9554_PINS_MASK; } - static int gpio_i2c_pca54xx_write(const struct gpio_i2c_options *options, enum pca55xx_cmd cmd, uint8_t value, TickType_t timeout) + static int gpio_i2c_pca54xx_write(const struct gpio_i2c_options *options, enum pca55xx_cmd cmd, uint8_t value) { uint8_t buf[] = { cmd, value }; esp_err_t err; - if ((err = i2c_master_write_to_device(options->port, GPIO_I2C_PCA9554_ADDR(options->addr), buf, sizeof(buf), timeout))) { + if ((err = i2c_master_write_to_device(options->port, GPIO_I2C_PCA9554_ADDR(options->addr), buf, sizeof(buf), options->timeout))) { LOG_ERROR("i2c_master_write_to_device port=%d addr=%u: %s", options->port, GPIO_I2C_PCA9554_ADDR(options->addr), esp_err_to_name(err)); return -1; } @@ -32,13 +32,13 @@ return 0; } - static int gpio_i2c_pca54xx_read(const struct gpio_i2c_options *options, enum pca55xx_cmd cmd, uint8_t *value, TickType_t timeout) + static int gpio_i2c_pca54xx_read(const struct gpio_i2c_options *options, enum pca55xx_cmd cmd, uint8_t *value) { uint8_t wbuf[] = { cmd }; uint8_t rbuf[1] = { }; esp_err_t err; - if ((err = i2c_master_write_read_device(options->port, GPIO_I2C_PCA9554_ADDR(options->addr), wbuf, sizeof(wbuf), rbuf, sizeof(rbuf), timeout))) { + if ((err = i2c_master_write_read_device(options->port, GPIO_I2C_PCA9554_ADDR(options->addr), wbuf, sizeof(wbuf), rbuf, sizeof(rbuf), options->timeout))) { LOG_ERROR("i2c_master_write_to_device port=%d addr=%u: %s", options->port, GPIO_I2C_PCA9554_ADDR(options->addr), esp_err_to_name(err)); return -1; } @@ -48,12 +48,24 @@ return 0; } - static int gpio_i2c_pca54xx_input(struct gpio_i2c_dev *dev, uint8_t mask, uint8_t *valuep, TickType_t timeout) + static int gpio_i2c_pca54xx_clear(const struct gpio_i2c_dev *dev) { uint8_t value; int err; - if ((err = gpio_i2c_pca54xx_read(&dev->options, PCA55XX_CMD_INPUT_PORT, &value, timeout))) { + if ((err = gpio_i2c_pca54xx_read(&dev->options, PCA55XX_CMD_INPUT_PORT, &value))) { + return err; + } + + return 0; + } + + static int gpio_i2c_pca54xx_input(const struct gpio_i2c_dev *dev, uint8_t mask, uint8_t *valuep) + { + uint8_t value; + int err; + + if ((err = gpio_i2c_pca54xx_read(&dev->options, PCA55XX_CMD_INPUT_PORT, &value))) { return err; } @@ -62,6 +74,7 @@ return 0; } + // XXX: what timeout to use for locked operations on shared gpio_i2c_dev? static int gpio_i2c_pca54xx_output(struct gpio_i2c_dev *dev, uint8_t mask, uint8_t value, TickType_t timeout) { int err = 0; @@ -75,7 +88,7 @@ LOG_DEBUG("dev=%p mask=%02x value=%02x -> output=%02x", dev, mask, value, dev->state.pca54xx.output); - if ((err = gpio_i2c_pca54xx_write(&dev->options, PCA55XX_CMD_OUTPUT_PORT, dev->state.pca54xx.output, timeout))) { + if ((err = gpio_i2c_pca54xx_write(&dev->options, PCA55XX_CMD_OUTPUT_PORT, dev->state.pca54xx.output))) { LOG_ERROR("gpio_i2c_pca54xx_write"); goto error; } @@ -86,6 +99,7 @@ return err; } + // XXX: what timeout to use for locked operations on shared gpio_i2c_dev? static int gpio_i2c_pca54xx_config(struct gpio_i2c_dev *dev, uint8_t mask, uint8_t value, TickType_t timeout) { int err = 0; @@ -99,7 +113,7 @@ LOG_DEBUG("dev=%p mask=%02x value=%02x -> config=%02x", dev, mask, value, dev->state.pca54xx.config); - if ((err = gpio_i2c_pca54xx_write(&dev->options, PCA55XX_CMD_CONFIG_PORT, dev->state.pca54xx.config, timeout))) { + if ((err = gpio_i2c_pca54xx_write(&dev->options, PCA55XX_CMD_CONFIG_PORT, dev->state.pca54xx.config))) { LOG_ERROR("gpio_i2c_pca54xx_write"); goto error; } @@ -110,25 +124,34 @@ return err; } - int gpio_i2c_pca54xx_init(struct gpio_i2c_pca54xx_state *state) + int gpio_i2c_pca54xx_init(struct gpio_i2c_dev *i2c_dev) { + struct gpio_i2c_pca54xx_state *state = &i2c_dev->state.pca54xx; + int err; + state->output = 0xff; state->inversion = 0x00; state->config = 0xff; + // clear interrupts + if ((err = gpio_i2c_pca54xx_clear(i2c_dev))) { + return err; + } + return 0; } int gpio_i2c_pca54xx_setup(const struct gpio_options *options) { + struct gpio_i2c_dev *i2c_dev = options->i2c_dev; int err; - if ((err = gpio_i2c_pca54xx_output(options->i2c_dev, pca55x_pins(options->out_pins), pca55x_pins(0 ^ options->inverted_pins), options->i2c_timeout))) { + if ((err = gpio_i2c_pca54xx_output(i2c_dev, pca55x_pins(options->out_pins), pca55x_pins(0 ^ options->inverted_pins), i2c_dev->options.timeout))) { LOG_ERROR("gpio_i2c_pca54xx_output"); return err; } - if ((err = gpio_i2c_pca54xx_config(options->i2c_dev, pca55x_pins(options->in_pins | options->out_pins), pca55x_pins(~options->out_pins), options->i2c_timeout))) { + if ((err = gpio_i2c_pca54xx_config(i2c_dev, pca55x_pins(options->in_pins | options->out_pins), pca55x_pins(~options->out_pins), i2c_dev->options.timeout))) { LOG_ERROR("gpio_i2c_pca54xx_config"); return err; } @@ -138,15 +161,18 @@ int gpio_i2c_pca54xx_setup_input(const struct gpio_options *options, gpio_pins_t pins) { - return gpio_i2c_pca54xx_config(options->i2c_dev, pca55x_pins(options->in_pins | options->out_pins), pca55x_pins(~(options->out_pins & ~pins)), options->i2c_timeout); + struct gpio_i2c_dev *i2c_dev = options->i2c_dev; + + return gpio_i2c_pca54xx_config(i2c_dev, pca55x_pins(options->in_pins | options->out_pins), pca55x_pins(~(options->out_pins & ~pins)), i2c_dev->options.timeout); } int gpio_i2c_pca54xx_get(const struct gpio_options *options, gpio_pins_t *pins) { + struct gpio_i2c_dev *i2c_dev = options->i2c_dev; uint8_t value; int err; - if ((err = gpio_i2c_pca54xx_input(options->i2c_dev, pca55x_pins(options->in_pins), &value, options->i2c_timeout))) { + if ((err = gpio_i2c_pca54xx_input(i2c_dev, pca55x_pins(options->in_pins), &value))) { return err; } @@ -157,11 +183,16 @@ int gpio_i2c_pca54xx_setup_output(const struct gpio_options *options, gpio_pins_t pins) { - return gpio_i2c_pca54xx_config(options->i2c_dev, pca55x_pins(options->in_pins | options->out_pins), pca55x_pins(~(options->out_pins & pins)), options->i2c_timeout); + struct gpio_i2c_dev *i2c_dev = options->i2c_dev; + + return gpio_i2c_pca54xx_config(i2c_dev, pca55x_pins(options->in_pins | options->out_pins), pca55x_pins(~(options->out_pins & pins)), i2c_dev->options.timeout); } int gpio_i2c_pca54xx_set(const struct gpio_options *options, gpio_pins_t pins) { - return gpio_i2c_pca54xx_output(options->i2c_dev, pca55x_pins(options->out_pins), pca55x_pins(pins ^ options->inverted_pins), options->i2c_timeout); + struct gpio_i2c_dev *i2c_dev = options->i2c_dev; + + return gpio_i2c_pca54xx_output(i2c_dev, pca55x_pins(options->out_pins), pca55x_pins(pins ^ options->inverted_pins), i2c_dev->options.timeout); } + #endif diff --git a/components/gpio/include/gpio.h b/components/gpio/include/gpio.h index f396e773..ba4f4d98 100644 --- a/components/gpio/include/gpio.h +++ b/components/gpio/include/gpio.h @@ -146,9 +146,8 @@ enum gpio_type { enum gpio_i2c_type type; i2c_port_t port; uint8_t addr; + TickType_t timeout; gpio_pin_t int_pin; - - /* XXX: no support for multiple i2c_gpio_dev sharing the same int_pin */ }; struct gpio_i2c_dev; @@ -187,11 +186,6 @@ struct gpio_options { // interrupt handler gpio_interrupt_func_t interrupt_func; void *interrupt_arg; - -#if GPIO_I2C_ENABLED - // for i2c devices - TickType_t i2c_timeout; -#endif }; /* Setup input interrupt handler */ diff --git a/main/Kconfig b/main/Kconfig index 6759717a..a1faf2bb 100644 --- a/main/Kconfig +++ b/main/Kconfig @@ -342,8 +342,13 @@ menu "qmsk-esp-i2c" range 0 15 default 0 + config I2C_GPIO_TIMEOUT + depends on I2C_GPIO_ENABLED + int "Timeout for I2C GPIO expander operations" + default 20 + config I2C_GPIO_INT_PIN - depends on I2C_GPIO_TYPE_PCA9534 || I2C_GPIO_TYPE_PCA9554 + depends on I2C_GPIO_ENABLED int "HOST GPIO pin for I2C bus interrupt, 0 to disable" range 0 39 default 0 diff --git a/main/atx_psu.c b/main/atx_psu.c index c5da2185..78f4ba9e 100644 --- a/main/atx_psu.c +++ b/main/atx_psu.c @@ -2,6 +2,7 @@ #include "atx_psu_config.h" #include "atx_psu_gpio.h" #include "atx_psu_state.h" +#include "user.h" #include "tasks.h" #include @@ -23,16 +24,14 @@ int init_atx_psu() return 0; } - if ((err = init_atx_psu_gpio(&atx_psu_config))) { - LOG_ERROR("init_atx_psu_gpio"); + if ((err = config_atx_psu_gpio(&atx_psu_config, &options.gpio_options))) { + LOG_ERROR("config_atx_psu_gpio"); return err; } - config_atx_psu_gpio(&atx_psu_config, &options); - LOG_INFO("timeout=%u", options.timeout); - if (atx_psu_new(&atx_psu, options)) { + if (atx_psu_new(&atx_psu, &options)) { LOG_ERROR("atx_psu_new"); return -1; } @@ -79,7 +78,8 @@ int wait_atx_psu_bit(enum atx_psu_bit bit, TickType_t timeout) } else if (atx_psu_power_good(atx_psu, bit, timeout)) { return 0; } else { - LOG_WARN("power_good timeout=%d expired, is ATX-PSU connected?", timeout); + LOG_WARN("power_good timeout=%dms expired, is ATX-PSU connected?", timeout * portTICK_PERIOD_MS); + user_alert(USER_ALERT_ERROR_ATX_PSU_TIMEOUT); // TODO: clear alert? return -1; } } diff --git a/main/atx_psu_gpio.c b/main/atx_psu_gpio.c index d4742cc6..21beb1e0 100644 --- a/main/atx_psu_gpio.c +++ b/main/atx_psu_gpio.c @@ -4,19 +4,11 @@ #include -#if GPIO_I2C_ENABLED - #define ATX_PSU_GPIO_I2C_TIMEOUT (20 / portTICK_RATE_MS) -#endif - -struct gpio_options atx_psu_gpio_options = { - -}; - -int init_atx_psu_gpio(const struct atx_psu_config *config) +int config_atx_psu_gpio(const struct atx_psu_config *config, struct gpio_options *gpio_options) { int err; - if ((err = set_gpio_type(&atx_psu_gpio_options, config->gpio_type))) { + if ((err = set_gpio_type(gpio_options, config->gpio_type))) { LOG_ERROR("invalid gpio_type=%d", config->gpio_type); return err; } @@ -28,10 +20,10 @@ int init_atx_psu_gpio(const struct atx_psu_config *config) config->power_enable_gpio ); - atx_psu_gpio_options.out_pins |= gpio_host_pin(config->power_enable_gpio); + gpio_options->out_pins |= gpio_host_pin(config->power_enable_gpio); if (config->power_enable_gpio_mode == ATX_PSU_GPIO_MODE_LOW) { - atx_psu_gpio_options.inverted_pins |= gpio_host_pin(config->power_enable_gpio); + gpio_options->inverted_pins |= gpio_host_pin(config->power_enable_gpio); } } @@ -42,10 +34,10 @@ int init_atx_psu_gpio(const struct atx_psu_config *config) config->power_good_gpio ); - atx_psu_gpio_options.in_pins |= gpio_host_pin(config->power_good_gpio); + gpio_options->in_pins |= gpio_host_pin(config->power_good_gpio); if (config->power_good_gpio_mode == ATX_PSU_GPIO_MODE_LOW) { - atx_psu_gpio_options.inverted_pins |= gpio_host_pin(config->power_good_gpio); + gpio_options->inverted_pins |= gpio_host_pin(config->power_good_gpio); } } @@ -53,43 +45,31 @@ int init_atx_psu_gpio(const struct atx_psu_config *config) const struct gpio_i2c_options *i2c_options; #endif - switch(atx_psu_gpio_options.type) { + switch(gpio_options->type) { case GPIO_TYPE_HOST: LOG_INFO("gpio host: in_pins=" GPIO_PINS_FMT " out_pins=" GPIO_PINS_FMT " inverted_pins=" GPIO_PINS_FMT, - GPIO_PINS_ARGS(atx_psu_gpio_options.in_pins), - GPIO_PINS_ARGS(atx_psu_gpio_options.out_pins), - GPIO_PINS_ARGS(atx_psu_gpio_options.inverted_pins) + GPIO_PINS_ARGS(gpio_options->in_pins), + GPIO_PINS_ARGS(gpio_options->out_pins), + GPIO_PINS_ARGS(gpio_options->inverted_pins) ); break; #if GPIO_I2C_ENABLED case GPIO_TYPE_I2C: - i2c_options = gpio_i2c_options(atx_psu_gpio_options.i2c_dev); - - atx_psu_gpio_options.i2c_timeout = ATX_PSU_GPIO_I2C_TIMEOUT; + i2c_options = gpio_i2c_options(gpio_options->i2c_dev); LOG_INFO("gpio i2c type=%s port=%d addr=%u timeout=%u: in_pins=" GPIO_PINS_FMT " out_pins=" GPIO_PINS_FMT " inverted_pins=" GPIO_PINS_FMT, config_enum_to_string(i2c_gpio_type_enum, i2c_options->type) ?: "?", i2c_options->port, i2c_options->addr, - atx_psu_gpio_options.i2c_timeout, - GPIO_PINS_ARGS(atx_psu_gpio_options.in_pins), - GPIO_PINS_ARGS(atx_psu_gpio_options.out_pins), - GPIO_PINS_ARGS(atx_psu_gpio_options.inverted_pins) + i2c_options->timeout, + GPIO_PINS_ARGS(gpio_options->in_pins), + GPIO_PINS_ARGS(gpio_options->out_pins), + GPIO_PINS_ARGS(gpio_options->inverted_pins) ); break; #endif } - if ((err = gpio_setup(&atx_psu_gpio_options))) { - LOG_ERROR("gpio_setup"); - return err; - } - return 0; } - -void config_atx_psu_gpio(const struct atx_psu_config *config, struct atx_psu_options *options) -{ - options->gpio_options = &atx_psu_gpio_options; -} diff --git a/main/atx_psu_gpio.h b/main/atx_psu_gpio.h index 686dd7ea..adce0594 100644 --- a/main/atx_psu_gpio.h +++ b/main/atx_psu_gpio.h @@ -4,5 +4,4 @@ #include -int init_atx_psu_gpio(const struct atx_psu_config *config); -void config_atx_psu_gpio(const struct atx_psu_config *config, struct atx_psu_options *options); +int config_atx_psu_gpio(const struct atx_psu_config *config, struct gpio_options *gpio_options); diff --git a/main/i2c_gpio.c b/main/i2c_gpio.c index 0f2830e5..b9e8c2d5 100644 --- a/main/i2c_gpio.c +++ b/main/i2c_gpio.c @@ -22,11 +22,13 @@ .type = GPIO_I2C_TYPE_PCA9534, .port = I2C_MASTER_PORT, .addr = CONFIG_I2C_GPIO_ADDR_PCA9534, + .timeout = (CONFIG_I2C_GPIO_TIMEOUT / portTICK_RATE_MS), .int_pin = CONFIG_I2C_GPIO_INT_PIN, #elif CONFIG_I2C_GPIO_TYPE_PCA9554 .type = GPIO_I2C_TYPE_PCA9554, .port = I2C_MASTER_PORT, .addr = CONFIG_I2C_GPIO_ADDR_PCA9554, + .timeout = (CONFIG_I2C_GPIO_TIMEOUT / portTICK_RATE_MS), .int_pin = CONFIG_I2C_GPIO_INT_PIN, #else #error "Invalid I2C_GPIO_TYPE configured" @@ -99,6 +101,7 @@ .type = config->type, .port = I2C_MASTER_PORT, .addr = config->addr, + .timeout = (CONFIG_I2C_GPIO_TIMEOUT / portTICK_RATE_MS), .int_pin = config->int_pin, }; diff --git a/main/leds_gpio.c b/main/leds_gpio.c index 2948f094..ad22ca5d 100644 --- a/main/leds_gpio.c +++ b/main/leds_gpio.c @@ -9,10 +9,6 @@ #if CONFIG_LEDS_GPIO_ENABLED - #if GPIO_I2C_ENABLED - #define LEDS_GPIO_I2C_TIMEOUT (20 / portTICK_RATE_MS) - #endif - // by interface struct gpio_options leds_gpio_options[LEDS_INTERFACE_COUNT] = { #if CONFIG_LEDS_SPI_ENABLED @@ -104,8 +100,6 @@ case GPIO_TYPE_I2C: i2c_options = gpio_i2c_options(options->i2c_dev); - options->i2c_timeout = LEDS_GPIO_I2C_TIMEOUT; - LOG_INFO("leds gpio[%s]: i2c type=%s port=%u addr=%u: out_pins=" GPIO_PINS_FMT " inverted_pins=" GPIO_PINS_FMT, config_enum_to_string(leds_interface_enum, interface), config_enum_to_string(i2c_gpio_type_enum, i2c_options->type) ?: "?", diff --git a/main/user.c b/main/user.c index 8a4223b1..a0709d83 100644 --- a/main/user.c +++ b/main/user.c @@ -43,6 +43,11 @@ static const char *user_alert_str(enum user_alert alert) case USER_ALERT_ERROR_WIFI: return "ERROR_WIFI"; case USER_ALERT_ERROR_START: return "ERROR_START"; case USER_ALERT_ERROR_DMX: return "ERROR_DMX"; + + case USER_ALERT_ERROR_LEDS_SEQUENCE: return "ERROR_LEDS_SEQUENCE"; + case USER_ALERT_ERROR_LEDS_SEQUENCE_READ: return "ERROR_LEDS_SEQUENCE_READ"; + case USER_ALERT_ERROR_ATX_PSU_TIMEOUT: return "ERROR_ATX_PSU_TIMEOUT"; + default: return NULL; } } diff --git a/main/user.h b/main/user.h index f567755b..8d800503 100644 --- a/main/user.h +++ b/main/user.h @@ -30,6 +30,7 @@ enum user_alert { USER_ALERT_ERROR_DMX, USER_ALERT_ERROR_LEDS_SEQUENCE, USER_ALERT_ERROR_LEDS_SEQUENCE_READ, + USER_ALERT_ERROR_ATX_PSU_TIMEOUT, USER_ALERT_MAX }; diff --git a/main/user_leds.c b/main/user_leds.c index 6d26bd46..5763c3bb 100644 --- a/main/user_leds.c +++ b/main/user_leds.c @@ -32,6 +32,7 @@ enum user_leds_state user_alert_led_state[USER_ALERT_MAX] = { [USER_ALERT_ERROR_DMX] = USER_LEDS_ON, [USER_ALERT_ERROR_LEDS_SEQUENCE] = USER_LEDS_ON, [USER_ALERT_ERROR_LEDS_SEQUENCE_READ] = USER_LEDS_FLASH, + [USER_ALERT_ERROR_ATX_PSU_TIMEOUT] = USER_LEDS_ON, }; // state @@ -45,10 +46,6 @@ bool user_leds_override[USER_LEDS_COUNT]; QueueHandle_t user_leds_input_queue; // config -#if GPIO_I2C_ENABLED - #define USER_LEDS_GPIO_I2C_TIMEOUT (20 / portTICK_RATE_MS) -#endif - #define USER_LED_MODE_OUTPUT_BITS (USER_LEDS_MODE_OUTPUT_BIT) #if CONFIG_STATUS_LEDS_USER_MODE_TEST #define USER_LED_MODE_INPUT_BITS (USER_LEDS_MODE_INPUT_BIT | USER_LEDS_MODE_INTERRUPT_BIT) @@ -108,7 +105,6 @@ static struct gpio_options user_leds_gpio = { .type = GPIO_TYPE_HOST, #elif CONFIG_STATUS_LEDS_GPIO_TYPE_I2C_GPIO_0 .type = GPIO_TYPE_I2C, - .i2c_timeout = USER_LEDS_GPIO_I2C_TIMEOUT, #else #error "Invalid STATUS_LEDS_GPIO_TYPE" #endif @@ -165,7 +161,7 @@ int init_user_leds() } #ifdef USER_LEDS_I2C_GPIO_DEV - // requires init_i2c_gpio() + // after init_i2c_gpio() user_leds_gpio.i2c_dev = USER_LEDS_I2C_GPIO_DEV; #endif @@ -176,9 +172,7 @@ int init_user_leds() #if GPIO_I2C_ENABLED case GPIO_TYPE_I2C: - LOG_INFO("i2c gpio: timeout=%d", - user_leds_gpio.i2c_timeout - ); + LOG_INFO("i2c gpio"); break; #endif }