Author Topic: Reading UART messages of different lengths  (Read 2893 times)

Offline Raffaele

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Reading UART messages of different lengths
« on: May 05, 2021, 06:08:15 PM »
Hi,
I'm trying to read UART messages of any length on a KL03 (does not support DMA).
I use fnRead in my task, and every time a new character is received the task is triggered.
My code is very simple

Code: [Select]
QUEUE_TRANSFER length;
while (   (length = fnRead(SerialPortID, uartMessage, MEDIUM_MESSAGE)) != 0 ){
counter++;
//fnDelayLoop(600);
}

Now, here is the problem, if I do not use that fnDelayLoop, the while is entered for each character, one at a time. So, for a message of n chars, there will be n interrupts to my task and n while loops. If, instead, I use the fnDelayLoop, the while is executed only one time for the whole message (which I prefer). My understanding is that without the delay, the while terminates because the characters are too slow with respect the the execution of the while loop and the uart rx buffer is empty, so the delay allows waiting for the whole message to arrive while still in the loop.

But in this way the delay to to be used depends on the length of the message that I don't know beforehand and it is not constant. And if the delay is not enough for a long messages, then its last part will come with the initial part of the next message.
Is there a better way to do this?
« Last Edit: May 05, 2021, 06:45:52 PM by Raffaele »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Reading UART messages of different lengths
« Reply #1 on: May 05, 2021, 10:13:39 PM »
Hi

Do you have a protocol that tells you how many bytes the message will contain? If you you can ignore input until its fnMsgs() value equals that size.
If you know that messages are received without gaps between bytes (as frames) you may be able to use the idle line interrupt to inform that there is a frame to be read instead.
If there is always a termination character (like a line feed) you could use message mode (rather than character mode) - see the UART user's guide at https://www.utasker.com/docs/uTasker/uTaskerUART.PDF and configure for message mode and b schedule only when there is a complete frame.

I think that your loop without a delay means that each time the task is scheduled there is one byte to read and then it quits before returning to do the same when the next byte is received.
With the delay there is initially one byte to be read but then the delay gives the UART (interrupt driven reception) the chance to receive a number of following bytes. Then, when the delay has completed and the input is read a second time a number of additional bytes are waiting (and possibly the complete frame if the delay is long enough).

Regards

Mark

Offline Raffaele

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Re: Reading UART messages of different lengths
« Reply #2 on: May 05, 2021, 10:44:49 PM »
Thanks Mark, you confirmed what I had assumed. Unfortunately I don't use a protocol that tells the size of the messages and using fnMsgs() would give me the same behavior, nor I have  a specific termination character. I think I can make the delay work then.

Thank you