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

Handling the UART when sleeping

I'm using simple_uart_init to enable UART I/O from my target. This all works fine but I'm not sure what to do with the UART before I sleep (by calling sd_app_event_wait) so that it does not consume power.

I'm especially concerned that the GPIO line associated with TX not leak current into the serial terminator.

I'm also slightly concerned that the UART remains "enabled" during sleep and I'm not sure whether it consumes power in that state, even when the CPU is sleeping.

Whatever I do for sleeping, I presume I can call simple_uart_init again when I wake up to set things up again for operation. Is this correct?

Parents
  • The code above works quite well for disabling and enabling the UART and I've confirmed that it achieves a substantial sleep current reduction.

    One remaining issue is that disabling the TX shortly after a call to simple_uart_putstring causes the last string to never be output on the UART and also results in the UART not getting successfully re-enabled.

    simple_uart_putstring repeatedly calls simple_uart_put, which is spinning on (NRF_UART0->EVENTS_TXDRDY!=1)

    If I add my own spin right after simple_uart_putstring by doing this: for( int i = 0 ; i < 1000000 ; i++ ) {} then everything works properly. I see the last string come out of the UART before sleeping and the re-enable works too. Without my additional spin delay, it doesn't work.

    So I guess that NRF_UART0->EVENTS_TXDRDY does not actually indicate that the UART is through sending data. Is there a flag I can use that will indicate that the UART TX is complete so that I can safely stop the TX and disable the UART?

Reply
  • The code above works quite well for disabling and enabling the UART and I've confirmed that it achieves a substantial sleep current reduction.

    One remaining issue is that disabling the TX shortly after a call to simple_uart_putstring causes the last string to never be output on the UART and also results in the UART not getting successfully re-enabled.

    simple_uart_putstring repeatedly calls simple_uart_put, which is spinning on (NRF_UART0->EVENTS_TXDRDY!=1)

    If I add my own spin right after simple_uart_putstring by doing this: for( int i = 0 ; i < 1000000 ; i++ ) {} then everything works properly. I see the last string come out of the UART before sleeping and the re-enable works too. Without my additional spin delay, it doesn't work.

    So I guess that NRF_UART0->EVENTS_TXDRDY does not actually indicate that the UART is through sending data. Is there a flag I can use that will indicate that the UART TX is complete so that I can safely stop the TX and disable the UART?

Children
  • NRF_UART0->EVENTS_TXDRDY indicates when a byte transmission has completed, so it should be safe to turn TX off once that happens. If STOPTX task has been called, the TXDRDY event will never happen, causing simple_uart_put() to spin as you described.

    I modified simple_uart_putstring() to only enable TX when needed. Could this modification work for you? (This is probably easier than what I suggested in the previous post)

    void simple_uart_putstring(const uint8_t *str)
    {
      uint_fast8_t i = 0;
      uint8_t ch = str[i++];
        
      NRF_UART0->TASKS_STARTTX = 1;
        
      while (ch != '\0')
      {
        simple_uart_put(ch);
        ch = str[i++];
      }
      
      NRF_UART0->TASKS_STOPTX = 1;
    }
    
Related