UART Clarifications

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

1. When I use buffer greater than 4 bytes, is your interrupt routine fires upon arrival of the first byte and move that byte to the RAM buffer thus applying byte-by-byte interrupt based transfer of bytes from the FIFO to the RAM?

   

Or, is it waiting for 4 bytes (thus stalling my program until all 4 bytes received) and operate as a 4 bytes interrupt based transfer of bytes from the FIFO to the RAM? in that case the "Byte Received interrupt" fires every 4 bytes for a long message?

   

2. If i want to use the On Byte Received interrupt as well, which will run first, your routine or my (please refer to both modes of using interrupts- in the interrupt C file and in the main)?  

   

3. Please describe 5 bytes transfer delay times:
how long do i have to wait between the time the interrupt fires and the time the first byte readable in the RAM buffer? how long do i have to wait for the next byte to be ready in the RAM buffer and so on.

   

4. Can i create a counter which will fire an interrupt after n bytes received in the RAM buffer? (how do I wire such counter to the UART?) 

   

5. Is there an option to create a "FIFO empty interrupt" for RX?

   

6. Is it possible to create UART with more than 4 bytes HW buffer (so my SW routine will not be interrupted until i want to check the buffer)?

   

7. Just to clear- all functions (both TX and RX) are going for the FIFO buffer in case of under 4 bytes buffer, and for the RAM buffer only (ignoring the existence of a FIFO buffer) for buffers over 4 bytes. please confirm.

   

Thanks in advance,

   

Asafya

0 Likes
16 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

1. The chars go into a hardware FIFO from where the internal interrupt picks them up as long as FIFO not empty putting them into a circular buffer of the given size.

   

 

   

There are principally two different exclusive ways to handle receive, do not mix them!!!

   

Let the internal interrupt handle everything. Polling UART_GetRxBufferSize() gives you the number of chars already in the buffer from which you can get them with UART_GetChar() from the buffer.

   

Handle everything yourself, get interrupted at each byte received, handle errors and read from FIFO into your own circular buffer. It's a nice programming lesson when you've got the time...

   

 

   

Interrupt handlers should be kept short, no polling, no delays. So a usual practice is

   

1st: Remove the cause of the interrupt

   

2nd: Set a global volatile variable to indicate what has happened.

   

In your main-loop check that variable, act accordingly and reset it.

   

What shall a FIFO empty interrupt be good for??? Most of the time the FIFO is empty, how will you remove that interrtupt cause????

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

a FIFO empty interrupt would give me an indication that your routine finished transferring a data packet from the FIFO to the SW buffer so i can start analyzing the data.

   

I am running 3 time critical (and very fast) UARTs and still wants the main to do some tasks during the small communication idle times. I wanted to avoid polling the UART_GetRxBufferSize() as it can't be done during a function (some of them are time consuming and hard to slice but can be interrupted) called from the main, and i would have to poll it for each UART after every line in the main.

   

i was looking for an interrupt based solution so while i'm analyzing (read, parse, analyze, respond)  UART1, i won't miss bytes coming on UART2 and UART3 . and analyze them (in the order they arrive) as soon as i finish with UART1. and continue to the main() as long as all 3 are silent.

   

i didn't want to mix them, i was just looking for that interrupt based solution and the "byte received interrupt" is the only interrupt available for me dealing with RX in UART.

   

will the circular buffer you suggested- one for each UART (did such things in the past so i forfeit the learning experience) be more or less process time-efficient than the internal interrupt routine?

   

and last, i will really like to hear more about how the internal interrupt works in case of a single byte in the FIFO and in case of 4 bytes in the FIFO (questions #1 and #3). thanks.

   

Thanks,

   

Asafya.

0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

#6: since that hardware buffer is just 4 bytes, you can use the RX FIFO FULL interrupt. If you need a larger buffer, an internal ISR is used that transfer bytes from HW buffer to the software buffer.

   

#4: AFAIK no. The PSoC4 SCB UART can create a FIFO level interrupt after n bytes, but not the PSoC5.

   

#5: no, because its not needed. Your code that reads data from the buffer can just check whether the buffer is empty or not. No interrupt needed. ISRs are there to notify coure program that something has changed by hardware, but hardware cannot empty the RX buffer.

   

#3: are you talking about RX or TX? On RX, the interrupt is fired when the first byte has arrived in the buffer, not before. The speed with which the buffer fills up depends on how fast data is sent to your PSoC.

   

#7: no, with a buffer size larger than 4 the hardware UART still works solely with the HW FIFO. But there is an ISR that manages the transfer between the SW and the HW FIFO for you.

0 Likes
Anonymous
Not applicable

Hi hli,

   

thanks for your response.

   

#6 is the RX FIFO FULL interrupt fires as soon as the 4th byte arrives? (so i have enough time to empty it before the 5th byte arrives)

   

#4 merd.

   

#5 when i do it from the main it is not responsive enough in my application while the byte received interrupt doesn't work well as it is too soon. that was the motivation behind question #4

   

#3 Sorry, RX. i was trying to understand the time frame (#3) and how is the internal interrupt mechanism is working (#1).
how is it linked to my data rate? (or- please look at question #1)
if there is only one byte. how much time will take the internal interrupt once fired to move it from the FIFO to SW buffer? is it 0.333 usec? will it stay there untill 4 bytes arrive? (again- question #1)
knowing the time frame it takes for the internal interrupt to move byte(s) from HW FIFO to SW Buffer will help me designing my routine.

   

#7 Sorry, i wasn't clear, by "functions" i meant API functions. for example, when i execute UART_GetRxBufferSize() :
for 4 bytes and under buffer it will show me the amount of bytes waiting in the FIFO HW Buffer
for 5 bytes or more it will show me the amount of bytes waiting in the SW buffer (ignoring the existence of a FIFO buffer).
please confirm.

0 Likes
Anonymous
Not applicable

couple more questions for UART clarifications:

   

8. Silly question, and yet to be sure- is the internal interrupt, in case of buffer bigger than 4 bytes, obey the priority I set for it in the interrupt priority tab (and not override me with the highest priority)?

   

9. if I connected an external interrupt: RX_ISR to that UART (buffer is bigger than 4 bytes) it will always fire on byte received (please confirm), will it obey its priority (being different than the internal interrupt) so the following sequence can occur:
the internal interrupt will fire (priority 1),
another (unrelated) time consuming interrupt will fire (priority 2),
the internal interrupt will fire again (priority 1) (new byte recieved), 
and only than the RX_ISR interrupt (priority 3) fires.
please confirm. 
it will also answer question #2 above.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Yes, some questions are silly 😉 Of course will the interrupt priority follow your assignments and not be changed.

   

A simple test (Just setting the UART buffer to 5) shows that you cannot have both interrupts. Rx character received interrupt is no longer a choice.

   

As I already told, all bytes from FIFO will be transferred to the buffer, so what you want to know when you ask "internal interrupt works in case of a single byte in the FIFO and in case of 4 bytes in the FIFO". The internal handling of the UART component does not differ from a self-written circular buffer algorithm (except that is is error-free).

   

What is the baud rate of your UART channels?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob.

   

thanks for your explanations. i have actually 5 UARTs 1Mbps each. and they can all transmit data to me simultaneously. am I asking too much of the PSoC 5?

   

I tried the simple test you suggested, and I saw differently. i can have both interrupts.
I can't uncheck the dimmed "on byte received" interrupt but it is checked and i have interrupt terminal to which i can connect my external interrupt and have two interrupts visible under the interrupt tab (internal... and RX_isr), i even checked RX_isr during runtime and it fired.

   

as such, let me ask you again if you can confirm or deny the possible sequence described in question #9

   

As for question #4- can I connect the external RX_isr to the reset port of a counter to generate a delayed interrupt (better than polling buffer size in the main for me)?

   

just to clear the internal mechanism- in a world with only one interrupt, it should function as a byte-by-byte (meaning every byte will fire the internal interrupt and it will move it to the SW buffer)
in case of several interrupts, the internal interrupt may be delayed and so the amount of bytes in the buffer when it fires will be moved to the SW buffer (Q#3: how much micro seconds it takes to move 4 bytes from the FIFO to the SW buffer?) and the interrupt will be cleared. the next byte will trigger the internal interrupt once more. please confirm.

   

Thanks again for your time,

   

Asafya

0 Likes
lock attach
Attachments are accessible only for community members.
odissey1
Level 9
Level 9
First comment on KBA 1000 replies posted 750 replies posted
        Asafya, By now you likely have all information needed, it is time to test the code. 5x1Mbs is tight. Attached is another incarnation of a project for reading UART into circular buffer, based on Bob Marlowe's explanation above. Use it for testing, first one UART, then two simultaneously... Good luck!   
0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

5Mbaud divided by 12 (8 + start and stop-bits) will result in about 450k interrupts per second. That is more than tough! I really question if that could be performed. you will have to make a test. Use "Release" setting for optimization.

   

 

   

Bob

0 Likes
Anonymous
Not applicable
        Thanks everyone for your help.   
0 Likes
HeLi_263931
Level 8
Level 8
100 solutions authored 50 solutions authored 25 solutions authored

Its not only that you get 450kbytes per second (which means about 100k interrupts per second if you use the FIFO FULL). But you also need to process this data somehow...

   

I would try to use DMA to get the data into larger memory areas where processing might be faster and easier.

0 Likes
Anonymous
Not applicable
        Thanks. I did try to use DMA. Still learning how to do that. Although it is possible to get data from all UARTs simultaneously, I have a reasonable assumption that most of the time I will have no more than two which should allow me the processing time and I tried to keep it efficient (lookup table). Thanks again for your help.   
0 Likes
OzTa_1570606
Level 1
Level 1
First like received First like given

How does UART component send 4 bytes? For example datagram for a stepper motor drive is shown below:

Which component do you use? UART? Or?

Thanks in advance!

0 Likes

ozta,

this thread is 5 years old, no one can see it. Please open a new discussion.

/odissey1

0 Likes

Hi BoTa,

I have started the thread and got some good information!

Which component to use for UART with 32 databits

0 Likes

Oz,

The UART has built-in 4 byte Rx and Tx FIFOs.  Therefore if the Tx FIFO is empty, if you place 4 bytes in the Tx FIFO (using UART_PutArray()) it will send out the 4 bytes with no further intervention from your application SW.

The issue is when you want to send more than 4 bytes in a sequence (like you want to with the TMC2208).

There are many ways to do this.  Some with better CPU performance than others.

  1. Push more bytes when the Tx FIFO is empty.  (Send at least 4 bytes at a time).
    • Keep the Tx Buffer size @ 4 bytes.
    • Configure the UART for a Tx interrupt of "Tx - On FIFO Empty".
    • Send the first 4 bytes by using UART_PutArray();
    • In the Tx_FIFO_Empty_ISR, look to see if there is any more data to send.  If so, UART_PutArray() with 4 more bytes (or as many as left if < 4bytes).
  2. Push more bytes when the Tx FIFO is not empty.  (Send 1 byte at a time).
    • Keep the Tx Buffer size @ 4 bytes.
    • Configure the UART for a Tx interrupt of "Tx - On FIFO Not Full".
    • Send the first 4 bytes by using UART_PutArray();
    • In the Tx_FIFO_Not_Full_ISR, verify the FIFO is not full using UART_ReadTxStatus().  If not full, send the next byte in the packet using UART_PutArray() or UART_PutByte().  If the packet is done, return from the ISR.
  3. Push more bytes when the Tx FIFO is not empty.  (Send 1 byte at a time).
    • Set the Tx Buffer size to the packet size.  In your case, 8 bytes. 
      This is basically identical to Option 2. listed above.
      The PSoC5 UART component will automatically enable the Tx ISR for "Tx - On FIFO Not Full".  It will also use it's own version of Tx_FIFO_Not_Full_ISR.

Option 1. is more efficient to reproduce CPU overhead to move bytes.

Option 2. and 3. are identical but 2. allows you control of the transfer if you need it.  Option 3. requires less coding by you.

There are more CPU efficient methods to move packet data which include DMA.  However I recommend starting with Option 3.  It's much simpler.   Get your TMC2208 comm working with the simplest method first. Develop the rest of your system with other application and driver code sections.   As time allows or CPU time becomes more critical, you can investigate further CPU performance enhancements.

Note:  One "quick and easy" CPU enhancement is to set the IMO clock to 24MHz and also set the USB clocking option.   This will provide a RC-base clocking with 0.25% accuracy and by setting the PLL to no higher than 70 MHz to have plenty of CPU idle cycles to improve your CPU overhead margin.

Len

Len
"Engineering is an Art. The Art of Compromise."