GniazdoCAN

SocketCAN to zestaw sterowników CAN typu open source i stos sieciowy wniesiony przez Volkswagen Research do jądra Linuksa . SocketCAN był wcześniej znany jako Low Level CAN Framework (LLCF).

Typowe warstwy komunikacji CAN. Z SocketCAN (po lewej) lub konwencjonalnym (po prawej).

Tradycyjne sterowniki CAN dla systemu Linux oparte są na modelu urządzeń znakowych. Zazwyczaj pozwalają tylko na wysyłanie i odbieranie ze sterownika CAN. Konwencjonalne implementacje sterowników urządzeń tej klasy umożliwiają tylko jednemu procesowi dostęp do urządzenia, co oznacza, że ​​wszystkie inne procesy są w międzyczasie blokowane. Ponadto wszystkie te sterowniki zwykle różnią się nieznacznie interfejsem aplikacji, co ogranicza przenośność. Z drugiej strony koncepcja SocketCAN wykorzystuje model urządzeń sieciowych, który umożliwia wielu aplikacjom równoczesny dostęp do jednego urządzenia CAN. Ponadto pojedyncza aplikacja może równolegle uzyskiwać dostęp do wielu sieci CAN.

Koncepcja SocketCAN rozszerza interfejs API gniazd Berkeley w systemie Linux, wprowadzając nową rodzinę protokołów, PF_CAN, która współistnieje z innymi rodzinami protokołów, takimi jak PF_INET dla protokołu internetowego . Komunikacja z magistralą CAN odbywa się więc analogicznie jak przy wykorzystaniu protokołu internetowego poprzez gniazda. Podstawowymi komponentami SocketCAN są sterowniki urządzeń sieciowych dla różnych kontrolerów CAN oraz implementacja rodziny protokołów CAN. Rodzina protokołów PF_CAN zapewnia struktury umożliwiające różne protokoły na magistrali: Raw Sockets do bezpośredniej komunikacji CAN i protokoły transportowe do połączeń punkt-punkt. Ponadto menedżer transmisji, który jest częścią rodziny protokołów CAN, udostępnia funkcje np. okresowego wysyłania komunikatów CAN lub realizowania złożonych filtrów komunikatów. Od Jądro Linuksa w wersji 5.10 rodzina protokołów obejmuje również implementację ISO-TP , CAN_ISOTP.

jądrze Linuksa 2.6.25 dodano łatki dla CAN . W międzyczasie dodano kilka sterowników kontrolerów i trwają prace nad dodaniem sterowników dla różnych kontrolerów.

Stosowanie

Aplikacja najpierw konfiguruje swój dostęp do interfejsu CAN poprzez inicjalizację gniazda (podobnie jak w komunikacji TCP/IP), a następnie powiązanie tego gniazda z interfejsem (lub wszystkimi interfejsami, jeśli aplikacja sobie tego życzy). Po związaniu gniazdo może być następnie używane jak UDP poprzez odczyt , zapis itp.

Python dodał obsługę SocketCAN w wersji 3.3. Biblioteka open source python-can zapewnia obsługę SocketCAN dla Pythona 2 i Pythona 3 [ odwołanie cykliczne ] .

Instalacja urządzenia CAN wymaga załadowania modułu can_dev i skonfigurowania łącza IP w celu określenia szybkości transmisji magistrali CAN, na przykład:


 $  modprobe can_dev  $  modprobe can  $  modprobe can_raw  $  zestaw  sudo ip  can0  typ  can bitrate  500000  $ sudo   konfiguracja  łącza ip  can0 

Istnieje również wirtualny sterownik CAN do celów testowych, który można załadować i utworzyć w systemie Linux za pomocą poniższych poleceń.


 $  modprobe can  $  modprobe can_raw  $  modprobe vcan  $  sudo ip link add dev vcan0  typ  vcan  $  sudo ip link  set  up vcan0  $  ip link show vcan0  3: vcan0: <NOARP,UP,LOWER_UP> mtu 16 qdisc noqueue stan UNKNOWN  link/can 

Poniższy fragment kodu to działający przykład interfejsu API SocketCAN, który wysyła pakiet przy użyciu surowego interfejsu. Opiera się na uwagach udokumentowanych w Linux Kernel .

 
 
 
 

 
 
 
 

 
 




	 
	 
	 #include  <stdio.h>  #include  <stdlib.h>  #include  <unistd.h>  #include  <string.h>  #include  <net/if.h>  #include  <sys/types.h>  #include  <sys /socket.h>  #include  <sys/ioctl.h>  #include  <linux/can.h>  #include  <linux/can/raw.h>  int  main  (  void  )  {  int  s  ;  int  nbajtów  ;  struktura   
	  
	  

	    

	        
		
		 
	 sockaddr_can  adres  ;  struct  can_frame  ramka  ;  struct  ifreq  ifr  ;  const  char  *  ifname  =  "vcan0"  ;  if  ((  s  =  socket  (  PF_CAN  ,  SOCK_RAW  ,  CAN_RAW  ))  ==  -1  )  {  perror  (  "Błąd podczas otwierania gniazda"  );  powrót  -1  ;  } 

	 
	  
	
	   
	  

	   strcpy  (  jeśli  .  nazwa_jeśli  ,  jeśli nazwa  );  ioctl  (  s  ,  SIOCGIFINDEX  ,  &  ifr  );  adres  .  can_family  =  AF_CAN  ;  adres  .  can_ifindex  =  ifr  .  ifr_ifindex  ;  printf  (  "  %s w indeksie %d  \n  "  ,  ifname  ,  ifr.ifr_ifindex  )  ; 

	        
		
		 
	

	   
	  
	 if  (  bind  (  s  ,  (  struct  sockaddr  *  )  &  addr  ,  sizeof  (  addr  ))  ==  -1  )  {  perror  (  "Błąd w powiązaniu gniazda"  );  powrót  -2  ;  }  ramka  .  can_id  =  0x123  ;  rama  .  can_dlc  =  2  ;  rama  .  dane 0  
	  

	     

	 
	
	 0
 [  ]  =  0x11  ;  rama  .  dane  [  1  ]  =  0x22  ;  nbajtów  =  write  (  s  ,  &  ramka  ,  sizeof  (  struct  can_frame  ));  printf  (  "Zapisano %d bajtów  \n  "  ,  nbajtów  );  powrót  ;  } 

Pakiet można przeanalizować na interfejsie vcan0 za pomocą narzędzia candump, które jest częścią pakietu can-utils SocketCAN.

 użytkownik@serwer:~/can-utils $  ./candump vcan0  vcan0 123 [2] 11 22 
  1. Bibliografia _ _ 14 maja 2021 r. – przez GitHub.
  2. ^ „Problem 10141: Obsługa SocketCan - śledzenie Pythona” . bugs.python.org .
  3. Bibliografia _
  4. ^ Można przeglądać online z Linux Kernel Documentation lub w linux/Documentation/networking/can.txt w najnowszych drzewach źródeł
  5. ^ can-utils https://github.com/linux-can/can-utils/

Linki zewnętrzne