zephyr: Bluetooth: hci: spi: host doesn't work on targets which do not support level triggered interrupts

Bug Description With zephyr v3.4, an application implementing an HCI HOST will constantly fail on targets which do not support GPIO level-triggered interrupts. However, this was working with versions of Zephyr prior to 3.3.

This change from edge to level-triggered interrupts was introduced in the following PR #57427 which addresses issue #53980.

Steps for Reproduction To replicate the issue, build a Bluetooth sample configure as a HCI HOST (i.e. with CONFIG_BT_HCI=y, CONFIG_BT_SPI=y and CONFIG_BT_CTLR=n) on a board that doesn’t support level-triggered GPIO interrupts (e.g., any stm32 board, nucleo -f429zi in my particular instance).

The problem arises when the host can’t configure the IRQ pin as a level-triggered interrupt via gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_LEVEL_ACTIVE); .

The stm32 driver explicitly tells level-triggered interrupts are not supported here.

Expected Result HCI HOST should ideally be functional even with targets that don’t support level-triggered interrupts.

Consequences As it stands, the HCI HOST is incompatible with targets that don’t support level-triggered interrupts.

Environment Details:

  • Linux Fedora 37
  • Zephyr v3.4.0
  • Zephyr SDK 0.16.1

Additional Information I imagine that only few targets support level-triggered interrupts. Consequently, it might be more effective to design the HCI driver with the assumption that only edge-triggered interrupts are supported.

While I haven’t yet formulated a resolution, I plan to think about it.

Edit: I edited my message to highlight that this issue was introduced by version 3.4 of zephyr.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 23 (14 by maintainers)

Commits related to this issue

Most upvoted comments

Given that I would prefer to continue using the level triggered interrupts as well, I might look into how to support both.

As this conversation is larger than this bug report, I opened a discussion: https://github.com/zephyrproject-rtos/zephyr/discussions/59646

According to current PR description, it was at least working on some platforms and there were some race conditions on some others. Now it appears to be fully broken where it was previously working.

It would work for some duration, until it deadlocked and never worked again. This was for all platforms, not just some.

For similar case, in general the commit introducing the regression is reverted and the point is reworked in order to provide a satisfying solution for all known use cases and configurations.

The fix is logically correct. If the IRQ line is active, we should be attempting to read the data. Triggering on an edge is insufficient and will eventually lead to a deadlock.

Assuming we take the suggested approach, the only “satisfying solution” is one in which equivalent behaviour to GPIO_INT_LEVEL_ACTIVE is obtained through some combination of GPIO_INT_EDGE_ACTIVE and gpio_pin_read. Assuming that the following is possible, why not instead implement it in a common software emulation layer that implementations can call if they don’t support GPIO_INT_MODE_LEVEL? The implementation is the same, and it benefits all drivers instead of just this.

Otherwise we might as well add a Github action that fails any PR that uses GPIO_INT_LEVEL_ACTIVE outside of the boards folder.

It’s also not really feasible to expect driver developers to check each implementation of peripherals they use to see what is and isn’t supported. My first expectation is that if its in a public header like zephyr/drivers/gpio.h then it’s fair game to use, and failure to support such a feature is more a problem for the micro implementation than the device driver.