Using IDLE / ILIE to terminiate UART DMA transfers?

cancel
Showing results for 
Search instead for 
Did you mean: 

Using IDLE / ILIE to terminiate UART DMA transfers?

807 Views
robertpoor
Contributor V

I'm implementing a Modbus library on the KL27Z.  Since Modbus RTU packets can be variable length, the Modbus protocol specifies (roughly) that the end of a packet is signaled by when the bytes stop coming.  (The spec actually specifies a gap of 3.5 bit periods ends a packet, but since communication is strictly master requests / slave responds, there's no significant penalty for relaxing that requirement.)

I'd like receive serial data via UART / DMA, but use the IDLE flag (and ILIE interrupt) in the UART to terminate the DMA reception.

Before I charge off and implement this myself, it's worth asking: has anyone else written something like this?  Do you have any code and/or words of wisdom to share?

- Robert

Tags (2)
0 Kudos
6 Replies

205 Views
mjbcswitzerland
Specialist V

Hi Robert

There is a flexible and industrially proven Modbus solution in the uTasker project which works on all Kinetis parts - see http://www.utasker.com/modbus.html
[Master/Slave ASCII/RTU/TCP, gateway and router with compete serial diagnostics implementation and float register support]. I have used it on 6 RTU interfaces in parallel at 115'200 Baud RTU (and RS485) mode on K parts and it was used in hoist controllers for the 52 ton video screens in the "the Claw" on U2's 360 degree tour: http://www.kinesys.co.uk/product/digihoist/

Modbus RTU specifies that 1.5..3.5 character idle time is to be considered as a timing error and frames rejected and 3.5 as end of RTU frame, which is how it is implemented (using PIT or FlexTimer/TPM). Due to this, DMA is not used for reception (although it optionally used for transmission). Also the same timer controls RTS timing on parts without modem control in the UART/LPUART.

Regards

Mark

P.S. Can also be used with FreeRTOS based projects.

P.P.S. The project does have free-running DMA support for the KL27 on all UARTs in case you want to try manipulating this to tweak DMA reception (if full conformance is not an issue).

0 Kudos

205 Views
robertpoor
Contributor V

Mark:

The uTasker Modbus implementation sounds great except for:

Due to [timing requirements], DMA is not used for reception... 

My oscilloscope and I are *very* familiar with Modbus timing.  :smileywink:  Our app is required to run in VLPR mode (4MHz system clock). 

Our current implementation receives bytes at interrupt level, keeps a time stamp for the most recently received byte, and the foreground loop processes the packet once it notices that the current time delta exceeds 3.5 bit periods.  This works reliably, but given the timing of the interrupt routine and slow system clock, the highest baud rate we can reliably handle is 19200.  I could probably tighten up the interrupt code, but I'd rather let the hardware do the work.

And since the foreground code demands frequent and periodic attention, I'd rather go all-in on DMA to reduce the processor burden at higher baud rates.

This is why we're seeking a DMA-based version.

P.P.S. The project does have free-running DMA support for the KL27 on all UARTs in case you want to try manipulating this to tweak DMA reception (if full conformance is not an issue).

That sounds promising!  I'll take a look.  Thanks!

- r

0 Kudos

205 Views
mjbcswitzerland
Specialist V

Robert

I can run Modbus RTU Rx in DMA mode on KL27 but its reliability depends on the speed and timing in the product/installation.

The problem with the idle detection is that it is fixed at around 1 character delay in the HW and so will fire too early for proper Modbus timing. If you are sure that the slave or master at the other end will never have idle periods within a valid message transmission that are longer than this it is of course no practical problem. If you only need to support 19200 Baud it "may" be generally Ok even if you haven't the other end fully under your control.

In the uTasker Modbus project there is a define called FAST_MODBUS_RTU which respects the 2.5..3.5 character timing at all baud rates, but if not used it relaxes the timing above 19'200 Baud, which is allowed according to the Modbus specs in order to be more tolerant with old UARTs (remembering that the Modbus spec dates back to the 1970s - I think - where UARTs/processors were often pushed to get the accuracy - your 4MHz VLPR would have been high-end back then). I have found that I often have to relax this when using USB-RS232 or USB-RS485 cables at the PC since they can have pauses that are otherwise detected as RTU frame termination (in the middle of Modbus frames...) This is what I would be worried about though (maybe OK at 19'200 max. but at 115kB I have had some converters that would not work in RTU mode) if the other end is something that can't be fully controlled, because there may be installations which fail. If you can at least specify known-good converters you will probably also be OK.

Regards

Mark

0 Kudos

205 Views
robertpoor
Contributor V

Where to begin... :smileyhappy:

Our host/master is always using the FT232 USB converter chip, and is driven by a library we control (the packet is always fully computed with CRC before transmission starts).  In addition, we never send or receive more than 6 words / 12 bytes of payload data.  Given all that, I think we can assume "gap-less" packets arriving at our client/slave.

But if the host/master OS inserts an intra-packet gap, and the slave interprets that as end-of-packet, the CRC will fail and the slave will silently drop the packet.  If there is an intra-packet gap that is so short that the slave doesn't notice, then the CRC will succeed and the packet will be processed normally.

As for using IDLE for end-of-packet detection; you are correct to say that IDLE's one-byte trigger is too short to meet the 3.5 byte delay specified by Modbus.  But -- not to be flippant -- so what?  If there's a gap of any length, it's *probably* the end of packet (see previous paragraph).  And if the CRC checks out, then it's definitely the end of packet.

Since the Modbus uses a strict "request / response" protocol in which all requests are initiated by the master, I think the only place where the 3.5 byte delay comes in to play is when the master wants to retry a packet -- it needs to make sure that enough time has elapsed so a request followed by a retry isn't interpreted as a single packet.  But the why would the master be retrying a packet after such a short timeout?

Perhaps I'm missing something fundamental here.  Let me know!  Thanks.

0 Kudos

205 Views
mjbcswitzerland
Specialist V

Robert

Your reflections are all good.

I just checked a Modbus RTU slave on a KL27 running at 2MHz and 19200 Baud in RTU mode and realised that it also depends on which UART or LPUART you are using on the KL27.


The UART has the mentioned single byte restriction but the LPUARTs can be configured to flag idle after 1, 2, 4, 8, 16, 32 or 64 characters. With this set to 4 characters it is quite suitable for fairly accurate RTU end of frame (it still can't recognise the illegal 1.5..3.5 space but - as you said - it is not a big deal) so would be safe.

To do it I opened the UART (or LPUART) in free-running DMA mode (this needs a modulo aligned circular buffer for the KL27's DMA to be able to do it but this is automatic in the uTasker driver) and installed an idle line interrupt (one character from stop bit if UART or 4 characters from stop bit if LPUART).
The DMA receives the frame to the circular buffer (up to 256 bytes according to max RTU frame size) and the idle line interrupt simply schedules the same operation as the 3.5 character timer otherwise does. This causes the collected buffer to be handled as Modbus RTU input and the Modbus response to be returned accordingly (I also use DMA on transmission).

Due to the slow clock I get 19230 Baud accuracy or I can also run at 115'2kBaud but with less accuracy (117'647 on the UART or 125kB on LPUARTs). Since it is fully DMA driven, apart from the idle line interrupt and the buffer handling, the processor load is almost negligable even at slow clock speeds.

Regards

Mark

0 Kudos

205 Views
mjbcswitzerland
Specialist V

Hi Robert

I made a short video of the complete operation:

https://youtu.be/OrqSn9x7N1E

This shows how I simulate in real time the KL27, its UART Tx and Rx DMA operation, plus idle line interrupt, as well as connection and operation with a real Modbus master tool (via COM port loop-back).

I show just the idle line interrupt handling in the debugger, leading to the Modbus reception handling but it may give an idea - in fact the only actual Modbus program change I needed was the three lines in fnSCIRxIdle() which is about what the original RTU timer did. (it operates on up to 3 UARTs [2 LPUARTs and 1 UART] although the DMA channels are restricted so not all can use DMA a the same time)

It shows how powerful simulation techniques can be to drastically reduce embedded development time.

Regards

Mark

0 Kudos