[fpc-pascal] Using built-in serial instead of synaser and the like for Linux console app?

Michael Van Canneyt michael at freepascal.org
Mon Aug 31 11:15:10 CEST 2020



On Mon, 31 Aug 2020, Bo Berglund via fpc-pascal wrote:

> On Fri, 21 Aug 2020 21:03:31 +0200, Bo Berglund via fpc-pascal
> <fpc-pascal at lists.freepascal.org> wrote:
>
>> Instead I need to add a thread for reading data so I can have an event
>> driven reception of data. It would read available data and fire off a
>> NotifyEvent to handle the incoming data in the main application.
>
> I have now started to implement a simple "fpserialport" class using
> the built-in serial unit and I am trying to add a reading thread so I
> can get an OnRxData event which is needed by many of the non-GUI
> applications I want to port to Fpc/Lazarus.
>
> It can be a simple TNotifyEvent where the user will implement the
> actual read or else a specific event procedure providing a TBytes
> container with the data. Both are possible.
>
> But when doing this I have run into a problem, how can I check how
> many Rx bytes are available to be read from the operating system?

There is some ioctl() function for that, but using that is not recommended.

The normal way of doing is is reading a buffer till no more data 
is read and then treat the buffer

>
> If I simply use the SerReadTimeout() function it will return either
> with 1 or more bytes or after the timeout. But there is a problem
> here:
>
> function SerReadTimeout(Handle: TSerialHandle; var Buffer; mSec:
> LongInt): LongInt;
>
> When calling this the Buffer length has to be set *beforehand* so the
> arriving data can fit inside the buffer, but how can I know how big
> Buffer must be?

Serial normally does not handle buffers >4k.

> I assume that if the Buffer is too small there will be an exception or
> else an overwrite of following memory?

Yes.

>
> The other variant of the read:
>
> function SerReadTimeout(Handle: TSerialHandle; var Buffer: array of
> byte; count, mSec: LongInt): LongInt;
>
> Here there is a count argument that will limit the amount of data read
> into the buffer, but from the code in serial.pp it seems like the
> function can in fact read more data into the buffer than count. The
> break condition is:
>
>  while fpSelect(Handle + 1, @readSet, nil, nil, @selectTimeout) > 0
> do begin
>    Inc(result,fpRead(Handle, Buffer[result], count - result));
>    if result >= count then // <== HERE possible overflow
>      break;
>    if Assigned(SerialIdle) then
>      SerialIdle(Handle)
>  end

That seems correct. since fpRead will never read more than Count bytes
(count-result is always less than count for positive result) result can at
most be Count.

(if fpRead returns a negative result, the algorithm is simply wrong, the
algorithm assumes the fpRead will always succeed)

Disregarding the error condition you can perfectly use this function.

Michael.


More information about the fpc-pascal mailing list