0

I have an imx8 module running Linux on my PCB and i would like some tips or pointers on how to modify the UART driver to allow me to be able to detect the end of frame very quickly (less than 2ms) from my user space C application. The UART frame does not have any specific ending character or frame length. The standard VTIME of 100ms is much too long

I am reading from a Sim card, i have no control over the data, no control over the size or content of the data. I just need to detect the end of frame very quickly. The frame could be 3 bytes or 500. The SIM card reacts to data that it receives, typically I send it a couple of bytes and then it will respond a couple of ms later with an uninterrupted string of bytes of unknown length. I am using an iMX8MP

I thought about using the IDLE interrupt to detect the frame end. Turn it on when any byte is received and off once the idle interrupt fires. How can I propagate this signal back to user space? Or is there an existing method to do this?

Engo
  • 39
  • 4
  • A UART frames each character/byte. You question seems to be about the end of a message/packet, something that the UART hardware cannot detect. IOW there is no concept of a message or packet frame at the hardware level. You need to reword your question. – sawdust Jun 08 '22 at 01:55
  • Ok i added some extra info – Engo Jun 08 '22 at 05:42
  • Generally in OSI model "A frame is a unit of data transmitting over the data link layer.". With this view @Engo is correct in his usage. In UARt communications framing is used at an different level and sawdust is correct. When doing data communications over a UART the concept of Framing becomes overloaded. – Gerhard Jun 09 '22 at 09:07

1 Answers1

1

Waiting for an "idle" is a poor way to do this.

Use termios to set raw mode with VTIME of 0 and VMIN of 1. This will allow the userspace app to get control as soon as a single byte arrives. See:

  1. How to read serial with interrupt serial?
  2. How do I use termios.h to configure a serial port to pass raw bytes?
  3. How to open a tty device in noncanonical mode on Linux using .NET Core

But, you need a "protocol" of sorts, so you can know how much to read to get a complete packet. You prefix all data with a struct that has (e.g.) A type and a payload length. Then, you send "payload length" bytes. The receiver gets/reads that fixed length struct and then reads the payload which is "payload length" bytes long. This struct is always sent (in both directions).

See my answer: thread function doesn't terminate until Enter is pressed for a working example.

What you have/need is similar to doing socket programming using a stream socket except that the lower level is the UART rather than an actual socket.

My example code uses sockets, but if you change the low level to open your uart in raw mode (as above), it will be very similar.


UPDATE:

How quickly after the frame finished would i have the data at the application level? When I try to read my random length frames currently reading in 512 byte chunks, it will sometimes read all the frame in one go, other times it reads the frame broken up into chunks. – Engo

In my link, in the last code block, there is an xrecv function. It shows how to read partial data that comes in chunks.

That is what you'll need to do.

Things missing from your post:

  1. You didn't post which imx8 board/configuration you have. And, which SIM card you have (the protocols are card specific).

  2. And, you didn't post your other code [or any code] that drives the device and illustrates the problem.

  3. How much time must pass without receiving a byte before the [uart] device is "idle"? That is, (e.g.) the device sends 100 bytes and is then finished. How many byte times does one wait before considering the device to be "idle"?

  4. What speed is the UART running at?

  5. A thorough description of the device, its capabilities, and how you intend to use it.

A uart device doesn't have an "idle" interrupt. From some imx8 docs, the DMA device may have an "idle" interrupt and the uart can be driven by the DMA controller.

But, I looked at some of the linux kernel imx8 device drivers, and, AFAICT, the idle interrupt isn't supported.

I need to read everything in one go and get this data within a few hundred microseconds.

Based on the scheduling granularity, it may not be possible to guarantee that a process runs in a given amount of time.

It is possible to help this a bit. You can change the process to use the R/T scheduler (e.g. SCHED_FIFO). Also, you can use sched_setaffinity to lock the process to a given CPU core. There is a corresponding call to lock IRQ interrupts to a given CPU core.

I assume that the SIM card acts like a [passive] device (like a disk). That is, you send it a command, and it sends back a response or does a transfer.

Based on what command you give it, you should know how many bytes it will send back. Or, it should tell you how many optional bytes it will send (similar to the struct in my link).

The method you've described (e.g.) wait for idle, then "race" to get/process the data [for which you don't know the length] is fraught with problems.

Even if you could get it to work, it will be unreliable. At some point, system activity will be just high enough to delay wakeup of your process and you'll miss the window.

If you're reading data, why must you process the data within a fixed period of time (e.g. 100 us)? What happens if you don't? Does the device catch fire?

Without more specific information, there are probably other ways to do this.

I've programmed such systems before that relied on data races. They were unreliable. Either missing data. Or, for some motor control applications, device lockup. The remedy was to redesign things so that there was some positive/definitive way to communicate that was tolerant of delays.

Otherwise, I think you've "fallen in love" with "idle interrupt" idea, making this an XY problem: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem

Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • I have no control over the content or length of the frames of UART bytes, it could be 3 bytes or 500, there is no such thing as frame end. Reading byte by byte is not practical. What is wrong with using the idle interrupt? If turned on mid transmission, it would exactly tell me when the frame is finished and no more data is being received – Engo Jun 08 '22 at 05:46
  • @Engo You don't have to read byte-by-byte. You can call `read` to attempt to read `N` bytes and the return value will be less than or equal to `N`, depending on how much is currently available to be read from the TTY. If the file is currently in blocking mode, it will only block until *some* data is available to be read (or EOF encountered), not until the full requested amount has been read (or EOF encountered). – Ian Abbott Jun 08 '22 at 16:44
  • How quickly after the frame finished would i have the data at the application level? When I try to read my random length frames currently reading in 512 byte chunks, it will sometimes read all the frame in one go, other times it reads the frame broken up into chunks. I need to read everything in one go and get this data within a few hundred microseconds – Engo Jun 08 '22 at 21:27
  • I have updated some info, I do knot know the length of the SIM response nor can I find it out, like I said in my original post you will have to believe me. I must catch the response extremely quickly or else the device on the other end of the chain which is expecting a response from the SIM will think the SIM is not present or has been removed. Just forget what I am reading from, it is irrelevant, I need to be able catch the end of the transmission extremely quickly or as quick as possible for my overall solution to work, the baud rate is around 250kbps, but thats also irrelevant – Engo Jun 09 '22 at 07:17
  • @Engo _the baud rate is around 250kbps, but thats also irrelevant_. No, it's not "irrelevant". If it were, I wouldn't be asking. _Edit_ your _question_ and post all this and the _other_ points (of the 5) I requested. And, any other relevant information. Don't try to filter what you think you need to post. Otherwise, like I said, an XY problem. – Craig Estey Jun 09 '22 at 13:53