Low power - disable UART while maintaining printk or printf functionality

So whatever I try, the only way to get my idle current consumption to an acceptable low value is to set CONFIG_SERIAL=n in my configuration. But then I don't get printk functionality. The lowest I can achieve using a nRF52DK & PPK2 is about 1mA, compared to 7uA with CONFIG_SERIAL=n.

I looked at lpuart, but I can't use that because I can't implement the handshake protocol, and the lpuart sample doesn't use printk anyway, it uses a raw buffer.

My gut feeling is it's the kernel keeping the uart alive.

I need ultra low power, but still need to send a report over uart based on a BLE event. This is for a port of an existing application built under SDK17 where I would simply set the register NRF_UART0->ENABLE directly.

This is using NCS 2.9.0

Can you advise?

Parents
  • Hello,

    If you don't need UART RX to be enabled, you can add the disable-rx property to your uart node in the devicetree. The idle current will then be around 20 uA while UART is enabled but idle. This can be further reduced by ensuring that the asynchronous UART driver API is enabled via CONFIG_UART_ASYNC_API and that CONFIG_UART_0_NRF_ASYNC_LOW_POWER is selected. With this configuration, the UART is automatically disabled after each transaction by the driver.

    &uart0 {
        /* Disable UARTE reception */
        disable-rx;
    };
    

    Best regards,

    Vidar

  • Sounds good,

    Can RX be re-enabled by code in this way? Sorry, I omitted to say earlier that I do also need to enable uart RX sometimes... I currently have a GPIO input dedicated to the task, think of it as half of the lpuart arrangement.

    (I can't change the hardware or handshaking arrangement as I need this code to be retro-compatible to existing product)

    FYI The uart is used primarily for sending a data packet to a connected system after a BLE transaction, but it is also used for a CLI interface for configuration by the user. Otherwise it will be idle.

    Thanks

  • I see. It is not possible to enable RX with this property set in the Devicetree. However, if you set CONFIG_PM_DEVICE=y in your configuration, you can use the "suspend" and "resume" action to control when the uart is to be enabled and disabled.

    #include <zephyr/pm/device.h>
    
    static struct device const *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    
    ...
    
    int main(void)
    { 
        ...
        
    	/* Disable UART to reduce System ON idle current */
    	err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND);
    	if (err) {
    		printk("UART suspend failed. (err %d)\n", err);
    		return 1;
    	}
    

Reply
  • I see. It is not possible to enable RX with this property set in the Devicetree. However, if you set CONFIG_PM_DEVICE=y in your configuration, you can use the "suspend" and "resume" action to control when the uart is to be enabled and disabled.

    #include <zephyr/pm/device.h>
    
    static struct device const *uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    
    ...
    
    int main(void)
    { 
        ...
        
    	/* Disable UART to reduce System ON idle current */
    	err = pm_device_action_run(uart_dev, PM_DEVICE_ACTION_SUSPEND);
    	if (err) {
    		printk("UART suspend failed. (err %d)\n", err);
    		return 1;
    	}
    

Children
No Data
Related