Hi,
We are developing a power sensitive application using the nrf54LM20A with a Quectel EG916Q modem (with our own provided out-of-tree driver handing the EG916Q scripts).
We have noticed a problem with using the nordic UARTE driver for zephyr via the zephyr ISR API connected to the ISR version of the modem_backed_uart driver, with runtime device power management enabled.
All functions well except that under many different situations, the modem_cellular driver closes modem_backend_uart_isr with the PM usage count imbalanced, stopping the UARTE peripheral from being automatically suspended at the end of usage.
Looking at the code, I notice a few things that seem incompatible between the uart_isr modem backend and the nordic UARTE driver:
- The modem_backend appears use uart_irq_tx_disable() and uart_irq_tx_enable() around putting tx data into the tx ring buffer in modem_backend_uart_isr_transmit(), rather than using a mutex or some other specific lock. This in itself seems OK, as the calls are matched.
- The zephyr ISR UART API for the UARTE driver seems to use the PM calls (pm_device_runtime_get() and pm_device_runtime_put_async()) to "hold" the UARTE device during some operations (such as, for example, disabling tx, as this happens somewhat asynchronously)
- If uart_irq_tx_enable() is called too soon after uart_irq_tx_disable(), before the disable actually finished, uart_irq_tx_enable() "gets" the pm runtime usage without the previously expected "put" being done.
The usage pattern I saw with the modem_cellular driver, talking to the EG916Q at 921600bps meant that almost every AT command resulted in the usage count creeping up.
My questions are:
- Is the modem_backend_uart_isr code using uart_irq_tx_disable/enable() expected and valid? Or is it likely to change.
- Is there any workaround or fix for the UARTE driver in progress?
We have also tried using the modem_backed_uart_async option, which balances the PM usage correctly, but suffers from the known RX timeout problem with UARTE. We are currently trying the async driver with the CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER Kconfig option, which seems use a separate timer peripheral for the RX timeout, but we do see some performance problems (some CMUX frames missing bytes), so it isn't an easy win.
I am currently considering changing the modem_backend_uart_isr code to protect the TX ringbuffer another way, but I would rather stick to known unmodified nRF Connect zephyr code.
Has anyone else experienced similar problems?
Regards,
Nathan Boyd.