Recent

Author Topic: CAN-BUS SocketCAN  (Read 9974 times)

jcdammeyer

  • Full Member
  • ***
  • Posts: 119
  • Embedded System Developer
    • Automation Artisans Inc.
Re: CAN-BUS SockectCAN
« Reply #30 on: March 03, 2021, 07:11:19 pm »
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. :)

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #31 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.  :)
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #32 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;
« Last Edit: March 08, 2021, 11:37:14 am by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #33 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...
« Last Edit: March 08, 2021, 02:48:33 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #34 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.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #35 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.  
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #36 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.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #37 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-)
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

ThomasK

  • New Member
  • *
  • Posts: 13
Re: CAN-BUS SockectCAN
« Reply #38 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
Started Pascal on a Siemens 4004/151 in 1977. TurboPascal 1.0 in 1984 on PC-Dos.

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #39 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
« Last Edit: March 11, 2021, 03:17:04 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #40 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.
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

ThomasK

  • New Member
  • *
  • Posts: 13
Re: CAN-BUS SockectCAN
« Reply #41 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.
Started Pascal on a Siemens 4004/151 in 1977. TurboPascal 1.0 in 1984 on PC-Dos.

Fred vS

  • Hero Member
  • *****
  • Posts: 2201
    • StrumPract is the musicians best friend
Re: CAN-BUS SockectCAN
« Reply #42 on: March 11, 2021, 03:33:57 pm »
@Avra: Wonderful! (like always with you  ;))

Many thanks.

Fre;D
I use Lazarus 2.0.6 32/64 and FPC 3.2.0 32/64 on Debian 10.2 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64 and Mac OS X Snow Leopard 32.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt, Carbon.

https://github.com/fredvs
https://gitlab.com/fredvs

avra

  • Hero Member
  • *****
  • Posts: 2144
    • Additional info
Re: CAN-BUS SockectCAN
« Reply #43 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...
« Last Edit: March 11, 2021, 03:49:01 pm by avra »
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

sstvmaster

  • Full Member
  • ***
  • Posts: 241
Re: CAN-BUS SockectCAN
« Reply #44 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
Windows 10 (64 bit)
Lazarus: 2.0.12 / Trunk x32

 

TinyPortal © 2005-2018