Skip to content

Commit

Permalink
Merge pull request #81 from qmsk/atx-psu-gpio-intr
Browse files Browse the repository at this point in the history
Fix I2C GPIO interrupts with ATX-PSU POWER_GOOD input
  • Loading branch information
SpComb authored Oct 19, 2024
2 parents 4cb2bcc + 55d15ef commit acdb297
Show file tree
Hide file tree
Showing 19 changed files with 375 additions and 183 deletions.
275 changes: 203 additions & 72 deletions components/atx_psu/atx_psu.c

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions components/atx_psu/include/atx_psu.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ 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.
*/
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);
Expand Down
2 changes: 1 addition & 1 deletion components/gpio/esp32/gpio_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
75 changes: 63 additions & 12 deletions components/gpio/esp32/gpio_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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;
}
}
Expand All @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion components/gpio/esp8266/gpio_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions components/gpio/esp8266/gpio_intr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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);
Expand Down
11 changes: 8 additions & 3 deletions components/gpio/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -45,15 +47,18 @@ 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();
#endif

#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);
Expand All @@ -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);
Expand Down
16 changes: 7 additions & 9 deletions components/gpio/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#if GPIO_I2C_ENABLED
#include <stdlib.h>

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])) {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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++) {
Expand Down
Loading

0 comments on commit acdb297

Please sign in to comment.