This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

UART low power shutdown issue

Hi! We're developing on an nrf52840dk and have been running in to some problems when we want the system to only pull currents in the size of a few microamps. As our system enters a low-power mode it shuts down all initiated peripherals. However for the UART there seems to be a problem when we uninitiate the peripheral. In our function a register write is done to ENABLE through nrf_uarte_disable:

__STATIC_INLINE void nrf_uarte_disable(NRF_UARTE_Type * p_reg)

{

    p_reg->ENABLE = UARTE_ENABLE_ENABLE_Disabled;

}

Even though the uart-instance is removed and no longer able to send/receive data the measured current is around 1 mA above what it should be; something is still running when it shouldn't be. One suggested solution is to further write on the register, more specifically to stop transmitting and receiving (TASK_STOPRX and TASK_STOPTX). We tried to add this before nrf_uarte_disable through:

nrf_uarte_event_clear(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_TXSTOPPED);

nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], NRF_UARTE_TASK_STOPTX);

nrf_uarte_task_trigger(nordic_nrf5_uart_register[instance], NRF_UARTE_TASK_STOPRX);

while (!nrf_uarte_event_check(nordic_nrf5_uart_register[instance], NRF_UARTE_EVENT_TXSTOPPED)){}

These function calls are based on the functions nrfx_uarte_tx_abort() and nrfx_uarte_rx_abort() where these calls are made. However this doesn't seem to solve the issue as the current still remains relatively high.

After further investigations we found that the radio peripheral contains a POWER-register at a certain offset (0xFFC) from the base adress which resets the entire register of the peripheral by first setting it to 0 and then 1.

However this register is not defined for any other peripheral than the radio in the datasheet/manual for the nRF52840 but we tried anyway to see if it was possible to do the same kind of reset for the serial as the radio. The UART we used had the base adress 0x40028000 and the register we wrote to was therefore 0x40028FFC. Writing 0 and then 1 on this position in the memory seemed to solve the problem as the drawn current dropped to a more reasonable value.

It solves the problem but it includes writing to a "hidden" register, why is this working and is there any other way to work around this problem other than these methods?

  • You have identified the usual workaround; search for "0x40002FFC" or "0x40028FFC" to see multiple posts on this issue. It is covered implicitly by errata 89 for a different peripheral ([89] GPIOTE: Static 400 µA current while using GPIOTE), but there doesn't seem to have been a specific errata issued for the uart, which has even higher unwanted current; Nordic might be able to say why not.

    I have these notes in my code though edit I see 2 versions:

      // Terminate UART transfers serial port - testing this to see if affects power consumption ToDo look into this again
      app_uart_close();
      // In app_uart_close() peripheral is disabled by writing 0 to the NRF_UARTE0->ENABLE
      // register. On 2840 this seems to not stop the HF clk and close the DMA bus, which could be a bug. Power
      // cycle the peripheral after calling app_uart_close() the current consumption goes down.
      *(volatile uint32_t *)0x40028FFC = 0;
      *(volatile uint32_t *)0x40028FFC;
      *(volatile uint32_t *)0x40028FFC = 1;
      or
      *(volatile uint32_t *)0x40002FFC = 0;
      *(volatile uint32_t *)0x40002FFC;
      *(volatile uint32_t *)0x40002FFC = 1;

    Given the following I assume the first is correct (which we have used on Uart 0):

    #define NRF_UARTE0_BASE             0x40002000UL
    #define NRF_UART0_BASE              0x40002000UL
    and
    #define NRF_UARTE10_BASE            0x40020000UL
    

    See this post: low-power-system-on-mode-in-ble_uart_app

  • Hi,

    Nordic might be able to say why not.

    New investigations shows that the real root cause for this issue is just a bug in the UARTE driver. The new driver version now waits for TX_STOPPED event before disabling the peripheral. This gracefully uinit of the UARTE peripheral was introduced in nrfx v1.7.2. See this link. (Note that SDK 15.3 is bundled with nrfx v1.6.2)

Related