Well this is not my problem.
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.
uses BaseUnix;
function GetSerialPortNames: string;
type
TSerialStruct = packed record
typ: Integer;
line: Integer;
port: Cardinal;
irq: Integer;
flags: Integer;
xmit_fifo_size: Integer;
custom_divisor: Integer;
baud_base: Integer;
close_delay: Word;
io_type: Char;
reserved_char: Char;
hub6: Integer;
closing_wait: Word; // time to wait before closing
closing_wait2: Word; // no longer used...
iomem_base: ^Char;
iomem_reg_shift: Word;
port_high: Cardinal;
iomap_base: LongWord; // cookie passed into ioremap
end;
var
i: Integer;
sr : TSearchRec;
sl: TStringList;
st: stat;
s: String;
fd: PtrInt;
Ser : TSerialStruct;
const TIOCGSERIAL = $541E;
PORT_UNKNOWN = 0;
begin
Result := '';
sl := TStringList.Create;
try
// 1. Alle möglichen Ports finden - find all possible ports
if FindFirst('/sys/class/tty/*', LongInt($FFFFFFFF), sr) = 0 then
begin
repeat
if (sr.Name <> '.') and (sr.Name <> '..') Then
if (sr.Attr and LongInt($FFFFFFFF)) = Sr.Attr then
sl.Add(sr.Name);
until FindNext(sr) <> 0;
end;
FindClose(sr);
// 2. heraussuchen ob ./device/driver vorhanden ist - checking if ./device/driver exists
for i := sl.Count - 1 Downto 0 Do
Begin
If Not DirectoryExists('/sys/class/tty/' + sl[i] + '/device/driver') Then
sl.Delete(i); // Nicht vorhanden >> Port existiert nicht
end;
// 3. Herausfinden welcher Treiber - checking which driver
st.st_mode := 0;
for i := sl.Count - 1 Downto 0 Do
Begin
IF fpLstat('/sys/class/tty/' + sl[i] + '/device', st) = 0 Then
Begin
if fpS_ISLNK(st.st_mode) Then
Begin
s := fpReadLink('/sys/class/tty/' + sl[i] + '/device/driver');
s := ExtractFileName(s);
// 4. Bei serial8250 Treiber muss der Port geprüft werden - with a serial8250 driver the port must be checked
If s = 'serial8250' Then
Begin
sl.Objects[i] := TObject(PtrInt(1));
fd := FpOpen('/dev/' + sl[i], O_RDWR Or O_NONBLOCK Or O_NOCTTY);
If fd > 0 Then
Begin
If FpIOCtl(fd, TIOCGSERIAL, @Ser) = 0 Then
Begin
If Ser.typ = PORT_UNKNOWN Then // PORT_UNKNOWN
sl.Delete(i);
end;
FpClose(fd);
end else sl.Delete(i); // Port kann nicht geöffnet werden - Port can't be opened
end;
End;
end;
end;
// 5. Dev anhängen - attach the device
for i := 0 To sl.Count - 1 Do
sl[i] := '/dev/' + sl[i];
Result := sl.CommaText;
finally
sl.Free;
end;
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.