SocketCAN

aus Wikipedia, der freien Enzyklopädie
Zur Navigation springen Zur Suche springen

SocketCAN ist eine Sammlung von CAN-Treibern und einer Netzwerkschicht, beigestellt von der Konzernforschung der Volkswagen AG zum Linux-Kernel als Open Source. Sie ist auch bekannt als Low Level CAN Framework (LLCF).

Typisches Schichtenmodell der CAN-Kommunikation, mit SocketCAN (links) oder konventionell (rechts)

Vorherrschende CAN-Treiber basieren auf dem Modell eines zeichenorientierten Gerätes (character device). Typischerweise erlauben diese Treiber für einen CAN-Controller nur das Senden und Empfangen. Die Implementierungen für diese Geräteklasse erlauben meist nur einem einzigen Prozess auf das Gerät zuzugreifen, d. h. für alle anderen Prozesse ist diese serielle Schnittstelle blockiert. Darüber hinaus ist die Schnittstelle des Treibers zur Anwendung im Detail unterschiedlich und nicht vereinheitlicht, was die Portabilität einer CAN-Anwendung verringert. Das SocketCAN-Konzept hingegen nutzt das Modell der Netzwerkgeräte. Es gestattet mehreren Anwendungen gleichzeitig auf CAN-Funktionen zuzugreifen. Auch können einzelne Anwendungen mehrere CAN-Netzwerke parallel nutzen.

Im Namen SocketCAN verbirgt sich bereits der wesentliche Aspekt von Sockets. Das SocketCAN Konzept erweitert die klassische Berkeley-Socket-API eines Betriebssystems. SocketCAN fügt dazu eine gemeinsame Protokoll-Familie genannt PF_CAN dem Netzwerk-Stack18 hinzu, welches neben anderen bekannten Protokoll-Familien wie z. B. PF_INET fürs Internet unabhängig koexistiert. Elementar besteht SocketCAN selbst aus Netzwerk-Treibern für CAN-Controller und einer Infrastruktur für neue CAN-Protokolle. Mit Raw-Sockets kann direkt auf den CAN-Bus zugegriffen werden.

Daneben gibt es Erweiterungen für Transportprotokolle wie z. B. ISO-TP. ISO-TP kann größere Datentelegramme bis 4095 Bytes in eine Folge kleinerer CAN-Frames segmentieren. Durch eine Adressierung in Form von zwei CAN-ID-Paaren ist der Aufbau einer Punkt-zu-Punkt-Verbindung möglich. Zusätzlich gibt es in SocketCAN ein Broadcast-Manager, der es ermöglicht CAN-Botschaften zu filtern und periodisch zu verschicken. Die Unterstützung für SocketCAN ist zum jetzigen Zeitpunkt ausschließlich für Linux ab der Kernel-Version 2.6.25 gegeben. SocketCAN wird aktiv weiter entwickelt, ständig kommen weitere Netzwerk-Treiber für CAN-Controller hinzu.

Die Anwendung richtet zunächst den Zugang der CAN-Schnittstelle durch Initialisierung eines Sockets (ähnlich einer TCP/IP-Kommunikation), bindet diesen Socket (bind) an eine Schnittstelle (oder alle Schnittstellen, sofern von der Anwendung beabsichtigt). Bei erfolgreicher Anbindung, ist der Socket durch z. B. die Funktionen fürs Lesen read(..) und Schreiben write(..) nutzbar.

Python unterstützt SocketCan ab Version 3.3.[1]

Das nachfolgende einfache Beispiel sendet und liest ein Paket durch die Nutzung des RAW-Socket.

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>

#include <linux/can.h>
#include <linux/can/raw.h>
#include <string.h>

/* At time of writing, these constants are not defined in the headers */
#ifndef PF_CAN
#define PF_CAN 29
#endif

#ifndef AF_CAN
#define AF_CAN PF_CAN
#endif

/* ... */

/* Somewhere in your app */

   /* Create the socket */
   int skt = socket( PF_CAN, SOCK_RAW, CAN_RAW );

   /* Locate the interface you wish to use */
   struct ifreq ifr;
   strcpy(ifr.ifr_name, "can0");
   ioctl(skt, SIOCGIFINDEX, &ifr); /* ifr.ifr_ifindex gets filled
                          * with that device's index */

   /* Select that CAN interface, and bind the socket to it. */
   struct sockaddr_can addr;
   addr.can_family = AF_CAN;
   addr.can_ifindex = ifr.ifr_ifindex;
   bind( skt, (struct sockaddr*)&addr, sizeof(addr) );

   /* Send a message to the CAN bus */
   struct can_frame frame;
   frame.can_id = 0x123;
   strcpy( (char *)frame.data, "foo" );
   frame.can_dlc = strlen( (const char *)frame.data );
   int bytes_sent = write( skt, &frame, sizeof(frame) );

   /* Read a message back from the CAN bus */
   int bytes_read = read( skt, &frame, sizeof(frame) );

Einzelnachweise

[Bearbeiten | Quelltext bearbeiten]
  1. bugs.python.org