Lazarus

Programming => Networking and Web Programming => Topic started by: rampinia on January 28, 2018, 10:20:35 am

Title: CAN-BUS SocketCAN
Post by: rampinia on January 28, 2018, 10:20:35 am
Hello to all

does anyone did programming socket in the class PF_CAN for accessing CAN-BUS in Linux?
On the wiki side I have seen there are not current constant declaration for such network protocoll.

If the pfsocket and others call are just wrapper for standard BSD socket call I think it is enaugh to declare the constant just porting from the standard linux header.

Any info?

Thanks
Title: Re: CAN-BUS SockectCAN
Post by: marcov on January 28, 2018, 10:43:14 am
Yes, the sockets unit are just wrappers. Best is if somebody finds the constants, tests it, and then submits a patch.
Title: Re: CAN-BUS SockectCAN
Post by: rampinia on January 28, 2018, 06:30:27 pm
Yes

got PF_CAN = 29 and CAN_RAW = 1 from sys/if.h

already run some tests with PF_CAN = 29 and CAN_RAW = 1 and it works.

I'm working a minimal porting from C header.
Title: Re: CAN-BUS SockectCAN
Post by: RM on March 11, 2019, 08:50:21 am
Hello at all, i am new here...

I try to establish a CAN connection on the raspberry pi (stretch), using free pascal.
I successfully created a raw socket with PF_CAN=29 and CAN_RAW=1.
And now i have to bind the socket to the hardware address, but i don't know how?

Code: Pascal  [Select][+][-]
  1. class procedure TSysBus.OpenSocket;
  2. var
  3.   s:Tsocket;
  4.   sa:TSockAddr;
  5. begin
  6.      s:=fpsocket(29, SOCK_RAW, 1);
  7.      sa.sa_family:=29;
  8.      sa.sa_data[0]:=???;
  9.      fpbind(s,@sa,SizeOf(sa));
  10.      FpClose(s);
  11. end;
  12.  

Can somebody give me an example, how i have to go on?
Thanks
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on August 21, 2020, 05:00:22 am
Anyone been able to create the equivalent of a simple the socketCAN utilities  candump using Lazarus
Code: Text  [Select][+][-]
  1. debian@ebb:~$ sudo /sbin/ip link set can1 up type can bitrate 250000
  2. debian@ebb:~$ candump can1
  3.   can1  721   [1]  05
  4.   can1  1A1   [8]  20 00 FF 0F A8 FD A8 FD
  5.  

No one answered RM and rampinia didn't post any other solutions.

Code: Pascal  [Select][+][-]
  1. procedure TSocketForm.Button1Click(Sender: TObject);
  2. var
  3.     i : integer;
  4. begin
  5.   // open socket
  6.   socket_result := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  7.   if (socket_result < 0) then begin
  8.         // perror("socket");
  9.     Edit1.text := 'Error #' + IntToStr(socket_result) + ' creating socket';
  10.   end
  11.   else begin
  12.     SAddr.sin_family := PF_CAN;
  13.     if fpconnect(socket_result, @SAddr, 0) = -1 then begin
  14.       Edit1.text := 'Socket can''t connect: ' + strerror(socketerror);
  15.     end;
  16.   end;
  17. end;
  18.  

The error is 'Operation not supported on Endpoint'

The C language candump doesn't use fpconnect() and the 'connect()' is deprecated and doesn't work either.  So although this is the document for fpconnect it uses deprecated functions rather than fpconnect().

https://www.freepascal.org/docs-html/current/rtl/sockets/fpconnect.html (https://www.freepascal.org/docs-html/current/rtl/sockets/fpconnect.html)

Plus it's more targeted at internet protocol sockets.

Ideas?

Title: Re: CAN-BUS SockectCAN
Post by: trev on August 21, 2020, 05:17:22 am
What about this (http://www.cananalyser.co.uk/index.html). The Windows/Linux SDK for Delphi is free.
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on August 23, 2020, 09:55:24 am
What about this (http://www.cananalyser.co.uk/index.html). The Windows/Linux SDK for Delphi is free.
Unfortunately from what I can see it doesn't address socketcan.

What I've found out so far is that socketcan and the utilities like candump work with the USB based CANUSB from Lawicel along with the internal BeagleBone Black CAN device and on a Pi, an SPI based MCP2515.

Further research shows that as simple as including 'can' in python programs brings in support for either the BBB or Pi. 

This is what I want to see for Lazarus.  I'd like to be able to plug in any device that has socketCAN support and have the application compile on that platform, or cross compile for that platform and just plain work.

What I've discovered is that this doesn't work for Lazarus yet.   So I need to find out where the sockets source code lives for the Pi and the Beagle and figure out why the fpconnect() returns an error.  Clearly it's broken or not properly documented.
Title: Re: CAN-BUS SockectCAN
Post by: Laksen on August 23, 2020, 11:10:19 am
Why are you calling connect and not bind?
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on October 22, 2020, 06:10:48 am
I think I have some time to dive back into this project. 
Why are you calling connect and not bind?
Even if I call bind (or fpbind) the issue is that the sockets code seems to be oriented towards ip and port numbers. 
Referencing this document
http://www.linuxhowtos.org/C_C++/socket.htm
I believe the socketCAN has to address the unix domain via the Linux File system. 
Recall my example from a previous post.
Code: Pascal  [Select][+][-]
  1.    
  2.     debian@ebb:~$ sudo /sbin/ip link set can1 up type can bitrate 250000
  3.     debian@ebb:~$ candump can1
  4.       can1  721   [1]  05
  5.       can1  1A1   [8]  20 00 FF 0F A8 FD A8 FD
  6.  
The can1 is the device which in the above example is a USB based CAN dongle.  On a Pi I can just as easily specify the SPI based MCP2515 CAN device in place of the USB device. 

For example from this tutorial
https://www.raspberrypi.org/forums/viewtopic.php?t=141052
Code: Pascal  [Select][+][-]
  1. pi@piv2:~ $ ls /sys/bus/spi/devices/spi0.0/net/
  2. can0
  3.  
  4. pi@piv2:~ $ sudo ip link set can0 up type can bitrate 125000
  5.  
  6. pi@piv2:~ $ sudo ifconfig
  7. can0   Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
  8.           UP RUNNING NOARP  MTU:16  Metric:1
  9.           RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  10.           TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  11.           collisions:0 txqueuelen:10
  12.           RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  13.  

So from the OS perspective the fact that one device is USB based and can be plugged into a WIN-PC MAC or Linux system while the other one is SPI based on the Pi the access via Linux is the same.

And the C Program candump.c creates identical output regardless of the hardware type.  (BTW, it's the same with the embedded inside the processor CAN device in a BeagleBone Black).

Code: Pascal  [Select][+][-]
  1. pi@piv2:~ $ candump can0
  2.   can0  001   [8]  11 22 33 44 55 66 77 88
  3.   can0  00003456   [8]  EF FE DD AD CB 67 98 AA
  4.  

Now in the C world, candump.c or cansend.c can be used as a template for a customized program to do whatever...  One might cut and paste parts into their application.    That's because the sockets library in C handles the parameters PF_CAN and SOCK_RAW, CAN_RAW.

The FPC sockets does not.  And yes I can define those but tunnel down into sockets.pp and and the system's ...sockh.inc we don't have a PF_CAN.  And without a PF_CAN and AF_CAN in the socket()  the connection aborts because it doesn't know what to do with it.

In order to cut and paste more of the code I'll have to continue this in another message from the Pi3 so I can post the Lazarus program I've used to discover this but I don't think the FPC code will matter at this point.

Search for candump.c and we find in
https://github.com/linux-can/can-utils/blob/master/candump.c

Code: Text  [Select][+][-]
  1. s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);

Later we bind to the socket
Code: C  [Select][+][-]
  1. if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  2.                         perror("bind");
  3.                         return 1;
  4.                 }
  5.  

Eventually after all the CAN_FD and filter handling we end up
Code: C  [Select][+][-]
  1. nbytes = recvmsg(s[i], &msg, 0);

So in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.  Is there any interest in this?  Who's allowed to change it. 

The project I started in Lazarus works fine with the USB based CAN dongle by treating it as a serial port which generates strings of characters representing the messages.  But I can't access the CAN devices built into the BeagleBone nor the Pi which is a cakewalk with Python or C.  And I'd like to be able to demonstrate CAN bus access from a USB dongle or the embedded hardware. 

What's the next step?
Title: Re: CAN-BUS SockectCAN
Post by: avra on October 22, 2020, 09:41:43 am
So in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.
PF_CAN is just a number. In linux sources you can find it defined as AF_CAN, which is defined as 29. So why don't you try that first?

You could also take a look at https://github.com/linux-can/socketcand if you wish to access CAN via CAN-ETH gateway daemon. You can install https://github.com/dschanoeh/Kayak as a handy GUI application that can access SocketCAN (and serial slcan through it) using socketcand.

Instead of using real slcan device as you do, maybe it would be easier if you use vcan instead and simulate CAN traffic for testing purposes. Once you get everything working you can then switch to a real device. If you wish I can give you several simple scripts to bring up VCAN environment, generate CAN traffic, and use SocketCAN directly or through socketcand and Kayak.

EDIT: I see now that you are looking at sources of candump. It will be much easier if you use simpler example from here:
https://www.beyondlogic.org/example-c-socketcan-code/
Title: Re: CAN-BUS SockectCAN
Post by: MarkMLl on October 22, 2020, 09:44:51 am
I believe the socketCAN has to address the unix domain via the Linux File system. 

Presumably you mean unix domain *socket* here. If so I agree that it's normally accessed via the filesystem, but otherwise the API is fairly similar to an inet datagram socket.


Code: [Select]
      if fpSelect(maxHandle + 1, @readSet, nil, nil, nil) >= 0 then begin

(* A message received on the inet domain socket must have a recognisable sender *)
(* since it might be needed for authentication purposes. A unix domain socket   *)
(* can be assumed to be protected by local permissions and capabilities.        *)

        if (UnixDomainSocket() >= 0) and (fpFD_ISSET(UnixDomainSocket(), readSet) = 1) then
          dispatchMessage(UnixDomainSocket(), false);
        if (InetDomainSocket() >= 0) and (fpFD_ISSET(InetDomainSocket(), readSet) = 1) then
          dispatchMessage(InetDomainSocket(), true)
      end

...

begin // dispatchMessage(), invoked as above, 2nd param is hasFrom
  FillByte(recvBuffer, SizeOf(recvBuffer), 0);
  if hasFrom then begin                 (* Inet domain socket                   *)
    FillByte(sa, SizeOf(sa), 0);
    saLength := SizeOf(sa);
    messageLength := fpRecvFrom(socket, @recvBuffer, SizeOf(recvBuffer), 0, @sa, @saLength)
  end else begin                        (* Unix domain socket                   *)
    saLength := -1;
    messageLength := fpRecv(socket, @recvBuffer, SizeOf(recvBuffer), 0)
  end;

(* There is no provision here for concatenated or fragmented messages, which we *)
(* of course shouldn't see since it's a datagram socket. Elsewhere, we try to   *)
(* work out the MTU by looking at padded backbone messages.                     *)

...

(* The result of this may be subsequently retrieved using UnixDomainSocket().
  If a .pid file indicates that an existing socket was created by an instance
  of this program that no longer exists then delete it. Create a fresh Unix
  Domain socket and save the handle, on failure save an error code. Both success
  and failure are silent.
*)
procedure CreateUnixDomainSocket(socketName: string);

var
  oldPid: longInt= -1;
  pidName: string;
  pidFile: text;
  uid: TUid;
  gid: TGid;

begin
  if socketName[1] = '~' then begin
    Delete(socketName, 1, 1);
    socketName := UserHome() + socketName
  end;
  pidName := socketName + '.pid';
  if FileExists(pidName) then
    try
      Write(StdErr, 'Opening old PID file... ');
      Assign(pidFile, pidName);
      Reset(pidFile);
      try
        Read(pidFile, oldPid);
        WriteLn(StdErr, 'OK, ' + IntToStr(oldPid))
      finally
        Close(pidFile)
      end
    except
      WriteLn(StdErr, 'failed');
      oldPid := -1
    end;

(* If we have managed to read a process ID file then check whether the relevant *)
(* process (an older instance of this program) still exists. If it does then we *)
(* shouldn't be trying to run this program, if it does not and a unix domain    *)
(* socket exists then try to delete it.                                         *)

  if (oldPid >= 0) and FileExists('/proc/' + IntToStr(oldPid)) then begin
    WriteLn(StdErr, 'WatchP0x already running, terminating.');
    Halt(9)
  end;
  if oldPid >= 0 then begin
    WriteLn(StdErr, 'Process ', oldPid, ' is not running');
    try
      if FileExists(socketName) then begin
        Write(StdErr, 'Deleting old unix domain socket ', socketName, '... ');
        DeleteFile(socketName);
        if not FileExists(socketName) then
          WriteLn(StdErr, 'OK')
        else
          WriteLn(StdErr, 'ineffective (critical error)')
      end else
        WriteLn(StdErr, 'No old socket')
    except
      WriteLn(StdErr, 'failed');
      unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS             *)
    end
  end;

(* Delete old PID file since it might be owned by a different user.             *)

  if FileExists(pidName) then begin
    Write(StdErr, 'Deleting old PID file... ');
    try
        DeleteFile(pidName);
        if not FileExists(pidName) then
          WriteLn(StdErr, 'OK')
        else
          WriteLn(StdErr, 'ineffective (critical error)')
    except
      WriteLn(StdErr, 'failed');
      unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS             *)
    end
  end;

(* Create a new PID file.                                                       *)

  try
    Write(StdErr, 'Creating new PID file... ');
    Assign(pidFile, pidName);
    Rewrite(pidFile);
    try
      WriteLn(pidFile, IntToStr(GetProcessID()));
      WriteLn(StdErr, 'OK, ', GetProcessID())
    finally
      Close(pidFile)
    end
  except
    WriteLn(StdErr, 'failed (critical error)');
    unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS               *)
  end;

(* Create the socket. Note that there is no suitable fpBind() for this.         *)

  Write(StdErr, 'Creating new unix domain socket... ');
  unixDomainSocketHandle := fpSocket(AF_UNIX, SOCK_DGRAM, 0);
  if Bind(unixDomainSocketHandle, socketName) then
    WriteLn(StdErr, 'OK')
  else begin
    WriteLn(StdErr, 'failed (continuing)');
    unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS               *)
  end;

(* Change socket owner and group to be the same as the executable, on the       *)
(* assumption that this is the user that will be executing all programs.        *)

// TODO : Bad assumption if setuid.

  Write(StdErr, 'Changing socket''s ownership... ');
  getOwner(ParamStr(0), uid, gid);
  if fpChown(socketName, uid, gid) = 0 then
    WriteLn(StdErr, 'OK')
  else begin
    WriteLn(StdErr, 'failed (continuing)');
//    unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS             *)
  end;

(* Set the socket to be writable by its owner (i.e. any cooperating program)    *)
(* and readable by its group (this program). I don't think very much of doing   *)
(* this but the computer on which this is running can be assumed to be          *)
(* physically secure leaving the major risk being that somebody unauthorised    *)
(* logs into it and runs one of this suite of programs.                         *)

  Write(StdErr, 'Relaxing socket''s read/write permissions... ');
  if fpChMod(socketName, &766) = 0 then
    WriteLn(StdErr, 'OK')
  else begin
    WriteLn(StdErr, 'failed (continuing), might need CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_NET_RAW=p+e');
    unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS               *)
  end

(* Since we're about to reliquish admin capabilities we won't be able to delete *)
(* the socket at program termination.                                           *)

end { CreateUnixDomainSocket } ;


(* The result of this may be subsequently retrieved using InetDomainSocket().
  Assume that any existing socket was deleted when its owner terminated. Create
  a fresh Inet Domain socket and save the handle, on failure save an error code.
  Both success and failure are silent.
*)
procedure CreateInetDomainSocket(port: integer);

var
  sockAddr: TSockAddr;

begin
  Write(StdErr, 'Creating new Internet domain socket (UDP, port ', port, ')... ');
  inetDomainSocketHandle := fpSocket(PF_INET, SOCK_DGRAM, 0);
  try
    sockAddr.sin_family:= AF_INET;
    sockAddr.sin_port:= hToNS(port);
    sockAddr.sin_addr.s_addr:= 0;
    FillChar(sockAddr.sin_zero[0], SIZEOF(sockAddr.sin_zero), #0);
    if fpBind(inetDomainSocketHandle, @sockAddr, SIZEOF(sockAddr)) = 0 then
      WriteLn(StdErr, 'OK')
    else begin
      WriteLn(StdErr, 'failed, might need CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_NET_RAW=p+e');
      inetDomainSocketHandle := -Abs(ErrNo)
    end
  except
    WriteLn(StdErr, 'failed, might need CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_NET_RAW=p+e');
    inetDomainSocketHandle := -Abs(ErrNo)
  end

(* Assume that this will be deleted automatically at program termination.       *)

end { CreateInetDomainSocket } ;

Quote
Recall my example from a previous post.

Code: Pascal  [Select][+][-]
  1.    
  2.     debian@ebb:~$ sudo /sbin/ip link set can1 up type can bitrate 250000
  3.     debian@ebb:~$ candump can1
  4.       can1  721   [1]  05
  5.       can1  1A1   [8]  20 00 FF 0F A8 FD A8 FD
  6.  

...

So in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.  Is there any interest in this?  Who's allowed to change it. 

Noting that you seem to have demonstrated that the "plug-in" nature of the Linux network stack functionality is working properly... are you saying that this is purely an FPC issue rather than a kernel one? At that point I'd expect that a patch via Mantis would be appropriate, particularly since this appears to move FPC and possibly Lazarus into an area that it's not previously supported.

MarkMLl
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on October 22, 2020, 10:07:36 am

Noting that you seem to have demonstrated that the "plug-in" nature of the Linux network stack functionality is working properly... are you saying that this is purely an FPC issue rather than a kernel one? At that point I'd expect that a patch via Mantis would be appropriate, particularly since this appears to move FPC and possibly Lazarus into an area that it's not previously supported.

MarkMLl


Yes for both the BeagleBone and Pi and as I understand pretty well all Linux systems the socketCAN capability works well.  As the attached screen shot generated by the return result from the socket call with PF_CAN as the parameter shows.  PF_CAN doesn't exist so of course it fails.  The PF_CAN with a value of 29 doesn't exist in the definitions for socket.pp or whatever code is ultimately executed.  And the PF can is required so the system knows where to go for the data during a read.

Code: Pascal  [Select][+][-]
  1. const
  2.   PF_CAN = 29;
  3.   CAN_RAW = 1;
  4.  

Trouble is, GitHub and the associated read me files are so convoluted that I have no idea where to even start much less what to compile (if at all) to be able to duplicate the operation of the C programs.    I could make the changes but I don't know where to start.

Here's the example.  I realize bind should probably be used but it doesn't make it past the socket call.
Code: Pascal  [Select][+][-]
  1. unit socketunit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Sockets, errors;
  9.  
  10. const
  11.   PF_CAN = 29;
  12.   CAN_RAW = 1;
  13.  
  14. type
  15.  
  16.   { TSocketForm }
  17.  
  18.   TSocketForm = class(TForm)
  19.     Button1: TButton;
  20.     Edit1: TEdit;
  21.     procedure Button1Click(Sender: TObject);
  22.   private
  23.  
  24.   public
  25.     socket_result : LongInt;
  26.     SAddr : TInetSockAddr;
  27.     Slen : TSockLen;
  28.     sin, sout : text;
  29.  
  30.   end;
  31.  
  32. var
  33.   SocketForm: TSocketForm;
  34.  
  35. implementation
  36.  
  37. {$R *.lfm}
  38.  
  39. { TSocketForm }
  40.  
  41. procedure TSocketForm.Button1Click(Sender: TObject);
  42. var
  43.     i : integer;
  44. begin
  45.   // open socket
  46.   socket_result := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  47.   if (socket_result < 0) then begin
  48.         // perror("socket");
  49.     Edit1.text := 'Error #' + IntToStr(socket_result) + ' creating socket';
  50.   end
  51.   else begin
  52.     SAddr.sin_family := PF_CAN;
  53.     SAddr.xpad := 'can0';
  54.     if fpconnect(socket_result, @SAddr, 0) = -1 then begin
  55.       Edit1.text := 'Socket can''t connect: ' + strerror(socketerror);
  56.     end;
  57.   end;
  58. end;
  59.  
  60. end.
  61.  
Title: Re: CAN-BUS SockectCAN
Post by: MarkMLl on October 22, 2020, 10:45:46 am
At the very least I suggest getting a bug report in  suggesting that FPC's definition of PF_INET (and possibly AF_INET?) should be accompanied by one for PF_CAN. However I think that you'd need to make sure that you could provide (links to) the appropriate numeric values for different OSes, since I don't think the numeric values can be relied upon to be constant... you're basically telling the OS how to populate an internal table.

MarkMLl
Title: Re: CAN-BUS SockectCAN
Post by: avra on October 22, 2020, 11:15:23 am
Here's the example.  I realize bind should probably be used but it doesn't make it past the socket call.
Because you are trying to use "SAddr : TInetSockAddr;" (C sockaddr) with SocketCAN, while you need to use C sockaddr_can. CAN C headers have not yet been translated to FPC. You will at least need sockaddr_can, ifreq and can_frame structures. You can find ifreq structure in \fpcsrc\packages\libc\src\nifh.inc, but the rest only in /usr/src/linux-source-5.8/include/uapi/linux/can.h and /usr/src/linux-source-5.8/include/uapi/linux/can/ (raw.h, bcm.h, error.h ...) waiting for translation.

Btw.1 You do not need CAN_FD for slcan devices since none of them implements faster CAN_FD yet (although CAN_FD is backwards compatible with slow CAN).
Btw.2 Did you read my previous message? I still think that socketcand path would be easier for you...
Title: Re: CAN-BUS SockectCAN
Post by: tetrastes on October 22, 2020, 12:39:40 pm
Code: Pascal  [Select][+][-]
  1.     if fpconnect(socket_result, @SAddr, 0) = -1 then begin
  2.  

Why the third parameter of fpconnect is zero?
Title: Re: CAN-BUS SockectCAN
Post by: MarkMLl on October 22, 2020, 01:29:16 pm
Code: Pascal  [Select][+][-]
  1.     if fpconnect(socket_result, @SAddr, 0) = -1 then begin
  2.  

Why the third parameter of fpconnect is zero?

Well spotted ;-)

For that matter, I have a lot of trouble tying https://www.freepascal.org/docs-html/rtl/sockets/fpconnect.html to anything remotely relevant.

MarkMLl
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on October 22, 2020, 07:06:19 pm
So in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.
PF_CAN is just a number. In linux sources you can find it defined as AF_CAN, which is defined as 29. So why don't you try that first?

EDIT: I see now that you are looking at sources of candump. It will be much easier if you use simpler example from here:
https://www.beyondlogic.org/example-c-socketcan-code/

True.  And in my example I assigned 29 to PF_CAN.  The beyondlogic example in C translated to pascal still suffers from the same issue that it's not handled in the socket library.  Thank you for that link.  It does simplify the code.  The candump.c has become more complicated with CAN_FD support which I'm not interested in looking at right now.  Especially since it's not supported by the MCP2515 and the BeagleBone internal CAN device nor many of the other existing CANopen modules out there.

I don't really want to add what appears to be an extra layer with TCP if I don't have to.  I'll download and compile socketcand to see if it fits in with what I want to do.

BTW, under winsock2.pp 29 is allocated to
Code: Pascal  [Select][+][-]
  1.   AF_TCNPROCESS   = 29;
  2.   AF_TCNMESSAGE   = 30;
  3.   AF_ICLFXBM      = 31;
  4.  
  5.   AF_MAX          = 32;
  6.  

My goal is to make something that runs on Windows, Pi and BeagleBones and other small modules running Linux.  Even LinuxCNC.  Not that concerned about Linux Desktop PCs.  The PC doesn't have the SPI or embedded CAN device so the CANUSB from Lawicel (or equivalent module with identical protocol) is what I'm currently targeting.

Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on October 22, 2020, 07:08:55 pm
Code: Pascal  [Select][+][-]
  1.     if fpconnect(socket_result, @SAddr, 0) = -1 then begin
  2.  

Why the third parameter of fpconnect is zero?

Well spotted ;-)

For that matter, I have a lot of trouble tying https://www.freepascal.org/docs-html/rtl/sockets/fpconnect.html to anything remotely relevant.

MarkMLl
Because I never got past the socket call and had not used bind which is what should be used.  Wasn't even worried about fpconnect or the Saddr once I dove down into the socket library and saw that AF_CAN  or PF_CAN equal to 29 was not supported which essentially means the socketCAN library working in C or Python also won't work.
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on October 22, 2020, 07:25:05 pm
Code: Pascal  [Select][+][-]
  1.     if fpconnect(socket_result, @SAddr, 0) = -1 then begin
  2.  

Why the third parameter of fpconnect is zero?
Awe Crap!  That's what I get for leaving a project for 2 months and then jumping back in not remembering where I stopped.  In fact both you and Mark are correct that I'm using fpconnect incorrectly.
My mistake is that I though I didn't make it past the socket call which I do and returns 11 and not a value < 0. 

OK.  Some steps backwards and then I'll report what I've discovered.  Sheesh. Newbie type mistake...
Title: Re: CAN-BUS SockectCAN
Post by: avra on February 22, 2021, 03:41:43 pm
For a start, I would like to update fpc's linux kernel header translations with missing AF_CAN, PF_CAN and some other constants.

Needed kernel header is at
Quote
/usr/src/linux-headers-5.10.0-0.bpo.3-common/include/linux/socket.h
and I want to update file
Quote
fpcsrc/packages/rtl-extra/src/linux/unxsockh.inc

Should I also update
Quote
fpcsrc/packages/rtl-extra/src/android/unxsockh.inc
as well?

I only intend to test linux...
Title: Re: CAN-BUS SockectCAN
Post by: MarkMLl on February 22, 2021, 03:56:43 pm
For a start, I would like to update fpc's linux kernel header translations with missing AF_CAN, PF_CAN and some other constants.
...
I only intend to test linux...

Noting that the AF_ and PF_ constants are used by user and/or kernel code to express an interest in a particular protocol facet, and that there aren't helpers to extend enumerations and subranges, I think that as a matter of policy they're worth getting into header files etc. as soon as they are standardised by the IETF or whoever's authoritative.

MarkMLl
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on February 23, 2021, 03:44:16 am
For now this project is on hold for while I catch up on a few others.  I'm working on a project that uses the TI TMS320F28379D and the CAN bus and Quadrature encoder interface.  Also not quite finished a CNC mill conversion.  https://youtu.be/I6lvnYhlez4 (https://youtu.be/I6lvnYhlez4)
When I get a few of these other projects out of the way I'll come back to Lazarus and see about the sockets and socketCAN.
Title: Re: CAN-BUS SockectCAN
Post by: avra on February 23, 2021, 08:19:58 am
For a start, I would like to update fpc's linux kernel header translations with missing AF_CAN, PF_CAN and some other constants.
...
I only intend to test linux...

Noting that the AF_ and PF_ constants are used by user and/or kernel code to express an interest in a particular protocol facet, and that there aren't helpers to extend enumerations and subranges, I think that as a matter of policy they're worth getting into header files etc. as soon as they are standardised by the IETF or whoever's authoritative.
Those constants are only a start. I searched FPC files for them, and found where they are and what should be updated. I need a little guiding since it is not simple 1:1 header translation and there is a split into several files - probably because of cross platforming. Only when this work is finished, can and j1939 can build on them.

As for the standardization... well, I don't know what to say. Try to search in sources for AF_BLUETOOTH and you will see that in some operating systems it is defined as 31 and in some as 36. It seams to be OS dependent and not tied to some standard...
Title: Re: CAN-BUS SockectCAN
Post by: MarkMLl on February 23, 2021, 08:33:04 am
As for the standardization... well, I don't know what to say. Try to search in sources for AF_BLUETOOTH and you will see that in some operating systems it is defined as 31 and in some as 36. It seams to be OS dependent and not tied to some standard...

Hmmm. Another of those things like the data returned by a stat() call, where OSes varied and Linux tried to follow the dominant OS on each platform.

I obviously knew that the numerical value of AF_ and PF_ couldn't be trusted to be the same, but I'd assumed that ultimately they were traceable to IETF or similar... I was obviously wrong.

MarkMLl
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on February 23, 2021, 08:41:44 am
The issue isn't only the AF_CAN and PF_CAN.  The lower levels need to deal with the socketCAN infrastructure.  The best way to do this is to research what happens with AF_CAN and PF_CAN in sockets.c.  The socketCAN interface has been usable in Linux now for almost 10 years.  In fact the newest code I was looking at now also supports CANFD which is an enhancement to the original CAN protocol that supports larger messages at higher data rates for the data part.

Even if CANFD was not supported initially I suspect the best thing to do is to port the socketCAN section from the C code to the pascal side.  Then rewrite, again without the CANFD support, the command line applications that are written in C like candump.

The candump application is clever enough to know the difference between a Lawicel CANUSB dongle and say the SPI based Pi MCP2515 or the Beagle embledded CAN device.  In both cases those devices show up as files that can be opened.

To do most of this one doesn't have to actually know much about CAN, although it's useful, but mostly about how Linux handles devices that are files and how the socket communications deals with them.  It's on my do list.
John


Title: Re: CAN-BUS SockectCAN
Post by: avra on February 23, 2021, 02:48:05 pm
The issue isn't only the AF_CAN and PF_CAN...
That's why I said that updating socket wrapper with new constants is just a first step. Next step would be CAN through SocketCAN (not via socketcand daemon which already allows us to connect to CAN using ethernet), and after that SAE J1939 which is a layer on top of CAN. That's what I'm after. CAN FD is not in my focus, but I will probably add it, too.

Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on February 23, 2021, 06:23:51 pm
The issue isn't only the AF_CAN and PF_CAN...
That's why I said that updating socket wrapper with new constants is just a first step. Next step would be CAN through SocketCAN (not via socketcand daemon which already allows us to connect to CAN using ethernet), and after that SAE J1939 which is a layer on top of CAN. That's what I'm after. CAN FD is not in my focus, but I will probably add it, too.
My focus will be CANopen with a monitor program that runs equally well on PCs with Windows, LinuxCNC, Pi and Beagles.  But I've worked with all sorts of CAN protocols..
http://www.autoartisans.com/rings/9S12-Controller.jpg (http://www.autoartisans.com/rings/9S12-Controller.jpg)  This M9S12 has 5 CAN channels and I've used it on one project that had a proprietary protocol on one channel, CANopen on two more actiing as bridge and two J1939, one to servo motors and one to the vehicle for engine RPM and transmission status.   Software on the PC to interface to this was done with Delphi to the USB port
This module here http://www.autoartisans.com/CAN/STU-2.jpg (http://www.autoartisans.com/CAN/STU-2.jpg) runs a PiZeroW and includes a PIC32 for the high speed CAN buffering and then SPI.  C software with pipes etc. to log CAN messages from an electric vehicle into Pi Linux.  I had to use C for that.  Would have been nice to be able to use Lazarus.
Both those projects are for clients so I can't disclose details.  But there are lots of other projects on the go that will be published for playing with CAN and Pi or BBB.

Title: Re: CAN-BUS SockectCAN
Post by: avra on March 02, 2021, 01:55:42 pm
CAN constants have been added to FPC 48867:
https://svn.freepascal.org/svn/fpc/trunk/packages/rtl-extra/src/linux/unxsockh.inc

Also other stuff not related to CAN has been added from .../include/linux/socket.h in Linux 5.10 headers.

Proceeding further steps...

UPDATE: Upon user's request here is a working link to this file in new gitlab repo:
https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/rtl-extra/src/linux/unxsockh.inc
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on March 02, 2021, 06:25:31 pm
Awesome.  You've probably already seen this but for convenience here's the link:
https://www.beyondlogic.org/example-c-socketcan-code (https://www.beyondlogic.org/example-c-socketcan-code)

I guess for example one would take the C code and create a Lazarus command line version of candump called pcandump to avoid mixing things up.  But it needs that sockets.pp (I think that was the file) modified to understand the AF_CAN and PF_CAN constants.

https://elinux.org/Can-utils (https://elinux.org/Can-utils)

The above link is to an example which has a link to the source which has a link to the doc.
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 03, 2021, 09:54:10 am
Awesome.  You've probably already seen this but for convenience here's the link:
https://www.beyondlogic.org/example-c-socketcan-code (https://www.beyondlogic.org/example-c-socketcan-code)
That is the link I gave in my first reply to this topic.  ;)

I guess for example one would take the C code and create a Lazarus command line version of candump called pcandump to avoid mixing things up.
My initial goal would be to make pascal versions of cantransmit, canreceive and canfilter from https://github.com/craigpeacock/CAN-Examples. Then I would probably move to J1939.

But it needs that sockets.pp (I think that was the file) modified to understand the AF_CAN and PF_CAN constants.
Already done. With latest trunk you simply include sockets and those constants are available.

https://elinux.org/Can-utils (https://elinux.org/Can-utils)
The above link is to an example which has a link to the source which has a link to the doc.
I am familiar with that, too. I am the author of https://github.com/linux-can/can-utils/blob/master/can-j1939-install-kernel-module.md  :D
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on March 03, 2021, 07:11:19 pm
https://elinux.org/Can-utils (https://elinux.org/Can-utils)
The above link is to an example which has a link to the source which has a link to the doc.

I am familiar with that, too. I am the author of https://github.com/linux-can/can-utils/blob/master/can-j1939-install-kernel-module.md  :D

Nice write-up on the install of can-J1939.  I like the fact that you explain how to fix it when it goes wrong.  So many people leave that out of their description. :)
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 04, 2021, 12:05:38 pm
Nice write-up on the install of can-J1939.  I like the fact that you explain how to fix it when it goes wrong.  So many people leave that out of their description. :)
Thanks, you're very kind. I'm glad you like it.  :)
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 08, 2021, 11:12:04 am
Here is Linux SocketCAN wrapper. Not a full one yet, but enough to be able to compile 1:1 pascal version of https://github.com/craigpeacock/CAN-Examples/blob/master/cantransmit.c.

It compiles, however something is wrong since with pascal version during runtime binding:

Code: Pascal  [Select][+][-]
  1.     if fpbind(s, @addr, sizeof(addr)) < 0 then

I get socket error 88 (ESysENOTSOCK - Socket operation on non-socket).

C version of cantransmit example binds without problems and sends good data to canreceive, and I can also see with other sniffing tools that SocketCAN messaging is working.

Could someone please take a closer look at this "Socket operation on non-socket" problem?

Code: Pascal  [Select][+][-]
  1. program cantransmit;
  2.  
  3. {$mode delphi} {$H+}
  4.  
  5. uses
  6.   cthreads, classes, sysutils, sockets, unixtype, baseunix, can;
  7.  
  8. procedure PError(const S : string);
  9. begin
  10.   WriteLn(S, ', SocketError = ', SocketError);
  11. end;
  12.  
  13. var
  14.   s:     cint = 0;
  15.   addr:  sockaddr_can;
  16.   ifr:   ifreq;
  17.   frame: can_frame;
  18. begin
  19.   try
  20.     Writeln('CAN Sockets Demo');
  21.     if fpsocket(PF_CAN, SOCK_RAW, CAN_RAW) < 0 then
  22.     begin
  23.       perror('Socket');
  24.       Exit;
  25.     end;
  26.  
  27.     ifr.ifr_name := 'vcan0' ;
  28.     fpioctl(s, SIOCGIFINDEX, @ifr);
  29.  
  30.     memset(@addr, 0, sizeof(addr));
  31.     addr.can_family := AF_CAN;
  32.     addr.can_ifindex := ifr.ifr_ifindex;
  33.  
  34.     if fpbind(s, @addr, sizeof(addr)) < 0 then
  35.     //if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then
  36.     begin
  37.       perror('Bind');
  38.       Exit;
  39.     end;
  40.  
  41.     frame.can_id   := $555;
  42.     frame.can_dlc  := 5;
  43.     frame.datatext := 'Hello'; // datatext field is a variant record of chars overlaying data field
  44.  
  45.     if fpwrite(s, frame, sizeof(can_frame)) <> sizeof(can_frame) then
  46.     begin
  47.       perror('Write');
  48.       Exit;
  49.     end;
  50.  
  51.     if fpclose(s) < 0 then
  52.     begin
  53.       perror('Close');
  54.       Exit;
  55.     end;
  56.  
  57.   except
  58.     on e:Exception do
  59.       WriteLn(e.Message);
  60.   end;
  61. end.
  62.  

Code: C  [Select][+][-]
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5.  
  6. #include <net/if.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/socket.h>
  9.  
  10. #include <linux/can.h>
  11. #include <linux/can/raw.h>
  12.  
  13. int main(int argc, char **argv)
  14. {
  15.         int s;
  16.         struct sockaddr_can addr;
  17.         struct ifreq ifr;
  18.         struct can_frame frame;
  19.  
  20.         printf("CAN Sockets Demo\r\n");
  21.  
  22.         if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
  23.                 perror("Socket");
  24.                 return 1;
  25.         }
  26.  
  27.         strcpy(ifr.ifr_name, "vcan0" );
  28.         ioctl(s, SIOCGIFINDEX, &ifr);
  29.  
  30.         memset(&addr, 0, sizeof(addr));
  31.         addr.can_family = AF_CAN;
  32.         addr.can_ifindex = ifr.ifr_ifindex;
  33.  
  34.         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  35.                 perror("Bind");
  36.                 return 1;
  37.         }
  38.  
  39.         frame.can_id = 0x555;
  40.         frame.can_dlc = 5;
  41.         sprintf(frame.data, "Hello");
  42.  
  43.         if (write(s, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame)) {
  44.                 perror("Write");
  45.                 return 1;
  46.         }
  47.  
  48.         if (close(s) < 0) {
  49.                 perror("Close");
  50.                 return 1;
  51.         }
  52.  
  53.         return 0;
  54. }

As you can see in code, I am using virtual vcan0 which you can create yourself if you follow instructions from https://www.elinux.org/Bringing_CAN_interface_up.

If needed sniffing tools can be found at https://www.elinux.org/Can-utils.

p.s. You need either trunk FPC, or you need to define missing CAN constants yourself as explained earlier in this thread.

UPDATE: The problem remains even when doing one of these:
Code: Pascal  [Select][+][-]
  1.     memset(@ifr, 0, sizeof(ifr));
Code: Pascal  [Select][+][-]
  1.     ifr.ifr_name := 'vcan0' + #0;
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 08, 2021, 12:15:12 pm
It looks like the problem is in fpioctl() call since this modified code:
Code: Pascal  [Select][+][-]
  1.     strcopy(ifr.ifr_name, 'vcan0');
  2.     WriteLn('before fpioctl: ifr.ifr_ifindex = ', ifr.ifr_ifindex);
  3.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then // SIOCGIFINDEX = $8933;
  4.     begin
  5.       WriteLn('after fpioctl: ifr.ifr_ifindex = ', ifr.ifr_ifindex);
  6.       WriteLn('fpGetErrno = ', fpGetErrno);
  7.       perror('IOctl');
  8.       Exit;
  9.     end;
exits with fpGetErrno = 25 and I can see that ifr.ifr_ifindex = 0 which tells me that vcan0 was not found at all,

while this modified part of C code:
Code: C  [Select][+][-]
  1.   strcpy(ifr.ifr_name, "vcan0" );
  2.   int i;
  3.   i = ioctl(s, SIOCGIFINDEX, &ifr);
  4.   if (i < 0){
  5.     perror("ioctl");
  6.     return 1;
  7.   };
  8.   printf("ioctl() = %d\n", i);
  9.   printf("ifr.ifr_ifindex = %d\n", ifr.ifr_ifindex);  
works well with ioctl() = 0 and ifr.ifr_ifindex = 3 which tells me that vcan0 was found properly.

So, is this a bug related to fpioctl() ???

UPDATE: No, it was not a bug in fpioctl(). Silly me, I forgot to get a handle in the first place.  :-[

I will provide working cantransmit a little later...
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 08, 2021, 02:44:19 pm
Here is a fully working SocketCAN transmit demo. First ever with FreePascal.  8-)

Code: Pascal  [Select][+][-]
  1. program cantransmit;
  2.  
  3. {$mode delphi} {$H+}
  4.  
  5. uses
  6.   cthreads, classes, sysutils, sockets, unixtype, baseunix, can;
  7.  
  8. procedure PError(const S : string);
  9. begin
  10.   WriteLn(S, ', SocketError = ', SocketError);
  11. end;
  12.  
  13. var
  14.   s:     cint = 0;
  15.   addr:  sockaddr_can;
  16.   ifr:   ifreq;
  17.   frame: can_frame;
  18. begin
  19.   try
  20.     Writeln('CAN Sockets Transmit Demo');
  21.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  22.     if s < 0 then
  23.     begin
  24.       perror('Socket');
  25.       Exit;
  26.     end;
  27.  
  28.     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;
  29.  
  30.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  31.     begin
  32.       perror('IOctl');
  33.       Exit;
  34.     end;
  35.  
  36.     memset(@addr, 0, sizeof(addr));
  37.     addr.can_family := AF_CAN;
  38.     addr.can_ifindex := ifr.ifr_ifindex;
  39.  
  40.     if fpbind(s, @addr, sizeof(addr)) < 0 then // equals to: if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then
  41.     begin
  42.       perror('Bind');
  43.       Exit;
  44.     end;
  45.  
  46.     frame.can_id   := $555;
  47.     frame.can_dlc  := 5;
  48.     frame.datatext := 'Hello'; // datatext field is a variant record of chars overlaying data field
  49.  
  50.     if fpwrite(s, frame, sizeof(can_frame)) <> sizeof(can_frame) then
  51.     begin
  52.       perror('Write');
  53.       Exit;
  54.     end;
  55.  
  56.     if fpclose(s) < 0 then
  57.     begin
  58.       perror('Close');
  59.       Exit;
  60.     end;
  61.  
  62.   except
  63.     on e:Exception do
  64.       WriteLn(e.Message);
  65.   end;
  66. end.
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 08, 2021, 03:34:55 pm
Also fully working SocketCAN receive demo. Enjoy!  :D

Code: Pascal  [Select][+][-]
  1. program canreceive;
  2.  
  3. {$mode delphi} {$H+}
  4.  
  5. uses
  6.   cthreads, classes, sysutils, sockets, unixtype, baseunix, can;
  7.  
  8. procedure PError(const S : string);
  9. begin
  10.   WriteLn(S, ', SocketError = ', SocketError);
  11. end;
  12.  
  13. var
  14.   s, i, nbytes: cint;
  15.   addr:  sockaddr_can;
  16.   ifr:   ifreq;
  17.   frame: can_frame;
  18. begin
  19.   try
  20.     Writeln('CAN Sockets Receive  Demo');
  21.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  22.     if s < 0 then
  23.     begin
  24.       perror('Socket');
  25.       Exit;
  26.     end;
  27.  
  28.     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;
  29.  
  30.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  31.     begin
  32.       perror('IOctl');
  33.       Exit;
  34.     end;
  35.  
  36.     memset(@addr, 0, sizeof(addr));
  37.     addr.can_family := AF_CAN;
  38.     addr.can_ifindex := ifr.ifr_ifindex;
  39.  
  40.     if fpbind(s, @addr, sizeof(addr)) < 0 then // equals to: if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then
  41.     begin
  42.       perror('Bind');
  43.       Exit;
  44.     end;
  45.  
  46.     nbytes := fpread(s, frame, sizeof(can_frame));
  47.     if nbytes < 0 then begin
  48.       perror('Read');
  49.       Exit;
  50.     end;
  51.  
  52.     Write(format('0x%03X [%d] ', [frame.can_id, frame.can_dlc]));
  53.     for i := 0 to frame.can_dlc - 1 do
  54.       Write(Format('%02X ', [frame.data[i]]));
  55.     WriteLn('');
  56.  
  57.     if fpclose(s) < 0 then
  58.     begin
  59.       perror('Close');
  60.       Exit;
  61.     end;
  62.  
  63.   except
  64.     on e:Exception do
  65.       WriteLn(e.Message);
  66.   end;
  67. end.
  68.  
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 09, 2021, 01:48:34 pm
SocketCAN filter demo:  :-X

Code: Pascal  [Select][+][-]
  1. program canfilter;
  2.  
  3. {$mode delphi} {$H+}
  4.  
  5. uses
  6.   cthreads, classes, sysutils, sockets, unixtype, baseunix, can, can.raw;
  7.  
  8. procedure PError(const S : string);
  9. begin
  10.   WriteLn(S, ', SocketError = ', SocketError);
  11. end;
  12.  
  13. var
  14.   s, i, nbytes: cint;
  15.   addr:         sockaddr_can;
  16.   ifr:          ifreq;
  17.   frame:        can_frame;
  18.   rfilter:      array[0..1] of can_filter;
  19. begin
  20.   try
  21.     Writeln('CAN Sockets Filter Demo');
  22.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  23.     if s < 0 then
  24.     begin
  25.       perror('Socket');
  26.       Exit;
  27.     end;
  28.  
  29.     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;
  30.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  31.     begin
  32.       perror('IOctl');
  33.       Exit;
  34.     end;
  35.  
  36.     memset(@addr, 0, sizeof(addr));
  37.     addr.can_family  := AF_CAN;
  38.     addr.can_ifindex := ifr.ifr_ifindex;
  39.  
  40.     if fpbind(s, @addr, sizeof(addr)) < 0 then // if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then
  41.     begin
  42.       perror('Bind');
  43.       Exit;
  44.     end;
  45.  
  46.     rfilter[0].can_id   := $550; // 1st CAN ID
  47.     rfilter[0].can_mask := $7F0; // 1st CAN MASK matches all frames with identifiers from $550 to $55F
  48.     rfilter[1].can_id   := $200; // 2nd CAN ID
  49.     rfilter[1].can_mask := $7FF; // 2nd CAN MASK matches only frames with identifier equal to $200 and nothing else
  50.  
  51.     fpsetsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, @rfilter, sizeof(rfilter));
  52.  
  53.     nbytes := fpread(s, frame, sizeof(can_frame));
  54.     if nbytes < 0 then begin
  55.       perror('Read');
  56.       Exit;
  57.     end;
  58.  
  59.     Write(format('0x%03X [%d] ', [frame.can_id, frame.can_dlc]));
  60.     for i := 0 to frame.can_dlc - 1 do
  61.       Write(Format('%02X ', [frame.data[i]]));
  62.     WriteLn('');
  63.  
  64.     if fpclose(s) < 0 then
  65.     begin
  66.       perror('Close');
  67.       Exit;
  68.     end;
  69.  
  70.   except
  71.     on e:Exception do
  72.       WriteLn(e.Message);
  73.   end;
  74. end.
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 11, 2021, 09:53:02 am
Finished conversion of all linux CAN headers (can, can.bcm, can.error, can.gw, can.isotp, can.j1939, can.netlink, can.raw and can.vxcan). I will see if I can shape it a little bit more, add some more demos, and prepare a patch for bug tracker. Demos for can and can.raw are already given, so I will probably add can.bcm and can.j1939 demos. If anyone is interested to contribute some other demos send me a PM and I will provide all header translations.

I guess that CAN support should be shaped as a FP package. That way it shall work out of the box with FP, as it already does with Python and C.

I should have done this a long time ago. Python and C are fine but there is no fun in that.  8-) :D 8-)
Title: Re: CAN-BUS SockectCAN
Post by: ThomasK on March 11, 2021, 03:01:32 pm
Hi, can you tell me where I can finde the required can and can.raw units you use in your solutions (Send ,receive, filter)?

Thanks and Best Regards,

Thomas
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 11, 2021, 03:11:35 pm
Hi, can you tell me where I can finde the required can and can.raw units you use in your solutions (Send ,receive, filter)?
Translated headers can be found in cantransmit.zip attached to message: https://forum.lazarus.freepascal.org/index.php/topic,39858.msg396883.html#msg396883. In just few days there have been almost 200 downloads.  8-) Since I have updated them a little, I have attached latest version of demos and all translated headers to this message.

Thanks and Best Regards
You're most welcome.   :D
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 11, 2021, 03:12:31 pm
@jcdammeyer: CAN FD receive and transmit demos are here.  It was not trivial to find info of what exactly to change when compared to legacy CAN but it works now. 8-)

Code: Pascal  [Select][+][-]
  1. //////////////////////////////////////////////////////////////////////////////////
  2. //                                                                              //
  3. //  This is a SocketCAN demo converted from C to Pascal by Zeljko Avramovic.    //
  4. //  Original code has GNU General Public License v3.0 and can be found at       //
  5. //  https://github.com/craigpeacock/CAN-Examples                                //
  6. //                                                                              //
  7. //  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:  //
  8. //  sudo modprobe vcan                                                          //
  9. //  sudo ip link add dev vcan0 type vcan                                        //
  10. //  sudo ip link set vcan0 mtu 72            # needed for CAN FD                //
  11. //  sudo ip link set vcan0 up                                                   //
  12. //                                                                              //
  13. //////////////////////////////////////////////////////////////////////////////////
  14.  
  15. program canfdtransmit;
  16.  
  17. {$mode delphi} {$H+}
  18.  
  19. uses
  20.   cthreads, classes, sysutils, sockets, baseunix, can, can.raw;
  21.  
  22. procedure perror(const S : string);
  23. begin
  24.   WriteLn(S, ', SocketError = ', SocketError);
  25. end;
  26.  
  27. var
  28.   s, err: cint;
  29.   addr:   sockaddr_can;
  30.   ifr:    ifreq;
  31.   frame:  canfd_frame;
  32. begin
  33.   try
  34.     Writeln('CAN FD Sockets Transmit Demo');
  35.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  36.     if s < 0 then
  37.     begin
  38.       if s = ESysENOPROTOOPT then
  39.         Writeln('CAN_RAW_FD_FRAMES socket option is not supported. Your kernel is probably too old.');
  40.       perror('Socket');
  41.       Exit;
  42.     end;
  43.  
  44.     strcopy(ifr.ifr_name, 'vcan0');
  45.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  46.     begin
  47.       perror('IOctl');
  48.       Exit;
  49.     end;
  50.  
  51.     memset(@addr, 0, sizeof(addr));
  52.     addr.can_family  := AF_CAN;
  53.     addr.can_ifindex := ifr.ifr_ifindex;
  54.  
  55.     if fpbind(s, @addr, sizeof(addr)) < 0 then
  56.     begin
  57.       perror('Bind');
  58.       Exit;
  59.     end;
  60.  
  61.     frame.can_id := $444;    // CAN FD message ID
  62.     frame.len    := 20;      // payload length will be 20 bytes
  63.     frame.data   := [$01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $10,
  64.                      $11, $12, $13, $14, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
  65.                      $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
  66.                      $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00];
  67.                      // shows as '0x444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive
  68.     {
  69.     frame.data[0]  := $01; // alternative for the above
  70.     frame.data[1]  := $02; // shows as '0x444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive
  71.     frame.data[2]  := $03;
  72.     frame.data[3]  := $04;
  73.     frame.data[4]  := $05;
  74.     frame.data[5]  := $06;
  75.     frame.data[6]  := $07;
  76.     frame.data[7]  := $08;
  77.     frame.data[8]  := $09;
  78.     frame.data[9]  := $0A;
  79.     frame.data[10] := $0B;
  80.     frame.data[11] := $0C;
  81.     frame.data[12] := $0D;
  82.     frame.data[13] := $0E;
  83.     frame.data[14] := $0F;
  84.     frame.data[15] := $10;
  85.     frame.data[16] := $11;
  86.     frame.data[17] := $12;
  87.     frame.data[18] := $13;
  88.     frame.data[19] := $14;
  89.     }
  90.  
  91.     err := fpsetsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, @ENABLE_CAN_OPTION, sizeof(ENABLE_CAN_OPTION));
  92.     if err <> 0 then
  93.     begin
  94.       if err = ESysENOPROTOOPT then
  95.         WriteLn('CAN FD Protocol not available. Try newer kernel');
  96.       perror('SetSockopt');
  97.       Exit;
  98.     end;
  99.  
  100.     if fpwrite(s, frame, sizeof(canfd_frame)) <> sizeof(canfd_frame) then
  101.     begin
  102.       perror('Write');
  103.       Exit;
  104.     end;
  105.  
  106.     if fpclose(s) < 0 then
  107.     begin
  108.       perror('Close');
  109.       Exit;
  110.     end;
  111.  
  112.   except
  113.     on e:Exception do
  114.       WriteLn(e.Message);
  115.   end;
  116. end.

Code: Pascal  [Select][+][-]
  1. //////////////////////////////////////////////////////////////////////////////////
  2. //                                                                              //
  3. //  This is a SocketCAN demo converted from C to Pascal by Zeljko Avramovic.    //
  4. //  Original code has GNU General Public License v3.0 and can be found at       //
  5. //  https://github.com/craigpeacock/CAN-Examples                                //
  6. //                                                                              //
  7. //  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:  //
  8. //  sudo modprobe vcan                                                          //
  9. //  sudo ip link add dev vcan0 type vcan                                        //
  10. //  sudo ip link set vcan0 mtu 72            # needed for CAN FD                //
  11. //  sudo ip link set vcan0 up                                                   //
  12. //                                                                              //
  13. //////////////////////////////////////////////////////////////////////////////////
  14.  
  15. program canfdreceive;
  16.  
  17. {$mode delphi} {$H+}
  18.  
  19. uses
  20.   cthreads, classes, sysutils, sockets, unixtype, baseunix, can, can.raw;
  21.  
  22. procedure perror(const S : string);
  23. begin
  24.   WriteLn(S, ', SocketError = ', SocketError);
  25. end;
  26.  
  27. var
  28.   s, i, nbytes, err: cint;
  29.   addr:              sockaddr_can;
  30.   ifr:               ifreq;
  31.   frame:             canfd_frame;
  32. begin
  33.   try
  34.     Writeln('CAN FD Sockets Receive Demo');
  35.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  36.     if s < 0 then
  37.     begin
  38.       perror('Socket');
  39.       Exit;
  40.     end;
  41.  
  42.     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;
  43.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  44.     begin
  45.       perror('IOctl');
  46.       Exit;
  47.     end;
  48.  
  49.     memset(@addr, 0, sizeof(addr));
  50.     addr.can_family  := AF_CAN;
  51.     addr.can_ifindex := ifr.ifr_ifindex;
  52.  
  53.     if fpbind(s, @addr, sizeof(addr)) < 0 then
  54.     begin
  55.       perror('Bind');
  56.       Exit;
  57.     end;
  58.  
  59.     err := fpsetsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, @ENABLE_CAN_OPTION, sizeof(ENABLE_CAN_OPTION));
  60.     if err <> 0 then
  61.     begin
  62.       if err = ESysENOPROTOOPT then
  63.         WriteLn('CAN FD Protocol not available. Try newer kernel');
  64.       perror('SetSockopt');
  65.       Exit;
  66.     end;
  67.  
  68.     nbytes := fpread(s, frame, sizeof(canfd_frame));
  69.     if nbytes < 0 then
  70.     begin
  71.       perror('Read');
  72.       Exit;
  73.     end;
  74.     if nbytes < sizeof(can_frame) then // paranoid check
  75.     begin
  76.       perror('Read: Incomplete CAN frame');
  77.       Exit;
  78.     end;
  79.  
  80.     if nbytes = CANFD_MTU then
  81.       WriteLn('CAN FD frame received with length ', IntToStr(frame.len))
  82.     else if nbytes = CAN_MTU then
  83.       WriteLn('CAN legacy frame received with length ', IntToStr(frame.len))
  84.     else
  85.       WriteLn('Invalid CAN(FD) frame received');
  86.  
  87.     Write(format('0x%03X [%d] ', [frame.can_id, frame.len]));
  88.     for i := 0 to frame.len - 1 do
  89.       Write(Format('%02.2X ', [frame.data[i]]));
  90.     WriteLn('');
  91.  
  92.     if fpclose(s) < 0 then
  93.     begin
  94.       perror('Close');
  95.       Exit;
  96.     end;
  97.  
  98.   except
  99.     on e:Exception do
  100.       WriteLn(e.Message);
  101.   end;
  102. end.
Title: Re: CAN-BUS SockectCAN
Post by: ThomasK on March 11, 2021, 03:26:32 pm

You're most welcome.   :D

Thanks a lot. I recently started progamming Pascal again. I started in 1977 on a Siemens 4004/151 with punch cards.....
My first application runs on a Pi.
Title: Re: CAN-BUS SockectCAN
Post by: Fred vS on March 11, 2021, 03:33:57 pm
@Avra: Wonderful! (like always with you  ;))

Many thanks.

Fre;D
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 11, 2021, 03:41:30 pm
@Avra: Wonderful! (like always with you  ;))

Many thanks.
You're very kind and you're most welcome.   :)

You can test canfdreceive either with provided canfdtransmit, or you can use can-utils like this:

for legacy CAN:
Quote
cansend vcan0 456#DEADBEEF

for CAN FD:
Quote
cansend vcan0 123##1112233445566778899AABBCC

for CAN XL:
Quote
Just kidding  :D :D :D. CAN XL is in testing phase and linux is not ready for it yet. But according to specification it should be compatible to CAN FD so we do not have to worry for now...
Title: Re: CAN-BUS SockectCAN
Post by: sstvmaster on March 11, 2021, 05:08:33 pm
@Avra: Many thanks.

Wouldn't it be better to upload your work to Bitbucket, Github, ..., and make an own repo for that?

Rgr Maik
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 12, 2021, 07:53:40 am
@Avra: Many thanks.
You're most welcome. I'm glad it's of use to others.  :P

Wouldn't it be better to upload your work to Bitbucket, Github, ..., and make an own repo for that?
This is just a temporary public playground. My final goal is to make SocketCAN header translations and demos integral part of FreePascal, so that CAN works out of the box without downloading anything additional. Like Python and C already have.

So far my development and testing is on Debian x86-64 via vcan, using can-utils and Kayak. I will probably also test it on Manjaro x86-64. While I do intend to test it with real hardware on Raspbery Pi and PocketBeagle in the future, I would appreciate any testing feedback I can get now. Especially on 32 and 64 bit ARM - even with just vcan.
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 15, 2021, 02:43:27 pm
Here is SocketCAN BCM cyclic demo where you let kernel take care of sending interval. Enjoy!  :D

Code: Pascal  [Select][+][-]
  1. //////////////////////////////////////////////////////////////////////////////////
  2. //                                                                              //
  3. //  This is a SocketCAN BCM cyclic demo created by Zeljko Avramovic             //
  4. //  FPC modified LGPL licence: https://wiki.freepascal.org/FPC_modified_LGPL    //
  5. //                                                                              //
  6. //  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:  //
  7. //  sudo modprobe vcan                                                          //
  8. //  sudo ip link add dev vcan0 type vcan                                        //
  9. //  sudo ip link set vcan0 mtu 72            # needed for CAN FD                //
  10. //  sudo ip link set vcan0 up                                                   //
  11. //                                                                              //
  12. //////////////////////////////////////////////////////////////////////////////////
  13.  
  14. program cancyclic;
  15.  
  16. {$mode delphi} {$H+}
  17.  
  18. uses
  19.   cthreads, classes, sysutils, sockets, baseunix, crt, can, can.bcm;
  20.  
  21. type
  22.   bcm_msg = record
  23.     head: bcm_msg_head_without_frames; // we shall use more then 1 frame so bcm_msg_head is not enough
  24.     frame: array[0..2] of can_frame;   // and we add here space for our 3 frames
  25.   end;
  26.  
  27. procedure perror(const S : string);
  28. begin
  29.   WriteLn(S, ', SocketError = ', SocketError);
  30. end;
  31.  
  32. var
  33.   s, i: cint;
  34.   addr: sockaddr_can;
  35.   ifr:  ifreq;
  36.   msg:  bcm_msg;
  37. begin
  38.   try
  39.     Writeln('CAN Sockets BCM Cyclic Demo');
  40.     s := fpsocket(PF_CAN, SOCK_DGRAM, CAN_BCM);
  41.     if s < 0 then
  42.     begin
  43.       perror('Socket');
  44.       Exit;
  45.     end;
  46.  
  47.     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;
  48.     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  49.     begin
  50.       perror('IOctl');
  51.       Exit;
  52.     end;
  53.  
  54.     memset(@addr, 0, sizeof(addr));
  55.     addr.can_family  := AF_CAN;
  56.     addr.can_ifindex := ifr.ifr_ifindex;
  57.  
  58.     if fpconnect(s, @addr, sizeof(addr)) < 0 then
  59.     begin
  60.       perror('Connect');
  61.       Exit;
  62.     end;
  63.  
  64.     msg.head.opcode        := TX_SETUP;
  65.     msg.head.can_id        := $567; // if TX_CP_CAN_ID flag is set then all messages shall have this CAN ID
  66.     msg.head.flags         := SETTIMER OR STARTTIMER OR TX_ANNOUNCE {OR TX_CP_CAN_ID} {OR TX_RESET_MULTI_IDX};
  67.     msg.head.nframes       := 3;
  68.     msg.head.count         := 0; // single interval (use only ival2)
  69.     msg.head.ival1.tv_sec  := 0;
  70.     msg.head.ival1.tv_usec := 0;
  71.     msg.head.ival2.tv_sec  := 0;
  72.     msg.head.ival2.tv_usec := 250000; // 250 ms interval between CAN messages
  73.     msg.frame[0].can_id    := $550; // not used if TX_CP_CAN_ID falg is set
  74.     msg.frame[0].can_dlc   := 2;
  75.     msg.frame[0].data      := [$01,$02,$03,$04,$05,$06,$07,$08];
  76.     msg.frame[1].can_id    := $551; // not used if TX_CP_CAN_ID falg is set
  77.     msg.frame[1].can_dlc   := 4;
  78.     msg.frame[1].data      := [$11,$12,$13,$14,$15,$16,$17,$18];
  79.     msg.frame[2].can_id    := $552; // not used if TX_CP_CAN_ID falg is set
  80.     msg.frame[2].can_dlc   := 8;
  81.     msg.frame[2].data      := [$21,$22,$23,$24,$25,$26,$27,$28];
  82.  
  83.     if fpwrite(s, msg, sizeof(msg)) <> sizeof(msg) then
  84.     begin
  85.       perror('Write');
  86.       Exit;
  87.     end;
  88.  
  89.     repeat
  90.       WriteLn('Press any key to stop...');
  91.       msg.frame[2].DataByte[0] := msg.frame[2].DataByte[0] + 1;
  92.       for i := 0 to msg.frame[2].can_dlc - 1 do
  93.         Write(Format('%02.2X ', [msg.frame[2].data[i]]));
  94.       WriteLn('');
  95.       WriteLn('');
  96.       fpwrite(s, msg, sizeof(msg)); // comment out this line if you do not want to publish changed frame[2]
  97.       Delay(2000); // loop every 2 seconds
  98.     until KeyPressed;
  99.  
  100.     if fpclose(s) < 0 then
  101.     begin
  102.       perror('Close');
  103.       Exit;
  104.     end;
  105.  
  106.   except
  107.     on e:Exception do
  108.       WriteLn(e.Message);
  109.   end;
  110. end.
  111.  
Title: Re: CAN-BUS SockectCAN
Post by: radek on March 16, 2021, 01:01:29 am
Hi,
I apologize in advance for my English, I am also interested in the implementation of CAN for Lazarus.

I wonder what the performance difference will be if I use:
1) This solution via SocketCAN
2) Direct control of IC MCP2518 via SPI bus using Lazarus
3) Direct control of IC MCP2518 via USB using IC MCP2210 (USB to SPI driver) libusb

I'm interested because I want the application to work under both Windows and Linux. When I use MCP2210 and MCP2518, I can control the CAN driver via SPI directly in Windows and Linux. If I use SocketCAN, then I have to implement another solution for Windows.
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 16, 2021, 08:35:47 am
I am also interested in the implementation of CAN for Lazarus.
Nice to hear  ;)

I wonder what the performance difference will be if I use:
1) This solution via SocketCAN
2) Direct control of IC MCP2518 via SPI bus using Lazarus
3) Direct control of IC MCP2518 via USB using IC MCP2210 (USB to SPI driver) libusb
Any modern PC or SBC CPU is capable of handling CAN without problems. Bottleneck is communication channel. In case of Lawicel/SLCAN/CAN232 it is serial communication - if you use classic AVR ATMEGA328 based Arduino it is 115200 (STM32 or ESP32 based ones may use speeds higher then that so they do not have that problem), you don't use filters and want to see all of high speed CAN traffic then expect to miss frames here and there. Using MCP2518 direct via SPI on Raspberry Pi or PocketBeagle for CAN and CAN FD is solid and comfortable. I haven't used MCP2518 over MCP2210 but I guess that might also skip frames. SocketCAN is just a Berkeley sockets abstraction layer over any Linux CAN hardware, and you use it the same with both SPI MCP2518 and Lawicel/SLCAN/CAN232 (there is no driver for MCP2518 over MCP2210). So, performance does not suffer if you use SocketCAN.

I'm interested because I want the application to work under both Windows and Linux. When I use MCP2210 and MCP2518, I can control the CAN driver via SPI directly in Windows and Linux. If I use SocketCAN, then I have to implement another solution for Windows.
Well, you said it all. Since you want your app to be used on both Windows and Linux, unfortunately you need to give up SocketCAN (unless someone implements it under Windows). Your best bet would be to use some STM32 or ESP32 Lawicel/SLCAN/CAN232 using higher serial speeds, which would probably avoid frame dropping unless you use it on a very, very high traffic 1Mbit CAN.

Also take a look at this discussion: https://forum.lazarus.freepascal.org/index.php/topic,51477.msg377993.html#msg377993
Title: Re: CAN-BUS SockectCAN
Post by: radek on March 16, 2021, 12:19:30 pm
Just to add, the MCP2210 is a High Speed USB HID driver for the SPI bus with speeds from 1500bps to 12Mbps, so there will be no bottleneck. The only problem is that I need to constantly read the 64 byte register to see if the MCP2518 has received any data, this may cause some CPU usage.
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 16, 2021, 02:08:42 pm
Just to add, the MCP2210 is a High Speed USB HID driver for the SPI bus with speeds from 1500bps to 12Mbps, so there will be no bottleneck. The only problem is that I need to constantly read the 64 byte register to see if the MCP2518 has received any data, this may cause some CPU usage.
It doesn't matter how fast you set it's SPI to talk to CAN chip. It seams to use USB HID, which is limited to 1000 messages per second where each message can have up to 64 bytes. You do the math. Ah yes, and while you are transferring data over USB you can not get new CAN messages.

https://github.com/daniel-santos/mcp2210-linux/issues/11
Title: Re: CAN-BUS SockectCAN
Post by: joelucsd on March 23, 2021, 10:23:02 pm
Thank you for the work to get the CANsocket working.  I pulled in the files from can.zip and it worked.  I am using an older version of FPC on the raspberry Pi.  The example worked.  I used that code as a template for my Lazarus project.

I needed an Extended ID.  Will look at that tomorrow.  Might just need to set the extended ID manually before stuffing the value into the frame field.

Regards,
Joel
Title: Re: CAN-BUS SockectCAN
Post by: avra on March 25, 2021, 08:28:09 am
Thank you for the work to get the CANsocket working.
You're most welcome.  ;)

I pulled in the files from can.zip and it worked.  I am using an older version of FPC on the raspberry Pi.  The example worked.  I used that code as a template for my Lazarus project.
Thank you for the report. I didn't catch time to test on Pi and PocketBeagle yet, so I'm glad to hear it works on Pi. Just for info, could you tell me what CAN hardware did you use during testing?

I needed an Extended ID.  Will look at that tomorrow.  Might just need to set the extended ID manually before stuffing the value into the frame field.
So far I have attached enough for 1:1 translation of various C examples you can find on the net. Right now I am working on bit packed overlays which would allow easy access to individual bits, and some higher level helper methods. After that I will probably add SAE J1939 (for trucks, buses, tractors, boats and heavy machinery) where Extended ID is used, and at the end provide a FPC patch so that we can all use SocketCAN out of the box.
Title: Re: CAN-BUS SocketCAN
Post by: joelucsd on March 25, 2021, 06:00:16 pm
I am running on a Raspberry Pi 4.
Raspbian GNU/Linux 10
FPC version is: 3.0.4+dfsg-22+rpi1
Lazarus: 2.0.0+dfsg-2   2019-03-01
I am using a USB to CAN adapter from www.inno-maker.com.  It is a nice cheap solution.
http://wiki.inno-maker.com/display/HOMEPAGE/usb2can
I got mine through Amazon
You do have to enable it with a couple of commands:
'sudo ip link set can0 type can bitrate 250000'
'sudo ifconfig can0 up'

I did get extended addressing to work.  Like I suggested, I just had to set bit 31 to select it before writing the ID into the frame structure.  Then it came out on the bus.  The Python library has an additional parameter in the call to say it is the 29 bit version of the ID.  Setting the bit manually before works fine.  You just need to know to do it.  (And I don't like the Python syntax.  So would rather use Pascal or C)
Title: Re: CAN-BUS SocketCAN
Post by: avra on March 26, 2021, 10:18:54 am
I am running on a Raspberry Pi 4.
Raspbian GNU/Linux 10
FPC version is: 3.0.4+dfsg-22+rpi1
Lazarus: 2.0.0+dfsg-2   2019-03-01
I am using a USB to CAN adapter from www.inno-maker.com.
Thanks for the report. I guess with 3.0.4 you had to manually add missing CAN constants.

You do have to enable it with a couple of commands:
'sudo ip link set can0 type can bitrate 250000'
'sudo ifconfig can0 up'
That's pretty standard for a CAN device that kernel can recognize.

I did get extended addressing to work.  Like I suggested, I just had to set bit 31 to select it before writing the ID into the frame structure.
I know. That's why I said "I am working on bit packed overlays which would allow easy access to individual bits".  ;)
Title: Re: CAN-BUS SocketCAN
Post by: avra on March 31, 2021, 11:14:03 am
I have implemented high level CAN access in can.hl unit. So, if you do your own code from scratch it is recommended to use this unit. Old low level C-like access will stay for easier future upgrades, and you will probably use it only when you want 1:1 translation of some C example from the net. In the attachment you will find new CAN examples hlcancyclic, hlcanfdreceive, hlcanfdtransmit, hlcanfilter, hlcanreceive and hlcantransmit. These are all "high level" versions of previous examples using can.hl unit (if you can give "high level" name to pascalish renaming, bit packed overlays and some helpers).

I hope you will find CAN usage more pleasant now.

@joelucsd: Take a look at hlcanfdtransmit which uses extended 29-bit CAN ID addressing now. It is as simple as this:
Code: Pascal  [Select][+][-]
  1.     CanFDFrame.ID.Value := $444444; // CAN FD message extended ID
  2.     CanFDFrame.ID.EFF   := true;    // confirm that we have 29-bit CAN ID

Talk is cheap. Here is what CAN code looks like now:
Code: Pascal  [Select][+][-]
  1. program hlcanfdtransmit; // higher level pascalized version of canfdtransmit demo
  2.  
  3. {$mode delphi} {$H+}
  4.  
  5. uses
  6.   cthreads, sysutils, sockets, baseunix, can, can.hl, can.raw;
  7.  
  8. procedure perror(const S : string);
  9. begin
  10.   WriteLn(S, ', SocketError = ', SocketError);
  11. end;
  12.  
  13. var
  14.   Err:          integer;
  15.   CanHandle:    TCanHandle;
  16.   CanAddr:      TCanSockAddr;
  17.   CanInterface: TCanIfreq;
  18.   CanFDFrame:   TCanFDFrame;
  19. begin
  20.   try
  21.     Writeln('CAN FD Sockets Transmit Demo');
  22.     CanHandle := CanSocket(SOCK_RAW, CAN_RAW);
  23.     if CanHandle < 0 then
  24.     begin
  25.       perror('Socket');
  26.       Exit;
  27.     end;
  28.  
  29.     CanInterface.Name := 'vcan0' + #0;
  30.     if CanIOCtl(CanHandle, SIOCGIFINDEX, CanInterface) < 0 then
  31.     begin
  32.       perror('IOctl');
  33.       Exit;
  34.     end;
  35.  
  36.     CanAddr.Clear;
  37.     CanAddr.CanFamily  := AF_CAN;
  38.     CanAddr.CanIfIndex := CanInterface.IfIndex;
  39.  
  40.     if CanBind(CanHandle, CanAddr) < 0 then
  41.     begin
  42.       perror('Bind');
  43.       Exit;
  44.     end;
  45.  
  46.     CanFDFrame.ID.Value := $444444; // CAN FD message extended ID
  47.     CanFDFrame.ID.EFF   := true;    // confirm that we have 29-bit CAN ID
  48.     CanFDFrame.Len      := 20;      // payload length will be 20 bytes
  49.     CanFDFrame.Data     := [$01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $10,
  50.                             $11, $12, $13, $14, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
  51.                             $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,
  52.                             $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00];
  53.                             // shows as '0x444444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive
  54.     {
  55.     CanFDFrame.Data[0]  := $01; // alternative for the above
  56.     CanFDFrame.Data[1]  := $02; // shows as '0x444444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive
  57.     CanFDFrame.Data[2]  := $03;
  58.     CanFDFrame.Data[3]  := $04;
  59.     CanFDFrame.Data[4]  := $05;
  60.     CanFDFrame.Data[5]  := $06;
  61.     CanFDFrame.Data[6]  := $07;
  62.     CanFDFrame.Data[7]  := $08;
  63.     CanFDFrame.Data[8]  := $09;
  64.     CanFDFrame.Data[9]  := $0A;
  65.     CanFDFrame.Data[10] := $0B;
  66.     CanFDFrame.Data[11] := $0C;
  67.     CanFDFrame.Data[12] := $0D;
  68.     CanFDFrame.Data[13] := $0E;
  69.     CanFDFrame.Data[14] := $0F;
  70.     CanFDFrame.Data[15] := $10;
  71.     CanFDFrame.Data[16] := $11;
  72.     CanFDFrame.Data[17] := $12;
  73.     CanFDFrame.Data[18] := $13;
  74.     CanFDFrame.Data[19] := $14;
  75.     }
  76.  
  77.     Err := CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, ENABLE_CAN_OPTION, SizeOf(ENABLE_CAN_OPTION));
  78.     if Err <> 0 then
  79.     begin
  80.       if Err = ESysENOPROTOOPT then
  81.         WriteLn('CAN FD Protocol not available. Try newer kernel');
  82.       perror('SetSockopt');
  83.       Exit;
  84.     end;
  85.  
  86.     if CanWrite(CanHandle, CanFDFrame) <> SizeOf(CanFDFrame) then
  87.     begin
  88.       perror('Write');
  89.       Exit;
  90.     end;
  91.  
  92.     if CanClose(CanHandle) < 0 then
  93.     begin
  94.       perror('Close');
  95.       Exit;
  96.     end;
  97.  
  98.   except
  99.     on e: Exception do
  100.       WriteLn(e.Message);
  101.   end;
  102. end.
  103.  

Code: Pascal  [Select][+][-]
  1. program hlcanfdreceive; // higher level pascalized version of canfdreceive demo
  2.  
  3. {$mode delphi} {$H+}
  4.  
  5. uses
  6.   cthreads, sysutils, sockets, baseunix, can, can.hl, can.raw;
  7.  
  8. procedure perror(const S : string);
  9. begin
  10.   WriteLn(S, ', SocketError = ', SocketError);
  11. end;
  12.  
  13. var
  14.   i, BytesNo:   byte;
  15.   Err:          integer;
  16.   CanHandle:    TCanHandle;
  17.   CanAddr:      TCanSockAddr;
  18.   CanInterface: TCanIfreq;
  19.   CanFDFrame:   TCanFDFrame;
  20. begin
  21.   try
  22.     Writeln('CAN FD Sockets Receive Demo');
  23.     CanHandle := CanSocket(SOCK_RAW, CAN_RAW);
  24.     if CanHandle < 0 then
  25.     begin
  26.       perror('Socket');
  27.       Exit;
  28.     end;
  29.  
  30.     CanInterface.Name := 'vcan0' + #0;
  31.     if CanIOCtl(CanHandle, SIOCGIFINDEX, CanInterface) < 0 then
  32.     begin
  33.       perror('IOctl');
  34.       Exit;
  35.     end;
  36.  
  37.     CanAddr.Clear;
  38.     CanAddr.CanFamily  := AF_CAN;
  39.     CanAddr.CanIfIndex := CanInterface.IfIndex;
  40.  
  41.     if CanBind(CanHandle, CanAddr) < 0 then
  42.     begin
  43.       perror('Bind');
  44.       Exit;
  45.     end;
  46.  
  47.     Err := CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, ENABLE_CAN_OPTION, SizeOf(ENABLE_CAN_OPTION));
  48.     if Err <> 0 then
  49.     begin
  50.       if Err = ESysENOPROTOOPT then
  51.         WriteLn('CAN FD Protocol not available. Try newer kernel.');
  52.       perror('SetSockopt');
  53.       Exit;
  54.     end;
  55.  
  56.     BytesNo := CanRead(CanHandle, CanFDFrame);
  57.     if BytesNo < 0 then
  58.     begin
  59.       perror('Read');
  60.       Exit;
  61.     end;
  62.  
  63.     if BytesNo = CANFD_MTU then    // test CAN FD with 'cansend vcan0 123##1223344556677889900'
  64.       WriteLn('CAN FD frame received with length ', IntToStr(CanFDFrame.Len))
  65.     else if BytesNo = CAN_MTU then // test legacy CAN with 'cansend vcan0 456#DEADBEEF'
  66.       WriteLn('CAN legacy frame received with length ', IntToStr(CanFDFrame.Len))
  67.     else
  68.       WriteLn('Invalid CAN(FD) frame received');
  69.  
  70.     Write(format('0x%03X [%d] ', [CanFDFrame.ID.Value, CanFDFrame.Len]));
  71.     for i := 0 to CanFDFrame.Len - 1 do
  72.       Write(Format('%02.2X ', [CanFDFrame.Data[i]]));
  73.     WriteLn('');
  74.  
  75.     if CanClose(CanHandle) < 0 then
  76.     begin
  77.       perror('Close');
  78.       Exit;
  79.     end;
  80.  
  81.   except
  82.     on e: Exception do
  83.       WriteLn(e.Message);
  84.   end;
  85. end.
  86.  

Hopefully, J1939 examples are next.

Remember, this is all still a playground and things may change until I include SocketCAN support into FP trunk.
Title: Re: CAN-BUS SocketCAN
Post by: avra on April 16, 2021, 02:20:52 pm
I've been thinking about creating some unique CAN tools. There are so many tools for sniffing, dumping and hacking your car CAN communication, but very few touch showing CAN error message details. The ones which do, show just a few selected messages, and there is none that shows all CAN error messages with their finest details in human readable form. So, I have created hlcanerrdump. Quite a unique tool created with FreePascal. Enjoy!

Code: Pascal  [Select][+][-]
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //                                                                                                //
  3. //  hlcanerrdump utility to display SocketCAN error messages, by Zeljko Avramovic (c) 2021        //
  4. //                                                                                                //
  5. //  Dual license:                                                                                 //
  6. //  1. FPC modified LGPL (chosen for compatibility with FreePascal and Lazarus)                   //
  7. //  2. BSD3              (chosen for compatibility with everything else)                          //
  8. //                                                                                                //
  9. //  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:                    //
  10. //  sudo modprobe vcan                                                                            //
  11. //  sudo ip link add dev vcan0 type vcan                                                          //
  12. //  sudo ip link set vcan0 mtu 72              # needed for CAN FD                                //
  13. //  sudo ip link set vcan0 up                                                                     //
  14. //                                                                                                //
  15. //  To simulate error messages use hlcanerrsim utility like this:                                 //
  16. //  ./hlcanerrsim LostArbitrationBit=09 TX BusOff Data7=AA Data6=BB                               //
  17. //                                                                                                //
  18. //  That should show in hlcanerrdump utility as:                                                  //
  19. //  0x04A [8] 16 00 80 00 00 00 BB AA  ERR=LostArbitrationBit09,BusOff,Prot(Type(TX),Loc(Unspec)) //
  20. //                                                                                                //
  21. //  Alternatively, you could use candump from can-utils to check error messages like this:        //
  22. //  candump -s -c -c -x -a any,0~0,#FFFFFFFF                                                      //
  23. //                                                                                                //
  24. ////////////////////////////////////////////////////////////////////////////////////////////////////
  25.  
  26. program hlcanerrdump; // dump CAN error messages
  27.  
  28. {$mode delphi} {$H+}
  29.  
  30. uses
  31.   classes, sysutils, strutils, sockets, baseunix, can, can.hl, can.raw, can.error, crt;
  32.  
  33. procedure perror(const S : string);
  34. begin
  35.   WriteLn(S, ', SocketError = ', SocketError);
  36. end;
  37.  
  38. var
  39.   i, BytesNo:   integer;
  40.   CanHandle:    TCanHandle;
  41.   CanAddress:   TCanSockAddress;
  42.   CanInterface: TCanIFreq;
  43.   CanFrame:     TCanFrame;
  44.   CanMask:      TCanErrMask;
  45.   CanFilter:    TCanFilter;
  46.   SockOpt:      cint;
  47.   ErrFlagStr:   string;
  48.   Errors:       TStringList;
  49. begin
  50.   try
  51.     try
  52.       WriteLn('CAN Sockets Error Messages Dump. Waiting for errors...');
  53.       Errors    := TStringList.Create;
  54.       CanHandle := CanSocket(SOCK_RAW, CAN_RAW);
  55.       if CanHandle < 0 then
  56.       begin
  57.         perror('Socket');
  58.         Exit;
  59.       end;
  60.  
  61.       CanInterface.Name := 'vcan0';
  62.       if CanIOCtl(CanHandle, SIOCGIFINDEX, CanInterface) < 0 then
  63.       begin
  64.         perror('IOctl');
  65.         Exit;
  66.       end;
  67.  
  68.       CanAddress.Clear;
  69.       CanAddress.CanFamily  := AF_CAN;
  70.       CanAddress.CanIfIndex := CanInterface.IfIndex;
  71.  
  72.       if CanBind(CanHandle, CanAddress) < 0 then
  73.       begin
  74.         perror('Bind');
  75.         Exit;
  76.       end;
  77.  
  78.       CanFilter.ID.InverseFilter              := true; // no normal CAN frames
  79.       CanFilter.Mask.Full                     := 0;    // inverting nothing gives us everything
  80.       // CanFilter.Mask.Error.LostArbitration := true; // you might want to exclude arbitration errors
  81.       CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_FILTER, CanFilter, SizeOf(CanFilter));
  82.  
  83.       CanMask.ERR := true;                // only error frames
  84.       CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, CanMask, SizeOf(CanMask));
  85.  
  86.       SockOpt := CanFcntl(CanHandle, F_GETFL);                        // get socket options
  87.       if SockOpt < 0 then
  88.       begin
  89.         perror('CanFcntl: Error = ' + CanGetErrNo.ToString);
  90.         Exit;
  91.       end;
  92.  
  93.       if CanFcntl(CanHandle, F_SETFL, SockOpt or O_NONBLOCK) < 0 then // set nonblock socket (to be able to exit after key press)
  94.       begin
  95.         perror('NonBlock: Error = ' + CanGetErrNo.ToString);
  96.         Exit;
  97.       end;
  98.  
  99.       repeat
  100.         BytesNo := CanRead(CanHandle, CanFrame);
  101.         if BytesNo = SizeOf(CanFrame) then
  102.         begin
  103.           Write(Format(IfThen(CanFrame.ID.EFF, '0x%08.8X [%d] ', '     0x%03.3X [%d] '), [CanFrame.ID.Value, CanFrame.DLC])); // extended or standard frame
  104.           for i := 0 to CanFrame.DLC - 1 do
  105.             Write(Format('%02.2X ', [CanFrame.Data[i]]));
  106.  
  107.           Errors.Clear;
  108.           if CanFrame.ID.Mask.Error.TxTimeout       then Errors.Add('TxTimeout');
  109.           if CanFrame.ID.Mask.Error.LostArbitration then Errors.Add('LostArbitrationBit' + Format('%.*d', [2, CanFrame.DataError.LostArbitration.BitNumber]));
  110.           if CanFrame.ID.Mask.Error.NoAck           then Errors.Add('NoAck');
  111.           if CanFrame.ID.Mask.Error.BusOff          then Errors.Add('BusOff');
  112.           if CanFrame.ID.Mask.Error.BusError        then Errors.Add('BusError');
  113.           if CanFrame.ID.Mask.Error.Restarted       then Errors.Add('Restarted');
  114.           if CanFrame.ID.Mask.Error.Controller      then
  115.           begin
  116.             ErrFlagStr := '';
  117.             if CanFrame.DataError.Controller.OverflowRX then ErrFlagStr := ErrFlagStr + 'OverflowRX,';
  118.             if CanFrame.DataError.Controller.OverflowTX then ErrFlagStr := ErrFlagStr + 'OverflowTX,';
  119.             if CanFrame.DataError.Controller.WarningRX  then ErrFlagStr := ErrFlagStr + 'WarningRX,';
  120.             if CanFrame.DataError.Controller.WarningTX  then ErrFlagStr := ErrFlagStr + 'WarningTX,';
  121.             if CanFrame.DataError.Controller.PassiveRX  then ErrFlagStr := ErrFlagStr + 'PassiveRX,';
  122.             if CanFrame.DataError.Controller.PassiveTX  then ErrFlagStr := ErrFlagStr + 'PassiveTX,';
  123.             if CanFrame.DataError.Controller.Active     then ErrFlagStr := ErrFlagStr + 'Active';
  124.             if ErrFlagStr.EndsWith(',') then SetLength(ErrFlagStr, ErrFlagStr.Length - 1);
  125.             Errors.Add('Ctrl(' + ErrFlagStr + ')');
  126.           end;
  127.           if CanFrame.ID.Mask.Error.Protocol        then
  128.           begin
  129.             ErrFlagStr := 'Type(';
  130.             if CanFrame.DataError.Protocol.Category.SingleBit          then ErrFlagStr := ErrFlagStr + 'SingleBit,';
  131.             if CanFrame.DataError.Protocol.Category.FrameFormat        then ErrFlagStr := ErrFlagStr + 'FrameFormat,';
  132.             if CanFrame.DataError.Protocol.Category.BitStuffing        then ErrFlagStr := ErrFlagStr + 'BitStuffing,';
  133.             if CanFrame.DataError.Protocol.Category.Bit0               then ErrFlagStr := ErrFlagStr + 'Bit0,';
  134.             if CanFrame.DataError.Protocol.Category.Bit1               then ErrFlagStr := ErrFlagStr + 'Bit1,';
  135.             if CanFrame.DataError.Protocol.Category.BusOverload        then ErrFlagStr := ErrFlagStr + 'BusOverload,';
  136.             if CanFrame.DataError.Protocol.Category.ActiveAnnouncement then ErrFlagStr := ErrFlagStr + 'ActiveAnnouncement,';
  137.             if CanFrame.DataError.Protocol.Category.TX                 then ErrFlagStr := ErrFlagStr + 'TX';
  138.             if ErrFlagStr.EndsWith(',') then SetLength(ErrFlagStr, ErrFlagStr.Length - 1);
  139.             ErrFlagStr := ErrFlagStr + '),Loc(';
  140.             case CanFrame.DataError.Protocol.Location of
  141.               CAN_ERR_PROT_LOC_UNSPEC:     ErrFlagStr := ErrFlagStr + 'Unspec';  // zero
  142.               CAN_ERR_PROT_LOC_SOF:        ErrFlagStr := ErrFlagStr + 'SOF';     // start of frame
  143.               CAN_ERR_PROT_LOC_ID28_21:    ErrFlagStr := ErrFlagStr + 'ID28_21'; // ID bits 28 - 21 (SFF: 10 - 3)
  144.               CAN_ERR_PROT_LOC_ID20_18:    ErrFlagStr := ErrFlagStr + 'ID20_18'; // ID bits 20 - 18 (SFF: 2 - 0 )
  145.               CAN_ERR_PROT_LOC_SRTR:       ErrFlagStr := ErrFlagStr + 'SRTR';    // substitute RTR (SFF: RTR)
  146.               CAN_ERR_PROT_LOC_IDE:        ErrFlagStr := ErrFlagStr + 'IDE';     // identifier extension
  147.               CAN_ERR_PROT_LOC_ID17_13:    ErrFlagStr := ErrFlagStr + 'ID17_13'; // ID bits 17-13
  148.               CAN_ERR_PROT_LOC_ID12_05:    ErrFlagStr := ErrFlagStr + 'ID12_05'; // ID bits 12-5
  149.               CAN_ERR_PROT_LOC_ID04_00:    ErrFlagStr := ErrFlagStr + 'ID04_00'; // ID bits 4-0
  150.               CAN_ERR_PROT_LOC_RTR:        ErrFlagStr := ErrFlagStr + 'RTR';     // RTR
  151.               CAN_ERR_PROT_LOC_RES1:       ErrFlagStr := ErrFlagStr + 'RES1';    // reserved bit 1
  152.               CAN_ERR_PROT_LOC_RES0:       ErrFlagStr := ErrFlagStr + 'RES0';    // reserved bit 0
  153.               CAN_ERR_PROT_LOC_DLC:        ErrFlagStr := ErrFlagStr + 'DLC';     // data length code
  154.               CAN_ERR_PROT_LOC_DATA:       ErrFlagStr := ErrFlagStr + 'DATA';    // data section
  155.               CAN_ERR_PROT_LOC_CRC_SEQ:    ErrFlagStr := ErrFlagStr + 'CRC_SEQ'; // CRC sequence
  156.               CAN_ERR_PROT_LOC_CRC_DEL:    ErrFlagStr := ErrFlagStr + 'CRC_DEL'; // CRC delimiter
  157.               CAN_ERR_PROT_LOC_ACK:        ErrFlagStr := ErrFlagStr + 'ACK';     // ACK slot
  158.               CAN_ERR_PROT_LOC_ACK_DEL:    ErrFlagStr := ErrFlagStr + 'ACK_DEL'; // ACK delimiter
  159.               CAN_ERR_PROT_LOC_EOF:        ErrFlagStr := ErrFlagStr + 'EOF';     // end of frame
  160.               CAN_ERR_PROT_LOC_INTERM:     ErrFlagStr := ErrFlagStr + 'INTERM';  // intermission
  161.             otherwise
  162.               ErrFlagStr := ErrFlagStr + 'Unknown';   // protocol location not recognized
  163.             end;
  164.             Errors.Add('Prot(' + ErrFlagStr + '))');
  165.           end;
  166.           if CanFrame.ID.Mask.Error.Transceiver then
  167.           begin
  168.             ErrFlagStr := '';
  169.             case CanFrame.DataError.Transceiver of
  170.               CAN_ERR_TRX_UNSPEC:              ErrFlagStr := ErrFlagStr + 'Unspec';            // $00, 0000 0000
  171.               CAN_ERR_TRX_CANH_NO_WIRE:        ErrFlagStr := ErrFlagStr + 'CanHiNoWire';       // $04, 0000 0100
  172.               CAN_ERR_TRX_CANH_SHORT_TO_BAT:   ErrFlagStr := ErrFlagStr + 'CanHiShortToBAT';   // $05, 0000 0101
  173.               CAN_ERR_TRX_CANH_SHORT_TO_VCC:   ErrFlagStr := ErrFlagStr + 'CanHiShortToVCC';   // $06, 0000 0110
  174.               CAN_ERR_TRX_CANH_SHORT_TO_GND:   ErrFlagStr := ErrFlagStr + 'CanHiShortToGND';   // $07, 0000 0111
  175.               CAN_ERR_TRX_CANL_NO_WIRE:        ErrFlagStr := ErrFlagStr + 'CanLoNoWire';       // $40, 0100 0000
  176.               CAN_ERR_TRX_CANL_SHORT_TO_BAT:   ErrFlagStr := ErrFlagStr + 'CanLoShortToBAT';   // $50, 0101 0000
  177.               CAN_ERR_TRX_CANL_SHORT_TO_VCC:   ErrFlagStr := ErrFlagStr + 'CanLoShortToVCC';   // $60, 0110 0000
  178.               CAN_ERR_TRX_CANL_SHORT_TO_GND:   ErrFlagStr := ErrFlagStr + 'CanLoShortToGND';   // $70, 0111 0000
  179.               CAN_ERR_TRX_CANL_SHORT_TO_CANH:  ErrFlagStr := ErrFlagStr + 'CanLoShortToCanHi'; // $80, 1000 0000
  180.             otherwise
  181.               ErrFlagStr := ErrFlagStr + 'Unknown'; // transceiver error not recognized
  182.             end;
  183.             Errors.Add('Trans(' + ErrFlagStr + ')');
  184.           end;
  185.  
  186.           if Errors.Count > 0 then
  187.             Write(' ERR=');
  188.  
  189.           for i := 0 to Errors.Count - 1 do
  190.           begin
  191.             Write(Errors.Strings[i]);
  192.             if i <> (Errors.Count - 1) then
  193.               Write(',');
  194.           end;
  195.           WriteLn('');
  196.         end;
  197.         Sleep(5);
  198.       until KeyPressed;
  199.  
  200.       if CanClose(CanHandle) < 0 then
  201.       begin
  202.         perror('Close');
  203.         Exit;
  204.       end;
  205.     except
  206.       on e: Exception do
  207.         WriteLn(e.Message);
  208.     end;
  209.   finally
  210.     Errors.Free;
  211.   end;
  212. end.
  213.  

Beta version attached here is tied to vcan0. Before I put it into FPC trunk I will make it accept CAN interface as a parameter.
Title: Re: CAN-BUS SocketCAN
Post by: avra on April 16, 2021, 02:29:25 pm
I have searched all the net and I could not find a single open source tool for simulating CAN error messages. None. Zero. So, I have created hlcanerrsim. A unique tool created with FreePascal. Enjoy!

UPDATE: Source exceeds single message limit, so you can find it in can.zip archive in previous message.
Title: Re: CAN-BUS SocketCAN
Post by: avra on April 28, 2021, 10:33:07 am
hlcanerrdump now accepts CAN interface as first parameter and CAN filter for error messages as further parameters. Especially useful example is to use IgnoreNoAck parameter for filtering NoAck messages.
Code: [Select]
avra@vm-debian:/mnt/e/can$ ./hlcanerrdump
CAN Sockets Error Messages Dump

Usage: hlcanerrdump <CAN interface> [options]

CAN interface:                   ( CAN interface is case sensitive )
    can1                         ( or can2, can3 or virtual ones like vcan0, vcan1...

Options:                         ( options are not case sensitive )
                                 ( ERROR CLASS (MASK) IN CAN ID: )
    IgnoreTxTimeout              ( filter TX timeout by netdevice driver error messages )
    IgnoreLostArbitration        ( filter lost arbitration error messages )
    IgnoreController             ( filter controller problem error messages )
    IgnoreProtocol               ( filter protocol error messages )
    IgnoreTransceiver            ( filter transceiver status error messages )
    IgnoreNoAck                  ( filter no ACK on transmission error messages )
    IgnoreBusOff                 ( filter bus off error messages )
    IgnoreBusError               ( filter bus error messages )
    IgnoreRestarted              ( filter controller restarted messages )
                                 ( DEBUG HELPERS: )
    ShowFilterAndMaskBits        ( display all filtering bits )

Examples:

    ./hlcanerrdump can1
    ( dump all CAN error messages from CAN interface can1 )

    ./hlcanerrdump vcan0 IgnoreNoAck IgnoreBusOff
    ( dump all CAN error messages from virtual CAN interface vcan0 except NoACk and BusOff)

hlcanerrsim now accepts CAN interface as first parameter. It still accepts error message types as parameters for forming simulated error messages.
Code: [Select]
avra@vm-debian:/mnt/e/can$ ./hlcanerrsim
CAN Sockets Error Messages Simulator

Usage: hlcanerrsim <CAN interface> [options]

CAN interface:                   ( CAN interface is case sensitive )
    can1                         ( or can2, can3 or virtual ones like vcan0, vcan1...

Options:                         ( options are not case sensitive )
                                 ( ERROR CLASS (MASK) IN CAN ID: )
    TxTimeout                    ( TX timeout by netdevice driver )
    NoAck                        ( received no ACK on transmission )
    BusOff                       ( bus off )
    BusError                     ( bus error, may flood! )
    Restarted                    ( controller restarted )
                                 ( ARBITRATIONLOST IN CAN ID + BIT NUMBER IN DATA[0]: )
    LostArbitrationBit=<00..29>  ( decimal bit number in bitstream )
                                 ( CONTROLLER IN CAN ID + ERROR STATUS IN DATA[1]: )
    OverflowRX                   ( RX buffer overflow )
    OverflowTX                   ( TX buffer overflow )
    WarningRX                    ( reached warning level for RX errors )
    WarningTX                    ( reached warning level for TX errors )
    PassiveRX                    ( reached error passive status RX, errors > 127 )
    PassiveTX                    ( reached error passive status TX, errors > 127 )
    Active                       ( recovered to error active state )
                                 ( PROTOCOL ERROR IN CAN ID + TYPE IN DATA[2]: )
    SingleBit                    ( single bit error )
    FrameFormat                  ( frame format error )
    BitStuffing                  ( bit stuffing error )
    Bit0                         ( unable to send dominant bit )
    Bit1                         ( unable to send recessive bit )
    BusOverload                  ( bus overload )
    ActiveAnnouncement           ( active error announcement )
    TX                           ( error occurred on transmission )
                                 ( PROTOCOL ERROR IN CAN ID + LOCATION IN DATA[3]: )
    SOF                          ( start of frame )
    ID28_21                      ( ID bits 21..28, SFF: 3..10 )
    ID20_18                      ( ID bits 18..20, SFF: 0..2 )
    SRTR                         ( substitute RTR, SFF: RTR )
    IDE                          ( identifier extension )
    ID17_13                      ( ID bits 13..17 )
    ID12_05                      ( ID bits 5..12 )
    ID04_00                      ( ID bits 0..4 )
    RTR                          ( RTR )
    RES1                         ( reserved bit 1 )
    RES0                         ( reserved bit 0 )
    DLC                          ( data length code )
    DATA                         ( data section )
    CRC_SEQ                      ( CRC sequence )
    CRC_DEL                      ( CRC delimiter )
    ACK                          ( ACK slot )
    ACK_DEL                      ( ACK delimiter )
    EOF                          ( end of frame )
    INTERM                       ( intermission )
                                 ( TRANSCEIVER ERROR IN CAN ID + STATUS IN DATA[4]: )
                                 ( CANH CANL )
    TransUnspec                  ( 0000 0000 )
    CanHiNoWire                  ( 0000 0100 )
    CanHiShortToBAT              ( 0000 0101 )
    CanHiShortToVCC              ( 0000 0110 )
    CanHiShortToGND              ( 0000 0111 )
    CanLoNoWire                  ( 0100 0000 )
    CanLoShortToBAT              ( 0101 0000 )
    CanLoShortToVCC              ( 0110 0000 )
    CanLoShortToGND              ( 0111 0000 )
    CanLoShortToCanHi            ( 1000 0000 )
                                 ( CUSTOM BYTE TO DATA[0..7]: )
    Data<0..7>=<00..FF>          ( write hex number to one of 8 payload bytes )

Examples:

    ./hlcanerrsim can1 LostArbitrationBit=09 TX BusOff Data7=AA Data6=BB
    ( can1: 9th arb. bit lost, transmission, bus off, controller specific info in Data[6] and Data[7] )

    ./hlcanerrsim vcan0 NoAck TxTimeout Active
    ( vcan0: received no ACK on transmission, driver timeout, protocol type active error announcement )

    ./hlcanerrsim vcan0 BusError CanHiNoWire Restarted INTERM
    ( vcan0: bus error, lost CANH wiring, controller restarted, protocol location intermission )
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on May 15, 2021, 02:40:45 pm
Hello Avra,

is there already a way to perform the actions which the 'ip' command does in pascal?

like "sudo ip link set can0 type can bitrate 125000 sample-point 0.875"
and "sudo ip link set can0 up"
and "sudo ip link set can0 down"?

I got the Inno-Maker CAN RS485 HAT to work with my test gear from PEAK and don't want to do work which is already done.....

Cheers,

Thomas
Title: Re: CAN-BUS SocketCAN
Post by: avra on May 16, 2021, 02:35:31 am
is there already a way to perform the actions which the 'ip' command does in pascal?

like "sudo ip link set can0 type can bitrate 125000 sample-point 0.875"
and "sudo ip link set can0 up"
and "sudo ip link set can0 down"?
Calling ip command from your pascal application and parsing the output would be the simplest solution. If you are not satisfied with that, you would have to use NETLINK sockets, since that is what ip command uses. Alternatively, you could use libsocketcan (a wrapper around netlink sockets for CAN) or libnl, but you would need to make your own wrapper.

https://lalten.github.io/libsocketcan/Documentation/html/group__extern.html#gaa01e52bcb6f4b873da7ce32cab38332d
https://github.com/jmore-reachtech/can-utils/blob/master/src/canconfig.c
https://www.infradead.org/~tgr/libnl/doc/api/group__can.html#gab6de57cdb6c42d48df432636e266700b
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on May 16, 2021, 10:45:20 am
Thanks.

Well, it seems that due to the 'C' in CAN most code is written in C >:(
Title: Re: CAN-BUS SocketCAN wrapper for libsocketcan
Post by: ThomasK on May 16, 2021, 03:03:41 pm
Hi,

I installed the library and am trying to call it.
Code: Pascal  [Select][+][-]
  1. unit LibSockCAN;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. //lib/arm-linux-gnueabihf/libsocketcan.so
  8. //libsocketcan.h
  9.  
  10. {$linklib c}
  11. {$linklib libsocketcan}
  12.  
  13. //function can_do_restart                   : longint; cdecl; external;
  14. function can_do_stop(const pchar)           : longint; cdecl; external;
  15. function can_do_start(const pchar)          : longint; cdecl; external;
  16. //function can_set_bitrate                  : longint; cdecl; external;
  17. //function can_set_bitrate_samplepoint      : longint; cdecl; external;
  18.  
  19. //uses
  20.  
  21. implementation
  22.  
  23.  
  24. end.
  25.  

The call is done as reaction to a Button:

Code: Pascal  [Select][+][-]
  1.  
  2. procedure TForm1.B_StartCan0Click(Sender: TObject);
  3. var
  4.   ifr_name : PChar;
  5.   myresult : integer;
  6. begin
  7.   ifr_name:= 'can0';
  8.   myresult:=can_do_start(ifr_name);
  9.   Label_StartResult.caption:=InttoStr(myresult);
  10. end;

No errors during compilation, but return code is -1.
Where is my error?

btw. the CAN-UTILS and the ip commands work
Title: Re: CAN-BUS SocketCAN
Post by: avra on May 16, 2021, 03:32:39 pm
Thanks.
You're welcome.  :)

it seems that due to the 'C' in CAN most code is written in C >:(
Well, Linux kernel 2.6.25 with first SocketCAN implementation was donated by Volkswagen in 2008, so besides much wider user base C also has about 13 years advantage - although we already have some unique and pretty useful error dump and error simulation tools. With FreePascal wrapper all SocketCAN code can be easily transferred with almost 1:1 translation. Just take a look at demos which do not start with hl prefix in their name. They are in Pascal but they look almost identical to their C roots. If you take a look at canconfig.c that I mentioned in previous post, you will see that besides SocketCAN (that is already part of the kernel) only libsocketcan is used additionally. So, if you create a libsocketcan wrapper then it should not be too hard to do an almost 1:1 translation, or extract just parts which you need for CAN setup in code. If that is too much, then you can always run ip command in a process and parse the output.

According to my free time, plan is to support J1939 (trucks, buses, heavy machinery, marine, military and agriculture), OBD-II (cars) and DBC file parsing (for automatic conversion of CAN messages to human readable form). If in the mean time I get some CANopen (plc, industrial automation, embedded) freelance work then I might consider supporting CANopen as well. For now, there is no plan to support libsocketcan.

UPDATE:

No errors during compilation, but return code is -1.
Where is my error?
I am not familiar with internals of libsocketcan so I can not tell. If I had to guess then I would first try to replace
Code: Pascal  [Select][+][-]
  1. ifr_name:= 'can0';
with
Code: Pascal  [Select][+][-]
  1. ifr_name:= 'can0' + #0;
If that doesn't work, then I would try to create the most simplest code in C which does the job, and then try to convert that to FreePascal with already mentioned 1:1 conversion method. That would eliminate a lot of unknowns of what works and what doesn't.

Ah, yes... You should also try to start your app as root, and check if can0 is not already started.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on May 16, 2021, 04:25:03 pm
Adding the #0 to the devince name changed nothing.

Title: Re: CAN-BUS SocketCAN
Post by: dseligo on May 16, 2021, 11:40:48 pm
According to my free time, plan is to support J1939 (trucks, buses, heavy machinery, marine, military and agriculture), OBD-II (cars) and DBC file parsing (for automatic conversion of CAN messages to human readable form). If in the mean time I get some CANopen (plc, industrial automation, embedded) freelance work then I might consider supporting CANopen as well. For now, there is no plan to support libsocketcan.

What device(s) do you use to interface with CAN bus?
Title: Re: CAN-BUS SocketCAN
Post by: avra on May 17, 2021, 12:44:51 am
What device(s) do you use to interface with CAN bus?
Pi, PocketBeagle and Arduino (AVR, STM32, ESP32)
Title: Re: CAN-BUS SocketCAN
Post by: dseligo on May 17, 2021, 02:54:14 pm
What device(s) do you use to interface with CAN bus?
Pi, PocketBeagle and Arduino (AVR, STM32, ESP32)

Does Arduino (AVR) has to be some specific type (e.g. AT90CAN128) or any will do?
What do you use between 'controller' and CAN bus?
Title: Re: CAN-BUS SocketCAN
Post by: Blade on May 17, 2021, 03:23:15 pm
This thread mentions C to Pascal translation several times.  I'm wondering if this is not also an opportunity to test out some of the automatic C to Pascal or C to Delphi translators.  Probably wouldn't be as good as being done manually by someone very fluent in both, but perhaps the automatic software could be useful in various cases.
Title: Re: CAN-BUS SocketCAN
Post by: avra on May 18, 2021, 12:58:09 am
What device(s) do you use to interface with CAN bus?
Pi, PocketBeagle and Arduino (AVR, STM32, ESP32)

Does Arduino (AVR) has to be some specific type (e.g. AT90CAN128) or any will do?
What do you use between 'controller' and CAN bus?

You can use some CAN based AVR as AT90CAN128 with just a TJA1050 or similar CAN transceiver, but it is more common to use simpler AVR (like ATMEGA328P) with MCP2515 and some CAN transceiver chip as MCP is much better supported. Using MCP2515 also means that besides using CAN directly from AVR, you can also use it from Linux as Lawicel/SLCAN based CAN gateway for SocketCAN with something like this: https://github.com/latonita/arduino-canbus-monitor, https://github.com/autowp/can-usb or https://github.com/mintynet/nano-can. You are limited with serial to USB chip speed on your Arduino so with speeds of 500kbps and higher expect dropped frames (and even with 250kbps if your CAN bus load is high). Although MCP2515 is the most supported CAN 2.0B chip on the planet, if you need CAN FD then it will not be enough and you will have to use MCP2518 and similar with a proper lib.

Although ESP32 is much more capable then standard AVRs, there is also a serial to USB chip so there is the same speed limit. It has internal CAN so there are libs which do not need MCP2515 to implement Lawicel/SLCAN which can be used from Linux SocketCAN. I have seen versions which use Bluetooth instead of serial to USB, but I have never tested them (https://github.com/michey/esp32_can and https://github.com/mintynet/esp32-slcan). There are also versions which support CAN FD and create a WiFi UDP tunnel to Linux SocketCAN via cannelloni protocol (https://github.com/PhilippFux/ESP32_CAN_Interface and https://github.com/epozzobon/lasagne), but I haven't tested them either.

STM32 has many microcontrollers (like STM32F103C8T6 BluePill for example) which support CAN out of the box and do not need MCP2515. They also have USB but unfortunately USB and CAN can not work at the same time, so some serial to USB must also be used. Look at https://github.com/kolyandex/CAN-to-USB-lawicel-for-stm32, https://github.com/GBert/misc/tree/master/stm32-slcan, https://github.com/geier99/STM32-CAN_CubeMX_Tests, https://github.com/darauble/lawicel-slcan, http://randomport.com/pages/usb-to-can.html and https://ucandevices.github.io.

Most of the mentioned devices can be used as very cheap Lawicel/SLCAN compatible protocol CAN gateways for Linux SocketCAN, but I personally do not use them for that. I use them as embedded devices when Linux SBC is an overkill or when long booting can not be tolerated. What is good about such Lawicel/SLCAN protocol compatible devices is that there is a lot of software for Windows that can use them, so that will be your CAN path if you are not a Linux fan. However, Linux SocketCAN path is much more powerful and standardized so unlike with Windows various software can work together using data simultaneously from the same CAN adapter.

Raspberry Pi needs a HAT with MCP2515/2517/2518. PocketBeagle and BeagleBone can also use MCP, but if you do not need CAN FD then built in CAN with some transceiver will be enough. There is no speed limit or dropped frames problem with Linux boards, so you can use SocketCAN at it's full glory.

SocketCAN also supports virtual CAN channels so you can play and learn even if you have no CAN adapter at all.

For a simple introduction to CAN, CAN FD, OBD-II, CANopen and J1939 take a look at these links:
https://www.csselectronics.com/screen/page/simple-intro-to-can-bus
https://www.csselectronics.com/screen/page/can-fd-flexible-data-rate-intro
https://www.csselectronics.com/screen/page/simple-intro-obd2-explained
https://www.csselectronics.com/screen/page/simple-intro-j1939-explained
https://www.csselectronics.com/screen/page/canopen-tutorial-simple-intro

Here is also a little old but still relevant Car Hacker's Handbook:
http://www.opengarages.org/handbook/

This thread mentions C to Pascal translation several times.  I'm wondering if this is not also an opportunity to test out some of the automatic C to Pascal or C to Delphi translators.  Probably wouldn't be as good as being done manually by someone very fluent in both, but perhaps the automatic software could be useful in various cases.
I use these all the time. They are good, but not perfect and I usually have to combine them. They can save you a lot of time, but can not save you from manual work completelly.
https://forum.lazarus.freepascal.org/index.php/topic,12763.msg66330.html#msg66330
https://forum.lazarus.freepascal.org/index.php/topic,53389.msg395085.html#msg395085
https://wiki.freepascal.org/C_to_Pascal
Title: Re: CAN-BUS SocketCAN
Post by: dseligo on May 18, 2021, 04:38:36 am
Thanks  :D

I will need some time to process this  :)
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on May 19, 2021, 01:24:21 pm
For now, there is no plan to support libsocketcan.

I see.

Anyway for my point of view it is better if an application takes care itself of all relevant initialisation and parameterisation tasks.
At least I am used to that working with an automation system for automotive test beds. Customers always complained to if they need more than one program to get an interface working.

I also found a fork of can-utils containing canconfig.c with a more recent date than 2009. 8). I will try to get short snippets to work, as you proposed and migrate then.

I tested my short app by starting it with admin rights, it failed too. Didn't find the file, it said in the console.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on May 30, 2021, 10:07:21 pm
Have you intentions to implement this:

Code: C  [Select][+][-]
  1. num_events = epoll_wait(fd_epoll, events_pending, currmax, timeout_ms);
  2.                 if (num_events == -1) {
  3.                         if (errno != EINTR)
  4.                                 running = 0;
  5.                         continue;
  6.                 }
  7.  

This would allow a read process not to wait until data is available.

I found that in the recent can-utils.
Title: Re: CAN-BUS SocketCAN
Post by: avra on May 31, 2021, 01:30:08 am
I found that in the recent can-utils.
Not everything is related to CAN. If you take a look at candump.c from can-utils you will see that it includes sys/epoll.h which is a standard linux header for which there is a man page https://linux.die.net/man/2/epoll_wait. As such, you could also search your fpc directory and find that translation for epoll_wait can already be found in your existing \fpcsrc\rtl\linux\linux.pp, so you already have everything needed.

You need to improve your source search fu a little, if you want the source to be with you.  :D ;) :D
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on May 31, 2021, 02:46:54 pm
I know that this is not only CAN related.
But this code snippet is from the latest https://github.com/linux-can/can-utils (https://github.com/linux-can/can-utils) candump.c.

I try to get this to work.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on June 03, 2021, 01:20:16 pm
@avra, I have put yor sent & transmit code together with the epoll routines from the latest candump.c into a GUI app for Lazarus.

It works principally, I can send, receive, see that there is data after calling epoll_wait.

But the num_events is always either 0 or 1 even if more than 1 message was sent to the port.
Code: Pascal  [Select][+][-]
  1. unit mainunit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, sockets, baseunix, can, linux;
  9.  
  10. type
  11.  
  12.   { TFCANTest }
  13.  
  14.   TFCANTest = class(TForm)
  15.     bInitcan0: TButton;
  16.     bSendData: TButton;
  17.     bReceiveData: TButton;
  18.     BClosecan0: TButton;
  19.     bEpollCreate: TButton;
  20.     bEpollQuery: TButton;
  21.     mLog: TMemo;
  22.     mLogTest: TMemo;
  23.     STnum_events: TStaticText;
  24.     STevents_pending: TStaticText;
  25.     StaticText3: TStaticText;
  26.     StaticText4: TStaticText;
  27.     procedure BClosecan0Click(Sender: TObject);
  28.     procedure bEpollCreateClick(Sender: TObject);
  29.     procedure bEpollQueryClick(Sender: TObject);
  30.     procedure bInitcan0Click(Sender: TObject);
  31.     procedure bReceiveDataClick(Sender: TObject);
  32.     procedure bSendDataClick(Sender: TObject);
  33.     procedure FormCreate(Sender: TObject);
  34.  
  35.   private
  36.     procedure Addmessages(mess2show: string);
  37.  
  38.   public
  39.  
  40.   end;
  41.  
  42.  
  43. const
  44.   AF_CAN = 29;
  45.   PF_CAN = 29;
  46.   CANDevice ='can0';
  47. type
  48. if_info = record
  49.   s            : integer;
  50.   cmdlinename  : ^byte;
  51.   dropcnt,
  52.   last_dropcnt : uint32;
  53. end;
  54. {
  55. type
  56.   EPoll_Data = record
  57.     case integer of
  58.       0: (ptr: pointer);
  59.       1: (fd: cint);
  60.       2: (u32: cuint);
  61.       3: (u64: cuint64);
  62.   end;
  63.   TEPoll_Data =  Epoll_Data;
  64.   PEPoll_Data = ^Epoll_Data;
  65.   EPoll_Event = record
  66.     Events: cuint32;
  67.     Data  : TEpoll_Data;
  68.   end;
  69.  
  70.   TEPoll_Event =  Epoll_Event;
  71.   PEpoll_Event = ^Epoll_Event;
  72. }
  73. var
  74.   FCANTest       : TFCANTest;
  75.   sock_info      : if_info;
  76.   events_pending : EPoll_Event;
  77.   event_setup    : EPoll_Event;
  78.   Pevent_Setup   : PEPoll_Event;
  79.   PPoll_Event    : PEPoll_Event;
  80.   fd_epoll,
  81.   num_events,
  82.   currmax        : integer;
  83.   s:     cint;
  84.   addr:  sockaddr_can;
  85.   ifr:   ifreq;
  86.   frame: can_frame;
  87.   timeout_ms : integer; //* default to no timeout */
  88.  
  89. implementation
  90.  
  91. {$R *.lfm}
  92.  
  93. { TFCANTest }
  94. procedure TFCANTest.Addmessages(mess2show: string);
  95. begin
  96.   mLogtest.Lines.BeginUpdate;
  97.   mLogtest.Lines.Add(mess2show);
  98.   mLogtest.Lines.EndUpdate;
  99.   mLogtest.SelStart := Length(mLogtest.Lines.Text)-1;
  100.   mLogtest.SelLength:=0;
  101. end;
  102.  
  103. procedure TFCANTest.FormCreate(Sender: TObject);
  104. begin
  105.   currmax            :=16;                                                       // number of CAN devices
  106.   event_setup.events :=EPOLLIN;
  107.   Pevent_Setup       :=@(event_setup);
  108.   PPoll_event        :=@(events_pending);
  109.   timeout_ms         :=10;
  110.   bInitcan0.caption  :=bInitcan0.caption + ' ' + CANDevice;
  111.   bClosecan0.caption  :=bclosecan0.caption + ' ' + CANDevice;
  112. end;
  113.  
  114. procedure TFCANTest.bInitcan0Click(Sender: TObject);
  115. var
  116.   perror : string;
  117. begin
  118.   s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  119.   if s < 0 then
  120.   begin
  121.     perror:='socket creation error';
  122.     mLog.Lines.Add(perror);
  123.     Addmessages(perror);
  124.     Exit;
  125.   end else begin
  126.      mLog.Lines.Add('Socket: '+inttostr(s));
  127.      Addmessages('Socket: '+inttostr(s));
  128.   end;
  129.   strcopy(ifr.ifr_name, CANDevice);
  130.   if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  131.   begin
  132.     perror:='error IOctl';
  133.     mLog.Lines.Add(perror);
  134.     Addmessages(perror);
  135.     Exit;
  136.   end;
  137.   memset(@addr, 0, sizeof(addr));
  138.   addr.can_family  := AF_CAN;
  139.   addr.can_ifindex := ifr.ifr_ifindex;
  140.   if fpbind(s, @addr, sizeof(addr)) < 0 then // if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then
  141.   begin
  142.     perror:='error bind';
  143.     mLog.Lines.Add(perror);
  144.     Addmessages(perror);
  145.     Exit;
  146.   end;
  147. end;
  148.  
  149. procedure TFCANTest.bReceiveDataClick(Sender: TObject);
  150. var
  151.   nbytes,
  152.   i      : integer;
  153.   perror : string;
  154. begin
  155.     nbytes := fpread(s, frame, sizeof(can_frame));
  156.     if nbytes < 0 then
  157.     begin
  158.       perror:='Error during Read';
  159.       mLog.Lines.Add(perror);
  160.       Addmessages(perror);
  161.       Exit;
  162.     end;
  163.     if nbytes < sizeof(can_frame) then // paranoid check
  164.     begin
  165.       perror:='Read: Incomplete CAN frame';
  166.       mLog.Lines.Add(perror);
  167.       Addmessages(perror);
  168.       Exit;
  169.     end;
  170.     Perror:=Format('0x%03X [%d] ', [frame.can_id and CAN_SFF_MASK, frame.can_dlc]);
  171.     for i := 0 to frame.can_dlc - 1 do
  172.       Perror:=Perror + Format('%02.2X ', [frame.data[i]]);
  173.     mLog.Lines.Add(perror);
  174.     Addmessages(perror);
  175. end;
  176.  
  177. procedure TFCANTest.bSendDataClick(Sender: TObject);
  178. var
  179.   perror : string;
  180.   psizef : integer;
  181. begin
  182.   frame.can_id   := $020;    // CAN message ID
  183.   frame.can_dlc  := 8;       // payload length will be 8 bytes
  184.   frame.data[0]  := $10;
  185.   frame.data[1]  := $11;
  186.   frame.data[2]  := $12;
  187.   frame.data[3]  := $13;
  188.   frame.data[4]  := $14;
  189.   frame.data[5]  := $15;
  190.   frame.data[6]  := $16;
  191.   frame.data[7]  := $17;
  192.  
  193. psizef:= fpwrite(s, frame, sizeof(can_frame));
  194. if psizef <> sizeof(can_frame) then
  195.   begin
  196.     perror:='error write ' + InttoStr(psizef);
  197.     mLog.Lines.Add(perror);
  198.     Addmessages(perror);
  199.     Exit;
  200.   end else begin
  201.     mLog.Lines.Add(InttoStr(psizef) + ' bytes written');
  202.     Addmessages(InttoStr(psizef) + ' bytes written');
  203.   end;
  204. end;
  205.  
  206. procedure TFCANTest.BClosecan0Click(Sender: TObject);
  207. var
  208.   perror : string;
  209. begin
  210.   if fpclose(s) < 0 then
  211.     begin
  212.       perror:='error close socket ';
  213.       mLog.Lines.Add(perror);
  214.       Addmessages(perror);
  215.       Exit;
  216.     end;
  217.   if fpclose(fd_epoll) < 0 then
  218.     begin
  219.       perror:='error close epoll ';
  220.       mLog.Lines.Add(perror);
  221.       Addmessages(perror);
  222.       Exit;
  223.     end;
  224. end;
  225.  
  226. procedure TFCANTest.bEpollCreateClick(Sender: TObject);
  227. var
  228.   pepollerr : integer;
  229. begin
  230.   fd_epoll := epoll_create(1);
  231.   if fd_epoll < 0 then begin
  232.     mLog.Lines.Add('epoll create error');
  233.     Addmessages('epoll create error');
  234.     Exit;
  235.   end;
  236.   pepollerr:= epoll_ctl(fd_epoll, EPOLL_CTL_ADD, s, pevent_setup);
  237.   if pepollerr< 0 then begin
  238.     mLog.Lines.Add(IntTostr(pepollerr)+ ' epoll add to socket error');
  239.     Addmessages(IntTostr(pepollerr)+ ' epoll add to socket error');
  240.     Exit;
  241.   end;
  242. end;
  243.  
  244. procedure TFCANTest.bEpollQueryClick(Sender: TObject);
  245. begin
  246.   num_events := epoll_wait(fd_epoll, PPoll_event, currmax, timeout_ms);
  247.   STnum_events.caption:= IntToStr(num_events);
  248.   STevents_pending.caption:=IntToStr(PPoll_event^.Events);
  249. end;
  250.  
  251.  
  252. end.
  253.  

This would be sufficient, because it can prevent that the read routine gets stuck if there is nothing to read.

But the candump repeats the reads as often as num_events.... may be not, because when it is fast enough it sees only one telegram.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on June 04, 2021, 01:23:17 pm
update.

ip commands added

{$i can.ioctl.inc}
{$i can.if.inc}
{$i can.sockios.inc}   included in zip.

epoll_wait delivers a '1' if the file descriptor has an EPOLLIN event. After all data is read, this returns to 0.

btw. runs on a Raspberry Pi 4 with inno maker dual RS485 and CAN Module, both isolated.
Other CAN device is attached to a W10 laptop. (Peak USB)
Maybe I try to get the USB-CAN running with a virtual machine on the laptop.
Title: Re: CAN-BUS SocketCAN
Post by: avra on June 05, 2021, 05:19:46 pm
But the num_events is always either 0 or 1 even if more than 1 message was sent to the port.
I am in the middle of industrial plant commissioning, so I will not be able to take a look at this before next week.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on June 06, 2021, 08:48:10 am
I am in the middle of industrial plant commissioning, so I will not be able to take a look at this before next week.

Thanks.
But I think the num_events as result of epoll_wait is not increased with number of events per input, but with number of inputs having an event.

If only one input is polled it can simply be seen as „true“ for having data to read, if the only event type is EPOLLIN.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on June 08, 2021, 10:19:01 am
I converted the LibSocketCAN library into a Pascal Unit.

beside the 'set' functions, which require root rights, the 'get' functions work as normal user.

Code: Pascal  [Select][+][-]
  1. unit LibSockCAN;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. //lib/arm-linux-gnueabihf/libsocketcan.so
  8. //libsocketcan.h
  9. uses can.netlink, ctypes,
  10.  
  11. if_linkpart;   // a short version of the linux/if_link.h
  12.  
  13. {$linklib c}
  14. {$linklib libsocketcan}
  15. type
  16.  pdword   = ^dword;
  17.  p_mybt   = ^can_bittiming;
  18.  p_mycm   = ^can_ctrlmode;
  19.  p_myclk  = ^can_clock;
  20.  p_mybtc  = ^can_bittiming_const;
  21.  p_mybcs  = ^can_berr_counter;
  22.  p_mycds  = ^can_device_stats;
  23.  p_myrls  = ^rtnl_link_stats64;  //defined in if_linkpart derived from <linux/if_link.h>  
  24.  rx_packets = qword;
  25.  
  26.  
  27. //These functions work only with root rights
  28.  
  29. function can_do_restart(myifname : ansistring) : longint; cdecl; external;
  30. function can_set_restart_ms(myifname : ansistring; restart_ms : dword) : longint; cdecl; external;
  31. function can_do_stop(myifname : ansistring) : longint; cdecl; external;
  32. function can_do_start(myifname : ansistring) : longint; cdecl; external;
  33. function can_set_bitrate(myifname : ansistring; bitrate : dword) : longint; cdecl; external;
  34. function can_set_bitrate_samplepoint(myifname : ansistring; bitrate, samplepoint : dword) : longint; cdecl; external;
  35. function can_set_bittiming(myifname : ansistring; mybt : p_mybt) : longint; cdecl; external;
  36. function can_set_ctrlmode(myifname : ansistring; mycm : p_mycm ) : longint; cdecl; external;
  37.  
  38. //These functions work with user rights
  39.  
  40. function can_get_restart_ms(myifname : ansistring; myrms : pdword)  :longint; cdecl; external;
  41. function can_get_bittiming(myifname : ansistring; mybt : p_mybt ) : longint; cdecl; external;
  42. function can_get_ctrlmode(myifname : ansistring; mycm : p_mycm) :longint; cdecl; external;
  43. function can_get_state(myifname : ansistring; mystate : pdword): longint; cdecl; external;
  44. function can_get_clock(myifname : ansistring; myclock : p_myclk) :longint; cdecl; external;
  45. function can_get_bittiming_const(myifname : ansistring; mybtc : p_mybtc) :longint; cdecl; external;
  46. function can_get_berr_counter(myifname : ansistring; mybcs : p_mybcs):longint; cdecl; external;
  47. function can_get_device_stats(myifname : ansistring; mycds : p_mycds):longint; cdecl; external;
  48. function can_get_link_stats(myifname : ansistring; myrls : p_myrls):longint; cdecl; external;
  49.  
  50.  
  51. implementation
  52.  
  53.  
  54. end.
  55.  


I have tested all the 'get' and from the 'set' the ones I would need.

Doing that, was easier than using ip commands and parsing the text returns for the desired value.
Title: Re: CAN-BUS SocketCAN
Post by: avra on June 09, 2021, 01:51:33 pm
But the num_events is always either 0 or 1 even if more than 1 message was sent to the port.
Based on a quick look, it seams to me that instead of a single PEPoll_event you should try to create an array of PEPoll_event, pass number of elements to epoll_create(), and pass PEPoll_event array to epoll_wait(). Exactly аs in C demo that you can find at https://linux.die.net/man/7/epoll. I know that epoll_create() with kernels newer then 2.6.8 should not care for size parameter (as long as it's positive), but C demo thinks that it does matter so you should probably listen to it (at least until you make it work).

I converted the LibSocketCAN library into a Pascal Unit.
Very nice and thank you! If you agree to put the same license as in my CAN wrapper and demos, then I can add your wrapper also - if you add some simple console demo (of course, it will be clear who is the author of which file). What I would probably do is rename LibSockCAN.pas to can.lib.pas, and rename if_linkpart.pas (which is missing, btw) to can.if.linkpart.inc and include it from can.lib unit. What do you think?
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on June 09, 2021, 02:50:44 pm
(at least until you make it work).
I actually don't care how many events occur, because the epoll is fixed to the event EPOLLIN. As long as the query returns '1' there is data to read, if
 it is '0' then not.

Very nice and thank you! If you agree to put the same license as in my CAN wrapper and demos, then I can add your wrapper also - if you add some simple console demo (of course, it will be clear who is the author of which file).
I can rework the whole stuff, no problem

Is really a console application required? A GUI exists, which I left out of the .zip due to its size and in case of a console app I would have to do a cmd parser......

What I would probably do is rename LibSockCAN.pas to can.lib.pas, and rename if_linkpart.pas (which is missing, btw) to can.if.linkpart.inc and include it from can.lib unit. What do you think?

I can do the renaming, the licensing stuff and and check if all is available, no problem. 

I am working on another topic : https://forum.lazarus.freepascal.org/index.php/topic,54944.msg408418.html#msg408418 (https://forum.lazarus.freepascal.org/index.php/topic,54944.msg408418.html#msg408418)
and want to solve that too.
Pic of the GUI attached.
Title: Re: CAN-BUS SocketCAN
Post by: avra on June 09, 2021, 06:45:30 pm
Is really a console application required? A GUI exists, which I left out of the .zip due to its size and in case of a console app I would have to do a cmd parser......
Although you can find basic cmd parsers in hlcanerrdump and hlcanerrsim, there is really no need to go that far. Just fix interface name and other needed parameters in code and that shall be fine. GUI advanced demos are nice, but SocketCAN package will be part of FPC and there is a good chance that it will run on a headless SBC without Lazarus, so simple console demos are more important.

What I would probably do is rename LibSockCAN.pas to can.lib.pas, and rename if_linkpart.pas (which is missing, btw) to can.if.linkpart.inc and include it from can.lib unit. What do you think?
I can do the renaming, the licensing stuff and and check if all is available, no problem.
Thanks! It would be great if you could use license templates from my demos and wrappers.

I am working on another topic : https://forum.lazarus.freepascal.org/index.php/topic,54944.msg408418.html#msg408418 (https://forum.lazarus.freepascal.org/index.php/topic,54944.msg408418.html#msg408418)
and want to solve that too.
Pic of the GUI attached.
Nice. I wrote a solution proposal there.
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on June 10, 2021, 11:17:37 am
Hello Avra,

I have reworked the library and included the definition for

Code: Pascal  [Select][+][-]
  1. rtnl_link_stats64  =   record

in can.lib.pas library itself, like in libsocketcan.h. Explanations of this data type can be found for example here https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h (https://github.com/torvalds/linux/blob/master/include/uapi/linux/if_link.h).

I updated the license disclaimer of the original libsocketcan.h and added it to the library.
Besides the can.lib.pas, only can.netlink.pas is required to use libsocketcan.

A demo GUI application for Lazarus is included, it does not exercise all functions with all parameters set, but the use becomes clear.
If you want to use "set" commands it must be started with root rights, otherwise they fail.

Feel free to use the lib.can.pas together with your code.

rgds, Thomas
Title: Re: CAN-BUS SocketCAN
Post by: avra on June 10, 2021, 03:31:01 pm
Thanks Thomas, very nice! I will take a look as soon as I get some free time.
Title: Re: CAN-BUS SocketCAN
Post by: avra on July 01, 2021, 03:45:27 pm
@Thomas: I have made small changes needed for your LibSocketCAN wrapper and demo to fit the rest of the project. Please review and comment if needed.

@Everyone: I am also thinking about making a high level pascal like interface to avoid ugly c naming in LibSocketCAN, like I already did for SocketCAN. However, I do not know if I should add it to can.hl.pas where the rest of the high level stuff is, or to a separate unit? I am in doubt since LibSocketCAN wrapper in can.lib.pas has {$linklib libsocketcan} which is a dependency that needs installation (from source or package manager), and I don't want to force that dependency to all SocketCAN users. Is lib dependency forced on everyone as soon as we include lib with $linklib, or we need to call something from that lib first? I do not know this so I ask if someone else knows?
Title: Re: CAN-BUS SocketCAN
Post by: ThomasK on July 28, 2021, 10:48:34 am
@Avra,

sorry for the late reply, I changed job so my days are very busy....

I will review the new demo and come back.

About integration of LibSocketCAN into can.hl my two cents are keep it as an tool on top, because  it is not always needed but a grip to do some diagnostics.

Chers!
Title: Re: CAN-BUS SocketCAN
Post by: avra on July 28, 2021, 12:43:16 pm
sorry for the late reply, I changed job so my days are very busy....

I will review the new demo and come back.
Take your time. No rush.

About integration of LibSocketCAN into can.hl my two cents are keep it as an tool on top, because it is not always needed but a grip to do some diagnostics.
Your wrapper will stay as can.lib unit, and future pascalish thin wrapper will be a separate can.lib.hl unit. That way we will still be able to easily convert C demos when needed, while having more eye pleasing pascalish named access as with the rest of the high level CAN.

I wish you well on your new job!
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on September 24, 2021, 10:04:17 am
@jcdammeyer: CAN FD receive and transmit demos are here.  It was not trivial to find info of what exactly to change when compared to legacy CAN but it works now. 8-)

Oh my gosh.  I've finally finished a fairly large work-work project this summer and was thinking about getting back to this and I must have missed an email that the thread had been updated. 
Wow! 

Time for me to dig back into this since it's part of a larger project on CANopen Lite I'd like to do with Lazarus.

In fact I'm using one of my dsPIC modules with very simple CANopen messaging from LinuxCNC to run a power drawbar.  The LinuxCNC code is python interfaced with the AXIS user interface but the connection is via the Lawicel CANUSB dongle and serial port commands. 

I'll go through the entire thread and do some testing as soon as I finish a CNC conversion to new AC Servos.  I really do want to get back to this.
John
Title: Re: CAN-BUS SockectCAN
Post by: avra on September 24, 2021, 12:24:45 pm
Oh my gosh.  I've finally finished a fairly large work-work project this summer and was thinking about getting back to this and I must have missed an email that the thread had been updated. 
Wow!
I'm glad you like the progress.  :D ;) :D

I'm waiting for my bithelpers (actually new name as agreed with devs is syshelpers) FPC patch to become fully accepted (direct bit/nibble/byte/word/dword array like access already works in trunk as can be seen at https://gitlab.com/freepascal.org/fpc/source/-/issues/39268), and then I will need to write syshelpers documentation. After that gets completed, plan is to polish SocketCAN a little more and make an official FPC patch so it can be used out of the box. Good news for you is that Lawicel works with SocketCAN. Bad news is that while J1939 base support exists (demos not included yet), CANopen support is not comming any time soon. Right now I need plain CAN and J1939 for some of my freelance work so that's in focus, but since I do CAN a lot it is possible that at some moment I will deal with CANopen, too. No promisses and no schedule, but tiny possibility is there. If you need CANopen now, then you will have to implement it on your own. Patches are welcome.
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on September 24, 2021, 07:30:21 pm
I'm glad you like the progress.  :D ;) :D
If you need CANopen now, then you will have to implement it on your own. Patches are welcome.
The problem with CANopen is it's huge and for 99% of the projects (IMHO) doesn't need to be.  For example, a big deal is made over the support of the configuration files.  Useful for the non-programmer mechanical engineer or installer but for someone who writes in Delphi or Lazarus not so much.  Building up the object dictionary (OD) to show the size of variables pointless and just takes up a lot of code/data space.  Creating a be all end all installation would be nice but also overkill and hard to understand and maintain.

So I'm proposing a CANopen Lite.  That can deal with COTS (Commercial Off The Shelf) devices but might require a bit of programming to interface with.  To start with I've started with a simple monitoring program that at the moment uses the CANUSB.  So far this software has run on WIN-PC, BeagleBone and Pi. 

To migrate to socketCAN it will need a level of abstraction built in so we can open a device like the internal processor built in CAN on a BeagleBone or a Pi3 HAT that uses the MCP2515 SPI to CAN device and of course the socketCAN version of CANUSB.  I have two HATs for the Pi, a cape for the Beagle and lots of CANUSB plus a few expensive commercial USB dongles.

I will of course make the entire program open source. 
Title: Re: CAN-BUS SockectCAN
Post by: avra on September 25, 2021, 01:02:20 am
To migrate to socketCAN it will need a level of abstraction built in so we can open a device like the internal processor built in CAN on a BeagleBone or a Pi3 HAT that uses the MCP2515 SPI to CAN device and of course the socketCAN version of CANUSB.
Step-by-step guide on using Lawicel CANUSB via SocketCAN: https://pascal-walter.blogspot.com/2015/08/installing-lawicel-canusb-on-linux.html
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on September 25, 2021, 01:10:02 am
To migrate to socketCAN it will need a level of abstraction built in so we can open a device like the internal processor built in CAN on a BeagleBone or a Pi3 HAT that uses the MCP2515 SPI to CAN device and of course the socketCAN version of CANUSB.
Step-by-step guide on using Lawicel CANUSB via SocketCAN: https://pascal-walter.blogspot.com/2015/08/installing-lawicel-canusb-on-linux.html

Yes.  Thank you.  That's not an issue.  I've dumped CAN packets from working systems using socketCAN with the CANUSB on the PI3/4.  But that's using the C language command line programs.   

A couple of years ago now I had to record Hydrogen powered vehicle CAN messages from ignition key on and the Pi wasn't capable of booting in under 14 seconds.   So instead I put together a small PIC32 with CAN module that logged/timestamped all CAN messages along with GPS information and sent them up via SPI to the PiZero once it was awake. On the Pi they were saved in files and another application would grab them and put them on the cloud for the engineers to use for diagnostics.

Really looking forward to playing with your socketCAN stuff.
John

Title: Re: CAN-BUS SockectCAN
Post by: avra on September 25, 2021, 11:02:03 am
I've dumped CAN packets from working systems using socketCAN with the CANUSB on the PI3/4.  But that's using the C language command line programs.
As you progress through pascal SocketCAN demos, you will see that low level units will help when you want to convert C examples from the net since it will mostly be 1:1 translation as far as SocketCAN part is concerned. Once you get a feeling, you will quickly advance to more natural pascalish high level unit.

Really looking forward to playing with your socketCAN stuff.
I wish you as much fun as I have!  :D
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on September 26, 2021, 05:49:40 am
I wish you as much fun as I have!  :D
Not quite yet.
Under Lazarus I can create a console project, add this
writeln('Hello World from my Console Application');
 in the appropriate spot and then either run it from the IDE or from the console with that output.

Opening the canreceive project from the can.zip file compiles but doesn't generate an executable on the Beaglebone as shown in the attached screen shot.

Code: Pascal  [Select][+][-]
  1.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
And the BBB sockets.pp doesn't have PF_CAN so the can.zip file by itself isn't enough to compile and test. 

ie. if I add this along with the perror function it complains about the missing PF_CAN
Code: Pascal  [Select][+][-]
  1.     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  2.     if s < 0 then
  3.     begin
  4.       perror('Socket');
  5.       Exit;
  6.     end;
  7.  

Would you be able to create a canreceive.zip with a console application who's sole purpose is to open say slcan0 and just dump out messages like your canreceive.  For example the 3 attachments show that the CANUSB on /dev/ttyUSB0 can be accessed as a serial port via the CANopenLite application but can also be configured as slcan0 as shown in the other photo working with the socketCAN candump application.

So my hardware works.  Now the software.

Title: Re: CAN-BUS SockectCAN
Post by: avra on September 26, 2021, 05:00:21 pm
BBB sockets.pp doesn't have PF_CAN
As mentioned at https://forum.lazarus.freepascal.org/index.php/topic,39858.msg396135.html#msg396135 you need newer FPC so getting trunk would be a good idea. If that is not for you, then instead you could simply define missing constants PF_CAN and AF_CAN as 29 somewhere in your code. After that, it would be good to create vcan0 virtual adapter and go through demos since they should all work out of the box.

Would you be able to create a canreceive.zip with a console application who's sole purpose is to open say slcan0 and just dump out messages like your canreceive.
Once you have demos working with vcan0, making them work with slcan0 should be trivial. For example, in canreceive.lpr or hlcanreceive.lpr, all you need is to replace 'vcan0' with 'slcan0' at one place in code (as shown in your 3rd attachment).
Title: Re: CAN-BUS SockectCAN
Post by: jcdammeyer on September 26, 2021, 07:22:11 pm
BBB sockets.pp doesn't have PF_CAN
As mentioned at https://forum.lazarus.freepascal.org/index.php/topic,39858.msg396135.html#msg396135 you need newer FPC so getting trunk would be a good idea. If that is not for you, then instead you could simply define missing constants PF_CAN and AF_CAN as 29 somewhere in your code. After that, it would be good to create vcan0 virtual adapter and go through demos since they should all work out of the box.
Sadly this link doesn't work anymore which is why I posted the question.
Quote
CAN constants have been added to FPC 48867:
https://svn.freepascal.org/svn/fpc/trunk/packages/rtl-extra/src/linux/unxsockh.inc
In fact I can't even access https://svn.freepasccal.org

Title: Re: CAN-BUS SockectCAN
Post by: dsiders on September 26, 2021, 08:07:10 pm
Quote
CAN constants have been added to FPC 48867:
https://svn.freepascal.org/svn/fpc/trunk/packages/rtl-extra/src/linux/unxsockh.inc
In fact I can't even access https://svn.freepasccal.org

You have two issues:

The URL was https://svn.freepascal.org and not https://svn.freepasccal.org.

They moved to GitLab a few months back and the svn server no longer exists. There is a GitHub SVN mirror at: https://github.com/fpc/FPCSource, but the vcs of record is git located at: https://gitlab.com/freepascal.org/fpc/source.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 26, 2021, 08:45:45 pm
Incorrect spelling.  Sorry about that.  If possible then the link way back should be edited to point to the correct location.

What I did is add the PF_CAN and AF_CAN definitions into my code.  I also did put them into unxsockh.inc but it didn't have any effect.  Perhaps there's another copy being used instead.

Here's the results of the code below where I cut and pasted the canreceive.lpr section:
Code: [Select]
debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication
Hello World from Console Application
CAN Sockets Receive Demo Rev 0.01
fpsocket call
fpioctl call
fpbind call
fpread call
Standard CAN frame received with length 1
0x718 [1] 05
debian@ebb:~/lazarus/AvraCAN$

Code: Pascal  [Select][+][-]
  1. program ConsoleApplication;
  2.  
  3. {$mode delphi}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Classes, SysUtils, CustApp,
  10.   { you can add units after this }
  11.   sockets, baseunix, can;
  12.  
  13. const
  14.          PF_CAN = 29;
  15.          AF_CAN = 29;
  16.  
  17. type
  18.  
  19.   { TMyApplication }
  20.  
  21.   TMyApplication = class(TCustomApplication)
  22.   protected
  23.     procedure DoRun; override;
  24.   public
  25.     constructor Create(TheOwner: TComponent); override;
  26.     destructor Destroy; override;
  27.     procedure WriteHelp; virtual;
  28.     procedure perror(const S : string);
  29.     procedure MyApplicationMain;
  30.   end;
  31.  
  32. { TMyApplication }
  33. procedure TMyApplication.perror(const S : string);
  34. begin
  35.   WriteLn(S, ', SocketError = ', SocketError);
  36. end;
  37.  
  38.  
  39. procedure TMyApplication.MyApplicationMain;
  40. var
  41.   s, i, nbytes, err: cint;
  42.   addr:              sockaddr_can;
  43.   ifr:               ifreq;
  44.   frame:             canfd_frame;
  45. begin
  46.   Writeln('Hello World from Console Application');
  47.   WriteLn('CAN Sockets Receive Demo Rev 0.01');
  48.   writeln('fpsocket call');
  49.   s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  50.   if s < 0 then
  51.   begin
  52.     perror('Socket');
  53.     Exit;
  54.   end;
  55.  
  56.   writeln('fpioctl call');
  57.   strcopy(ifr.ifr_name, 'slcan0'); // ifr.ifr_name := 'vcan0' + #0;
  58.   if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  59.   begin
  60.     perror('IOctl');
  61.     Exit;
  62.   end;
  63.  
  64.   writeln('fpbind call');
  65.   memset(@addr, 0, sizeof(addr));
  66.   addr.can_family  := AF_CAN;
  67.   addr.can_ifindex := ifr.ifr_ifindex;
  68.  
  69.   if fpbind(s, @addr, sizeof(addr)) < 0 then
  70.   begin
  71.     perror('Bind');
  72.     Exit;
  73.   end;
  74.  
  75.   writeln('fpread call');
  76.   nbytes := fpread(s, frame, sizeof(frame));
  77.   if nbytes < 0 then
  78.   begin
  79.     perror('Read');
  80.     Exit;
  81.   end;
  82.  
  83.   if nbytes = CANFD_MTU then    // test CAN FD with 'cansend vcan0 123##1223344556677889900'
  84.     WriteLn('CAN FD frame received with length ', IntToStr(frame.len))
  85.   else if nbytes = CAN_MTU then // test legacy CAN with 'cansend vcan0 456#DEADBEEF'
  86.     WriteLn('Standard CAN frame received with length ', IntToStr(frame.len))
  87.   else
  88.     WriteLn('Invalid CAN(FD) frame received');
  89.  
  90.   Write(Format('0x%03X [%d] ', [frame.can_id and CAN_EFF_MASK, frame.len]));
  91.   for i := 0 to frame.len - 1 do
  92.     Write(Format('%02.2X ', [frame.data[i]]));
  93.   WriteLn('');
  94.  
  95.   if fpclose(s) < 0 then
  96.   begin
  97.     perror('Close');
  98.     Exit;
  99.   end;
  100.  
  101. end;
  102.  
  103. procedure TMyApplication.DoRun;
  104. var
  105.   ErrorMsg: String;
  106. begin
  107.   // quick check parameters
  108.   ErrorMsg:=CheckOptions('h', 'help');
  109.   if ErrorMsg<>'' then begin
  110.     ShowException(Exception.Create(ErrorMsg));
  111.     Terminate;
  112.     Exit;
  113.   end;
  114.  
  115.   // parse parameters
  116.   if HasOption('h', 'help') then begin
  117.     WriteHelp;
  118.     Terminate;
  119.     Exit;
  120.   end;
  121.  
  122.   { add your program here }
  123.   MyApplicationMain;
  124.  
  125.   // stop program loop
  126.   Terminate;
  127. end;
  128.  
  129. constructor TMyApplication.Create(TheOwner: TComponent);
  130. begin
  131.   inherited Create(TheOwner);
  132.   StopOnException:=True;
  133. end;
  134.  
  135. destructor TMyApplication.Destroy;
  136. begin
  137.   inherited Destroy;
  138. end;
  139.  
  140. procedure TMyApplication.WriteHelp;
  141. begin
  142.   { add your help code here }
  143.   writeln('Usage: ', ExeName, ' -h');
  144. end;
  145.  
  146. var
  147.   Application: TMyApplication;
  148. begin
  149.   Application:=TMyApplication.Create(nil);
  150.   Application.Title:='My Application';
  151.   Application.Run;
  152.   Application.Free;
  153. end.
  154.  
  155.  

No idea why canreceive.lpr won't compile into an executable.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 26, 2021, 10:32:19 pm
I've updated the program and formatted it to match the socketCAN candump program.  Only does standard IDs, no Extended ID or CANFD.  CANFD likely won't happen as I have absolutely no CANFD units here and no desire to actually use it.  99.9% of everything I have in stock in drivers, devices, dongles are all non-CANFD.

Quote
debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication
CAN Sockets Receive Demo Rev 0.1 Build 5
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  298   [7]  00 00 00 00 01 00 00
slcan0  718   [1]  05
debian@ebb:~/lazarus/AvraCAN$

And here's the updated console application.  I'll hang a module on that generates Extended 29 bit ID messages and add support for that to match candump.  I'll also add a command line parameter that allows defining which CAN device is to be used.  Since this test is on a Beagle I'll put the CAN cape on it, verify with the socketCAN candump that it works and then test it with the Lazarus program.

Code: Pascal  [Select][+][-]
  1. program ConsoleApplication;
  2.  
  3. {$mode delphi}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Classes, SysUtils, CustApp,
  10.   { you can add units after this }
  11.   crt,  { for the keypressed function }
  12.   sockets, baseunix, can;  { for socketCAN support }
  13.  
  14. const
  15.          PF_CAN = 29;  // Not defined in libraries yet.
  16.          AF_CAN = 29;
  17.  
  18. type
  19.  
  20.   { TMyApplication }
  21.  
  22.   TMyApplication = class(TCustomApplication)
  23.   protected
  24.     procedure DoRun; override;
  25.   public
  26.     constructor Create(TheOwner: TComponent); override;
  27.     destructor Destroy; override;
  28.     procedure WriteHelp; virtual;
  29.     procedure perror(const S : string);
  30.     procedure MyApplicationMain;
  31.   end;
  32.  
  33. { TMyApplication }
  34. procedure TMyApplication.perror(const S : string);
  35. begin
  36.   WriteLn(S, ', SocketError = ', SocketError);
  37. end;
  38.  
  39.  
  40. procedure TMyApplication.MyApplicationMain;
  41. var
  42.   s, i, nbytes, err: cint;
  43.   addr:              sockaddr_can;
  44.   ifr:               ifreq;
  45.   frame:             canfd_frame;
  46.  
  47. begin
  48. //  Writeln('Hello World from Console Application');
  49.   WriteLn('CAN Sockets Receive Demo Rev 0.1 Build 5');
  50. //  writeln('fpsocket call');
  51.   s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);
  52.   if s < 0 then
  53.   begin
  54.     perror('Socket');
  55.     Exit;
  56.   end;
  57.  
  58. //  writeln('fpioctl call');
  59.   strcopy(ifr.ifr_name, 'slcan0'); // ifr.ifr_name := 'vcan0' + #0;
  60.   if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then
  61.   begin
  62.     perror('IOctl');
  63.     Exit;
  64.   end;
  65.  
  66. //  writeln('fpbind call');
  67.   memset(@addr, 0, sizeof(addr));
  68.   addr.can_family  := AF_CAN;
  69.   addr.can_ifindex := ifr.ifr_ifindex;
  70.  
  71.   if fpbind(s, @addr, sizeof(addr)) < 0 then
  72.   begin
  73.     perror('Bind');
  74.     Exit;
  75.   end;
  76.  
  77.   while (not keypressed) do begin
  78.     //  writeln('fpread call');
  79.       nbytes := fpread(s, frame, sizeof(frame));
  80.       if nbytes < 0 then
  81.       begin
  82.         perror('Read');
  83.         Exit;
  84.       end;
  85.  
  86.       if nbytes = CANFD_MTU then    // test CAN FD with 'cansend vcan0 123##1223344556677889900'
  87.         WriteLn('CAN FD frame received with length ', IntToStr(frame.len))
  88.       else if nbytes = CAN_MTU then // test Standard CAN with 'cansend vcan0 456#DEADBEEF'
  89.     //    WriteLn('Standard CAN frame received with length ', IntToStr(frame.len))
  90.           write(ifr.ifr_name, '  ')
  91.       else
  92.         WriteLn('Invalid CAN(FD) frame received');
  93.  
  94.       Write(Format('%03X   [%d]  ', [frame.can_id and CAN_EFF_MASK, frame.len]));
  95.       for i := 0 to frame.len - 1 do
  96.         Write(Format('%02.2X ', [frame.data[i]]));
  97.       WriteLn('');
  98.   end;
  99.  
  100.   if fpclose(s) < 0 then
  101.   begin
  102.     perror('Close');
  103.     Exit;
  104.   end;
  105.  
  106. end;
  107.  
  108. procedure TMyApplication.DoRun;
  109. var
  110.   ErrorMsg: String;
  111. begin
  112.   // quick check parameters
  113.   ErrorMsg:=CheckOptions('h', 'help');
  114.   if ErrorMsg<>'' then begin
  115.     ShowException(Exception.Create(ErrorMsg));
  116.     Terminate;
  117.     Exit;
  118.   end;
  119.  
  120.   // parse parameters
  121.   if HasOption('h', 'help') then begin
  122.     WriteHelp;
  123.     Terminate;
  124.     Exit;
  125.   end;
  126.  
  127.   { add your program here }
  128.   MyApplicationMain;
  129.  
  130.   // stop program loop
  131.   Terminate;
  132. end;
  133.  
  134. constructor TMyApplication.Create(TheOwner: TComponent);
  135. begin
  136.   inherited Create(TheOwner);
  137.   StopOnException:=True;
  138. end;
  139.  
  140. destructor TMyApplication.Destroy;
  141. begin
  142.   inherited Destroy;
  143. end;
  144.  
  145. procedure TMyApplication.WriteHelp;
  146. begin
  147.   { add your help code here }
  148.   writeln('Usage: ', ExeName, ' -h');
  149. end;
  150.  
  151. var
  152.   Application: TMyApplication;
  153. begin
  154.   Application:=TMyApplication.Create(nil);
  155.   Application.Title:='My Application';
  156.   Application.Run;
  157.   Application.Free;
  158. end.
  159.  
  160.  

John
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 26, 2021, 10:47:28 pm
Oh and the messages you see are generated by the module in the photo.  The buttons enable an air cylinder and butterfly impact wrench to act as a power drawbar and are displayed on the Pi4 LinuxCNC display.  The Mist Coolant has been turned on so the 0x44 represents that output command and in the high nibble the output status.   You can see the bits in the PDO message changing as I press the button and the drawbar state machine is activated with one other output also switched ON.  The Pi4 LinuxCNC talks to the CAN bus via another Lawicel CANUSB. 

Quote
CAN Sockets Receive Demo Rev 0.1 Build 5
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  298   [7]  02 44 00 00 01 00 02
slcan0  298   [7]  00 66 00 00 06 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 66 00 00 06 00 00
slcan0  298   [7]  00 66 00 00 06 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 66 00 00 06 00 00
slcan0  298   [7]  00 66 00 00 06 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  718   [1]  05

It's not yet mounted on the machine.  I only just learned about postings from avra on this.  For some reason I missed the email that things were being done.  Been a busy summer.  And yes.  Now I'm having fun again. ;D
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 27, 2021, 01:04:06 am
This link had me confused for a bit, especially since I was referencing CAN0 in my notes too. 
https://github.com/BlueAndi/beaglebone_black_socketcan (https://github.com/BlueAndi/beaglebone_black_socketcan)
However, that same cape does say CAN1 on it so when I switched to setting it up as CAN1 candump now works.
I recompiled the ConsoleApplication again to use can1 and then slcan0 and the Beagle now has two functional CAN bus channels; Lawicel CANUSB and the internal Beagle bone CAN1

Quote
debian@ebb:~$ candump can1
  can1  298   [7]  00 44 00 00 01 00 00
  can1  718   [1]  05
  can1  298   [7]  00 44 00 00 01 00 00
  can1  298   [7]  00 44 00 00 01 00 00
  can1  718   [1]  05
  can1  298   [7]  00 44 00 00 01 00 00
^Cdebian@ebb:~$ cd lazarus/AvraCAN/
debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication
CAN Sockets Receive Demo Rev 0.1 Build 6
can1  298   [7]  00 44 00 00 01 00 00
can1  718   [1]  05
can1  298   [7]  00 44 00 00 01 00 00
can1  298   [7]  00 44 00 00 01 00 00
can1  718   [1]  05
can1  298   [7]  00 44 00 00 01 00 00
can1  298   [7]  00 44 00 00 01 00 00
can1  718   [1]  05
debian@ebb:~/lazarus/AvraCAN$ sudo ifconfig slcan0 up
[sudo] password for debian:
debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication
CAN Sockets Receive Demo Rev 0.1 Build 7
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  718   [1]  05
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  298   [7]  00 44 00 00 01 00 00
slcan0  718   [1]  05
debian@ebb:~/lazarus/AvraCAN$
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 27, 2021, 08:59:05 am
BTW, if anyone wants more of a write-up on socketCAN this link might be useful.  The link is also in the can.pas application provided by avra:
https://www.kernel.org/doc/html/v5.10/networking/can.html (https://www.kernel.org/doc/html/v5.10/networking/can.html)

Also back in 2013 when I attended the CANopen Conference in Germany the attached pdf was one of the presentations.  This presentation goes over the Volkswagon contribution by Oliver Hartkopp who is also referenced in the can.pas document.

Just a bit of history...
Title: Re: CAN-BUS SocketCAN
Post by: avra on September 28, 2021, 01:47:04 pm
I also did put them into unxsockh.inc but it didn't have any effect.
That would have also worked after FPC rebuilding.

No idea why canreceive.lpr won't compile into an executable.
What is the compilation error message? What FPC/LAZ/OS/ARCH/Bitness combo was used? Did you manage to compile other demos?

Also back in 2013 when I attended the CANopen Conference in Germany the attached pdf was one of the presentations.
Nice and simple bridge and ISO examples.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 28, 2021, 07:14:33 pm
I also did put them into unxsockh.inc but it didn't have any effect.
That would have also worked after FPC rebuilding.
Unfortunately at this point you lose me on what to do there.  I ran fpcupdeluxe to install the same version on the PC, Pi3/4 and BBB.  I would need the simpleton step by step procedure to do the 'FPC rebuilding' along with a "why I am doing what I'm doing"

Quote
No idea why canreceive.lpr won't compile into an executable.
What is the compilation error message? What FPC/LAZ/OS/ARCH/Bitness combo was used? Did you manage to compile other demos?
I opened up the .lpi project from Lazarus and did a build.  The screen capture I posted earlier and again here shows the result.  I tried a number of options with no success in creating an executable.  That's when I used the lazarus 'new' and selected console application program to create my stock application.  Then coppied and pasted the key parts that were needed to duplicate the basic functionality of candump.

Last night I created a new folder 'lazcandump' and copied over the initial files that appeared to be needed based on the uses clause and the {$i lines.  And then a bunch more that I'm not sure where were {$i when the compiler complained.  {It was late.  Easier to copy over than figure out why}

It now accepts 'can1' or 'slcan0' on the command line and then dumps the messages in the same way as the socketCAN candump.  I plugged a mcp2515 CAN hat into a Pi4 running LinuxCNC.  I think I still have to install Lazarus on that Pi4 but the socketCAN candump shows the messages created by the CANUSB when a checkbox is clicked on the LinuxCNC AXIS display.  More on that by the end of the day if all goes well.

Quote
Also back in 2013 when I attended the CANopen Conference in Germany the attached pdf was one of the presentations.
Nice and simple bridge and ISO examples.

I do have a zip of the entire conference proceedings (47MB) including my presentation (1.4MB) all too big to post here.

Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 28, 2021, 07:58:59 pm
There we go.  The 29 bit Extended IDs in addition to 11 bit Standard IDs are now also supported in the lazcandump.  The Extended ID message is only sent on change of one of the two checkboxes in LinuxCNC with a single byte of null data.  ie.  No important information.  Just the message to show it works.  The captured data here from the CANUSB  was done with puTTY into the BBB while lazcandump was also running on a terminal screen on the BBB working with the internal CAN1.

Oh and via puTTY I can run lazcandump can1 while it's also running on the BBB terminal session so it's sharing nicely.

Next step, make lazcandump  work on the Pi4

Quote
slcan0       298 [7]  00 00 00 00 01 00 00
slcan0       298 [7]  00 00 00 00 01 00 00
slcan0       318 [1]  04
slcan0  12345678 [1]  00
slcan0       718 [1]  05
slcan0       298 [7]  00 44 00 00 01 00 00
slcan0       298 [7]  00 44 00 00 01 00 00
slcan0       718 [1]  05
slcan0       298 [7]  00 44 00 00 01 00 00
slcan0       318 [1]  00
slcan0  12345678 [1]  00
slcan0       298 [7]  00 00 00 00 01 00 00

Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 29, 2021, 05:29:31 am
I'm ready to try it on the Raspberry Pi4.  However something odd and this may not be the right thread to ask the question.
 
The Pi4 has the folder fcpupdeluxe as shown in the attached photo.  However there's no shortcut to it on the desktop.  I don't remember at what point I stopped with the installation or if I even installed it.

The BBB has this as the desktop link:
Quote
[Desktop Entry]
Version=1.0
Encoding=UTF-8
Type=Application
Icon=/home/debian/fpcupdeluxe/lazarus/images/icons/lazarus.ico
Exec=/home/debian/fpcupdeluxe/lazarus/lazarus --pcp="/home/debian/fpcupdeluxe/config_lazarus" %f
Name=Lazarus_fpcupdeluxe
GenericName=Lazarus IDE with Free Pascal Compiler
Category=Application;IDE;Development;GUIDesigner;Programming;
Categories=Application;IDE;Development;GUIDesigner;Programming;
Keywords=editor;Pascal;IDE;FreePascal;fpc;Design;Designer;


Suggestions?
Thanks
John
Title: Re: CAN-BUS SocketCAN
Post by: avra on September 29, 2021, 09:32:15 am
I also did put them into unxsockh.inc but it didn't have any effect.
That would have also worked after FPC rebuilding.
Unfortunately at this point you lose me on what to do there.  I ran fpcupdeluxe to install the same version on the PC, Pi3/4 and BBB.  I would need the simpleton step by step procedure to do the 'FPC rebuilding' along with a "why I am doing what I'm doing"
FPC rebuild steps for Windows: https://forum.lazarus.freepascal.org/index.php/topic,55358.msg411825.html. Shouldn't be too difficult to adapt for Linux. Ah, yes... do not forget to rebuild Lazarus as well, so IDE can be aware of FPC changes.

Quote
No idea why canreceive.lpr won't compile into an executable.
What is the compilation error message? What FPC/LAZ/OS/ARCH/Bitness combo was used? Did you manage to compile other demos?
I opened up the .lpi project from Lazarus and did a build.  The screen capture I posted earlier and again here shows the result.  I tried a number of options with no success in creating an executable.
I can see on the screenshot that compilation was a success, so canreceive file should be created. It also seams that you tried to run it from IDE, which I do not recommend. Better try to run it from the terminal. If file canreceive exists, then maybe you just need to manually flag it as an executable? What about other demos? Could you compile them and run, or not?

I do have a zip of the entire conference proceedings (47MB) including my presentation (1.4MB) all too big to post here.
What was the topic of your presentation?

The Pi4 has the folder fcpupdeluxe as shown in the attached photo.  However there's no shortcut to it on the desktop.  I don't remember at what point I stopped with the installation or if I even installed it.

The BBB has this as the desktop link:
Excluding path difference, I have identical desktop shortcut on my Debian XFCE system so you should be good to copy and use yours in another system.

I'm so glad to see your progress.  :D
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 29, 2021, 10:06:15 am
1. Really.  It didn't compile it.  Very strange.
Quote
debian@ebb:/$ sudo find / -name canreceive*
[sudo] password for debian:
/home/debian/lazarus/AvraCAN/canreceive.lpi
/home/debian/lazarus/AvraCAN/canreceive.lpr
/home/debian/lazarus/AvraCAN/backup/canreceive.lpi
/home/debian/lazarus/AvraCAN/backup/canreceive.lpr
/home/debian/lazarus/AvraCAN/backup/canreceive.lps
/home/debian/lazarus/AvraCAN/canreceive.lps
debian@ebb:/$

2. The paper was titled "A large scale CAN bus system".  I put the document here:  http://www.autoartisans.com/rings/ALargeScaleCANbusSystem.pdf (http://www.autoartisans.com/rings/ALargeScaleCANbusSystem.pdf)

3. I'll try creating a shortcut.  I have no worries about both the CANUSB and SPI MCP2515 working as they both work with the C language candump.
Title: Re: CAN-BUS SocketCAN
Post by: avra on September 30, 2021, 11:33:57 am
1. Really.  It didn't compile it.  Very strange.
Do you have problems generating executable only with canreceive demo, or you have problems with all demos (hlcanreceive...)? If all demos suffer the same problem, then it might be dir/file access rights problem and you could try another directory or fix access rights.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 30, 2021, 06:47:00 pm
1. Really.  It didn't compile it.  Very strange.
Do you have problems generating executable only with canreceive demo, or you have problems with all demos (hlcanreceive...)? If all demos suffer the same problem, then it might be dir/file access rights problem and you could try another directory or fix access rights.

Haven't had a chance to try that yet.  Yesterday was a battle to get fpcupdeluxe installed on the Pi4 LinuxCNC.  Each time a failure near the end.  Google on the error and others have had the same and the support statement was closing this issue it's a Lazarus problem...

But eventually I did get it running and have the same version of Lazarus installed on the Pi4.  Now to make sure that LED sample works.  Probably have to add the same changes we did in the spring to the library.

Then on BBB finally after much feedback from Robert Nelson got Buster and a Buster kernel installed on the BBB. 

So today I'll take another look at your examples.  Are you compiling them from within Lazarus or just using FPC and command line?
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 30, 2021, 09:34:19 pm
1. Really.  It didn't compile it.  Very strange.
Do you have problems generating executable only with canreceive demo, or you have problems with all demos (hlcanreceive...)? If all demos suffer the same problem, then it might be dir/file access rights problem and you could try another directory or fix access rights.

Haven't had a chance to try that yet.  Yesterday was a battle to get fpcupdeluxe installed on the Pi4 LinuxCNC. 

So today I'll take another look at your examples.  Are you compiling them from within Lazarus or just using FPC and command line?

Alright.  My project loads and compiles correctly on the Pi4 with Lazarus.
I load yours, say hlcanreceive.lpi and the screen shot says it all I think.
Your canreceive.lpi does have files because I added them on the beagle and then dragged that folder over to the Pi.
As you can see on the screen shot I'm using Lazarus IDE v2.0.10  since that's what's on the Beagle.  Also it's the only one that would actually install without lazarus compile failures on the Pi4.  On the WIN-PC with 2.0.8 r62944 it behaves the same.  The source code file doesn't appear.

So let's look at the .lpi file for the simple console application I made from within Lazarus and had the key elements of your receive code cut and pasted.  Using the now 30 year old CodeWright from Borland with the side by side compare perhaps you can see why mine loads the lpr file.  In the Project inspector mine shows ConsoleApplication.pas.

Hopefully this helps?




Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on September 30, 2021, 09:37:51 pm
Here's a zip of the console application
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 01, 2021, 12:19:34 pm
After seeing that your project inspector is empty, and that when comparing LPIs - one XML file has <BuildModes Count = "1"> and the other one has just <BuildModes>, it is clear that all LPI files have been saved in new Lazarus 2.1+ XML file format, and that was the reason why you have not been able to load project properly, because you have old Lazarus 2.0. For a quick fix you can use this tool: https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/applications/fixlp/, but as a permanent solution I will change all project files to be saved in old compatibility mode.
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 01, 2021, 01:23:36 pm
Attached latest SocketCAN with fixed example projects LPIs. Old Lazarus is now able to open all projects.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 01, 2021, 06:22:27 pm
Attached latest SocketCAN with fixed example projects LPIs. Old Lazarus is now able to open all projects.

I'll try it today.   

At the moment I have to stay with the old Lazarus.  After the 4th try with Stable, Trunk and a mix of those I finally went Trunk and 2.0.10 for Lazarus on the Debian Pi4 LinuxCNC install.   That's the only one that actually would build to completion and put the icon on the desktop.  And at that point I was able to build my code along with that LED 7 segment display program that had the paint issue.  I've forgotten exactly what that was.  Will have to look through the old posts although the code seems to work.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 01, 2021, 06:28:41 pm
After seeing that your project inspector is empty, and that when comparing LPIs - one XML file has <BuildModes Count = "1"> and the other one has just <BuildModes>, it is clear that all LPI files have been saved in new Lazarus 2.1+ XML file format, and that was the reason why you have not been able to load project properly, because you have old Lazarus 2.0. For a quick fix you can use this tool: https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/applications/fixlp/, but as a permanent solution I will change all project files to be saved in old compatibility mode.

I've downloaded it to my PC and then dragged and dropped onto the Pi and the Beagle via windows explorer.  Since I'm running 2.0.10 on the Windows systems too I'll also try it there.

What was the reasoning to cripple all old versions of Lazarus with a change to the project format?  Would it not have been better to leave the old and add a replacement for Buildmodes that would be ignored?  For backward compatibility?
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 01, 2021, 06:37:54 pm
After seeing that your project inspector is empty, and that when comparing LPIs - one XML file has <BuildModes Count = "1"> and the other one has just <BuildModes>, it is clear that all LPI files have been saved in new Lazarus 2.1+ XML file format, and that was the reason why you have not been able to load project properly, because you have old Lazarus 2.0. For a quick fix you can use this tool: https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/applications/fixlp/, but as a permanent solution I will change all project files to be saved in old compatibility mode.

I've downloaded it to my PC and then dragged and dropped onto the Pi and the Beagle via windows explorer.  Since I'm running 2.0.10 on the Windows systems too I'll also try it there.

As the screen shot shows, it went from no files in the project to the list with the members.pas missing and of course won't compile because termio is missing but then this project was never meant to be compatible with windows lazarus so that's no real surprise.

More when I get to the Linux systems.

Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 01, 2021, 11:22:43 pm
Amazing how much time this eats up.

Although the fixlp program compiled and ran and modified the lpi programs it did not create a workable solution.  At least not with 2.0.10

I downloaded the can.zip and that one did work with canreceive.lpi and after modifying to use slcan0 I was able to capture a CAN message.  However compiling hlcanreceive.lpi created a list of 5 files as shown in the screen capture but it breaks. The one I converted had 7 files including members.pas and sockios.pas which also doesn't compile.

So there are still some path issues.
the -canzip is from the latest can.zip posted.  The -fixlp is the older one that was 'fixed' by fixlp.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 02, 2021, 02:05:15 am
Loaded the LinuxCNC MicroSD into the Pi4.
Created fixlp folder and compiled fixlp
ran from AvraCAN
./fixlp/fixlp hlcanreceive.lpi
which created the new .lpi and .lpi.bak
Check with file compare and only the expected changes were there.  As the screen shot shows, the members.pas file is not to be found but there are 7 files there.
Added the PC_CAN and AF_CAN constants and compiled for slcan0.
Then first ran it with slcan0 and saw a real CAN message from the Lawicel CANUSB.
Next recompiled with can0 and saw a real CAN message from the MCP2515 HAT.

No idea why the other Pi Linux system is having trouble.

Next I'll try this on the BeagleBone Black.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 02, 2021, 02:12:30 am
Here's the difference between the LinuxCNC Pi4 and the regular Pi4 Linux.
Version Value is different and both MainUnit Value and Modes Count don't exist in the fixlp file that doesn't work.

I wonder why. 
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 04, 2021, 04:53:37 pm
@jcdammeyer:

SocketCAN was never meant to be used with older FPC like 3.0.4. Even newer 3.2.x does not have needed constants. I use it with trunk since there is a plan for SocketCAN to end up in FPC 3.4 or 4.0, whichever comes first. Lazarus version should not matter at all, but it did since I used Lazarus trunk which introduced new LPI format. I fixed that in latest can.zip so use that instead.

While constants like AF_CAN, PF_CAN and PF_RDS can be added manually, whole units like termio certainly can't, so I wouldn't bother with such old FPC. Sorry, I do not provide support for that.

When I see that you still have members.pas in your LPI file, that tells me that you did not use latest can.zip where I fixed that (fixlp is also not needed with this latest archive). Btw, not having members.pas file in directory does not stop compilation at all. It just notifies you that it could not be found, and since it was not used at all - it didn't matter anyway.

I'm glad you somehow managed to compile at all, even with old FPC.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 04, 2021, 06:16:30 pm
I probably get confused at times too with which system is which.  I'm running a Pi Linux version on one MicroSD and a LinuxCNC on the other.  Add to that a Debian system on the Beagle which was no longer supported so with the help of Robert Nelson was able to upgrade the kernel and the OS to the latest version. 

I've only stayed with 2.0.10 because that worked on WIN-10, WIN-7, Linux, LinuxCNC, Pi3/4 and Beagle.  Upgrading one of those to a newer version means it has to be done on everything which is a lot of work.  I've found in the past that it's best to not be on the bleeding edge but I guess trying out socketCAN for Lazarus is really still working on the bleeding edge.

I recall from looking at older Delphi libraries that I thought I saw {$ifdef... statements that tested versions of the compiler.  Should that not then be in socketCAN libraries so if one tries to compile applications that require > 3.2.x that the compiler complains and stops.  If sample applications are dependent on that then should that not also exist in those samples?

But if it's time to upgrade then so be it.

Title: Re: CAN-BUS SocketCAN
Post by: avra on October 05, 2021, 01:15:52 am
I recall from looking at older Delphi libraries that I thought I saw {$ifdef... statements that tested versions of the compiler.  Should that not then be in socketCAN libraries so if one tries to compile applications that require > 3.2.x that the compiler complains and stops.  If sample applications are dependent on that then should that not also exist in those samples?
It was never meant to make SocketCAN a library that works with any FPC version. It can be forced but it would be a mine field which I do not recommend. In one of the old messages in this thread you can find exact FPC revision that I added missing constants to, and which has everything else needed - but if you do not feel like hunting it down, then current trunk FPC will do. This is just a playground and SocketCAN will be part of FPC, so there will be no need for ifdefs in code. As for Lazarus, my last can.zip does not depend on Lazarus 2.1+ any more and should work with any Lazarus 2.0.x and maybe even older.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 05, 2021, 01:34:41 am
Thanks,
The two windows systems (WIN-7 and WIN-10) have been upgraded to trunk and trunk.  The reason for maintaining windows compatibility isn't just for socketCAN but also for that graphical issue a few months back.  Now I have to find out where I put all the packages.  Sloppy on my part.

And therein lies the problem with constantly updating.  All the lpk packages have to be rebuilt and installed into the IDE.  It was always the worst part of upgrading Delphi too.

Then I'll upgrade my Linux systems.
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 06, 2021, 11:09:17 am
The two windows systems (WIN-7 and WIN-10) have been upgraded to trunk and trunk.
Since projects can now be opened in older Lazarus, there was no real need to use Lazarus trunk, but it will not hurt. In case you want to be able to open your own projects saved with Lazarus 2.1+ in Lazarus 2.0.x and older, you can go to Project Options / Misellaneous and check Maximize compatibility of project files (LPI and LPS). That's all I did in latest can.zip, so fixlp is not needed any more.

If you use fpcupdeluxe, then it would be wise to write down exact revision of FPC and LAZ combo you used at one place, and then tell fpcupdeluxe to download that exact combo on each system you use for SocketCAN. That would eliminate a lot of ifs in case of problems.

And therein lies the problem with constantly updating.  All the lpk packages have to be rebuilt and installed into the IDE.  It was always the worst part of upgrading Delphi too.
If you use fpcupdeluxe, then once you install it in one OS/CPU combo, you can simply copy whole dir and desktop shortcut to another machine with the same (or compatible) OS/CPU combo. That's all. No need for reinstallation all over again. And sometimes cross compilation can also save the day...
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 06, 2021, 07:02:35 pm
Since projects can now be opened in older Lazarus, there was no real need to use Lazarus trunk, but it will not hurt. In case you want to be able to open your own projects saved with Lazarus 2.1+ in Lazarus 2.0.x and older, you can go to Project Options / Misellaneous and check Maximize compatibility of project files (LPI and LPS). That's all I did in latest can.zip, so fixlp is not needed any more.

For some reason, even after 3 tries I couldn't get the trunk/trunk version to install on the Pi4 LinuxCNC version.  What finally worked was the trunk fpc which then built your examples correctly.   The 2.0.10 Lazarus did install and that's what I was running on the others.  And that created the same problem from 6 months ago.
Code: Pascal  [Select][+][-]
  1.     if (DevCtx.IsNullPen and (DevCtx.IsNullBrush or Winding)) then
Had to go back through all my postings to find that solution and now the sample 7 segment programs work on all three systems.  The Pi is using FPC 3.3.1 and Laz 10.0.2.  The Beagle is using Laz 10.0.2 and I think 3.3.1 but for some reason the compiler version isn't showing up on the messages.  The same boxes appear to be checked in the Project Options verbosity.  I only updated the FPC on the Beagle.  PCs are both running 3.3.1 and Laz 2.3.0 but then Windows never had the issue with the "Winding".

Quote
If you use fpcupdeluxe, then it would be wise to write down exact revision of FPC and LAZ combo you used at one place, and then tell fpcupdeluxe to download that exact combo on each system you use for SocketCAN. That would eliminate a lot of ifs in case of problems.

And therein lies the problem with constantly updating.  All the lpk packages have to be rebuilt and installed into the IDE.  It was always the worst part of upgrading Delphi too.
If you use fpcupdeluxe, then once you install it in one OS/CPU combo, you can simply copy whole dir and desktop shortcut to another machine with the same (or compatible) OS/CPU combo. That's all. No need for reinstallation all over again. And sometimes cross compilation can also save the day...

In either case, updating to 3.3.1 allows all your examples to compile.  Thanks for all your help. 

Now I have to chase the usual BBB kernal and OS update issues.  Seems now the paths to the SPI devices have changed so once again Derek Molloy's book has sections now that are wrong.    And where I used to be able to read a 1-Wire device on the BBB it no longer shows up.  Probably something in the cape EEROM.  Constant upgrades that break old programs are such a pain. 

Title: Re: CAN-BUS SocketCAN
Post by: avra on October 06, 2021, 08:56:43 pm
...that created the same problem from 6 months ago... Had to go back through all my postings to find that solution and now the sample 7 segment programs work on all three systems.
Well, LCL evolves so from time to time you need to check your projects for compatibility. SocketCAN should work with your old Lazarus, but your project which uses some GUI features that changed in newer Lazarus was the reason for incompatibility. Glad you fixed that after all.

In either case, updating to 3.3.1 allows all your examples to compile.  Thanks for all your help.
You're most welcome. I'm glad that you can finally compile all SocketCAN demos.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 06, 2021, 10:21:38 pm
I had already started my own CANopen unit which included a CAN message data structure.  I'll see if I can't convert that over to use the socketCAN data structures and add {$ifdef for WIN or LINUX so I can still run with the CANUSB on the windows systems but switch over to socketCAN on the Linux ones.  That will allow me to use the MCP2515 devices on the Pi and the internal CAN device on the Beagle.

When that's all done and working I'll post the Lazarus source code for the project.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 12:02:03 pm
Noting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 19, 2021, 07:29:42 pm
Noting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces.

MarkMLl

It's because I have four of the CANUSB from Lawicel in Sweden that it is one of the first tools I grab but the software support for monitoring isn't the best.  I think there are clones from China for even less.

For some monitoring on my car before a friend loaned me a Code Monitor I built up an Arduino with the add on SPI based CAN board.  It would be easy enough to clone the basic serial side of the CANUSB protocol on it.

I also have a dongle from RM Michaelides with their software that is very good but over $500.  It's that user software that I'm sort of cloning onto Lazarus.   The Lazarus software works with the serial port (COMx: on windows, /dev/ttyUSBx on Linux).

I also have a KVaser Lief USB dongle.  Rarely use it.  They are even more money.

For the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI.

The Lazarus software has a long way to go.  I've been side tracked by other projects but I can zip up what I have if you want it.
John
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 08:27:10 pm
It's because I have four of the CANUSB from Lawicel in Sweden that it is one of the first tools I grab but the software support for monitoring isn't the best.  I think there are clones from China for even less.

Thanks for that. I see http://www.can232.com/?page_id=16 and note that that's described as having an FTDI interface, so I've got a fair degree of confidence that Linux will see it (as remarked elsewhere, I've bought lots of stuff over the last year or so that has an embedded serial chip).

Is the clone you're thinking about something like https://www.ebay.co.uk/itm/143099880796 ?

I can see the various SPI interfaces, but at least initially I want to be able to exercise some kit from my desk.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 19, 2021, 08:32:51 pm
Noting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces.

Linux has best tools and allows greatest hacking capability, so you could use these (Pi based on MCP2515):
For the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI.

Lawicel based ones work with both Windows and Linux (and can occasionally drop frames on very congested 1Mbit networks), but above ones are my favorites (especially if you have proper DBC files for automatic data decoding). For software/hardware specifics read my older messages.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 08:44:26 pm
Noting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces.

Linux has best tools and allows greatest hacking capability, so you could use these (Pi based on MCP2515):
For the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI.

Lawicel based ones work with both Windows and Linux (and can occasionally drop frames on very congested 1Mbit networks), but above ones are my favorites (especially if you have proper DBC files for automatic data decoding). For software/hardware specifics read my older messages.

Thanks Avra, noted. It's all extremely tentative at the moment, I anticipate it would be entirely point-to-point and low-speed.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 19, 2021, 08:44:54 pm

Thanks for that. I see http://www.can232.com/?page_id=16 and note that that's described as having an FTDI interface, so I've got a fair degree of confidence that Linux will see it (as remarked elsewhere, I've bought lots of stuff over the last year or so that has an embedded serial chip).

Is the clone you're thinking about something like https://www.ebay.co.uk/itm/143099880796 ?

I can see the various SPI interfaces, but at least initially I want to be able to exercise some kit from my desk.

MarkMLl

The biggest problem with that one and most of the crap coming from China is that the CAN bus is designed for 3 wires, not two.  Ground is a fundamental part of the circuit and it's find if you have an arduino or Pi which is also powered from the vehicle 12V power system as at some point the arduino power ground matches up with the vehicle CAN bus ground .

The late Steve Corrigan at TI (he designed TI's CAN driver chips) and I had a long discussion about that.  I even set up two 82C250 CAN transceivers both run from 9V batteries into 78L05 regulators.  I coupled only the two CAN signals so no physical ground connection.  There was no problem sending with only two wires so you'd think it would be fine.  Which is why you see the crap out there not supplying a ground assuming the vehicle ground is on both.  But here's the reason you need the ground.

Ultimately it's possible for the ground from one device to be connected to the ground from the other through some peculiar way.  Now the two CAN signals which are referenced to ground (2.5V is recessive relative to their own ground) could have more than 7V between the two grounds.  This results in a common mode voltage that is higher than the transceiver and it pops.  Or worse you don't exceed it but you get a lot of bus faults that are sporadic and non-deterministic.   The error counters go up and down and you can't pinpoint the reason.  As soon as you put the scope on it the errors  go away.

So watch out for dongles that don't provide the standard DB-9 CANopen pin format.  Notice on this link they don't make the ground pin optional.

https://www.kvaser.com/about-can/the-can-protocol/can-connectors/ (https://www.kvaser.com/about-can/the-can-protocol/can-connectors/)


Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 08:54:22 pm
Thanks for the reminder about grounding and the extra link, I actually had much of that stuff drummed into me when I was hooking up an early not-quite-PC LAN in about 1984 :-)

For the moment this is strictly desktop-experimentation (well, desktop plus a cable to my antenna mast) and if anything production comes of it cost will be little object (you ought to see the cost of the traditional opposition...)

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 19, 2021, 08:55:13 pm
Noting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces.

Linux has best tools and allows greatest hacking capability, so you could use these (Pi based on MCP2515):
For the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI.

Lawicel based ones work with both Windows and Linux (and can occasionally drop frames on very congested 1Mbit networks), but above ones are my favorites (especially if you have proper DBC files for automatic data decoding). For software/hardware specifics read my older messages.

Yes the problem with the Lawicel using the COMx: on windows is more to do with the USB side of things.  The CANUSB buffers a fair number of messages and uses the 8bit bus based SJA1000 CAN device.  But if the USB can't get them out fast enough (the serial port driver is the issue) then at really high bus speeds with 100% utilized bus there can be problems. 

There is a DLL based driver that doesn't have the overhead of the serial port.  However I don't think that's supported on Linux.

If you are using 29 bit Extended IDs then you can use 135 bits as a general rule for largest message size including stuff bits.  So at 1MBps we're talking 135uS per message with the bus at 100%.  That's only about 7.5kHz with the largest messages.  But if you are running standard IDs with only one or two bytes in the messages now you can go back to back about 64 bits and double the message rate just over 15kHz.    A 10Mhz SPI bus has no trouble with this.  But it's hard to do that with a PC unless it's USB with a dedicated driver, not the serial port.

For example:  15kHz for a Lawicel message might be t12325566<CR>  which is 10 characters.  That's 150 kbaud and most USB interfaces start to break down above 115Kbaud.  Although DMX512A for light shows are 250kbaud.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 08:59:52 pm
most USB interfaces start to break down above 115Kbaud.  Although DMX512A for light shows are 250kbaud.

Particularly if they use a counterfeit chip. I'm amassing a photo collection...

As a slight aside, if deciding on a default "Baud rate" ** for a serial link it's worth considering that some Arduino-like devices (e.g. ESP32) don't support below 38k4.

MarkMLl

** I know, that's why I put it in quotes.
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 19, 2021, 09:01:02 pm
Thanks for the reminder about grounding and the extra link, I actually had much of that stuff drummed into me when I was hooking up an early not-quite-PC LAN in about 1984 :-)

For the moment this is strictly desktop-experimentation (well, desktop plus a cable to my antenna mast) and if anything production comes of it cost will be little object (you ought to see the cost of the traditional opposition...)

MarkMLl

I started working with CAN and the 82C200 in 1992.  Before there were CAN drivers.  The 82C200 (now SJA1000) had drivers on board for resistive termination and was rated at max 100kbps.  We were using it at 333kbps only because the original author made a config mistake aiming for 500kbps.  By the time I figured that out there were too many systems in the field.

A year later Philips came out with the 82C250 and we were given 250 to play with.  A bunch of machines went out with those and only later when we started having problems did we learn they were pre-production prototypes never meant for distribution in the field.  They had a serious issue with returning to recessive state and floated all over the place.

My solution was a resistor array that pulled the CAN_H to 2.4V and the CAN_L to 2.6V during the recessive state.  During dominant the device would still go 4.0V for CAN_H and 1.0V for CAN_L and all was good. 

Good times....
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 19, 2021, 09:04:01 pm
most USB interfaces start to break down above 115Kbaud.  Although DMX512A for light shows are 250kbaud.

Particularly if they use a counterfeit chip. I'm amassing a photo collection...

As a slight aside, if deciding on a default "Baud rate" ** for a serial link it's worth considering that some Arduino-like devices (e.g. ESP32) don't support below 38k4.

MarkMLl


** I know, that's why I put it in quotes.
Just remember that UARTs have 'BAUD' rates and CAN has BitRates.  BAUD is derived from Baudot and 5 bits of data with a start bit and two stop bits.  Now of course we tend to use 8 bits with one start and one stop.  So a Baud rate of 9600 baud means exactly 960 characters per second.  Calling CAN rate a baud rate tells you nothing. 

Pet peeve of mine.  Sorry.... %)


Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 09:04:23 pm
A colleague at Lowbrow had had his PhD (possibly at Liverpool) paid for by Ripaults designing a vehicle data bus. He joined at the same time as I did- late '83- which gives some idea of the timeframe... there must have been many companies working on the same thing.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 19, 2021, 09:06:35 pm
A colleague at Lowbrow had had his PhD (possibly at Liverpool) paid for by Ripaults designing a vehicle data bus. He joined at the same time as I did- late '83- which gives some idea of the timeframe... there must have been many companies working on the same thing.

MarkMLl

I think that's why you see so many busses on the OBD-II connector.  Now I think it's all standardized on CAN and for heavy vehicles J1939.  For the military stuff I worked on it was MilCAN which is still standard J1939 but with some 'rules' of behavior for the messaging.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 19, 2021, 09:07:58 pm
Yes, I've also seen RS232 on it. Range Rover suspension...

(Later:) I've ordered one of those cheap interfaces and will report back. My suspicion is that that jumper probably ties one side of the data to (USB) ground...

At a pinch I should be able to monitor the bus with my logic analyser, which is good for +-40V :-)

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 20, 2021, 02:04:59 pm
Ground is a fundamental part of the circuit and it's find if you have an arduino or Pi which is also powered from the vehicle 12V power system as at some point the arduino power ground matches up with the vehicle CAN bus ground.
There are galvanic isolated Pi shields like https://www.sg-electronic-systems.com/can-bus-dual-iso-v2-1-shield-for-raspberry/ which help when you must have separate power supply for your equipment. I solve that problem simply by powering Pi from the vehicle (Pi Zero is sufficient for CAN hacking), and then ssh or vnc to Pi from my laptop via WiFi. I even have a 4.3" display and small wireless keyboard for the Pi, but I find laptop access more convenient in 90% of the cases.
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 20, 2021, 02:18:46 pm
(Later:) I've ordered one of those cheap interfaces and will report back.
There are AVR, ESP32 and STM32 projects which implement Lawicel protocol, so if at the end you become unsatisfied with your device then you can go DIY path.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on October 20, 2021, 02:24:11 pm
(Later:) I've ordered one of those cheap interfaces and will report back.
There are AVR, ESP32 and STM32 projects which implement Lawicel protocol, so if at the end you become unsatisfied with your device then you can go DIY path.

Understood, and the transceiver boards are available cheaply in this country from the usual suspects... unlike cheap USB-connected interfaces. So I'm just trying to think ahead...

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 28, 2021, 07:12:46 pm
... I solve that problem simply by powering Pi from the vehicle (Pi Zero is sufficient for CAN hacking), and then ssh or vnc to Pi from my laptop via WiFi.
Happy me just ordered 2 of these new toys: https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on November 16, 2021, 11:44:31 am
(Later:) I've ordered one of those cheap interfaces and will report back. My suspicion is that that jumper probably ties one side of the data to (USB) ground...

The cheap interface (little black box with a blue/white label) has a jumper which controls whether a resistor is across the lines, but neither line is tied to ground unless there's provision for that in the interface chip (SIT1050). The markings on the main chip are obliterated but plugged into an unconfigured Linux system is identified as 10c4:ea60 CP210x (/dev/ttyUSBx).

Spurious rules in 60-gpsd.rules aliased this as a GPS device, I chopped those since I've got several things with one of those chips in it and I don't want anything getting in the way (now all I need to do is re-enable all the gpsd stuff before I forget about it).

I find I need to load a custom module and bring a link up manually, after which I can see an interface:


# modprobe slcan
# slcand -o -c -f -s4 /dev/ttyUSB2 can0
# ip link set can0 up

6: can0: <NOARP,UP,LOWER_UP> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can


At this point I need to do more research. I'm attached on a one-to-one basis to a device with documented addresses, and I need to read and possibly write some of those. Any suggestions would be appreciated, and I'll post any updates I work out myself.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: avra on November 24, 2021, 12:33:25 am
I need to load a custom module and bring a link up manually
That is normal. See https://pascal-walter.blogspot.com/2015/08/installing-lawicel-canusb-on-linux.html

I'm attached on a one-to-one basis to a device with documented addresses, and I need to read and possibly write some of those. Any suggestions would be appreciated
Install can-utils. Although there are other tools you can find if you search through my older messages in this thread, everything needed is already there. It is best if you have CAN messaging docs for your devices, but CAN hacking is not that hard, either. In hacking you try to physically change something on your device and while spying CAN network you try to interpret data changes you see in the messages (CAN data messages are usually heavily bit packed records with no bits wasted and no byte alignment). Without docs it will be hard to guess how to send data to device, so it might be helpful to already have a device which writes to target device. Then all you need is to spy those messages and simply replicate them or try to guess the message data structure when you need to have a variable parameter.

Here is some real life example. Let's say that you're lucky and in your car you have a button without any function attached to it, and you are not satisfied with just 2 speeds for your rain wiper blades. You need to spy the vehicle CAN network (usually there are more CAN networks then just one you access through OBD-II interface), and then look for new messages, or changes in existing messages when you press that button. Then you spy for message which shows when you press button for a single manual rain wiper blade cycle. Now, you should have everything needed to write a program which waits for a single, double, or long click on unused button to set custom interval which will be used for commanding rain wiper blades, and increase or decrease it in case of a need. When everything works the way you want on your Pi, you can program some Arduino like board and leave your custom device permanently in the car.

Happy you, problem solved!  :D :D :D

Now imagine other ideas like protecting your vehicle start up with morse like taps on a button. Sky is the limit.... Have fun!  %) 8) %)

PS: If you do not have unused button in your car, you will probably be able to find a button to which you can safely add double, triple or long click. There are even cheap wireless bluetooth multimedia buttons which you can attach to your wheel or on your dashboard. They can be used as custom additional buttons for your bluetooth Arduino (all ESP microcontrollers have BT) when you can not find any unused button in your car.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on November 24, 2021, 08:25:13 am
Current situation is that I've been looking through dumps that various other people have captured, but they don't interact with the specific device I've got standalone. I'm in the middle of making a T-cable to tap into a live system, which needs a couple of moderately-expensive connectors: until then I can't be 100% sure that slcan etc. is working properly.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: avra on November 24, 2021, 08:49:50 am
I'm in the middle of making a T-cable to tap into a live system, which needs a couple of moderately-expensive connectors
There are contactless crocodile clips which can be used if you only need to spy data without sending anything (like just spying J1939):
https://copperhilltech.com/cancrocodile-contactless-can-bus-j1708-reader/

or tap into cable system without connectors using intrusive T splitters:
https://www.aliexpress.com/item/4001147302536.html

You might also use thin needles hack to tap into the system without a need for an expensive connector.

Of course, nothing like a real thing. But these days receiving products from online ordering can take forever.
Title: Re: CAN-BUS SocketCAN
Post by: MarkMLl on November 24, 2021, 09:11:11 am
I've got the connectors, just need steel myself for the crimping... it's a one-time assembly with environmental seals etc.

£20 for a pair isn't too bad, considering. But in principle it should be possible to have a stock of "close enough" pins and receptacles and 3D-print the housings on demand.

MarkMLl
Title: Re: CAN-BUS SocketCAN
Post by: unoAchtung on October 20, 2022, 03:13:13 pm
Impressive work!

How do I do if I want to find out which channels that are available on the device (can0, can1, etc.)?
Title: Re: CAN-BUS SocketCAN
Post by: jcdammeyer on October 20, 2022, 06:26:28 pm
Boy it's been over a year since I did anything with this.  Work-work and COVID shutdows got in the way.  In a few months I should be able to get back to this project.  I've pretty well abandoned the BeagleBone Black.  The OS just keeps changing with respect to I/O breaking existing code. 
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 22, 2022, 01:40:57 pm
Impressive work!
Thanks!  ;)

How do I do if I want to find out which channels that are available on the device (can0, can1, etc.)?
Using ifconfig from net-tools package can show CAN device interfaces that you have already brought up:
Code: Pascal  [Select][+][-]
  1. ifconfig | grep can
but beware that out of the box linux does not bring any interfaces automatically. You have to do it on your own if there is no vendor script for that purpose. You can find relevant tutorials in my initial posts.
Title: Re: CAN-BUS SocketCAN
Post by: unoAchtung on October 24, 2022, 09:55:16 am
If I want to list the devices in my FPC application, how can I get the devices through FPC code?
Title: Re: CAN-BUS SocketCAN
Post by: avra on October 24, 2022, 11:17:31 am
If I want to list the devices in my FPC application, how can I get the devices through FPC code?
Either asume that ifconfig is installed and each CAN interface has CAN word in it's name so you can use output of this command line:
Code: Pascal  [Select][+][-]
  1. avra@vm-debian:~$ ifconfig | grep can | sed -r 's#:.*##'
  2. vcan0
  3. vcan1
or analyze source code of ifconfig and try to replicate part of it's functionality in pascal:
https://github.com/giftnuss/net-tools/blob/master/ifconfig.c

EDIT:

Ok, I was playing a little so here is version 2 which still depends on net-tools package and CAN substring in interface name:
Code: Pascal  [Select][+][-]
  1. avra@vm-debian:~$ netstat -i | grep can | sed -r 's# .*##'
  2. vcan0
  3. vcan1
and version 3 which lists all can, vcan and vxcan interfaces without depending on net-tools package or CAN substring in their name:
Code: Pascal  [Select][+][-]
  1. avra@vm-debian:~$ ip link show type can | grep : | sed -r 's#: <.*##' | sed -r 's#.* ##' && ip link show type vcan | grep : | sed -r 's#: <.*##' | sed -r 's#.* ##' && ip link show type vxcan | grep : | sed -r 's#: <.*##' | sed -r 's#.* ##'
  2. vcan0
  3. vcan1

As you can guess, of all command lines version 3 is the best since ip command exists in most modern distros (iproute2 package). However, you should not asume anything and always do the checking on your own.
TinyPortal © 2005-2018