Kinetis (K10) UART DMA rx error handling

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Kinetis (K10) UART DMA rx error handling

1,774 Views
jarkko
Contributor I

I currently have UART(0) rx running with DMA (circular buffer which is processed from task by using CITER-register to check if new data has been received) and it works ok. I am really concerned what happens if framing error (FE) or parity error (PF) appears, how it can be recognized and recovered.

CPU manual (http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K10P144M120SF3RM.pdf?fsrch=1&sr=4&p...) does not cover that situation at all. I found a couple of discussions which by the way does not relief my concerns at all.. Some where else has been also said that manual S1+D register reading operations cannot be used during DMA and it sounds logical after reading those topics.

https://community.freescale.com/thread/301651

https://community.freescale.com/thread/301031

I have also tested that UART error IRQ (BSD_INT_ID_UART0_ERR) can be used together with DMA (at least in overrun (OR) case works) but "suprisingly" the S1-register is empty when that UART error handler is serviced...

When the DMA irq really occurs other than INTHALF & INTMAJOR cases, it looks to appear at least from overrun (OR) (not documented anywhere) error does it occur also from FE & PF?

For me it looks like that one solution could be to use UART error IRQ and if that occurs then discard all the data from DMA ring-buffer collected so far because it cannot be known which byte(s) have had FE or PF error (and of course do not try to do S1+D reading just use error_IRQ as an indication) - I am afraid that even this requires some bubble gum to do it so that also the task processing the ring buffer receives the information early enough. If DMA irq occurs in every uart failure then that could be used instead because currently we are not using INTMAJOR nor INTHALF (still the UART error irq sounds to be more robust...)

This new continuous DMA transfer shall not give OR error even though other DMA channels have higher priority especially if UART rx FIFO is used? We are currently running with 460800 but planning to rise it to 921600, and if it (OR) somehow still happens can the DMA self recover the OR bit or not? If DMA cannot ack the OR situation and it is theoretically possible how in the earth you can notice it without reading S1-register, can you somehow pause the DMA (so that you can do S1+D) and then continue the DMA where it were so that it does not require new "initialization" meaning that acquisition starts from the beginning of the ring buffer...

Short history why I am concerned:

Previously we had a little a bit different DMA approach which resulted in losing some bytes here and there without any visible uart error - do not fully understand how this is possible because the missing byte was always the one which was suppose to come first when new DMA request was given (uart fifo was also in use)... Method was "single shot" DMA uart rx transfer (with only INTMAJOR_MASK in CSR) where the used protocol itself was parsed in DMA interrupt and parser told how many bytes should be read next and new DMA rx transfer was triggered. Maybe the problem was that DREQ bit was not set in CSR (instead we disabled the uart's RIE in the DMA interrupt but there is of course delay until IRQ is served) - I don't want to go back to old code to test this assumption.

- overall this approach looked non-optimal because it required a lot of irq-time to do operations so I decided to use DMA as it should be used and that resolved also the byte missing problems...

Based on my brief tests with old method it looks like that at least the overrun situation gives DMA irq ("HW_DMA1_IRQ" in case  of uart0 rx) even though the required byte count for DMA transfer completition is not fullfilled (citer != biter && citer != 0) -- this is completely undocumented feature but of course it makes sense because otherwise DMA operation would be jammed because OR prevents receiving more characters...

Overall I want to say that uart error handling while using DMA is not very well covered anywhere, not in CPU manuals (where it should be) and not here in the forums, basically the issue has been raised here but not any workaround has been presented (some/all example codes does handle errors at all). I already apologize if there is topic handling this issue, I just couldn't find it...

Labels (1)
0 Kudos
1 Reply

787 Views
jarkko
Contributor I

I'll guess that I figured out how the error shall be handled (or at least one way to do it).

1. Establish uart error IRQ & disable DMA IRQ (just in case if/when error triggers this one also) or at least do not do any error related handling there

2a. In uart error isr, stop DMA (DMA_CERQ) & disable uart RX (to prevent fifo overflow while recovering from error)

2b. Inform task (event) that error has occured & DMA stopped (set also one direct extra flag, see NOTE)

2c. S1+D reads + RX_fifo_flush

3a. In task, when error event received: reset ring buffer read counters
3b. start DMA again & enable uart rx

NOTE: Also in the task when processing ring buffer normally the "extra flag" needs to checked after reading CITER-value to determine that error hasn't just happened and bytes at least so far are valid and ok to process...

So some "bubble gum" needed, especially the rx-disabling but if baudrates are ~1M then it takes only 80us to fill the fifo so there is no guarantee that task manages to handle the event in such small time...

0 Kudos