Lazarus

Programming => Packages and Libraries => Topic started by: ThomasK on March 14, 2021, 04:04:47 pm

Title: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on March 14, 2021, 04:04:47 pm
Hi,

I use TLAZSerial with an isolated RS485 HAT connected to the Pi's native serial I/O and an USB to RS485 isolated device to communicate with several power meters using ModBus protocoll. That works fine.

I also want to use CAN so I bought the above mentioned HAT.
With the driver installed, I can see the 2 new serial ports:

pi@raspberrypi:~ $ ls -l /dev/ttyS*
crw-rw---- 1 root dialout   4, 64 Mär 14 13:10 /dev/ttyS0
crw-rw---- 1 root dialout 235,  0 Mär 14 13:10 /dev/ttySC0
crw-rw---- 1 root dialout 235,  1 Mär 14 13:10 /dev/ttySC1
pi@raspberrypi:~ $

When I use the Demo GPS Simulator application, I can select both /dev/ttySC0 & /dev/ttySC1 devices.
But when I try to open the port, I get the following error message:

"Could not open device /dev/ttyS-2"

I tried it with GTKTerm, but here the two devices /dev/ttySC0 & /dev/ttySC1 do not show up in the selectable device list. Connecting USB adapter it works.

I already wrote to innomaker, but since GTKterm does not show the devices I have no clue where the problem lies. I searched the forum for the term "/dev/ttyS-2" without result.

Thanks and Best Regards.
 
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 14, 2021, 04:39:48 pm
You get a bonus point for checking with gtkterm. Two possible things to try: (i) look at serial.pp which comes with FPC (i.e. not Lazarus), it doesn't try to check the validity of the name parameter. (ii) step into the LazSerial code that opens the port, and see if it's trying to parse the name e.g. as part of an attempt to list valid serial ports.

I must admit that I've never seen the ttySC* form, and I've spent a fair amount of time with kernel documentation etc. working out valid names. What type of device actually implements it, and does it really use the serial API?

MarkMLl


Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: winni on March 14, 2021, 04:40:06 pm
Hi

Since Linux kernel 2.4 (~ 2000) /dev/ttyS2 is not a legal device name anymore.

It was renamed to   /dev/tts/2

Winni
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 14, 2021, 04:41:42 pm
Rubbish.


$ ls -lt /dev/ttyS*
crw-rw---- 1 root dialout 4, 65 Feb 26 09:00 /dev/ttyS1
crw-rw---- 1 root dialout 4, 66 Feb 26 09:00 /dev/ttyS2
crw-rw---- 1 root dialout 4, 67 Feb 26 09:00 /dev/ttyS3
crw-rw---- 1 root dialout 4, 64 Feb 26 09:00 /dev/ttyS0


...and before anybody calls me out for being undiplomatic, I suggest referring to

https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/devices.txt

specifically char device major 4.

MarkMLl

Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: winni on March 14, 2021, 08:14:52 pm
No Mister Rubbish

You are not undiplomatic .


You just have no knowledge about Linux history.

If you had then you should have said:

"devfs is not up-to-date"

Have a nice rubbish time

Winni
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 14, 2021, 10:11:26 pm
@winni, the link I cited is Torvalds's own documentation. /dev/ttyS* is still the name for PC-style UARTS... if you believe otherwise then produce an authoritive reference and if you can't then stop muddying the water.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: winni on March 14, 2021, 10:31:19 pm
@winni, the link I cited is Torvalds's own documentation. /dev/ttyS* is still the name for PC-style UARTS... if you believe otherwise then produce an authoritive reference and if you can't then stop muddying the water.

MarkMLl

Read the kernel specification about 2.4 and the devfs.
And the come back.

The fact the the 2 CV is an oldtimer does not mean that there was never one.
Gosh
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: trev on March 15, 2021, 12:49:15 am
Starting with kernel 2.4, a new system of device naming was created. It makes it easy to deal with a huge number of devices. But there's an option to continue using the old names. However, a new device may not have an old-style name so then one must use the new devfs. For a detailed description of it see: https://web.archive.org/web/20090504075850/http://www.atnf.csiro.au/people/rgooch/linux/docs/devfs.html. Also see the kernel documentation tree: filesystems/devfs.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: Jurassic Pork on March 15, 2021, 01:29:51 am
hello,
Quote
devfsd is a device manager for the Linux kernel. Primarily, it creates device nodes in the /dev directory when kernel drivers make the underlying hardware accessible.[1] The nodes exist in a virtual device file system named devfs. In systems that support many different types of hardware, each of which has its own device nodes, this is more convenient than creating all possible device nodes beforehand and in a real filesystem.

While devfs was a step forward, it had several disadvantages of its own.[2] Since version 2.5 of the Linux kernel, devfs has been succeeded by udev and devtmpfs.[3]

Friendly, J.P

Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 15, 2021, 09:32:46 am
While devfs was a step forward, it had several disadvantages of its own.[2] Since version 2.5 of the Linux kernel, devfs has been succeeded by udev and devtmpfs.[3]

In practical terms I think it's fair to say that the /dev/ttyS* devices are a special case since apart from anything else there appears to be a general convention that four device nodes always exist irrespective of whether there are corresponding physical devices. I think this comes from the kernel because of long-term problems enumerating legacy devices, but it's a long time since I've had to poke around that particular area.

It used to be that /dev/ttyS* was also used for "dumb" multiport PCI etc. cards which could be enumerated, but it's a long time since I've seen one. I'd be open to the suggestion that the /dev/tts* series was being used in this case, but am just a bit sceptical since they don't appear in Torvalds's https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/devices.txt which is a definitive kernel document and is being maintained.

I'm obviously familiar with the other series of names: /dev/ttyUSB*, /dev/ttyACM*, /dev/ttyAM* and the rest, as well as older names for things like ISDN ports which still were broadly handled by the serial API.

I'm slightly concerned by OP's /dev/ttySC* names but I presume they correspond to


       205 = /dev/ttySC0      SC26xx serial port 0
       206 = /dev/ttySC1      SC26xx serial port 1
       207 = /dev/ttySC2      SC26xx serial port 2
       208 = /dev/ttySC3      SC26xx serial port 3


where the SC26xx are apparently NXP devices. https://linux-kernel.vger.kernel.narkive.com/MR53ugNh/serial-sc26xx-device-name might be relevant, but at this point I think we really do need to know what kernel module OP sees being loaded (dmesg output) and I think we also need him to step through the device open sequence in case the name is getting mnagled... only he can do that since I don't think that anybody else here has that hardware.

@JurassicPork: had an interesting one yesterday. I added a SIGUSR1 handler to a program to extract timing info while it was running, and found it broke timeout code in serial.pp. I need to revisit that at some point but aren't looking forward to it since I'll need to recreate a SunOS/Solaris system for testing since there are differences in the way fpSelect() works.

MarkMLl

      

Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on March 15, 2021, 02:24:52 pm
Hi,

I found /tty/SC0 twice in the mentioned text document.
I am not a specialist in controlling devices, but I think, that the lazsynafpc.pas does not take care of the variant /tty/SCx devices.
Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.GetComNr(Value: string);
  2. begin
  3.   FComNr := PortIsClosed;
  4.   if pos('COM', uppercase(Value)) = 1 then
  5.     FComNr := StrToIntdef(copy(Value, 4, Length(Value) - 3), PortIsClosed + 1) - 1;
  6.   if pos('/DEV/TTYS', uppercase(Value)) = 1 then
  7.     FComNr := StrToIntdef(copy(Value, 10, Length(Value) - 9), PortIsClosed - 1);
  8. end;

Code: Pascal  [Select][+][-]
  1.   if FComNr <> PortIsClosed then
  2.     FDevice := '/dev/ttyS' + IntToStr(FComNr);
  3.   // Comport already owned by another process?          {HGJ}
  4.  
  5.     ScanForPorts( '/dev/rfcomm*',true);
  6.  //   ScanForPorts( '/dev/pts/*');
  7.     ScanForPorts( '/dev/ttyUSB*',true);
  8.     ScanForPorts( '/dev/ttyS*',false);
  9.     ScanForPorts( '/dev/ttyAM*',true); // for ARM board
  10.  
the scan for ports will find /dev/ttySn and /dev/ttySCn but will rest of the unit treats the equal.

my four cents.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 15, 2021, 02:36:56 pm
I am not a specialist in controlling devices, but I think, that the lazsynafpc.pas does not take care of the variant /tty/SCx devices.

I think the code you posted shows at least part of the problem, but is that used when opening the port or just when an attempt is being made to enumerate available devices?

What happens when you use serial.pp? I did the last maintenance on that and it's a very thin wrapper around the OS calls, so isn't going to reject a name in a form it doesn't recognise.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: sstvmaster on March 15, 2021, 07:32:55 pm
Same problem: https://www.raspberrypi.org/forums/viewtopic.php?t=297282
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 15, 2021, 07:59:13 pm
Same problem: https://www.raspberrypi.org/forums/viewtopic.php?t=297282

Something that stands out in that is that he was using


dmesg | grep tty


etc. rather than


dmesg | tail -25


My suspicion is that the stuff logged in dmesg depends entirely on messages being generated by kernel modules, and if for some reason those messages don't include what's being grepped for then he'll be missing important stuff.

In this sort of situation the most useful commands are


$ ls -lt /dev | head -25
$ dmesg -e | tail -25


both of which will have useful human-readable timestamps. Following on from that, if the OS has recognised the device then there will be something in the /sys/class tree... it's unlikely that the demo programs are bit-banging a memory-mapped device if they are actually identifying it as /dev/ttySC*.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on March 15, 2021, 08:00:04 pm
Hi,

using serial.pp opens and closes both devices (/dev/ttySC0 & /dev/ttySC1) and returns a handle.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 15, 2021, 08:17:11 pm
using serial.pp opens and closes both devices (/dev/ttySC0 & /dev/ttySC1) and returns a handle.

Right, so that narrows it down quite a lot.

I use serial.pp exclusively, but I'm not necessarily suggesting that you do since it's really intended for lower-level use: it doesn't return neat component-style events and so on and you'd probably need to get to grips with threads for anything non-trivial.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: sstvmaster on March 15, 2021, 09:55:14 pm
Can this help?
Code: Pascal  [Select][+][-]
  1.   if pos('/DEV/TTYSC', uppercase(Value)) = 1 then
  2.     FComNr := StrToIntdef(copy(Value, 11, Length(Value) - 9), PortIsClosed - 1);
  3.  

Add this after line 866 of lazsynaser.pas
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 15, 2021, 10:33:35 pm
This doesn't directly help OP's problem, but TBH I think that any attempt to have a "whitelist" of known names is hazardous. My own code uses a regex like   r.Expression := '(tty\D+)\d+'; to find out what major devices are represented (plus /dev/rfcomm* as a special case), sorts by major device number, then for each of those gets the minor devices... the result of that is that the display order is comparatively sane with ttyS0 preceding ttyAMA0 (RPi console) and so on.

MarkMLl

Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: sstvmaster on March 15, 2021, 11:42:39 pm
@MarkMLl, Thank you.

Quote
So wie ich es verstanden habe sind die Seriellen Ports vorhanden, nur kann LazSerial nicht damit umgehen.
Mit der serial.pp und "/dev/ttySC*" funktioniert es ja.

Vielleicht kann Jurassic Pork LazSerial dahin gehend erweitern. Eventuell kann er auch deinen Regex nutzen.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: Jurassic Pork on March 16, 2021, 02:06:32 am
hello,
When I use the Demo GPS Simulator application, I can select both /dev/ttySC0 & /dev/ttySC1 devices.
But when I try to open the port, I get the following error message:
"Could not open device /dev/ttyS-2"
i have found where there is a problem to use a port like /dev/ttySC0
it is in the procedure  connect of the TBlockSerial class in lazsynaser.pas here  (lines 15,26):
Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.Connect(comport: string);
  2. {$IFDEF MSWINDOWS}
  3. var
  4.   CommTimeouts: TCommTimeouts;
  5. {$ENDIF}
  6. begin
  7.   // Is this TBlockSerial Instance already busy?
  8.   if InstanceActive then           {HGJ}
  9.   begin                            {HGJ}
  10.     RaiseSynaError(ErrAlreadyInUse);
  11.     Exit;                          {HGJ}
  12.   end;                             {HGJ}
  13.   FBuffer := '';
  14.   FDevice := comport;
  15.   GetComNr(comport);
  16. {$IFDEF MSWINDOWS}
  17.   SetLastError (sOK);
  18. {$ELSE}
  19.   {$IFNDEF FPC}
  20.   SetLastError (sOK);
  21.   {$ELSE}
  22.   fpSetErrno(sOK);
  23.   {$ENDIF}
  24. {$ENDIF}
  25. {$IFNDEF MSWINDOWS}
  26.   if FComNr  <> PortIsClosed then
  27.     FDevice := '/dev/ttyS' + IntToStr(FComNr);
  28.   // Comport already owned by another process?          {HGJ}
  29.   if FLinuxLock then

With the procedure GetComNr :
Code: Pascal  [Select][+][-]
  1. [procedure TBlockSerial.GetComNr(Value: string);
  2. begin
  3.   FComNr := PortIsClosed;
  4.   if pos('COM', uppercase(Value)) = 1 then
  5.     FComNr := StrToIntdef(copy(Value, 4, Length(Value) - 3), PortIsClosed + 1) - 1;
  6.   if pos('/DEV/TTYS', uppercase(Value)) = 1 then
  7.     FComNr := StrToIntdef(copy(Value, 10, Length(Value) - 9), PortIsClosed - 1);
  8. end;

when the device is /dev/ttySC0 or /dev/ttySC1 or /dev/ttySD0  for example  we have -2 in the FComNr variable, it is why you have :
Quote
"Could not open device /dev/ttyS-2"

what you can try, it is to replace this line in lazsynaser.pas :
Code: Pascal  [Select][+][-]
  1.  if FComNr  <> PortIsClosed then
  2.  
with this one :
Code: Pascal  [Select][+][-]
  1.  if FComNr  > PortIsClosed then
  2.  
Not sure that it is the better solution but for /dev/ttySCx  it doen't change the name of the device.
recompile the package Lazserial after the change.
Don't forget that lazsynaser.pas come from synaser.pas then there is the same problem in synaser.
Friendly, J.P
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on March 16, 2021, 11:12:47 am
@Jurassic Pork

Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.GetComNr(Value: string);
  2. begin
  3.   FComNr := PortIsClosed;
  4.   if pos('COM', uppercase(Value)) = 1 then
  5.     FComNr := StrToIntdef(copy(Value, 4, Length(Value) - 3), PortIsClosed + 1) - 1;
  6.   if pos('/DEV/TTYS', uppercase(Value)) = 1 then
  7.     FComNr := StrToIntdef(copy(Value, 10, Length(Value) - 9), PortIsClosed - 1);
  8. end;
  9.  
I wonder if the FComNr is correctly extracted the length of /DEV/TTYSC0 is 11, and 2 chars will be copied. (11-9).
Anyway the device never can be found because:
Code: Pascal  [Select][+][-]
  1. $IFNDEF MSWINDOWS}
  2.   if FComNr  <> PortIsClosed then
  3.     FDevice := '/dev/ttyS' + IntToStr(FComNr);
  4.  
will always produce a FDEVICE string like 'dev/ttys' + number' but not a  'dev/ttysc' + number

I try to modify both procedures to differentiate between different length of device basic names:
I found quite a large variety in the mentioned device list:


/dev/ttySnnn   UART serial port device

/dev/ttySAn      Strong ARM builtin serial port
/dev/ttySCn      SC26xx serial port
/dev/ttySCn      SCI serial port
/dev/ttySGn      SGI Altix console port
/dev/ttySIn      SmartIO Port
/dev/ttySRnnn   RIO port

/dev/ttySMXn   Motorola i.MX - port

/dev/ttySIOCnn   Altix ioC3 serial card
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: Jurassic Pork on March 16, 2021, 11:26:02 am
hello,
I try to modify both procedures to differentiate between different length of device basic names:
I found quite a large variety in the mentioned device list:

/dev/ttySnnn   UART serial port device

/dev/ttySAn      Strong ARM builtin serial port
/dev/ttySCn      SC26xx serial port
/dev/ttySCn      SCI serial port
/dev/ttySGn      SGI Altix console port
/dev/ttySIn      SmartIO Port
/dev/ttySRnnn   RIO port

/dev/ttySMXn   Motorola i.MX - port

/dev/ttySIOCnn   Altix ioC3 serial card

have you try only  my change :
Code: Pascal  [Select][+][-]
  1. if FComNr  > PortIsClosed then
with devices like :
Quote
/dev/ttySAn      Strong ARM builtin serial port
/dev/ttySCn      SC26xx serial port
/dev/ttySCn      SCI serial port
/dev/ttySGn      SGI Altix console port
/dev/ttySIn      SmartIO Port
/dev/ttySRnnn   RIO port

/dev/ttySMXn   Motorola i.MX - port

/dev/ttySIOCnn   Altix ioC3 serial card
FcomNr value is -2 and you doesn't alter the device name

FComNr seems to be used only to have the port number for  legacy serial ports  (COM on windows /dev/ttySxx on linux) .
For example when i use the USB serial ports /dev/ttyUSB00 and /dev/ttyUSB01 , i have no problem using TLazserial component while the FComNr value is -1.

Friendly, J.P
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on March 16, 2021, 11:44:52 am
I try to modify both procedures to differentiate between different length of device basic names:
I found quite a large variety in the mentioned device list:

/dev/ttySnnn   UART serial port device

/dev/ttySAn      Strong ARM builtin serial port
/dev/ttySCn      SC26xx serial port
/dev/ttySCn      SCI serial port
/dev/ttySGn      SGI Altix console port
/dev/ttySIn      SmartIO Port
/dev/ttySRnnn   RIO port

/dev/ttySMXn   Motorola i.MX - port

/dev/ttySIOCnn   Altix ioC3 serial card

Plus /dev/rfcomm*, plus /dev/AMA0 for an RPi. See message #17, the only reliable way of doing this is to match /dev/tty, then process the letters and digits that follow separately.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on March 16, 2021, 05:51:37 pm
Hello,


have you try only  my change :
Code: Pascal  [Select][+][-]
  1. if FComNr  > PortIsClosed then

Friendly, J.P

I have only a device which shows up as

/dev/ttySC0 and /dev/ttySC1      

which can be succesfully opened with the mod.
Since I can't test the other devices I would only adapt for these.

and as I already wrote an USB device, which already is working.

Kind Regards,

ThomasK
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on March 16, 2021, 06:47:44 pm

Plus /dev/rfcomm*, plus /dev/AMA0 for an RPi. See message #17, the only reliable way of doing this is to match /dev/tty, then process the letters and digits that follow separately.

MarkMLl

I showed only the devices with varieties of /dev/ttyS, because they cause trouble with the TLazserial which tries to retrieve the numbering of the ttyS devices.

The proposed mod works.

But there are still problems with the hardware: When the device is not opened, it blocks the traffic on the RS485 Bus, I can receive data but not send. For me it seems, that there are some details in handling of RTS CTS which are not documented very well.
I am in contact with the supplier. Hopefully the CAN part of the board works better.

Rgds,

ThomasK
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: tetrastes on March 16, 2021, 08:24:11 pm

With the procedure GetComNr :
Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.GetComNr(Value: string);
  2. begin
  3.   FComNr := PortIsClosed;
  4.   if pos('COM', uppercase(Value)) = 1 then
  5.     FComNr := StrToIntdef(copy(Value, 4, Length(Value) - 3), PortIsClosed + 1) - 1;
  6.   if pos('/DEV/TTYS', uppercase(Value)) = 1 then
  7.     FComNr := StrToIntdef(copy(Value, 10, Length(Value) - 9), PortIsClosed - 1);
  8. end;


when the device is /dev/ttySC0 or /dev/ttySC1 or /dev/ttySD0  for example  we have -2 in the FComNr variable, it is why you have :
Quote
"Could not open device /dev/ttyS-2"

what you can try, it is to replace this line in lazsynaser.pas :
Code: Pascal  [Select][+][-]
  1.  if FComNr  <> PortIsClosed then
  2.  
with this one :
Code: Pascal  [Select][+][-]
  1.  if FComNr  > PortIsClosed then
  2.  
Not sure that it is the better solution but for /dev/ttySCx  it doen't change the name of the device.
recompile the package Lazserial after the change.
Don't forget that lazsynaser.pas come from synaser.pas then there is the same problem in synaser.
Friendly, J.P

Yes, this problem was always presented in synaser. You must change in GetComNr
Code: Pascal  [Select][+][-]
  1.   if pos('/DEV/TTYS', uppercase(Value)) = 1 then
  2.     FComNr := StrToIntdef(copy(Value, 10, Length(Value) - 9), PortIsClosed);
  3.  

so it will return the expected value in considered case (i.e. PortIsClosed, not PortIsClosed - 1).
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on April 10, 2021, 08:21:32 pm
In the meantime I checked the Python samples and found that they are using:

Code: Pascal  [Select][+][-]
  1. TIOCGRS485 = 0x542E
  2. TIOCSRS485 = 0x542F
  3. SER_RS485_ENABLED         = 0b00000001
  4. SER_RS485_RTS_ON_SEND     = 0b00000010
  5. SER_RS485_RTS_AFTER_SEND  = 0b00000100
  6. SER_RS485_RX_DURING_TX    = 0b00010000
  7.  
Unfortunately TIOCGRS485 = 0x542E ff. definitions are not included in the termios.inc in the section ARM CPU. So I will continue Jugend forscht.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on April 10, 2021, 09:00:38 pm
In the meantime I checked the Python samples and found that they are using:

Code: Pascal  [Select][+][-]
  1. TIOCGRS485 = 0x542E
  2. TIOCSRS485 = 0x542F
  3. SER_RS485_ENABLED         = 0b00000001
  4. SER_RS485_RTS_ON_SEND     = 0b00000010
  5. SER_RS485_RTS_AFTER_SEND  = 0b00000100
  6. SER_RS485_RX_DURING_TX    = 0b00010000
  7.  
Unfortunately TIOCGRS485 = 0x542E ff. definitions are not included in the termios.inc in the section ARM CPU. So I will continue Jugend forscht.

Presumably you're running the standard 32-bit OS (whatever they call it these days). If those actually work on that platform I suggest raising it as a bug via Mantis; they're probably omitted since nobody has had a report of that hardware combination.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: alpine on April 10, 2021, 09:10:43 pm
I've not read this thread entirely, but seeng:
Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.GetComNr(Value: string);
  2. begin
  3.   FComNr := PortIsClosed;
  4.   if pos('COM', uppercase(Value)) = 1 then
  5. ...
  6.  

Just wanted to note that on Windows, the general form is '\\.\COMxx' and the above code will have troubles with that.

Regards,
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: sstvmaster on April 10, 2021, 11:33:12 pm
...
the general form is '\\.\COMxx' and the above code will have troubles with that.
...

Not quite, in lazsynaser.pas (from LazSerial package) on line 982 there is the following:
Code: Pascal  [Select][+][-]
  1. FDevice := '\\.\COM' + IntToStr(FComNr + 1);
so it is correct in the end.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: alpine on April 11, 2021, 12:12:31 am
Okay, let's go through ...

lazsynaser.pas:929

Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.Connect(comport: string); // comport:='\\.\COM12'
  2.   ...
  3.   FBuffer := '';
  4.   FDevice := comport; // FDevice:='\\.\COM12'
  5.   GetComNr(comport); // FComNr:=PortIsClosed (because both pos('COM', uppercase(Value)) <> 1 and pos('/DEV/TTYS', uppercase(Value)) <> 1
  6.   ...
  7.   if FComNr <> PortIsClosed then // False!
  8.     FDevice := '\\.\COM' + IntToStr(FComNr + 1); // Skipped
  9.   FHandle := THandle(CreateFile(PChar(FDevice), GENERIC_READ or GENERIC_WRITE,
  10.     0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0));
  11. // CreateFile() uses the same string as given in comport argument
  12.   ...
  13.  

My question is: What is the purpose of FComNr variable and GetComNr() method? (At least in Windows)

A little bit of clarification - my previous remark was based purely on the code snippet I saw in the discussion. I do not use the LazSerial component and I am not familiar with it.

Regards,
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on April 11, 2021, 11:00:29 am
Well this is not my problem. :D

It is cured by a small modification Jurassic Pork proposed (Reply #21). Now I can select and use the  /dev/TTYSC0 and  /dev/TTYSC1.

I want to get a dual RS485 HAT to work. Basically I use the sample application of TLAZSerial for testing to avoid problems between chair and keyboard and a Windows computer with an USB to RS422/485 adapter which works reliably. As terminal software for monitoring and sending I use cleverterm-2.4.4 which also supports ModBus RTU by generating the CRCs on its own.

But since this is based for handling the serial devices functionally to the features of Synaser it is also limited to it.
Synaser does not know about RS485 devices.

For the problem not finding the correct device names a solution was shown in 2017 in the german Lazarus forum but there was never a reply to it. I have to check if it can be found in the Synapse trunk.

Code: Pascal  [Select][+][-]
  1. uses BaseUnix;
  2. function GetSerialPortNames: string;
  3. type
  4. TSerialStruct = packed record
  5.   typ: Integer;
  6.   line: Integer;
  7.   port: Cardinal;
  8.   irq: Integer;
  9.   flags: Integer;
  10.   xmit_fifo_size: Integer;
  11.   custom_divisor: Integer;
  12.   baud_base: Integer;
  13.   close_delay: Word;
  14.   io_type: Char;
  15.   reserved_char: Char;
  16.   hub6: Integer;
  17.   closing_wait: Word; // time to wait before closing
  18.   closing_wait2: Word; // no longer used...
  19.   iomem_base: ^Char;
  20.   iomem_reg_shift: Word;
  21.   port_high: Cardinal;
  22.   iomap_base: LongWord; // cookie passed into ioremap
  23. end;
  24. var
  25.   i: Integer;
  26.   sr : TSearchRec;
  27.   sl: TStringList;
  28.   st: stat;
  29.   s: String;
  30.   fd: PtrInt;
  31.   Ser : TSerialStruct;
  32. const TIOCGSERIAL = $541E;
  33.   PORT_UNKNOWN = 0;
  34. begin
  35.   Result := '';
  36.   sl := TStringList.Create;
  37.   try
  38.     // 1. Alle möglichen Ports finden - find all possible ports
  39.     if FindFirst('/sys/class/tty/*', LongInt($FFFFFFFF), sr) = 0 then
  40.     begin
  41.       repeat
  42.         if (sr.Name <> '.') and (sr.Name <> '..') Then
  43.           if (sr.Attr and LongInt($FFFFFFFF)) = Sr.Attr then
  44.             sl.Add(sr.Name);
  45.       until FindNext(sr) <> 0;
  46.     end;
  47.     FindClose(sr);
  48.     // 2. heraussuchen ob ./device/driver vorhanden ist  - checking if ./device/driver exists
  49.     for i := sl.Count - 1 Downto 0 Do
  50.     Begin
  51.       If Not DirectoryExists('/sys/class/tty/' + sl[i] + '/device/driver') Then
  52.         sl.Delete(i); // Nicht vorhanden >> Port existiert nicht
  53.     end;
  54.     // 3. Herausfinden welcher Treiber  - checking which driver
  55.     st.st_mode := 0;
  56.     for i := sl.Count - 1 Downto 0 Do
  57.     Begin
  58.       IF fpLstat('/sys/class/tty/' + sl[i] + '/device', st) = 0 Then
  59.       Begin
  60.         if fpS_ISLNK(st.st_mode) Then
  61.         Begin
  62.           s := fpReadLink('/sys/class/tty/' + sl[i] + '/device/driver');
  63.           s := ExtractFileName(s);
  64.           // 4. Bei serial8250 Treiber muss der Port geprüft werden - with a serial8250 driver the port must be checked
  65.           If s = 'serial8250' Then
  66.           Begin
  67.             sl.Objects[i] := TObject(PtrInt(1));
  68.             fd := FpOpen('/dev/' + sl[i], O_RDWR Or O_NONBLOCK Or O_NOCTTY);
  69.             If fd > 0 Then
  70.             Begin
  71.               If FpIOCtl(fd, TIOCGSERIAL, @Ser) = 0 Then
  72.               Begin
  73.                 If Ser.typ = PORT_UNKNOWN Then // PORT_UNKNOWN
  74.                   sl.Delete(i);
  75.               end;
  76.               FpClose(fd);
  77.             end else sl.Delete(i); // Port kann nicht geöffnet werden - Port can't be opened
  78.           end;
  79.         End;
  80.       end;
  81.     end;
  82.     // 5. Dev anhängen - attach the device
  83.     for i := 0 To sl.Count - 1 Do
  84.       sl[i] := '/dev/' + sl[i];
  85.    Result := sl.CommaText;
  86.   finally
  87.     sl.Free;
  88.   end;
  89. end;

For developping the application I use a RS422/485 HAT for which uses a NE555 in a monoflop configuration to create the RTS_after_write by hardware very efficiently to handle the switching of the driver from *RE to DI. For the real use I need more RS485 ports.

With the new hardware I manipulate the RTS signal by the from application form to evaluate the behavoir of the board, but this should really be done by the OS.
After searching for the string "TIOCGRS485" I found that this missing in the TERMIOS definitions for ARM.

I will uses some functions in Synaser to modify them to set the TERMIOS record with the required flags and see if it does switch from transmit to receive on its own.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on April 11, 2021, 11:14:12 am
After searching for the string "TIOCGRS485" I found that this missing in the TERMIOS definitions for ARM.

Specifically, it's in aarch64 but not in the 32-bit section. If it works, report the omission as a bug on Mantis.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: tetrastes on April 11, 2021, 11:20:02 pm
Okay, let's go through ...

lazsynaser.pas:929

Code: Pascal  [Select][+][-]
  1. procedure TBlockSerial.Connect(comport: string); // comport:='\\.\COM12'
  2.   ...
  3.   FBuffer := '';
  4.   FDevice := comport; // FDevice:='\\.\COM12'
  5.   GetComNr(comport); // FComNr:=PortIsClosed (because both pos('COM', uppercase(Value)) <> 1 and pos('/DEV/TTYS', uppercase(Value)) <> 1
  6.   ...
  7.   if FComNr <> PortIsClosed then // False!
  8.     FDevice := '\\.\COM' + IntToStr(FComNr + 1); // Skipped
  9.   FHandle := THandle(CreateFile(PChar(FDevice), GENERIC_READ or GENERIC_WRITE,
  10.     0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0));
  11. // CreateFile() uses the same string as given in comport argument
  12.   ...
  13.  

My question is: What is the purpose of FComNr variable and GetComNr() method? (At least in Windows)

A little bit of clarification - my previous remark was based purely on the code snippet I saw in the discussion. I do not use the LazSerial component and I am not familiar with it.

Regards,

At least in Windows its only purpose is to use 'COM12' or '/dev/ttyS11' instead of '\\.\COM12'  ;)
As it is said in synaser.pas:
Code: Pascal  [Select][+][-]
  1.     {:Connects to the port indicated by comport. Comport can be used in Windows
  2.      style (COM2), or in Linux style (/dev/ttyS1). When you use windows style
  3.      in Linux, then it will be converted to Linux name. And vice versa! However
  4.      you can specify any device name! (other device names then standart is not
  5.      converted!)
  6.      .
  7.      .
  8.      .
  9.     }
  10.     procedure Connect(comport: string); virtual;
  11.  

Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: alpine on April 11, 2021, 11:42:14 pm
@tetrastes
Now I see it, as long you specify 'COMx', x < 10, it will do the work. Thanks!
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: tetrastes on April 12, 2021, 12:03:39 am
x may be any.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: alpine on April 12, 2021, 12:24:52 am
x may be any.

Right, my 2¢ in.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on April 16, 2021, 10:12:32 am
After searching for the string "TIOCGRS485" I found that this missing in the TERMIOS definitions for ARM.

Specifically, it's in aarch64 but not in the 32-bit section. If it works, report the omission as a bug on Mantis.

MarkMLl

I got it to work. I will post later the code snippets. How can I report this as a bug? Do you have a link?
Rgds.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on April 16, 2021, 10:16:31 am
I got it to work. I will post later the code snippets. How can I report this as a bug? Do you have a link?

Well done. Please report via https://bugs.freepascal.org/ since that will mean it's "in the system" as far as the library maintainers go: the important thing is that the need to know that RS485 actually exists on that architecture from the kernel's POV.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on April 16, 2021, 01:44:52 pm
I added the required definitions, functions and procedures in the LazSynaSer and LazSerial Units.
Code: Pascal  [Select][+][-]
  1. //|============================================================================|
  2. // copied into Unit LazSynaSer after line 172
  3. {$IFDEF UNIX}
  4. type
  5.   Tserial_RS485 = record
  6.                     flags                      : cardinal;
  7.                     delay_rts_before_send      : cardinal;
  8.                     delay_rts_after_send       : cardinal;
  9.                     padding    : array [0..4] of cardinal;
  10.   end;
  11.  
  12. const
  13.   TIOCGRS485 = $542E;                          //Read Flags
  14.   TIOCSRS485 = $542F;                          //Set Flags
  15.   SER_RS485_ENABLED         = $0001;
  16.   SER_RS485_RTS_ON_SEND     = $0002;
  17.   SER_RS485_RTS_AFTER_SEND  = $0004;
  18.   SER_RS485_RX_DURING_TX    = $0010;
  19.  
  20. var
  21.   RS485conf :  Tserial_rs485;
  22. {$ENDIF}
  23. //
  24. //|============================================================================|
  25.  

also

Code: Pascal  [Select][+][-]
  1. //*****************************************************************************
  2. // copied into Unit LazSynaSer after line 566
  3. {$IFDEF UNIX}
  4.  
  5.     function StatusRS485 : cardinal; virtual;
  6.  
  7.     procedure EnableRS485 (value : boolean); virtual;
  8.  
  9. {$ENDIF}
  10. //
  11. //*****************************************************************************
  12.  

and finally

Code: Pascal  [Select][+][-]
  1. //******************************************************************************
  2. //copied into Unit LazSynaSer after implementation
  3. {$IFDEF UNIX}
  4. procedure TBlockSerial.EnableRS485 (value:boolean);
  5. begin
  6.   if value then with RS485conf do
  7.     begin
  8.       flags := SER_RS485_ENABLED or SER_RS485_RTS_AFTER_SEND;
  9.       delay_rts_before_send  := 0;
  10.       delay_rts_after_send   := 0;
  11.     end else
  12.       RS485conf.flags :=  0;
  13.   fpioctl(FHandle, TIOCSRS485, @RS485conf);
  14. end;
  15.  
  16. function TBlockSerial.StatusRS485 : cardinal;
  17. begin
  18.     fpioctl(FHandle, TIOCGRS485, @RS485conf);
  19.     result:= RS485conf.flags;
  20. end;
  21. {$ENDIF}
  22. //
  23. //******************************************************************************
  24.  

In LazSerial the calls for the application:

Code: Pascal  [Select][+][-]
  1. //******************************************************************************
  2. //copied into Unit LazSerial after line 203
  3. {$IFDEF UNIX}
  4.  
  5.     function GetRS485Status : Cardinal;
  6.     procedure EnableRS485Port(OnOff : boolean);
  7.  
  8. {$ENDIF}
  9. //
  10. //******************************************************************************
  11.  

and also

Code: Pascal  [Select][+][-]
  1. //******************************************************************************
  2. //copied into Unit LazSerial after implementation
  3. {IFDEF UNIX}
  4.  
  5. function TLazSerial.GetRS485Status : Cardinal;
  6. begin
  7.   result:=FSynSer.StatusRS485;
  8. end;
  9.  
  10. procedure TLazSerial.EnableRS485Port(OnOff : boolean);
  11. begin
  12.   FSynSer.EnableRS485(OnOff);
  13. end;
  14. {ENDIF}
  15. //
  16. //******************************************************************************
  17.  

I am quite sure that there is potential for improvements, but this works for me.
Since the baudrate is 9600, the switch over time is not critical, it works like a charm.
Test was done with a 4B and the Raspberry Pi RS485&CAN Module from Inno-Maker.
fpc 3.0.4, Lazarus 2.0.12, LazSerial v0.3, LazSynaSer 007.005.002.

It is entered in Mantis.

CAN tests still to come.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on April 16, 2021, 02:07:24 pm
@ThomasK If they don't go into the bugtracking system they will get lost. It's your responsibility to do that.

MarkMLl
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: ThomasK on April 16, 2021, 02:09:25 pm
@ThomasK If they don't go into the bugtracking system they will get lost. It's your responsibility to do that.

MarkMLl

Just done 0038763, I had to register first - now I go walk the dog.
Title: Re: Error on using hardware Raspberry Pi Inno-Maker RS485&CAN Module with TLAZserial
Post by: MarkMLl on April 16, 2021, 02:54:01 pm
Just done 0038763, I had to register first - now I go walk the dog.

Well done. Keep an eye on it in case somebody does a "Don't understand your banter old chap" :-)

MarkMLl
TinyPortal © 2005-2018