Recent

Author Topic: FPC Serial SerRead Usage  (Read 314 times)

GeneCode

  • New Member
  • *
  • Posts: 19
  • What is the cost of lies?
FPC Serial SerRead Usage
« on: October 14, 2019, 08:08:20 am »
I am using FPC Serial to communicate with a device i have with PC.

The transmitting part (SerWrite) works nicely I love it. But I am having issues with SerRead. Hope you can help me.

The port opening is no issue as it works with SerWrite, the reading part code is as follows:

Code: Pascal  [Select]
  1. {$H+}{$LongStrings ON} // just in case
  2. ...
  3. implementation
  4.  
  5. var
  6. s: String;
  7.  

In a TimerCallback, i have this:

Code: Pascal  [Select]
  1. procedure TForm1.readTimerTimer(Sender: TObject);
  2. begin
  3.    s := '';
  4.    WriteLn('read');
  5.    status := SerRead(serialhandle,s,10);
  6. end;

This application is windows app but I enabled the console so I can see WriteLn in console.
The issue crash happens at second time reading (since I can see first 'read' in console but not subsequent ones), it seems 's' becomes not available anymore for some reason.
Exception: SIGSEGV error and debugger just show assembly language that I dont understand.

The timer is called every 500ms. And the data sent from device is about every 500ms, $00 $11 $22.... $FF (packet of 16 bytes of arbitrary values). I did try writeln(inttostr(status)), and yes first call of timer shows '10' (ie length of data received) was successful. But I can't access the 's' variable. it just crashes.

« Last Edit: October 14, 2019, 08:09:53 am by GeneCode »
Windows 10
Lazarus 1.8.4

PaulRowntree

  • Jr. Member
  • **
  • Posts: 63
    • Paul Rowntree
Re: FPC Serial SerRead Usage
« Reply #1 on: October 14, 2019, 08:48:45 am »
Sorry geneCode, I use TLazSerial by JurassicPork ... works very well even at high data rates.  If you are willing to switch, I would be glad to help you ...
Paul Rowntree
- coding for instrument control, data acquisition & analysis, CNC systems

MarkMLl

  • Full Member
  • ***
  • Posts: 249
Re: FPC Serial SerRead Usage
« Reply #2 on: October 14, 2019, 09:42:09 am »
The issue crash happens at second time reading (since I can see first 'read' in console but not subsequent ones), it seems 's' becomes not available anymore for some reason.
Exception: SIGSEGV error and debugger just show assembly language that I dont understand.

The timer is called every 500ms. And the data sent from device is about every 500ms, $00 $11 $22.... $FF (packet of 16 bytes of arbitrary values). I did try writeln(inttostr(status)), and yes first call of timer shows '10' (ie length of data received) was successful. But I can't access the 's' variable. it just crashes.

Look at the declaration of SerRead():

{ Reads a maximum of "Count" bytes of data into the specified buffer.
  Result: Number of bytes read. }
function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt;

That's an array of bytes, so what you're actually doing is overwriting the structure that defines the string rather than reading into the string.

Serial.pp is intended as a low-level interface, I did the last round of modifications to it adding SerReadTimeout(), what I use it for is low-level binary operations driving non-standard protocols... that looks like the sort of thing you're doing /but/ the way you should be using it is by assuming that the OS will buffer whatever's coming in, reading it back a byte at a time, and feeding that to a state machine.

MarkMLl

Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

GeneCode

  • New Member
  • *
  • Posts: 19
  • What is the cost of lies?
Re: FPC Serial SerRead Usage
« Reply #3 on: October 14, 2019, 09:57:00 am »
The issue crash happens at second time reading (since I can see first 'read' in console but not subsequent ones), it seems 's' becomes not available anymore for some reason.
Exception: SIGSEGV error and debugger just show assembly language that I dont understand.

The timer is called every 500ms. And the data sent from device is about every 500ms, $00 $11 $22.... $FF (packet of 16 bytes of arbitrary values). I did try writeln(inttostr(status)), and yes first call of timer shows '10' (ie length of data received) was successful. But I can't access the 's' variable. it just crashes.

Look at the declaration of SerRead():

{ Reads a maximum of "Count" bytes of data into the specified buffer.
  Result: Number of bytes read. }
function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt;

That's an array of bytes, so what you're actually doing is overwriting the structure that defines the string rather than reading into the string.

Serial.pp is intended as a low-level interface, I did the last round of modifications to it adding SerReadTimeout(), what I use it for is low-level binary operations driving non-standard protocols... that looks like the sort of thing you're doing /but/ the way you should be using it is by assuming that the OS will buffer whatever's coming in, reading it back a byte at a time, and feeding that to a state machine.

MarkMLl

Hi MarkMLl

I tried SerReadTimeout, but seems to having same issue.

Code: Pascal  [Select]
  1. var  
  2.  rb           : array of byte;
  3. ...
  4. status := SerReadTimeOut(serialhandle,rb,100);
  5.    if (status>0) then begin
  6.       WriteLn(IntToHex(rb[0],2));
  7.       WriteLn(IntToStr(status));
  8.    end;

I am guessing status is only either 1 (have data) and 0 (no data)?
With serRead, i am getting no. of bytes, but for this it only shows 1 when i send a data packet (16 bytes).

Even then, it crash at accessing rb[0] and sure enough when i hover mouse on top of rb, it shows rb()
why has it cleared before I even manage to read it? Is there any configurations that i am missing?
« Last Edit: October 14, 2019, 10:01:08 am by GeneCode »
Windows 10
Lazarus 1.8.4

GeneCode

  • New Member
  • *
  • Posts: 19
  • What is the cost of lies?
Re: FPC Serial SerRead Usage
« Reply #4 on: October 14, 2019, 09:58:54 am »
Sorry geneCode, I use TLazSerial by JurassicPork ... works very well even at high data rates.  If you are willing to switch, I would be glad to help you ...

Hi Paul, I tried TLazSerial before but I was having issues with it as explained in HERE:
https://forum.lazarus.freepascal.org/index.php/topic,46953.msg335718.html#msg335718.
Windows 10
Lazarus 1.8.4

MarkMLl

  • Full Member
  • ***
  • Posts: 249
Re: FPC Serial SerRead Usage
« Reply #5 on: October 14, 2019, 10:16:38 am »
I tried SerReadTimeout, but seems to having same issue.

Code: Pascal  [Select]
  1. var  
  2.  rb           : array of byte;
  3. ...
  4.  

I am guessing status is only either 1 (have data) and 0 (no data)?
With serRead, i am getting no. of bytes, but for this it only shows 1 when i send a data packet (16 bytes).

Even then, it crash at accessing rb[0] and sure enough when i hover mouse on top of rb, it shows rb()
why has it cleared before I even manage to read it? Is there any configurations that i am missing?

DO NOT USE A MANAGED TYPE SUCH AS A STRING OR A DYNAMIC ARRAY!!!!!

Code: Pascal  [Select]
  1. (* Collect a file and return it as a StringList which must eventually be freed
  2.   by the caller. Any error results in memory being freed and nil returned.
  3. *)
  4. function GetXModem(serialHandle: TSerialHandle): TStringList;
  5. ...
  6.  
  7. var
  8.   orphan: string= '';
  9.   header: array[0..2] of byte;
  10.   data: array[0..127] of byte;
  11.   checksum: array[0..0] of byte;
  12. ...
  13.  
  14.       FillByte(header, SizeOf(header), 0);
  15. //    DebugWriteLn('== Expect header');
  16.       if SerReadTimeout(serialHandle, header, SizeOf(header), 1000) <> SizeOf(header) then begin
  17.         dump(false, header);
  18.         goto nakForHeader
  19.       end;
  20.       dump(false, header);
  21.       eotCount := 0;
  22. ...
  23.  
« Last Edit: October 14, 2019, 10:18:33 am by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

GeneCode

  • New Member
  • *
  • Posts: 19
  • What is the cost of lies?
Re: FPC Serial SerRead Usage
« Reply #6 on: October 14, 2019, 11:40:44 am »
Hi MarkMLl

thanks a lot I didn't know about Managed Types.  :o
Changing the variable type to defined array solved this issue.

Thanks a lot!
Windows 10
Lazarus 1.8.4

MarkMLl

  • Full Member
  • ***
  • Posts: 249
Re: FPC Serial SerRead Usage
« Reply #7 on: October 14, 2019, 11:58:34 am »
Basically,  array of byte  means different things depending on whether it's a variable declaration or a parameter.

If it's a variable declaration it behaves approximately the same as a string (declared without a length) in that what's allocated is a control block which points to an address on the heap.

If it's a parameter it means any array of bytes without a declared length which is why the length is usually passed as a separate parameter.

What you were doing was overwriting the control block, which was never going to work as expected :-)

Serial.pp, and in particular the SerRead() and SerWrite() procedures, are actually fairly thin wrappers around OS calls. However SerReadTimeout() is a bit more sophisticated since it handles various timing issues- the details of which can vary even among different members of the unix tribe, note also the comment about the callback which is relevant if SerDrain(), SerBreak or SerReadTimeout() is being called from the main thread (which also handles the GUI) but not if it's in a background thread... if you don't grok that just remember it against the time you start using threads.
« Last Edit: October 14, 2019, 01:16:11 pm by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.