ReadWithTimeout function

Discussion to talk about software related topics only.
Post Reply
tpannone
Posts: 69
Joined: Fri Feb 15, 2013 1:04 pm

ReadWithTimeout function

Post 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?
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: ReadWithTimeout function

Post 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);
}
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: ReadWithTimeout function

Post by pbreed »

At least one Error Timetick should be TimeTick
tpannone
Posts: 69
Joined: Fri Feb 15, 2013 1:04 pm

Re: ReadWithTimeout function

Post 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.
tpannone
Posts: 69
Joined: Fri Feb 15, 2013 1:04 pm

Re: ReadWithTimeout function

Post by tpannone »

Is TimeTick a system variable available for use in 3.2, or does the programmer create it?
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: ReadWithTimeout function

Post 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.
tpannone
Posts: 69
Joined: Fri Feb 15, 2013 1:04 pm

Re: ReadWithTimeout function

Post 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.
User avatar
pbreed
Posts: 1080
Joined: Thu Apr 24, 2008 3:58 pm

Re: ReadWithTimeout function

Post 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.
shockwave77598
Posts: 22
Joined: Sat May 27, 2017 10:38 am

Re: ReadWithTimeout function

Post 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.
Post Reply