Issue with resuming UART1 on nRF9151 after PM suspend with BLE module

Board/Setup:

  • Board: nRF9151 DK / nRF9151 SoC

  • Peripheral: External BLE module connected via UART1

  • Use case: BLE module is only needed during commissioning. After commissioning, it can remain powered down to save energy.

Scenario / Problem:
We are using Zephyr OS with the nRF Connect SDK. Our goal is to reduce power consumption when the BLE module is not needed.

  • With UART1 running continuously for BLE communication, the device consumes ~7 mA.

  • When we suspend UART1 using Zephyr PM (pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND)), the current drops to ~700 μA, which is acceptable.

  • Issue: After suspending UART1, attempting to resume it using pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME) followed by uart_config_get() or uart_configure() consistently fails with -134 (EIO).

From investigation:

  • The PM resume successfully powers the UART peripheral, but the hardware is not responsive immediately.

  • uart_config_get() fails both before suspend and after resume if the BLE transport or peripheral is active, because the driver cannot communicate with the hardware.

  • Adding delays after resume does not solve the problem.

Goal:

  • Suspend UART1 to save power when BLE is not needed.

  • Be able to resume UART1 reliably when commissioning is required again.

  • Avoid relying on uart_config_get() since it fails with the current setup.

My Code:

/* Suspend UART device */
int ble_uart_suspend(void)
{
	int err;

	if (!device_is_ready(uart_dev))
	{
		WR_ERR("UART device not ready\n");
		return -ENODEV;
	}

	err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND);
	if (err)
	{
		WR_ERR("Failed to suspend UART: %d\n", err);
		return err;
	}

	WR_INF("UART suspended successfully\n");
	return 0;
}

/* Resume UART device */
int ble_uart_resume(void)
{
	int err;

	if (!device_is_ready(uart_dev))
	{
		WR_ERR("UART device not ready");
		return -ENODEV;
	}

	err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME);
	if (err)
	{
		WR_ERR("Failed to resume UART: %d", err);
		return err;
	}

	WR_INF("UART resumed successfully");
	return 0;
}

Support Needed:

  1. Is there a recommended way in Zephyr to safely resume a UART peripheral connected to a BLE module on nRF9151 after PM suspend?

  2. Are there any platform-specific constraints on nRF91 UART peripherals that we need to account for when suspending/resuming?

  3. Can the approach of using a static UART configuration safely replace uart_config_get() in this scenario?

Parents
  • the current drops to ~700 μA, which is acceptable

    You accept 100x more than it should be, at least considering the nRF9151 (~7µA).

    I frequently use pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND) and pm_device_action_run(uart_dev, PM_DEVICE_ACTION_RESUME). After resume the first bytes may be lost or crippled, but a "retry" usually solves that.

    I'm not aware, that the UART needs to be explicitly reconfigured after suspend/resume.
     

  • You accept 100x more than it should be, at least considering the nRF9151 (~7µA).

    I

    When I call system_off(), the current drops to around 5 µA, since most of my peripherals are off. Without this, the consumption is about 700 µA (after suspending UART1), which is still better than the 7 mA I had before. The 700 µA draw mainly comes from two sensors on I²C. One of them, the LIS2DW12, requires continuous power. I can’t power it off because it loses its configuration and only outputs 0 after wake-up. So most of the 700 µA consumption is due to this sensor.

    In my code, if I don’t call pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND) and let it run as before, my BLE module works fine. But when I call suspend and then resume, it stops working.

    I have two UARTs in my application: UART0 for debugging and UART1 for the BLE module.

    I am also suspending the Zephyr console, and after resuming it.

  • Not sure, why you get these results.

    About the uart_config_get():

    Did you enable the required CONFIG_UART_USE_RUNTIME_CONFIGURE ? If not, try that ;-).

    It's long ago, that I was common with debugging UART issues. What helped me in that past was a 2 channel UART2USB TTL converter (or 2 single channel). The TTL level must match your GPIO level (e.g. 3.3V). Connect the RXs of the 2 Channel UART2USB with both UART (rx/tx) you want to debug. That should make it visible, what's going on.

    As I wrote, I would assume some lost or crippled bytes, and a retransmission should help here. Crossing the fingers. 

  • Thank you for your input! I’m not seeing any UART errors related to the configuration, so that seems fine. However, my ANNAB module still isn’t getting configured properly. Could you please advise on how I might resolve this issue?

  • I'm just an other user and no Nordic engineer.

    But I consider, that you will need the UART traces to see, if the nRF9151 or the ANNAB (ublox ANNA B?) isn't working as expected. Without that UART traces I don't see, how someone will be able to help you.

    (For those UART traces you will need the 2 channel or 2 1 channel UART2USB TTL adapters as I wrote above.)

  • Thank you for your suggestion! I tested my code on the nRF9151 DK using a UART2USB TTL adapter, and the UART is working properly. I was able to send a few commands via TTL, and my code processed them as expected. So it seems the UART, along with the suspend and resume logic, is functioning fine.

    It might be that there’s some issue with the ANNAB112 module itself.

    Thanks again for your help!

Reply Children
No Data
Related