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????
#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.
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 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)
#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).
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.
it will also answer question #2 above.
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?
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, 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!
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.
Thanks everyone for your help.
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.
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.