Page 1 of 1

ReadWithTimeout function

Posted: Mon May 04, 2020 2:12 pm
by tpannone
This question is a continuation of my serial port issue and question about queues and FIFOs.

In an attempt to speed up my serial port reads, I'm reading a character from the serial port using the ReadWithTimeout() function, looking for the '$' character which signifies the start of a data sentence from my serial AHRS. The sentence length is fixed at 95 bytes (93 bytes of data followed by '\r' and '\n'). Once I recognize the start character, I want to use ReadWithTimeout() to read the next 94 characters from the serial buffer.

Unfortunately, the function usually only reads 30-34 bytes at a time (and occasionally 70-74 bytes). This jives with the 2nd paragraph in the function description, "The addition of a time-out does not cause the function to block until the maximum number of bytes specified in the function call is available." I'm pretty confident a full sentence (95 bytes, 230.4K baud, 50Hz data rate) is in the serial buffer to be read, so I'm not sure why it stops at 30-34 bytes. The description says I need to keep calling ReadWithTimeout() until I get the number of bytes I want.

Can you provide me with a little more detail on how the ReadWithTimeout() function works with regards to reading the serial buffer?

Re: ReadWithTimeout function

Posted: Mon May 04, 2020 3:33 pm
by pbreed
Serial takes time to transfer data,,,,
So the you see the $, then read whats still in the buffer (34 chars)
The rest had not arrived yet...

ReadWithTimeout could return a single byte,,,,


The later libraries in 3.2 have the function:
int ReadAllWithTimeout(int fd, char *buf, int nbytes, unsigned long timeout);
This does not port straight across because 2.92. is missign some of the classes in the new release....

Here is my quick sloppy untested port of that function to 2.X

int ReadAllWithTimeout(int fd, char *buf, int nbytes, unsigned long timeout)
{
int nread = 0;
int rv = 0;
unsigned long exit_by =Timetick+timeout;

while ((nread < nbytes) && (rv >= 0))
{
unsigned long cur_time=TimeTick; //Copy this because TimeTick could incrment during the function.
if(cur_time<exit_by)
{
rv = ReadWithTimeout(fd, buf+nread, nbytes-nread, exit_by-cur_time);
if (rv >= 0)
{
nread += rv;
}
}
else break;
}
return (nread ? nread : rv);
}

Re: ReadWithTimeout function

Posted: Mon May 04, 2020 3:34 pm
by pbreed
At least one Error Timetick should be TimeTick

Re: ReadWithTimeout function

Posted: Tue May 05, 2020 6:44 am
by tpannone
Thanks pbreed. I just assumed the data was available. I wasn't counting on the serial taking that long to transfer data into the serial buffers.

Since I was getting 30-34 bytes for a read, my next test was to break my reads into close to equal segments, such as 25,25,25,14. That still has to be faster than reading one byte at a time which is what I was originally doing, and which works fine for slow incoming data from a GPS or navigation system.

Thanks for the code snippet. I'll check it out. I'm currently running Eclipse 2.7.7.

Re: ReadWithTimeout function

Posted: Tue May 05, 2020 7:03 am
by tpannone
Is TimeTick a system variable available for use in 3.2, or does the programmer create it?

Re: ReadWithTimeout function

Posted: Tue May 05, 2020 9:04 am
by pbreed
#include <utils.h>

TimeTick is the RTOS time counter.
All RTOS timeout events are in TimeTicks.
(Not task switches, just timeout events)

You also have Secs (full seconds) availible.

Re: ReadWithTimeout function

Posted: Wed May 06, 2020 5:32 am
by tpannone
Great. Thanks pbreed.

Final question. What is the type VDWORD as shown in utils.h? I'm guessing some variation of a DWORD.

Re: ReadWithTimeout function

Posted: Wed May 06, 2020 6:48 am
by pbreed
V for volatile...
Meaning its likely to change at any time and the compiler can't optimize it away,,,


Suppose Secs was not volatile...

while(Secs<10)
{
OSTimeDly(20);
}

The compiler will only check Secs on entry, since nothing in the while loop changes Secs, the compiler will optimize the check away....
If you mark it volatile then the compiler actually checks it every time.

So any variable that you touch/read in separate tasks or interrupts must be marked volatile.

Re: ReadWithTimeout function

Posted: Thu May 21, 2020 11:25 am
by shockwave77598
Usually with Serial you'll want to read one character at a time from the serial stream, and handle it as you go.
#define SIZEPACKET 95

unsigned int CharsIn;
char tempchar;
char inbuff[SIZEPACKET+1];

int ReadData()
{
while (dataavailable())
{
tempchar = GetChar();
if(tempchar == $)
{ CharsIn = 0; }
if (CharsIn < SIZEPACKET)
{
inbuff[CharsIn] = tempchar;
CharsIn +=1;
if (CharsIn == SIZEPACKET)
{ return 1; // full packet is received}

}
}
return 0;
}

This checks to see if a character is available. If so, it loops fetching characters. If the character is $
then the recording of the sentence resets to zero. When 95 characters have been read you get a 1 out.
Only in this case will you get a 1 and not a zero. If you have no data to read, 0. If you've read a partial
sentence and no more data is available, 0.