cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 5, 3 & 1 MCU

Esteemed Contributor II

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

   


 

0 Likes
Reply
6 Replies
Anonymous
Not applicable

Bob, this is valuable information. Thanks for sheing this with the rest of the community.

0 Likes
Reply
Valued Contributor II


Thank you, Bob!
It seems the program requires a tiny delay between calls.
I put CyDelayUs (0) - that was enough:
while(UART_Busy())  {   CyDelayUs(0); };
Unfortunately I was unable to change it for a PSoC4 SCB-UART ((
4 years have passed... so quickly((

0 Likes
Reply
Esteemed Contributor

This should get incorporated into module datasheet. Even

   

sleep ap notes.

   

 

   

Just sayin.

   

 

   

Regards, Dana.

0 Likes
Reply
Anonymous
Not applicable

Good one.

0 Likes
Reply
Esteemed Contributor II

Interestingly it took three years since someone dug out that post!

   

Glad when I have helped someone and thanks for reviewing and improving!

   

I agree with Dana that this problem should be at least mentioned in the Sleep() API of the UART.

   

 

   

Bob

0 Likes
Reply
Esteemed Contributor

Bob, file a CASE to get the docs modified.

   

 

   

Regards, Dana.

0 Likes
Reply