Hello,
I am having some trouble using Zephyr I2C microchip,mcp230xx gpio expander interrupts with nRF5340 DK. I am using nRF Connect v2.3.0, and it appears that the devicetree parameter int-gpios is not yet merged into the current nRF Connect version. I am able to read the the pins using polling, but would like to get the interrupts working.
I have attempted copying over the following files to my workspace
- microchip,mcp230xx.yaml
- microchip,mcp23xxx.yaml
- gpio_mcp230xx.c
- gpio_mcp23xxx.c
- gpio_mcp230xx.h
- Kconfig.mcp23xxx
and updated
- gpio/Kconfig
- gpio/Kconfig.mcp23xxx
- gpio/CMakeLists.txt
however, I still do not understand how to implement the interrupt in my main.c code.
I have read over this previous case, https://devzone.nordicsemi.com/f/nordic-q-a/94886/gpio-p1-xx-interrupt-configuration, but it appears that it uses gpio_interrupt, which is implemented differently than the "int-gpios" used within the dts file for mcp230xx.
I have included my code in the attachments.
Best regards,
Victor
#include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/drivers/gpio.h> #include <zephyr/drivers/i2c.h> #define I2C1_NODE DT_NODELABEL(mcp23017_20) static const struct i2c_dt_spec gpioExpander = I2C_DT_SPEC_GET(I2C1_NODE); #define INT_NODE DT_PHANDLE(DT_PATH(soc, peripheral_40000000, i2c_9000, mcp23017_20), interrupt_gpios) /* STEP 9 - Increase the sleep time from 100ms to 10 minutes */ #define SLEEP_TIME_MS 10*60*1000 /* SW0_NODE is the devicetree node identifier for the node with alias "sw0" */ #define SW0_NODE DT_ALIAS(gpioext20p0) static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios); /* LED0_NODE is the devicetree node identifier for the node with alias "led0". */ #define LED0_NODE DT_ALIAS(led0) static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); /* STEP 4 - Define the callback function */ void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { gpio_pin_toggle_dt(&led); } /* STEP 5 - Define a variable of type static struct gpio_callback */ static struct gpio_callback button_cb_data; void main(void) { int ret; if(!device_is_ready(gpioExpander.bus)) { printk("I2C bus %s is not ready!\n\r", gpioExpander.bus->name); return; } if (!device_is_ready(led.port)) { return; } if (!device_is_ready(button.port)) { return; } ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); if (ret < 0) { return; } ret = gpio_pin_configure_dt(&button, GPIO_INPUT); if (ret < 0) { return; } /* STEP 3 - Configure the interrupt on the button's pin */ ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE ); /* STEP 6 - Initialize the static struct gpio_callback variable */ gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); /* STEP 7 - Add the callback function by calling gpio_add_callback() */ gpio_add_callback(button.port, &button_cb_data); while (1) { /* STEP 8 - Remove the polling code */ k_msleep(SLEEP_TIME_MS); } }
/ { gpio_external { compatible = "gpio-keys"; mcp23017_20p0: mcp23017_20p0 { gpios = <&mcp23017_20 0 GPIO_ACTIVE_HIGH>; }; mcp23017_20p1: mcp23017_20p1 { gpios = <&mcp23017_20 1 GPIO_ACTIVE_HIGH>; }; mcp23017_20p2: mcp23017_20p2 { gpios = <&mcp23017_20 2 GPIO_ACTIVE_HIGH>; }; mcp23017_20p3: mcp23017_20p3 { gpios = <&mcp23017_20 3 GPIO_ACTIVE_HIGH>; }; mcp23017_20p4: mcp23017_20p4 { gpios = <&mcp23017_20 4 GPIO_ACTIVE_HIGH>; }; mcp23017_20p5: mcp23017_20p5 { gpios = <&mcp23017_20 5 GPIO_ACTIVE_HIGH>; }; mcp23017_20p6: mcp23017_20p6 { gpios = <&mcp23017_20 6 GPIO_ACTIVE_HIGH>; }; mcp23017_20p7: mcp23017_20p7 { gpios = <&mcp23017_20 7 GPIO_ACTIVE_HIGH>; }; mcp23017_20p8: mcp23017_20p8 { gpios = <&mcp23017_20 8 GPIO_ACTIVE_HIGH>; }; mcp23017_20p9: mcp23017_20p9 { gpios = <&mcp23017_20 9 GPIO_ACTIVE_HIGH>; }; mcp23017_20p10: mcp23017_20p10 { gpios = <&mcp23017_20 10 GPIO_ACTIVE_HIGH>; }; mcp23017_20p11: mcp23017_20p11 { gpios = <&mcp23017_20 11 GPIO_ACTIVE_HIGH>; }; mcp23017_20p12: mcp23017_20p12 { gpios = <&mcp23017_20 12 GPIO_ACTIVE_HIGH>; }; mcp23017_20p13: mcp23017_20p13 { gpios = <&mcp23017_20 13 GPIO_ACTIVE_HIGH>; }; mcp23017_20p14: mcp23017_20p14 { gpios = <&mcp23017_20 14 GPIO_ACTIVE_HIGH>; }; mcp23017_20p15: mcp23017_20p15 { gpios = <&mcp23017_20 15 GPIO_ACTIVE_HIGH>; }; }; aliases { gpioext20p0 = &mcp23017_20p0; gpioext20p1 = &mcp23017_20p1; gpioext20p2 = &mcp23017_20p2; gpioext20p3 = &mcp23017_20p3; gpioext20p4 = &mcp23017_20p4; gpioext20p5 = &mcp23017_20p5; gpioext20p6 = &mcp23017_20p6; gpioext20p7 = &mcp23017_20p7; gpioext20p8 = &mcp23017_20p8; gpioext20p9 = &mcp23017_20p9; gpioext20p10 = &mcp23017_20p10; gpioext20p11 = &mcp23017_20p11; gpioext20p12 = &mcp23017_20p12; gpioext20p13 = &mcp23017_20p13; gpioext20p14 = &mcp23017_20p14; gpioext20p15 = &mcp23017_20p15; }; }; &i2c1 { mcp23017_20: mcp23017@20 { compatible = "microchip,mcp230xx"; reg = < 0x20 >; gpio-controller; ngpios = < 16 >; #gpio-cells = < 2 >; int-gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>; }; };
CONFIG_GPIO=y CONFIG_I2C=y CONFIG_GPIO_MCP230XX=y