Recent

Author Topic: LazSerial and DataModule Problem  (Read 337 times)

FOV_2001

  • New member
  • *
  • Posts: 8
LazSerial and DataModule Problem
« on: December 12, 2019, 04:18:15 pm »
Hi All,

First of all, thanks for readme, and if its posible, to help me.

Here is my Scenario:

I have a Main application, that call a Library that take care of devices tha uses Serial Comunication, due to I'm using LazSerial component

On Windows, the systems Works OK
Main application, and Library (.dll)

On Linux:
Main application, and Library (.so)
The Main initialize the Library OK, with no errors. Call to the Serial Connection, define connection conditions like Port, Baud, etc, and Open It.

The Unit (serial1) received the ONSTATUS event like HR_Connect, immediatly received an interruption again, with code HR_SerialClose, after that, the event call DataPortSerial unit (compiles with LazSerial) and on the line 332 -> FSerialClient := TSerialClient.Create(True);

The system Hangs, probably jumping to the Sky. No more answer to nothing, keyboard do not responde, and on debuggin, only solution, to stop it.

My first confession : My knoledge about Linux is pretty close to ZERO.

All comments, suggestions and critics Will be appreciated.

I've commented on my code all ones, that on my opinion was irrelevant, but feel free to ask any thing you consider important. 

THANKS IN ADVANCE

Code: Pascal  [Select]
  1.  
  2. unit serial1;
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6. interface
  7.  
  8. uses
  9.   Classes, SysUtils, IniFiles, LazSerial, LazSynaSer;
  10.  
  11. const
  12.   Prefix = 'BV EBDS';
  13.   CTRL_Omnibus   = $10;
  14.   CTRL_Calibrate = $40;
  15.   CTRL_Download  = $50;
  16.   CTRL_Auxiliary = $60;
  17.   CTRL_Extended  = $70;
  18.  
  19.  
  20. type
  21.  
  22.   { TMod_Billetero }
  23.  
  24.   TMod_Billetero = class(TDataModule)
  25.     LazSerial1: TLazSerial;
  26.     procedure LazSerial1Status(Sender: TObject; Reason: THookSerialReason;
  27.       const Value: string);
  28.   private
  29.     PP  :String;
  30.     Function  Conectar( Inicializar_BV: Boolean): Integer;
  31.  
  32.   public
  33.  
  34.     Function  Start_Up (Boot_BV: Boolean): Longint;
  35.     Function  Cerrar: Longint;
  36.  
  37.   end;
  38.  
  39. var
  40.   Mod_Billetero: TMod_Billetero;
  41.  
  42. implementation
  43.  
  44. {$R *.lfm}
  45.  
  46. Function TMod_Billetero.Cerrar: Longint;
  47. begin
  48.   //TXTime.Enabled:=false;
  49.   //RXTime.Enabled:=false;
  50.  
  51.   if LazSerial1.Active then
  52.     begin
  53.       LazSerial1.SynSer.Purge;
  54.       LazSerial1.Close;
  55.     end;
  56.  
  57.  { if BV_Bill_Config.Operativo then
  58.     begin
  59.       BV_Bill_Config.Operativo := False;
  60.     end; }
  61.  
  62.   {if Activar_Logs then
  63.     Registro_Log(Archivo_Logs,Prefix,'DLL Correctamente Cerrada');  }
  64.  
  65.   Result := 0;
  66. end;
  67.  
  68. Function TMod_Billetero.Start_Up (Boot_BV: Boolean) : Integer;
  69. var
  70.  Log_Dir : String;
  71.  Temp_Str : String;
  72.  FIniFileName : String;
  73.  Grabar : Boolean;
  74.  IniFile : TIniFile;
  75.  Temp_Int : Integer;
  76.  App_Name : String;
  77.  
  78. begin
  79.   {$IFDEF LINUX}
  80.    IniFile := TIniFile.Create(
  81.    GetAppConfigFile(False) + '.conf');
  82.   {$ELSE}
  83.    IniFile := TIniFile.Create(
  84.    ExtractFilePath(Application.EXEName) + 'SimuGps.ini');
  85.   {$ENDIF}
  86.  
  87. {  Temp_Str := ExtractFilePath  (Get_Aplication_Name);
  88.   {$IFDEF MSWINDOWS}
  89.   Log_Dir  := Temp_Str + 'Logs\';
  90.   {$ENDIF}
  91.  
  92.   {$IFDEF Linux}
  93.   Log_Dir  := Temp_Str + 'Logs';
  94.   {$ENDIF}
  95.  
  96.   if Not DirectoryExists(Log_Dir) then
  97.     CreateDir(Log_Dir);
  98.  
  99.   Temp_Str := ExtractFileName(Get_Aplication_Name);
  100.  
  101.   Archivo_logs := ChangeFileExt(Temp_Str,'.log');
  102.  
  103.   {$IFDEF MSWINDOWS}
  104.   Archivo_Logs := Log_Dir + Archivo_Logs;
  105.   {$ENDIF}
  106.  
  107.   Temp_Str := Get_Aplication_Name;
  108.   App_Name := Temp_Str;
  109.  
  110.   FIniFileName := ChangeFileExt(Temp_Str, '.ini');
  111.  
  112.   Grabar := False;
  113.  
  114.   if Not FileExists(FIniFilename) then
  115.      begin
  116.        Grabar := True;
  117.      end;
  118.  
  119.   IniFile      := TIniFile.Create(FIniFileName);
  120.  
  121.   Temp_Int := IniFile.ReadInteger('LOGS', 'Activar', 1);
  122.  
  123.   if Temp_Int = -1 then
  124.     begin
  125.       Grabar := true;
  126.       Activar_Logs := True;
  127.     end
  128.   else
  129.     Activar_Logs := (Temp_Int = 1);
  130.  
  131.   Temp_Int := IniFile.ReadInteger('LOGS', 'Nivel', -1);
  132.  
  133.   if Temp_Int = -1 then
  134.     begin
  135.       Grabar := true;
  136.       Log_Level := L_Info;
  137.     end
  138.   else
  139.     Log_Level := Temp_Int;
  140.  
  141.   Temp_Int := IniFile.ReadInteger('Lenguaje', 'Idioma', -1);
  142.  
  143.   if Temp_Int = -1 then
  144.     begin
  145.       Grabar := true;
  146.       LenguajeIndex := 1;
  147.     end
  148.   else
  149.     LenguajeIndex := Temp_Int;
  150.  
  151.   if Grabar then
  152.     begin
  153.       if Activar_Logs then
  154.         IniFile.WriteInteger('LOGS', 'Activar', 1)
  155.       else
  156.         IniFile.WriteInteger('LOGS', 'Activar', 0);
  157.     end;
  158.  
  159.   IniFile.Free;
  160.  
  161.   if Activar_Logs then
  162.     begin
  163.       Registro_Log(Archivo_Logs,Prefix,'#################################');
  164.       Registro_Log(Archivo_Logs,Prefix,'           EBDSCOMM');
  165.       Registro_Log(Archivo_Logs,Prefix,' Iniciando Servicio por Start_Up');
  166.       Registro_Log(Archivo_Logs,Prefix,'#################################');
  167.       Registro_Log(Archivo_Logs,Prefix,'Version de DLL : ' + About);
  168.       Registro_Log(Archivo_Logs,Prefix,'Indentificador de Hardware : ' + Get_Identifier);
  169.     end;
  170.  
  171.   if Leer_Valores_Default then // Arranco con algo configurado por las dudas
  172.     begin
  173.       if Not Load_Variables_Entorno_Puerto(true) then // Si no esta configurado - Configuro y Guardo
  174.         begin
  175.           Result := -2;
  176.           Exit;
  177.         end
  178.       else
  179.         if Not Load_Variables_Entorno_Billetes(true) then // Si no esta configurado - Configuro y Guardo
  180.           begin
  181.             Result := -2;
  182.             Exit;
  183.           end
  184.         else
  185.           begin
  186.             Cargar_Tabla_Paises;
  187.             BV_Protocolo := 'EBDS';
  188.             StrPLCopy(PChar(@BV_Bill_Config.Protocolo[0]), BV_Protocolo, High(BV_Bill_Config.Protocolo));  }
  189.             Result := Conectar(Boot_BV);
  190.        {   end;
  191.     end
  192.   else
  193.     begin // Aca no deberia entrar NUNCA
  194.       Result := -1;
  195.       Exit;
  196.     end;    }
  197. end;
  198.  
  199. procedure TMod_Billetero.LazSerial1Status(Sender: TObject;
  200.   Reason: THookSerialReason; const Value: string);
  201. begin
  202.   case Reason of
  203.      HR_SerialClose : begin
  204.                         pp :='Cerrado';
  205. //                        StatusBar1.SimpleText := 'Port ' + Value + ' closed';
  206.                       end;
  207.      HR_Connect     : begin
  208.                         pp :='Conectado';
  209. //                        StatusBar1.SimpleText := 'Port ' + Value + ' connected';
  210.                       end;
  211.      HR_CanRead     : begin
  212.                         pp :='Puede Leer';
  213. //                        StatusBar1.SimpleText := 'CanRead : ' + Value ;
  214.                       end;
  215.      HR_CanWrite    : begin
  216.                         pp :='Puede Escribir';
  217. //                        StatusBar1.SimpleText := 'CanWrite : ' + Value ;
  218.                       end;
  219.      HR_ReadCount   : begin
  220.                         pp :='Conteo de Lectura';
  221. //                        StatusBar1.SimpleText := 'ReadCount : ' + Value ;
  222.                       end;
  223.      HR_WriteCount  : begin
  224.                         pp :='Conteo de Escritura';
  225. //                        StatusBar1.SimpleText := 'WriteCount : ' + Value ;
  226.                       end;
  227.      HR_Wait        : begin
  228.                         pp :='Wait';
  229. //                        StatusBar1.SimpleText := 'Wait : ' + Value ;
  230.                       end;
  231.    end ;
  232.  
  233. end;
  234.  
  235. Function  TMod_Billetero.Conectar( Inicializar_BV: Boolean): Integer;
  236. begin
  237.   LazSerial1.Device:= '/dev/ttyUSB0';
  238.   LazSerial1.DataBits:= db7bits;
  239.   LazSerial1.Parity:= pEven;
  240.   LazSerial1.BaudRate:= br__9600;
  241.   LazSerial1.open;
  242.   Result := 0;
  243. end;
  244.  
  245.  
  246. initialization
  247.     try
  248.       Mod_Billetero := TMod_Billetero.Create(nil);
  249.   except
  250.     begin
  251.       //Result := -1;
  252.     end;
  253.   end;
  254.  
  255. finalization
  256.   if Assigned(Mod_Billetero) then
  257.     begin
  258.       FreeAndNil(Mod_Billetero);
  259.     end;
  260. end.
  261.    
  262.  
  263.  

MarkMLl

  • Hero Member
  • *****
  • Posts: 610
Re: LazSerial and DataModule Problem
« Reply #1 on: December 12, 2019, 05:39:45 pm »
I wasn't even aware of that package. I normally use the standard serial.pp unit which comes with FPC, I know it works since I was the last person to do any maintenance on it.

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.

FOV_2001

  • New member
  • *
  • Posts: 8
Re: LazSerial and DataModule Problem
« Reply #2 on: December 12, 2019, 07:25:33 pm »
Thanks for your prompt response, any clue where I can start? the documentation is very high level for my knowledge,

Again thanks, now we have an start point

FOV_2001

  • New member
  • *
  • Posts: 8
Re: LazSerial and DataModule Problem
« Reply #3 on: December 12, 2019, 08:50:31 pm »
Just an ADDON, I'm allready insert the user on the dialout group

MarkMLl

  • Hero Member
  • *****
  • Posts: 610
Re: LazSerial and DataModule Problem
« Reply #4 on: December 12, 2019, 09:24:51 pm »
Thanks for your prompt response, any clue where I can start? the documentation is very high level for my knowledge,

Well, I can't really comment on LazSerial or any of the other high-level ones since when I worked on serial.pp it was specifically to support low-level stuff: at the time I was working on a serial port monitoring program to allow me to reverse-engineer the protocol between two HP instruments (which were actually serial port monitors :-) What I can say is that it works equally well in both the main (GUI) thread or a background thread, and that it was tested against Linux, Solaris and Windows.

/If/ you decided to take a look at it, what I'd suggest is that you went through a sequence of simple steps: open a port, check the handle is valid, set the port parameters (without hardware handshake), transmit a sequence of bytes, close the port. Then start looking at reception, but READ THE COMMENTS in the serial.pp file.

On linux, the kernel has a lot of hardware "tweaks" for the serial port which generally speaking are accessed via fpIoctl() calls applied to the handle you get back from SerOpen(). Hopefully you won't need them, but they're there if you do.

MarkMLl
« Last Edit: December 12, 2019, 09:35:36 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.

FOV_2001

  • New member
  • *
  • Posts: 8
Re: LazSerial and DataModule Problem
« Reply #5 on: December 12, 2019, 09:44:54 pm »
Thanks for your prompt response, any clue where I can start? the documentation is very high level for my knowledge,

Well, I can't really comment on LazSerial or any of the other high-level ones since when I worked on serial.pp it was specifically to support low-level stuff: at the time I was working on a serial port monitoring program to allow me to reverse-engineer the protocol between two HP instruments (which were actually serial port monitors :-) What I can say is that it works equally well in both the main (GUI) thread or a background thread, and that it was tested against Linux, Solaris and Windows.

/If/ you decided to take a look at it, what I'd suggest is that you went through a sequence of simple steps: open a port, check the handle is valid, set the port parameters (without hardware handshake), transmit a sequence of bytes, close the port. Then start looking at reception, but READ THE COMMENTS in the serial.pp file.

On linux, the kernel has a lot of hardware "tweaks" for the serial port which generally speaking are accessed via fpIoctl() calls applied to the handle you get back from SerOpen(). Hopefully you won't need them, but they're there if you do.

MarkMLl

Thanks a lot for your proposal. I'll take a look for that way, and of course, post the result.

Rgds,

Fernando

MarkMLl

  • Hero Member
  • *****
  • Posts: 610
Re: LazSerial and DataModule Problem
« Reply #6 on: December 12, 2019, 10:35:19 pm »
If you have a problem raise it here, and if I don't respond PM me to make sure I've seen it. Reading a port lacks a peek (i.e. non-destructive read) function, and lacks a blocking single-byte read, but since the unit is basically a thin wrapper around kernel operations they're not difficult to add. There's some things that aren't easy: a few weeks ago I was looking at a modem simulator to allow me to test other code and I had to give up on auto-speed detection since there wasn't an easy way to preserve parity and framing information.

Here's a very simple (and somewhat simplified) program reading test data from an attached single-board computer:

Code: [Select]
  serialHandle := SerOpen(ParamStr(1));
  if serialHandle < 1 then begin
    WriteLn('Cannot open "' + ParamStr(1) + '"');
    Halt(2)
  end;
  try
    if ParamCount > 1 then
      bps := parseBps(ParamStr(2));
    if bps <= 0 then begin
      WriteLn('Cannot parse speed "' + ParamStr(2) + '"');
      Halt(3)
    end;
    SerSetParams(serialHandle, bps, 8, NoneParity, 1, []);
    WriteLn('Port ' + ParamStr(1) + ', ', bps, ' BPS, ^C to terminate.');
...
    while true do begin

// This is intentionally simplified. Get output working first, then we'll deal with input.

      if SerRead(serialHandle, thisCh) < 1 then begin
        WriteLn('Device read failure');
        Halt(4)
      end;
      case thisCh of
        #$0d: begin
...
  finally
    SerClose(serialHandle)
  end
end.

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.