Suspending the UART using PM_DEVICE ACTION_SUSPEND does not reduce power consumption that much

Hello

As the title says, I am suspending the UART using PM_DEVICE ACTION_SUSPEND, but the power consumption is not decreasing significantly.

With CONFIG_SERIAL=n and no UART used, power consumption is now around 20uA.

When using pm_device_action_run, the power consumption was about 1.3mA.

Please tell me the correct way to stop UART.

SDK : nrf Connect SDK 2.6.1

Board : Raytac MDBT42Q-DB

#include <zephyr/kernel.h>
#include <zephyr/pm/device.h>
#include <zephyr/logging/log.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/uart.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

static uint8_t Buffer[16];

static const struct device *Uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

static void Callback(const struct device *dev, struct uart_event *evt, void *user_data);

int main(void)
{
#if defined(CONFIG_SERIAL)
    if (!device_is_ready(Uart))
    {
        LOG_ERR("device is not ready");
        return 0;
    }

    const struct uart_config cfg = {
        .baudrate = 1000000,
        .parity = UART_CFG_PARITY_NONE,
        .stop_bits = UART_CFG_STOP_BITS_1,
        .data_bits = UART_CFG_DATA_BITS_8,
        .flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS,
    };

    int err = uart_configure(Uart, &cfg);
    if (err)
    {
        LOG_ERR("uart_configure (%d)", err);
        return 0;
    }

    err = uart_callback_set(Uart, Callback, NULL);
    if (err)
    {
        LOG_ERR("uart_callback_set (%d)", err);
        return 0;
    }

    err = uart_rx_enable(Uart, Buffer, sizeof(Buffer), 1000);
    if (err)
    {
        LOG_ERR("uart_rx_enable (%d)", err);
        return err;
    }

    int count = 0;
    while (count < 10)
    {
        k_msleep(1000);
        LOG_INF(".");
        count++;
    }
    err = pm_device_action_run(Uart, PM_DEVICE_ACTION_SUSPEND);
    if (err)
    {
        LOG_ERR("pm_device_action_run (%d)", err);
        return 0;
    }
    else
    {
        LOG_INF("SUSPEND");
    }
#endif
    while(true)
    {
        k_msleep(1000);
        LOG_INF(".");
    }

    return 0;
}

static void Callback(const struct device *dev, struct uart_event *evt, void *user_data)
{
    switch (evt->type)
    {
    case UART_TX_DONE:

        break;
    case UART_TX_ABORTED:

        break;
    case UART_RX_RDY:

        break;
    case UART_RX_BUF_REQUEST:

        break;
    case UART_RX_BUF_RELEASED:

        break;
    case UART_RX_DISABLED:

        break;
    case UART_RX_STOPPED:

        break;
    default:
        break;
    }
}

Parents Reply
  • Hello,

    Thank you. I ran your application, and noticed that you are setting up the UART in the application, and not in the devicetree. Also, you have CONFIG_UART_USE_RUNTIME_CONFIGURE=y in your prj.conf. 

    This is of course fine, but that also means that the UART is not properly disabled when you run the command:

    err = pm_device_action_run(Uart, PM_DEVICE_ACTION_SUSPEND);

    I also noticed that the logging was output on your UART as well as on RTT, although it looks like you tried to disable it. So I did some changes to your prj.conf as well as disabling the UART runtime using uart_rx_disable(). 

    After doing those things, it looks like it behaves as you'd expect.

    Give it a go, and let me know if it doesn't work.

    power_test_patch.zip

    Best regards,

    Edvin

Children
Related