Using zephyr MCP23xxx driver for buttons with Nordic nrf CAF buttons module?

Developing a device based on the nrf5340/nrf7002 pair, with a user interface.

I decided to use the Nordic 'buttons' and 'click-buttons' modules from the CAF framework for my device button handling.

This worked fine on the dev board (nrf5340DK). 

However, on the real board, we used a MCP23017 ioexpander for the button IOs (there are never enough direct gpios, especially when the nrf7002 interface uses up 11 all by itself...).

In principle, it seems I just update the DTS to change the gpio controller from gpio0 to ioexp0, and its all good...

however, when compiling with this DTS I get:

connect/nrf/subsys/caf/modules/buttons.c
In file included from C:/work/dev/nordic_connect/zephyr/include/zephyr/arch/arm/arch.h:20,
from C:/work/dev/nordic_connect/zephyr/include/zephyr/arch/cpu.h:19,
from C:/work/dev/nordic_connect/zephyr/include/zephyr/kernel_includes.h:37,
from C:/work/dev/nordic_connect/zephyr/include/zephyr/kernel.h:17,
from C:/work/dev/nordic_connect/nrf/subsys/caf/modules/buttons.c:9:
C:/work/dev/if-device-nrf53/cc1-med/build/zephyr/include/generated/devicetree_generated.h:2424:52: error: 'DT_N_S_soc_S_peripheral_50000000_S_i2c_9000_S_mcp23017_20_P_port' undeclared here (not in a function); did you mean 'DT_N_S_soc_S_peripheral_50000000_S_i2c_9000_S_mcp23017_20_P_reg'?
2424 | #define DT_N_S_buttons_S_button_0_P_gpios_IDX_0_PH DT_N_S_soc_S_peripheral_50000000_S_i2c_9000_S_mcp23017_20
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree.h:4343:29: note: in definition of macro 'DT_CAT3'
4343 | #define DT_CAT3(a1, a2, a3) a1 ## a2 ## a3
| ^~
C:/work/dev/if-device-nrf53/cc1-med/configuration/cc1medv1_nrf5340_cpuapp/cc1_med_buttons_def.h:32:19: note: in expansion of macro 'DT_PROP'
32 | { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_left), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_left), gpios) }, // 'left' button
| ^~~~~~~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree.h:4349:41: note: in expansion of macro 'DT_N_S_buttons_S_button_0_P_gpios_IDX_0_PH'
4349 | #define DT_CAT6(a1, a2, a3, a4, a5, a6) a1 ## a2 ## a3 ## a4 ## a5 ## a6
| ^~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree.h:1592:9: note: in expansion of macro 'DT_CAT6'
1592 | DT_CAT6(node_id, _P_, prop, _IDX_, idx, _PH)
| ^~~~~~~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree/gpio.h:54:9: note: in expansion of macro 'DT_PHANDLE_BY_IDX'
54 | DT_PHANDLE_BY_IDX(node_id, gpio_pha, idx)
| ^~~~~~~~~~~~~~~~~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree/gpio.h:66:9: note: in expansion of macro 'DT_GPIO_CTLR_BY_IDX'
66 | DT_GPIO_CTLR_BY_IDX(node_id, gpio_pha, 0)
| ^~~~~~~~~~~~~~~~~~~
C:/work/dev/if-device-nrf53/cc1-med/configuration/cc1medv1_nrf5340_cpuapp/cc1_med_buttons_def.h:32:27: note: in expansion of macro 'DT_GPIO_CTLR'
32 | { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_left), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_left), gpios) }, // 'left' button
| ^~~~~~~~~~~~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree.h:4341:24: note: in expansion of macro 'DT_N_ALIAS_butt_lef'
4341 | #define DT_CAT(a1, a2) a1 ## a2
| ^~
C:/work/dev/nordic_connect/zephyr/include/zephyr/devicetree.h:238:25: note: in expansion of macro 'DT_CAT'
238 | #define DT_ALIAS(alias) DT_CAT(DT_N_ALIAS_, alias)
| ^~~~~~
C:/work/dev/if-device-nrf53/cc1-med/configuration/cc1medv1_nrf5340_cpuapp/cc1_med_buttons_def.h:32:40: note: in expansion of macro 'DT_ALIAS'
32 | { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_left), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_left), gpios) }, // 'left' button
| ^~~~~~~~

Does this mean the CAF buttons module cannot be used with the MCP23xxx driver? I thought the whole point of this insanely complicated DTS stuff was to make this sort of hw transition easy???

hoping I have just misunderstood...

Parents
  • this is my buttons_def.h:

    static const struct gpio_pin col[] = {
    };

    static const struct gpio_pin row[] = {
            { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_left), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_left), gpios)  },              // 'left' button
            { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_home), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_home), gpios)  },              // 'home' button
            { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_right), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_right), gpios) },                // 'right button
            { .port = DT_PROP(DT_GPIO_CTLR(DT_ALIAS(butt_alert), gpios), port), .pin = DT_GPIO_PIN(DT_ALIAS(butt_alert), gpios) },                // alert hall sensor
    };
    I guess the problem is that the definition expects a port/pin pair of integers, instead of a DT_NODE to define the GPIO and there is no 'port' on the ioexpander?
  • Hi BrianW,

    I thought the whole point of this insanely complicated DTS stuff was to make this sort of hw transition easy???

    This depends on the kind of replacement. For example, replacing the UART output of a module from an actual UART port to a USB CDC ACM is simple, because the USB CDC ACM supports the same APIs too.

    Though for the case of GPIO expander, it would work. See for example, the Thingy:52's LED definition and usage is the same as that of the nRF52 DK, even though the Thingy:52's LEDs are controlled by an IO Expander, and the nRF52 DK's LEDs are controlled by the SoC's GPIO ports.

    The problem in this case is that the CAF Button Module is made to only work with the nRF SoC's GPIO controllers. To be specific, the module appears designed specifically for the use-case of PC keyboard matrix that uses a nRF SoC's GPIO port to sweep.

    Is your application built on top of the CAF?

    Hieu

  • Is your application built on top of the CAF?

    Yes, we are using the event framework and some CAF modules. Although now I am wondering if this is really a production ready framework in the Zephyr environment.

    I already gave up on the led module (kept causing core dumps), and now will be giving up on the buttons module... 

  • BrianW said:
    Although now I am wondering if this is really a production ready framework in the Zephyr environment.

    I would say that it is production ready, but unfortunately quite dated. I can say that the team has received some feedback about CAF recently, and updating it is on their list.

    BrianW said:
    I already gave up on the led module (kept causing core dumps)

    Ok... that should not happen. I haven't used it lately, but it worked for me before. If you want to look into it, please open a new case and either I or someone else will help you look into it.

    BrianW said:
    now will be giving up on the buttons module... 

    I probably agree with the decision to skip on the CAF Button module for your case.

    As I mentioned, it was designed for keyboard matrix, so it keeps track of keys in rows and columns. In addition, it was implemented long ago, before a lot of recent good Devicetree updates, and hasn't been updated yet.

    Yet, if you find the idea of event-base framework of CAF fitting, we can explore the option of a custom module.

  • Yet, if you find the idea of event-base framework of CAF fitting, we can explore the option of a custom module.

    I have essentially switched to this - a basic button click module that generates the same button events as the CAF one, so my other event based modules can work as before using the app_event_* framework.

  • I think that is the best approach considering the information you have given me. It's great to know that it is working for you.

Reply Children
Related