Hi,
I'm making progress with using the UARTE in bare metal programming. My goal is to have maximum control over my system and provide a reliably and robust realtime implementation. So this time, I have some more sophisticated questions that are not documented in the Product Specification.
Reliable handling of UART data flow
It seems like the UARTE modules have an internal FIFO in addition to the EasyDMA feature. The documentation in the Product Specification suggests that there might be multiple bytes in waiting in the internal FIFO when the last byte of the current RX buffer is written and the ENDRX event is generated. It is especially mentioned in reference to the STPORX task, which might trigger an ENDRX event with data remaining in the internal FIFO (which needs a FLUSHRX task to write the remaining bytes via EasyDMA).
Question 0: How big is the internal FIFO of the UARTE modules?
Question 1: What happens to the remaining bytes in the internal FIFO when a new STARTRX task is triggered? Will the FIFO content be written to the EasyDMA buffer without date being lost? Or will the bytes in the internal FIFO be discarded when a STARTRX task is triggered? For reliable data reception (that does not miss any bytes on the UART while the receive buffer is switched), it would only make sense to continue writing the internal FIFO content when STARTRX is triggered, especially in combination with the ENDRX-STARTRX short which immediately restarts reception if the buffer is full.
Question 1a: When using the ENDRX-STARTRX short, will there no data be lost if the old EasyDMA buffer is full, and the STARTRX task continues reception into the next buffer?
Question 1b: When using the ENDRX-STARTRX short, if STOPRX is triggered before the current buffer is full, because of the short, reception should automatically be continued into the next buffer, just like question 1a mentioned. Will there also be no data loss in this case? Is this the way to manually trigger a safe/robust buffer switch and handle available data?
Question 2: I documented my approach in the following flow chart. Will this work without data loss? My goal is to take advantage of the UARTE capabilities and use large buffers that allow for using low priority UARTE interrupts that do not interfere with other time critical code in the system.
How to detect a BREAK condition
I consider using a BREAK condition for synchronizing communication shortly before the beginning of a data packet. Unfortinately, there is very little information available about the BREAK bit in the ERRORSRC status word.
Question 3: Is the BREAK bit just set by the SoC (when RxD stays low for too long) and must be reset by software? Or is it automatically reset of a rising edge is detected on the RxD line, so that it does automatically reflect the current RxD state?
Question 4: Is the BREAK bit only set while reception is active (STARTRX triggered, ENDRX not triggered yet)? Or can I completely stop reception, wait for the BREAK bit to become active (e.g. by polling the bit), and then manually start reception?
Question 5: If I detect a BREAK condition and trigger STARTRX while RxD is still low. Will I get an error event (interrupt) again? Or will the UARTE module just wait for the next falling edge on RxD (which is the trigger for the Start bit of a transmission) and start receiving?
Quetion 6: There is a ERROR-STOPRX short. If this short is combined with the ENDRX-STARTRX short, can this combination be used to trigger a receive buffer switch as described in my flowchart n question 2? Or will there be two ERROR events (one for frame error and one for break condition) in short sequence that will trigger a double buffer switch within very short time and mess up my approach from above? (I guess it would be nice to have an additional BREAK event for this kind of configuration...)
Update: Oh my... I must have confused something with the shorts definitions... it is actually ENDRX-STOPRX, not ERROR-STOPRX. Just assume that I use the ERROR event in combination with the PPI to trigger the STOPRX task. (Or maybe the STARTRX task, if there is no need to manually stop a previous reception - see question 7.)
By the way, it would be nice to have a BREAK event in a future version of the UARTE device for such purposes (and to prevent double events because of the frame error). Just a little suggestion for the engineers ;)
Question 7: What happens if the STARTRX task is triggered while reception is already active? (Will reception be restarted at the next RXD.BUFFER? Will ENDRX be triggered? Or will nothing happen at all?)
Using UARTE as FIFO
It would be very nice to use the UARTE as a simple FIFO. Just configure a large enough circular buffer and use the current EasyDMA reception state as the head, and an additional softwware variable which is advanced by polling as the tail. Reception is automaticaly continued at 0 by using the ENDRX-STARTRX short. The problem is that the RXD.AMOUNT value, which is considered the head of the fifo, is only updated once reception has stopped.
Question 8: Is there any way to access the current state of the RXD EasyDMA unit which reflects the current buffer state in RAM? (If not, can you consider making it available in the next generation of devices? Naming it something like RXD.CURRENTAMOUNT or RXD.PROGRESSED or so? The information is already available in the system anyway...)
Question 9: Considering what I have read in the documentation, it is not reliable to use the RXDRDY event in combination with a counter to manually count the received bytes and use it as the FIFO head, as the reflected data might not have been written to the EasyDMA buffer yet. (Also, I would be a bit worried about glitches when the counter module and the EasyDMA module go out of sync.) Do you agreee that this is not a reliable way to implement a simple and efficient FIFO with UARTE? Do you have any other suggestions?
Best regards,
Michael