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

nRF52840 UART0 sleep current behavior

I have a custom board built around the nRF52840, which spends most of its life sleeping.  I'm able to achieve ~3uA current draw when it is sleeping, but I've recently started running into corner cases where the current draw is much higher.  I suspect that it is an issue with UART0.

As a specific example, if I disable UART0 and the other peripherals before going to sleep, I hit 3uA.  However, if I transmit on the UART just before disabling it, I see ~620uA of current in sleep.  Waiting on nrfx_uarte_tx_in_progress() and using delays does not seem to resolve the issue.

Here's a stripped down version of my code.  The "printf("Going to sleep...\r\n");" is the offending line.  If I comment that out, the sleep current is ok.  Any idea how to fix this?

int main(void)
{
    int32_t r;
    
    // Initialize HW peripherals
    r = HWC_UartInit();
    if(r) SC_printf("HWC_UartInit: failed to initialize (%i)\r\n", r);
    
    printf("Going to sleep...\r\n");

    // Uninitialize UART
    HWC_UartDeinit();
      
    __SEV();    // Send an event (guarantees an event is set)
    __WFE();    // Will wake up immediately, clearing the event
    __WFE();    // This will put the device to sleep for realzies

    // Reinitialize the UART
    HWC_UartInit();
    
    SC_printf("Awake again...\r\n");
        
    while(1);
}

int32_t HWC_UartInit()
{
    nrfx_uarte_config_t uartConfig = NRFX_UARTE_DEFAULT_CONFIG;

    uartConfig.pseltxd = PIN_UART_TX;
    uartConfig.pselrxd = PIN_UART_RX;
    uartConfig.hwfc = NRF_UARTE_HWFC_DISABLED;
    uartConfig.parity = NRF_UARTE_PARITY_EXCLUDED;
    uartConfig.baudrate = NRF_UARTE_BAUDRATE_115200;
    
    nrfx_err_t e = nrfx_uarte_init(&uartInstance, &uartConfig, HWC_UartEventHandle);
    if(NRFX_SUCCESS==e) e = nrfx_uarte_rx(&uartInstance, &rxByte, 1);
    
    return NRFX_SUCCESS == e ? 0 : -1;
}

void HWC_UartDeinit()
{
    nrfx_uarte_rx_abort(&uartInstance);
    nrfx_uarte_uninit(&uartInstance);
    
    // Need to restart UARTE0 to reduce power.  This may be related to an erratum.
    // devzone.nordicsemi.com/.../184882
    *(volatile uint32_t *)0x40002FFC = 0;
    *(volatile uint32_t *)0x40002FFC;
    *(volatile uint32_t *)0x40002FFC = 1;
}

Parents
  • It turns out that the problem can still occur even if I do not transmit any data on the UART immediately before going to sleep.  I would immediately assume this to be a FW issue if not for the fact that it can be reproduced in trivial applications.  The sleep current of ~620 uA seems very suspicious - I'm using a supply voltage of 3V, so it would correspond nicely with 2 pulldown resistors being enabled.  Explicitly initializing the UART pins as GPIOs with no pulls before going to sleep doesn't change anything though.

Reply
  • It turns out that the problem can still occur even if I do not transmit any data on the UART immediately before going to sleep.  I would immediately assume this to be a FW issue if not for the fact that it can be reproduced in trivial applications.  The sleep current of ~620 uA seems very suspicious - I'm using a supply voltage of 3V, so it would correspond nicely with 2 pulldown resistors being enabled.  Explicitly initializing the UART pins as GPIOs with no pulls before going to sleep doesn't change anything though.

Children
No Data
Related