6 Replies Latest reply on Dec 8, 2011 12:50 AM by udayan.umapathi

    When is an UART busy

    user_1377889

      Hi Community,
      lately I came over the question how to detect if an UART is ready with its transmission.
      This is not as easy as it seems as first sight. An UART has up to 3 areas where the data to be transmitted is stored:
      1st The buffer (when defined in the module configuration)
      2nd The FIFO, 4 bytes deep holding untransmitted data, fed with bytes from Buffer in the interrupt routine
      3rd Often forgotten, the Tx-shift-register, holding the actually transmitted byte

         

      An API to get information whether the buffer is already empty is UART_GetTxBufferSize() which does not return the
      size as the name would suggest, but the number of used bytes in the buffer. Thus a returned value of 0 (zero) indicates an empty buffer.

         

      To have a look at the FIFO state we have the API UART_ReadTxStatus() which not only indicates an empty FIFO with a bit-mask named

         

      UART_TX_STS_FIFO_EMPTY but indicates a complete transmission of the tx-shift-register with a mask named UART_TX_STS_COMPLETE.
      Unfortunately this bit is reset when read with the API.

         

      When writing a function to return the busy state of an UART we have to consider following facts:
      Buffer must be empty
      FIFO must be empty
      Transfer must be complete.

         

      The problem is, when looking at "Transfer must be complete" the API sets the state to "Transfer NOT complete" which would at a next
      questioning for a busy UART return "Busy" and this answer can lead into an infinite loop when waiting for a "Ready" UART.

         

      So, a function to give a correct result is a bit complicated. I append one to this post.

         

      When is the function needed?
      All the management when transfering data is handled by the supplied UART-routines, so there is no need. But when you have to stop the UART for any

         

      reason (mostly to enter sleep mode) you must be sure that all communication is made.

         

      Here is the function:

         

       

         

       

         


      uint8 UART_Busy(void)
      {
      uint8 STS;
      static uint8 FirstTimeCalled = TRUE;
      #define Busy 1 // Just for better readabiliy (I hope)

         

      STS = UART_ReadTxStatus();
      if (!((UART_GetTxBufferSize() == 0) && (STS & UART_TX_STS_FIFO_EMPTY))) // Are the UART buffers empty?
      {
      FirstTimeCalled = FALSE;
      return Busy; // Buffers NOT empty, return "Busy"
      }
      else // UART buffers empty, but last byte may be transfered currently
      {
      if (STS & UART_TX_STS_COMPLETE) // Is Transfer completed? Bit was reset with call to UART_ReadTxStatus()
      {
      FirstTimeCalled = TRUE; // Yes, we are done
      return !Busy;
      }
      else // Transfer not completed or called the first time after a !Busy returned
      {
      if (FirstTimeCalled) return !Busy;
      return Busy;
      }
      }
      #undef Busy
      }

         

       

         

       

         

      Have fun
      Bob