You can use UART_ReadtxStatus() to check for an empty Tx FIFO.
(Actually PutChar() is blocking, but in blocks only when the Tx FIFO is full, and its 4 bytes...)
you need to wait for BOTH fifo empty and transmit complete. the fifo can hold upto 4 bytes and the 'shift register' for output is a separate byte. so you have to have the fifo empty AND the last bit shifted out.
Description: Reads the status register for the TX portion of the UART.
Return Value: uint8: Contents of the TX Status register
UART_TX_STS_COMPLETE If set, indicates byte was transmitted
UART_TX_STS_FIFO_EMPTY If set, indicates the TX FIFO is empty
UART_TX_STS_FIFO_FULL If set, indicates the TX FIFO is full
UART_TX_STS_FIFO_NOT_FULL If set, indicates the FIFO is not full
Side Effects: This function reads the TX status register, which is cleared on read.
Here's some code that I used in a PSoC3 - should also work in a PSoC4. I set fUARTTransmitActive to TRUE whenever I transmit anything. SleepFunc() only gets called after everything is completely transmitted.
/* Read our TX status byte to make sure we don't sleep when still transmitting data */
bTXStatus = UART_1_ReadTxStatus(); /* Some of these bits clear on read, so just read once before checking! */
/* Here we need to do some checking to make sure it is OK to go to sleep. We want to wait until any
* serial transmit has been completed.
* Here are the conditions that need to be satisfied:
* 1. UART_1_GetTxBufferSize() == 0: We don't have any data in the transmit buffer which has not been loaded
* into the UART FIFO.
* 2. bTXStatus & UART_1_TX_STS_FIFO_EMPTY: The UART TX FIFO is empty
* 3. !((fUARTTransmitActive == TRUE) && !(bTXStatus & UART_1_TX_STS_COMPLETE)) : If we didn't transmit this
* wake cycle (fUARTTransmitActive == FALSE), we can safely go to sleep. If we did transmit this cycle and
* TX complete is set (i.e. byte has completely transmitted), we can safely go to sleep. We cannot go to
* sleep if we did transmit this cycle and TX complete is not set (i.e. byte has not completely transmitted).
* NOTE that we can't just simply check TX complete, since it won't be set if we didn't transmit this cycle
* (but it would be OK to go to sleep in that case).
if ((UART_1_GetTxBufferSize() == 0 ) && (bTXStatus & UART_1_TX_STS_FIFO_EMPTY) && !((fUARTTransmitActive == TRUE) && !(bTXStatus & UART_1_TX_STS_COMPLETE)))
fUARTTransmitActive = FALSE; /* Reset flag before sleep */
If its really just about a single byte, checking the transmit state might be enough (because the byte is starting to be send as soon as it got put into the transmit buffer).