Low Level CAN Framework


Application Programmers Interface




Version 1.0.0



2006-02-20




Contents


Introduction

Among various projects in the research department of Volkswagen AG there is a so-called Low Level CAN Framework (LLCF) developed for easy access of the communication layers of the Controller Area Network (CAN) for applications. The Low Level CAN Framework should, where possible, be modular in design to the greatest possible extent to achieve reuse in other projects.

Essential components of the LLCF are the network (!) Driver for the different CAN controller and the overlying protocols such as TP1.6, TP2.0, MCNet, ISO-TP, etc. These components are implemented in the Linux Kernel and are using the standardized Socket interface. The goal of this concept is that communication on the CAN bus be as far as possible similar to the ordinary use of TCP/IP sockets. This is only partly possible because the CAN bus has a number of differences with TCP/IP and Ethernet:

Figure 1: Different addressing between Ethernet / CAN
\begin{figure}\begin{center}
\par
\psfig{file=frame_types.eps}
\par\end{center}\end{figure}

These differences mean that the structure struct sockaddr_can is not entirely analogous to the known struct sockaddr_in for the TCP/IP protocol family. The process to establish a connection and the use of open sockets for data exchange, however, are heavily based on TCP/IP model.

Besides this document, there are also the manual pages: socket(2), bind(2), listen(2), accept(2), connect(2), read(2), write(2), recv(2), recvfrom(2), recvmsg(2), send(2), sendto(2), sendmsg(2), socket(7), packet(7) relevant to LLCF. The manual mages ip(7), udp(7) and tcp(7) give insights on the foundations on which the LLCF is based.

The Low Level CAN Framework is in addition to the known protocols, such as the the ones from the Internet Protocol family PF_INET. A new protocol family PF_CAN has been introduxed. To meet time constraints, the implementation of the various CAN protocols has been made as kernel modules, in the kernel context. An implementation in user sapce could not have met the same constraints. During execution of different applications (leading to several open socket instances), the same code is used for execution.

Figure 2: The LLCF in the Linux-Kernel
\begin{figure}\begin{center}
\par
\psfig{file=llcf_overview.eps}
\par\end{center}\end{figure}

The LLCF provides various transport protocols and the so-called Broadcast-Manager (BCM). In addition a RAW socket is provided, to give direct access to the CAN bus without intervening protocol layers.

A special feature is the so-called LLCF RX-dispatcher. It is used to manage the addressing of CAN-frames by CAN ID. By using the LLCF functions rx_register() and rx_unregister(), the protocol modules can register one or more CAN-IDs they are interested in and the LLCF-core module will dispatch the messages at the reception automatically. The LLCF-core module sends to the CAN bus a local echo ('local loopback') of sent CAN frames to allow all applications on a system to share the same information.

Figure 3: The LLCF Kernel module in Linux Kernel
\begin{figure}\begin{center}
\par
\psfig{file=llcf_module.eps}
\par\end{center}\end{figure}

For the connection of the CAN network drivers, a new 'Ethernet protocol type' ETH_P_CAN was introduced to allow the transit of the received CAN frames through the Linux network layer. The LLCF-core module registers himself as recipient of ETH_P_CAN 'Ethernet frames' to the kernel.

Through the consistent implementation of the CAN bus with interfaces from the established information technology standard, many opportunities open up for the user (programmer). I.e. Any number of sockets (also different socket types on different CAN buses) from one or more applications can be open simultaneously. When communicating with different sockets, for example, select(2) can be used to write efficient and simple code.


Legal Notices

Volkswagen requires that the users read, understood and accepted the following the legal notices.


In the source code of the Low Level CAN Framework there is the following notice:

/*
 * Copyright (c) 2002-2005 Volkswagen Group Electronic Research
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, the following disclaimer and
 *    the referenced file 'COPYING'.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Volkswagen nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * Alternatively, provided that this notice is retained in full, this
 * software may be distributed under the terms of the GNU General
 * Public License ("GPL") version 2 as distributed in the 'COPYING'
 * file from the main directory of the linux kernel source.
 *
 * The provided data structures and external interfaces from this code
 * are not restricted to be used by modules with a GPL compatible license.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * Send feedback to <socketcan-users@lists.berlios.de>
 *
 */

Extended Disclaimer

In the scope of the German law there is also, in case of free transfer from gross negligence or intentionally concealed defects, the possibility that the author can be held liable for resulting (consequential) damage.

Although the authors strive to make available error-free software, they cannot exclude bugs. Therefore, the user that agrees to the use of Low Level CAN Framework, agrees to the disclaimer in relation to the Authors and Volkswagen AG and fully recognize and waive any legal options / claims in the event of Defects / damage / damages resulting from the use of the LLCF.

Logo

The logo of the Low Level CAN Framework('/dev/$<$ beetle $>$') is a compound figurative mark owned by Volkswagen AG. It symbolizes the integration of the vehicle in a neighborhood of the standard information technology.

Linux Module License

Part of the complete LLCF distribution is not subject to the GNU Public License, but is proprietary code of Volkswagen AG. This is the source code of the individual Kernel modules marked with the macro MODULE_LICENSE("Volkswagen Group closed source"). When loading those LLCF modules in the Kernel the following warning message will be displayed:

Warning: loading can-tp20.o will taint the kernel: Volkswagen Group closed source
See http://www.tux.org/lkml/#export-tainted for information about tainted modules
Module tainted loaded, with warnings

This is a warning that the module is not loaded under the GNU Public License, but it does not affect the functionality of the Low Level CAN FrameworkTypically, however, questions about error messages generated by 'contaminated' tainted kernels are not, in general, commented / answered by the Linux community.

Modules, which are under the GNU Public License contain the macro MODULE_LICENSE("GPL").

Transport protocols

The complete LLCF distribution contained protocol modules for Transport protocols (currently TP1.6 VAG, VAG TP2.0, Bosch MCNet) that are only available in conjunction with a Non Disclosure Agreement (NDA) available for suppliers of Volkswagen AG. This protocol modules have no reference drivers.

The source code for the designated CAN transport protocol is clearly separated modules, and existed before integration in the Linux Kernel:

This TP code is in clearly seperate modules and had a life outside Linux
from the beginning and does something self-contained that doesn't
really have any impact on the rest of the kernel. The transport
protocol drivers have been originally written for something else and
do not need any but the standard UNIX read/write kind of interfaces.
See <http://www.atnf.csiro.au/people/rgooch/linux/docs/licensing.txt>

MCNet is a CAN transport protocol by Robert Bosch GmbH. The implmentation is covered by MCNet disclaimers ANFORDERUNG DER MCNet-SPEZIFIKATION dated 13.07.1998. More information on MCNet are available from:

Robert Bosch GmbH
Abteilung K7/EFT62
Postfach 77 77 77
D-31132 Hildesheim

Contact:
Dr. Uwe Zurmühl $<$uwe.zurmuehl@de.bosch.com$>$
Detlef Rode $<$detlef.rode@de.bosch.com$>$


General information on the socket API in LLCF

For communication on the CAN bus a new protocol family PF_CAN has been implemented in the socket Layer. From the user, or programmer's, point of view it is analogous to Internet protocol sockets (protocol family PF_INET) with the standard system calls socket(2), bind(2), listen(2), accept(2), connect(2), read(2), write(2) und close(2). See also the introduction in chapter 1.

In contrast to the address structure of Internet addresses (sockaddr_in), the addressing of the PF_CAN sockets needs other content. The address structure is sockaddr_can, defined in the include file af_can.h:

struct sockaddr_can {
    sa_family_t   can_family;
    int           can_ifindex;
    union {
        struct { canid_t rx_id, tx_id; } tp16;
        struct { canid_t rx_id, tx_id; } tp20;
        struct { canid_t rx_id, tx_id; } mcnet;
    } can_addr;
};

In addition to the interface index of the CAN interface, the CAN-IDs tx_id and rx_id is particularly relevant for the respective transport protocols. Transport protocols offer on the CAN bus a virtual point-to-point connection between two CAN-IDs.

Another important structure represents the CAN frame, that the include file can.h defines:

typedef __u32 canid_t;

struct can_frame {
    canid_t can_id;      /* 32 bit CAN_ID + EFF/RTR flags */
    __u8    can_dlc;     /* data length code: 0 .. 8 */
    __u8    data[8] __attribute__ ((aligned(8)));
};

/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */
#define CAN_RTR_FLAG 0x40000000U /* remote transmission request */

/* valid bits in CAN ID for frame formats */
#define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */
#define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */

The structure can_frame contains the elements of a CAN frame, as defined on the CAN bus. The arrangement of the Data (byte order, word order, Little/Big Endian) on the CAN-bus is generally not defined, so the data elements data[] are kept in an array of 8 bytes. Since the data elements, however, focus on an 8 byte memory limit, access is possible up to a width of 64 bits:

#define U64_DATA(p) (*(unsigned long long*)(p)->data)

U64_DATA(&myframe) = 0xFFFFFFFFFFFFFFFFULL;
U64_DATA(&myframe) = 0;

By separating the information in the include files af_can.h and can.h, only the include file can.h is necessary to create a CAN network-driver.

Timestamp

For the applications in the CAN environment it is often of interest an accurate timestamp, that is the time of reception of a message from CAN bus. Such a timestamp can be read with ioctl(2) after reading a message from the socket. This also applies to the sockets of transport protocols, where the timestamp is that of the last corresponding TPDU. The call - for example ioctl(s, SIOCGSTAMP, &tv)- is used in the respective test programs for illustrative purposes.

The timestamp on Linux have a resolution of one microsecond and the reception of a CAN frame in CAN-Network Device is set automatically.


RAW Sockets

Raw sockets allow direct reception and transmission of messages on a CAN bus. Open a RAW socket like this:

s = socket(PF_CAN, SOCK_RAW, 0);

The open socket must first be bound using bind(2) to a CAN-bus interface. The transport protocols address elements tx_id and rx_id in the struct sockaddr_can structure have no role. The following code binds the open socket s to the CAN-Interface CAN1:

struct sockaddr_can addr;
struct ifreq ifr;

addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, "can1");
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_ifindex = ifr.ifr_ifindex;
bind(s, (struct sockaddr *)&addr, sizeof(addr));

It can now use read(2) to receive all CAN frames available on the bus and write(2) to send CAN frames.

read(2) and write(2) use the structure struct can_frame. For each CAN frame to be sent one call write(2) must be made and for for each call to read(2) one CAN frame is received.

For simultaneous reception of messages on all CAN network interfaces (for example, with recvfrom(2)) use zero (0) as the interface index (for example: addr.can_ifindex = 0). The transmission of CAN frames over such a RAW socket must then make use of sendmsg(2).

The RAW socket provides a simple filter function by specifying ranges of CAN IDs that can be filtered out from the data stream. This may be done before calling bind(2) with the system call setsockopt(2) and an array of simple filters to be set. In this Example, all CAN IDs from 0x200 - 0x2FF are passed:

struct can_filter rfilter;

rfilter.can_id   = 0x200; /* SFF frame */
rfilter.can_mask = 0xF00;

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

By using rfilter.can_id |= CAN_INV_FILTER; the filter can also be reversed so that in this case, the CAN-IDs from 0x200 - 0x2FF would not be allowed through.

struct can_filter rfilter[4];

rfilter[0].can_id   = 0x80001234;   /* Exactly this EFF frame */
rfilter[0].can_mask = CAN_EFF_MASK; /* 0x1FFFFFFFU all bits valid */
rfilter[1].can_id   = 0x123;        /* Exactly this SFF frame */
rfilter[1].can_mask = CAN_SFF_MASK; /* 0x7FFU all bits valid */
rfilter[2].can_id   = 0x200 | CAN_INV_FILTER; /* all, but 0x200-0x2FF */
rfilter[2].can_mask = 0xF00;        /* (CAN_INV_FILTER set in can_id) */
rfilter[3].can_id   = 0;            /* don't care */
rfilter[3].can_mask = 0;            /* ALL frames will pass this filter */

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

For using the filter function, the include file raw.h is involved. A change of the filter at run time is possible with additional calls to mansetsockopt2.

Test programms

candump
is a program that receives CAN frames over a RAW socket from one or more CAN device(s) and outputs them in a readable form - available with time stamps. The described filter function of RAW sockets (see above) can be used with adjustable command line parameters. The output can be also in ASC format.

If candump is called without parameters, a help text is shown:

hartko@pplinux1:~/llcf/src/test > ./candump 
Usage: candump [can-interfaces]
Options: -m <mask>   (default 0x00000000)
         -v <value>  (default 0x00000000)
         -i <0|1>    (inv_filter)
         -t <type>   (timestamp: Absolute/Delta/Zero)
         -c          (color mode)
         -s <level>  (silent mode - 1: animation 2: nothing)
         -b <can>    (bridge mode - send received frames to <can>)
         -a          (create ASC compatible output)
         -1          (increment interface numbering in ASC mode)
         -A          (enable ASCII output)

When using more than one CAN interface the options
m/v/i have comma seperated values e.g. '-m 0,7FF,0'

Examples of the use of candump: Simple example to look at two CAN buses. Timestamps start from zero.

hartko@pplinux1:~/llcf/src/test > candump can0 can1 -t z
(0.000000) can0  3FC  [1] 05 
(0.001185) can0   64  [8] 20 14 3F 16 B8 0B 98 3A 
(0.002396) can0   66  [8] 39 00 A1 45 00 00 00 00 
(0.015395) can0   C9  [6] 13 01 00 00 10 27 
(0.028665) can1  110  [3] 87 00 00 
(0.049990) can0  3FC  [1] 05 
(0.051176) can0   64  [8] 20 14 3F 16 B8 0B 98 3A 
(0.052386) can0   66  [8] 39 00 A1 45 00 00 00 00 
(0.065397) can0   C9  [6] 13 01 00 00 10 27 
(0.099974) can0  3FC  [1] 05 
(0.101159) can0   64  [8] 20 14 3F 16 B8 0B 98 3A

Open two CAN buses. Timestamps start from zero. Output in ASC format. The channel numbers are increased by 1 (can0 $\Rightarrow$ 1, can1 $\Rightarrow$ 2).

hartko@pplinux1:~/llcf/src/test > candump can0 can1 -t z -a -1
date Tue Oct 18 09:39:57 2005
base hex  timestamps absolute
no internal events logged
   0.0000 1  3FC          Rx   d 1 05 
   0.0011 1  64           Rx   d 8 20 14 3F 14 B8 0B 98 3A 
   0.0023 1  66           Rx   d 8 49 00 A1 45 00 00 00 00 
   0.0154 1  C9           Rx   d 6 13 01 00 00 10 27 
   0.0286 2  110          Rx   d 3 87 00 00 
   0.0500 1  3FC          Rx   d 1 05 
   0.0512 1  64           Rx   d 8 20 14 3F 14 B8 0B 98 3A 
   0.0524 1  66           Rx   d 8 49 00 A1 45 00 00 00 00 
   0.0654 1  C9           Rx   d 6 13 01 00 00 10 27 
   0.0999 1  3FC          Rx   d 1 05 
   0.1011 1  64           Rx   d 8 20 14 3F 14 B8 0B 98 3A

Filtering messages on CAN0 with bit mask 0x7FC and comparative value 0x66. Timestamp with time difference.

hartko@pplinux1:~/llcf/src/test > candump can0 -m 0x7FC -v 0x66 -t d 
CAN ID filter[0] for can0 set to mask = 000007FC, value = 00000066 
(0.000000) can0   64  [8] 1B 14 3F 21 B8 0B 98 3A 
(0.001202) can0   66  [8] B9 DA A0 45 00 00 00 00 
(0.048833) can0   64  [8] 1B 14 3F 21 B8 0B 98 3A 
(0.001192) can0   66  [8] EB DA A0 45 00 00 00 00 
(0.048790) can0   64  [8] 1B 14 3F 21 B8 0B 98 3A

Filtering messages on CAN0 with bit mask 0x7FC and comparative value 0x66. Timestamp with time difference. The CAn bus CAN1 is read without filtering.

hartko@lin1:~/llcf/src/test > candump can0 can1 -m 0x7FC,0 -v 0x66,0 -t d 
CAN ID filter[0] for can0 set to mask = 000007FC, value = 00000066 
(0.000000) can0   64  [8] 20 14 3F 14 B8 0B 98 3A 
(0.001202) can0   66  [8] 48 00 A1 45 00 00 00 00 
(0.048794) can0   64  [8] 20 14 3F 14 B8 0B 98 3A 
(0.001201) can0   66  [8] 48 00 A1 45 00 00 00 00 
(0.026214) can1  110  [3] 87 00 00 
(0.003006) can1  41B  [4] 1C 12 02 FF 
(0.019612) can0   64  [8] 20 14 3F 14 B8 0B 98 3A 
(0.001201) can0   66  [8] 48 00 A1 45 00 00 00 00 
(0.048770) can0   64  [8] 20 14 3F 14 B8 0B 98 3A

Inverted filter on CAN0 with bit mask 0x7FC and comparative value 0x66. The CAN bus CAN1 has no filtering. The timestamp is displayed completely, i.e. in seconds since 01/01/1970. Analog to 'date +%s' see date(1).

hartko@pplinux1:~/llcf/src/test > candump can0 can1 -m 0x7FC,0 -v 0x66,0 -i 1,0 -t a 
CAN ID filter[0] for can0 set to mask = 000007FC, value = 00000066 (inv_filter)
(1129625880.726372) can0   C9  [6] 13 01 00 00 10 27 
(1129625880.739543) can1  110  [3] 87 00 00 
(1129625880.760949) can0  3FC  [1] 05 
(1129625880.776377) can0   C9  [6] 13 01 00 00 10 27 
(1129625880.810983) can0  3FC  [1] 05 
(1129625880.811580) can1  41C  [4] 1D 12 02 FF 
(1129625880.826379) can0   C9  [6] 13 01 00 00 10 27 
(1129625880.839544) can1  110  [3] 87 00 00 
(1129625880.860955) can0  3FC  [1] 05 
(1129625880.876380) can0   C9  [6] 13 01 00 00 10 27 
(1129625880.910986) can0  3FC  [1] 05

tst-raw
is a program to test RAW sockets. Uses the read(2) system call.
tst-raw-filter
is a programm to test the filter function of RAW sockets. Uses the recvfrom(2) system call.
tst-raw-sendto
is a program to send a CAN-Frame on a non-bound interface with the sendto(2) system call.
canecho
is a program that after receiving a CAN frame retransmits it with the CAN ID increased by 1. It was implemented for the first trials of a real CAN bus interface. Since the LLCF V0.6 has the local echo functionality implemented, canecho is suitable only to carry out full load test ...


Sockets for Broadcast-Manager

The Broadcast-Manager provides functions to send messages on the CAN bus once or periodically, as well as notify of changes in received CAN frames, recognizing specific CAN IDs.

The Broadcast-Manager must meet the following requirements:

Transmission side:

Receiving side:


Communication with the Broadcast-Manager

In contrast to the raw socket (chapter 4), the socket of Broadcast-Manager is not used to send individual CAN frames, instead longer user data structures are transmitted.

Broadcast-Manager is rather a programmable interface that is controlled by special messages from the user via the socket interface.

To use Broadcast-Manager the include file to be used is bcm.h.

A socket for Broadcast-Manager is created with:

s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);

With a call to connect() on the socket, the CAN interface is assigned. If a process must operate on multiple CAN buses, it must therefore open several sockets. It is also possible that a process opens multiple instances (sockets) of Broadcast-Manager on a single CAN-bus, if that makes sense for the application programmer to structure different data flows. Every single instance of Broadcast-Manager is able to realize any number of filter and/or send requests.

addr.can_family = AF_CAN;
strcpy(ifr.ifr_name, "can0");
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_ifindex = ifr.ifr_ifindex;

connect(s, (struct sockaddr *)&addr, sizeof(addr));

All messages from the (user) process to Broadcast-Manager have the same structure. It consists of a message header with the command and several values and zero or more CAN frames, depending on the command used and the action requested:

struct bcm_msg_head {
    int opcode;                   /* command */
    int flags;                    /* special flags */
    int count;                    /* run 'count' times ival1 then ival2 */
    struct timeval ival1, ival2;  /* intervals */
    canid_t can_id;               /* 32 Bit SFF/EFF. MSB set at EFF */
    int nframes;                  /* number of can_frame's in the next field */
    struct can_frame frames[0];
};

The value of nframes indicates how many user data frames follow the message header. The user data frames are used to describe the actual content of a CAN message:

struct can_frame {
    canid_t can_id;      /* 32 bit CAN_ID + EFF/RTR flags */
    __u8    can_dlc;     /* data length code: 0 .. 8 */
    __u8    data[8] __attribute__ ((aligned(8)));
};

The opcode defines the kind of message. Messages from the user to Broadcast-Manager control the operations of the Broadcast-Manager, replies from the Broadcast-Manager indicate certain changes to the user, timeouts, etc.

The transmit and receive path of the Broadcast-Manager are two independent functional blocks.

For the transmit path the following opcodes exist:

TX_SETUP
for setting up and modifying transmission requests
TX_DELETE
to delete send requests
TX_READ
to read out the current broadcasting commands (for debugging purposes)
TX_SEND
for sending a single CAN message

For the receive path the following opcodes exist:

RX_SETUP
for setting and modifying receive filters
RX_DELETE
for deleting receive filters
RX_READ
to read out the current receive filter (for debugging purposes)

The Broadcast-Manager sends response messages in the same form. The Broadcast-Manager sends these these opcodes:

TX_STATUS
in response to TX_READ
TX_EXPIRED
is sent when the counter count reaches ival1 (only if flag TX_COUNTEVT is set, see below)
RX_STATUS
in response to RX_READ
RX_TIMEOUT
sent if the time-controlled reception of a message failed
RX_CHANGED
sent if the first or a revised CAN message was received

Each of these opcode functions uses the can_id referenced.

In addition, there are optional flags which can influence Broadcast-Managers behavior:

SETTIMER :
set the value of ival1, ival2 and count
STARTTIMER :
start the timer with the actual value of ival1, ival2 and count. Starting the timer leads simultaneously to emit a can_frame.
TX_COUNTEVT :
create the message TX_EXPIRED when count expires
TX_ANNOUNCE :
A change of data by the process is emitted immediatly. (Requirement of 'Changing Now' - BAES)
TX_CP_CAN_ID :
copies the can_id from the message header attached to each of can_frame. This is intended only as usage simplification.
TX_RESET_MULTI_IDX :
forces a reset of the index counter from the update to be sent by multiplex message even if it would not be necessary because of the length. See page [*].
RX_FILTER_ID :
there is no filtering of the user data. A match with the received message can_id automatically leads to a RX_CHANGED. so use caution in cyclic messages! If RX_FILTER_ID flag is set, the CAN frame in RX_SETUP can be ignored (i.e., nframes = 0).
RX_RTR_FRAME :
the filter passed is used as CAN message to be sent when receiving an RTR frame.
RX_CHECK_DLC :
A change of the DLC leads to an RX_CHANGED.
RX_NO_AUTOTIMER :
If the timer ival1 in the RX_SETUP has been set equal to zero, on receipt of the CAN message the timer for the timeout monitoring is automatically started. Setting this flag prevents the automatic start timer.
RX_ANNOUNCE_RESUME :
refers also to the time-out supervision of the management RX_SETUP. By setting this flag, when an RX-outs occours, a RX_CHANGED will be generated when the (cyclic) receive restarts. This will happen even if the user data have not changed.


TX_SETUP

With TX_SETUP a specific CAN ID for cyclic send is set or changed.

Typically, it is used with a structure in which the components can_id, flags (SETTIMER, STARTTIMER), count=0, ival2=100ms, nframes=1 are set and the user data in the can_frame structure are filled in accordingly. This variable is then transmitted with the write() system call on the socket to Broadcast-ManagerExample:

    struct {
      struct bcm_msg_head msg_head;
      struct can_frame frame[4]; /* just an example */
    } msg;

    msg.msg_head.opcode  = TX_SETUP;
    msg.msg_head.can_id  = 0x42;
    msg.msg_head.flags   = SETTIMER|STARTTIMER|TX_CP_CAN_ID;
    msg.msg_head.nframes = 1;
    msg.msg_head.count = 0;
    msg.msg_head.ival1.tv_sec = 0;
    msg.msg_head.ival1.tv_usec = 0;
    msg.msg_head.ival2.tv_sec = 0;
    msg.msg_head.ival2.tv_usec = 100000;
    msg.frame[0].can_id    = 0x42; /* obsolete when using TX_CP_CAN_ID */
    msg.frame[0].can_dlc   = 3;
    msg.frame[0].data[0]   = 0x123;
    msg.frame[0].data[1]   = 0x312;
    msg.frame[0].data[2]   = 0x231;

    write(s, &msg, sizeof(msg));

The message length for the command TX_SETUP is, therefore, {[bcm_msg_head] [can_frame]+} i.e. a message header and at least one CAN-Frame.

Timer specifics

The timer can be set to 0 ms (ival1 and ival2). In this case, the variable should be transferred with the flag SETTIMER Broadcast-ManagerTo start a cyclic send timer with the given values, the flags SETTIMER and STARTTIMER in the element flags have to be set.

To complement the above example, you can work with two intervals for the cyclical transmission of the CAN message. Here, the CAN message is sent first count times with interval ival1 and then by an explicit deletion with TX_DELETE or by stopping the timer, with the interval ival2. The interval ival2 may be zero, in which case the transmission after the first count messages stops. If count is zero, the value of ival1 has no role and does not need to be specified.

If the flag STARTTIMER is set, the first CAN message is sent out immediately.

It is important for the user, when switching the Broadcast-Manager from the interval +ival1+ to +ival2+ (the transmission may stop), that the flag TX_COUNTEVT of Broadcast-Manager can be used. When the value count is decremented down to zero, the flag TX_COUNTEVT is set, and Broadcast-Manager sends a message with the opcode TX_EXPIRED to the process. This message contains only a message header (+nframes+ = 0).

Modification of data at runtime

At runtime, the data in the CAN message can be changed. The data are modified in the variable and transferred with the opcode TX_SETUP to the Broadcast-ManagerThis can generate the following special cases:
  1. The cycle should be restarted: set the flag STARTTIMER
  2. The cycle is to be retained, but the changed / appended data will be sent immediately once: set the flag TX_ANNOUNCE
  3. The cycle should be maintained and the changed data is sent instead of the older one: default behavior

Note: when restarting the cycle, the last timer values set (ival1, ival2) are not modified by Broadcast-Manager. But if working with two timers, the value of count is decremented for the period by Broadcast-Manager.


Transmitting different data (multiplexed message datagram)

The Broadcast-Manager can also send multiplex messages. This is needed if, for example, the first byte of user data contains a value used to look up information in the following seven bytes. Another application is the switching / toggling of data content. To use this, a structure with more than one user data frame after the header must be sent to Broadcast-ManagerAs a consequence not a single CAN-ID is sent to the Broadcast-Manager but a number of can_frame. The various user data are sent consecutively in the cycle of transmission. I.e. two can_frame are alternately sent in the desired interval. A change in the data at runtime, causes the transmssion of the the first can_frame the update changed. If the number of messages did not change, a reset of the index can be done by setting the flag TX_RESET_MULTI_IDX.


TX_DELETE

This message will delete the entry for the transmission of the CAN-message with the specified can_id CAN identifier. The message length for the command TX_DELETE is {[bcm_msg_head]} (only the header).


TX_READ

With this message, the current state is read for the specified can_id CAN identifier, i.e. CAN message to be sent, counter, timer values, etc. Broadcast-Manager responds with a message with the opcode TX_STATUS that contains the item. The length of this answer can be different from the original TX_SETUP request. The message length for the command TX_READ is {[bcm_msg_head]} (only a message header).


TX_SEND

To send a single CAN message, without using the special functionality of Broadcast-Manager the TX_SEND opcode is used. In this case one structure is generated in which the components can_id, can_dlc, data[] are filled with the appropriate values. The Broadcast-Manager sends the CAN message directly to the socket defined by the CAN bus. The message length for the command TX_SEND is {[bcm_msg_head] [can_frame]} (i.e. a message header and exactly one CAN-Frame).

Note: of course, single CAN message can be sent with the RAW socket. But you would have to open a RAW socket for a single CAN message when you have an already open BCM-Socket. That is a disproportionately large programming effort.


RX_SETUP

RX_SETUP is used to create or change a receive job for a specific CAN ID. The Broadcast-Manager is used to filter such CAN messages according to various criteria, and send a message to the process for changes and/or timeouts.

Similar to the opcode TX_SETUP (see page [*], a Broadcast-Manager message structure has to be created. The message length for the command RX_SETUP is {[bcm_msg_head] [can_frame]+} (i.e. a message header and at least one CAN-Frame).

In contrast to TX_SETUP the components of the structure in the context of the receiving functionality have some other meanings when they are sent from the process at the Broadcast-Manager:

count
no function
ival1
timeout for CAN message reception
ival2
reduction of RX_CHANGED messages
can_data
contains a mask to filter user data

Timeout monitoring

If the Broadcast-Manager does not receive a CAN message for a longer period than ival1, a message is sent to the process with the opcode RX_TIMEOUT. This message contains only a message header (nframes = 0). A timeout monitoring is not in this case started again.

Typically, the timeout monitoring starts with the reception of a CAN message. By setting the flag STARTTIMER in the RX_SETUP the timeout is immediately started. Setting the flag RX_NO_AUTOTIMER prevents the automatic start of the surveillance timeout when receiving a CAN message.

Background: The automatic start of the surveillance timeout when receiving a message makes each occurring cyclic failure of a CAN message clearly, without the user having to do anything.

To recognize a resumption of the cycle under the same user data securely, the flag RX_ANNOUNCE_RESUME must be set.

Reduction of RX_CHANGED messages

Even when the filtering of user data is active, the user application can be overwhelmed by RX_CHANGED messages when the data change rapidly (e.g. speed).

For this purpose, the timer ival2 can be set. It describes the minimum period in which successive RX_CHANGED messages for each can_id may be sent from the Broadcast-Manager.

Note: If, during the blocked time, further changed CAN messages are received, the last valid one will be transferred after the lockout with a RX_CHANGED. It can happen that intermittent (e.g. alternating) state transitions are lost.

Note for MUX messages: After the lockout, all occurring RX_CHANGED messages are sent in succession to the process. I.e. a change for each MUX entry is displayed.

Message filtering (user data - simple)

Analogous to the transfer of user data in TX_SETUP (see page [*]), in RX_SETUP a mask can be set to filter the incoming user data. Only the first user data entry (data[]) of the structure can_frame is evaluated by the Broadcast-Manager for message filtering.

A bit set in the mask in this case means that the corresponding bit in the CAN message must be monitored for a change.

In a received CAN message, if one change is detected from the last received message in one of the bits specified in the mask, the message RX_CHANGED with the full CAN frame received will be sent to the process. The first time a message is received, the received CAN frame is generally sent to the process - only then it can eventually be tested for changes. Tip: by setting the filter mask to zero, the process will receive a unique example of an otherwise cyclical message.

Message filtering (user data - multiplex)

If there is a CAN message with a single CAN-ID to be transferred with cyclically repetitive content, it is called a multiplex message. For example in the first byte of the payload of the CAN frame a MUX identifier is inserted, which defines the meaning of the next bytes. Example: if the first byte (byte 0) has the value 0x02 then in the bytes 1-7 the number of Km is available. If, otherwise, in the first byte (byte 0) the value is 0x04, then in the bytes 1-7 the running hours number is registered. And so on.

Such multiplex messages can managed by Broadcast-Manager by sending more than a user data frame can_frame for a CAN-ID (see page [*]).

In order to filter multiplex messages, there must be at least two (nframes $\geq$ 2) can_frame sent to the Broadcast-Manager, where the first can_frame contains the MUX mask and the second can_frame the user data mask, as described above. The points that define the MUX-mask are in the user data masks, they are distinguished by the MUX Identifier in the user data.

For the example above it would mean:

The first byte in the first can_frame (the MUX-mask) would be 0xFF - the following 7 bytes would be 0x00 - this is the MUX-mask defined. The following two can_frame each contain at least in the first byte the 0x02 or 0x04 values so that the identifier of the Multiplex messages are defined. In addition, (reasonably) in the user data other bits are set, which for example correspond to a change in operating hours.

Figure 4: Example of the multiplex filter usage
\begin{figure}\begin{center}
\psfig{file=bcm_mux_filter.eps}\par
\end{center}\end{figure}

A change in a multiplex message with a particular MUX identifier results in a message RX_CHANGED to the process with the received CAN Frame. I.e. the process must assess the basis of the MUX-Identifiers from the Broadcast-Manager message received.

In the example shown (Figure 4), the MUX-mask in byte 0 on 0x5F is set. When receiving RX-frame no message is sent to the user (MUX-identifier is not known). With RX-frame 2 there is a message (MUX-known identifier and relevant data have changed at the first receive operation). By receiving the RX-Frame 3 (changes in the yellow-marked bits) no message is sent to the user, because no changes are in any relevant data on the registered identifier MUX.

Message filtering (length of user data - DLC)

When requested, Broadcast-Manager can additionally monitor a change in the CAN message specified user data. In addition, the received Data Length Code (DLC) can be compared with the reference message. If a difference is detected an RX_CHANGED message is sent to the process. To enable this functionality the flag RX_CHECK_DLC must be set in flags.


LLCF status in /proc Filesystem

The Low Level CAN Framework supports the /proc file system and provides statistics and information about internal structures and states in human-readable form. The information can be queried with:

cat /proc/net/can/stats

Next the other files are explained.

Version information: /proc/net/can/version

The LLCFversion information can be read by opening the file /proc/net/can/version. These are the first 6 characters from LLCF_VERSION_CODE, copied into a buffer with llcf_version_code = strtoul(mybuffer, (char **)NULL, 16);, and built with the following rule:

LLCF_VERSION_CODE = (((MAJORVERSION) << 16) + ((MINORVERSION) << 8) + (PATCHLEVEL))

hartko@pplinux1:~> cat /proc/net/can/version 
010000 [ Volkswagen AG - Low Level CAN Framework (LLCF) v1.0.0-rc1 ]

Statistics: /proc/net/can/stats

With the statistics offered you can get information such as the current volume of data and the proportion of the application's matched CAN frames in the ratio of all the CAN-Bus received CAN frames.

The information is updated by the LLCF once a second.

hartko@pplinux1:~> cat /proc/net/can/stats 

      811 transmitted frames (TXF)
   319427 received frames (RXF)
    69504 matched frames (RXMF)

       21 % total match ratio (RXMR)
        0 frames/s total tx rate (TXR)
        0 frames/s total rx rate (RXR)

      100 % current match ratio (CRXMR)
        2 frames/s current tx rate (CTXR)
      166 frames/s current rx rate (CRXR)

      100 % max match ratio (MRXMR)
        2 frames/s max tx rate (MTXR)
      167 frames/s max rx rate (MRXR)

        6 current receive list entries (CRCV)
        6 maximum receive list entries (MRCV)

Resetting statistics: /proc/net/can/reset_stats

Resetting the statistical information can be internal, for the overflow of counters, or user-initiated. After the reset of the statistical information, an additional line (STR) is output. This example shows the impact in a running system, compared to the one above.

hartko@pplinux1:~> cat /proc/net/can/reset_stats 
LLCF statistic reset #1 done.
hartko@pplinux1:~> cat /proc/net/can/stats 

       31 transmitted frames (TXF)
     2585 received frames (RXF)
     2585 matched frames (RXMF)

      100 % total match ratio (RXMR)
        1 frames/s total tx rate (TXR)
      165 frames/s total rx rate (RXR)

      100 % current match ratio (CRXMR)
        2 frames/s current tx rate (CTXR)
      165 frames/s current rx rate (CRXR)

      100 % max match ratio (MRXMR)
        2 frames/s max tx rate (MTXR)
      167 frames/s max rx rate (MRXR)

        6 current receive list entries (CRCV)
        6 maximum receive list entries (MRCV)

        1 statistic resets (STR)

Internal receive lists on the RX dispatcher

LLCFmodules use the LLCFRX dispatcher to receive each CAN-IDs (or a range of CAN-IDs) of certain from CAN network interfaces. This leads to the registration of an entry in a corresponding receiver list, where any registered CAN ID is a function with a parameter (E.g. a module specific reference as 'user data' or 'sk'). It is called when the CAN Frame with the corresponding CAN-ID is received. Together with the debug functionality it can be the basis for understanding the operation of the LLCF.

For fast processing of received CAN frames, the RX-dispatcher maintains various receive lists (for each CAN Network Interface):

rcvlist_all
This list receives all CAN frames, typically this is for RAW sockets without filters (see chapter 4).
rcvlist_fil
This list receives frames that match a simple bitmask-defined range (e.g. 0x200 - 0x2FF).
rcvlist_inv
This list receives frames that do not match a simple bitmask-defined range (the inverse of rcvlist_fil).
rcvlist_eff
This list receives frames that have an Extended Frame Format (29 bit identifier)
rcvlist_sff
This list receives frames that have a Standard Frame Format (11 bit identifier)

By dividing the receiving lists, the effort to find and comparing the received CAN frames with the registered receive filters is minimized.

Thus, for example the list 'rcvlist_sff' is an array with 2048 entries (11 bits CAN-ID) with a singly linked list for each CAN-IDs received. The content filter can be easily applied and pass on a matching message.

Currently the functionality of the extended CAN frames is not used in current projects, because the registration of individual EFF frames in a singly-linked list can be slow. For intensive use, 'rcvlist_eff' should be implemented as an hash table (analogous to 'rcvlist_sff'), to ensure efficient processing.

If you want to watch all the receive lists at once, you can type:

hartko@pplinux1:~> cat /proc/net/can/rcvlist_*

receive list 'rx_all':
  device   can_id   can_mask  function  userdata   matches  ident
   can1      000    00000000  f8c995ac  f0e59280     42726  raw
  device   can_id   can_mask  function  userdata   matches  ident
   can0      000    00000000  f8c995ac  f0e59800     55240  raw


receive list 'rx_eff':
  (can1: no entry)
  (can0: no entry)


receive list 'rx_fil':
  device   can_id   can_mask  function  userdata   matches  ident
   can1      200    00000700  f8c995ac  f0e5b380         0  raw
  (can0: no entry)


receive list 'rx_inv':
  (can1: no entry)
  (can0: no entry)


receive list 'rx_sff':
  (can1: no entry)
  device   can_id   can_mask  function  userdata   matches  ident
   can0      123    000007ff  f8c86bec  e2e14380        29  bcm
   can0      456    000007ff  f8c86bec  ea954880         0  bcm
   can0      789    000007ff  f8c86bec  e30e6200       130  bcm
   can0      3FF    000007ff  f8c86bec  deaf2580        14  bcm
   can0      740    000007ff  f8c93680  e48322c4       178  tp20

You can also do this:

hartko@pplinux1:~> cat /proc/net/can/rcvlist_sff

receive list 'rx_sff':
  (can1: no entry)
  device   can_id   can_mask  function  userdata   matches  ident
   can0      123    000007ff  f8c86bec  e2e14380        29  bcm
   can0      456    000007ff  f8c86bec  ea954880         0  bcm
   can0      789    000007ff  f8c86bec  e30e6200       130  bcm
   can0      3FF    000007ff  f8c86bec  deaf2580        14  bcm
   can0      740    000007ff  f8c93680  e48322c4       178  tp20

CAN network devices in the directory /proc/net/drivers

In this directory there are CAN network drivers with their Proc file system entries. Currently this is only for the SJA1000 driver supplied in src/drivers/sja1000, whose details are briefly described.

Driver status: /proc/net/drivers/sja1000-xxx

Here, the state of the CAN controllers and their associated CAN bus is shown (see the documentation for the Philips SJA1000).

hartko@pplinux1:~> cat /proc/net/drivers/sja1000-gw2
CAN bus device statistics:
       errwarn  overrun   wakeup   buserr   errpass  arbitr   restarts clock        baud
can0:        0        0        0        0        0        0        0   20000000      500
can0: bus status: OK, RXERR: 0, TXERR: 0
can1:        0        0        0        0        0        0        0   20000000      100
can1: bus status: OK, RXERR: 0, TXERR: 0
can2:        0        0        0        0        0        0        0   20000000      100
can2: bus status: OK, RXERR: 0, TXERR: 0
can3:        0        0        0        0        0        0        0   20000000      500
can3: bus status: OK, RXERR: 0, TXERR: 0

Registers: /proc/net/drivers/sja1000-xxx_regs

Here are how the 32 registers of the SJA1000 CAN controller appear. (See the documentation for the Philips SJA1000).

hartko@pplinux1:~> cat /proc/net/drivers/sja1000-gw2_regs 
SJA1000 registers:
can0 SJA1000 registers:
00: 02 00 0c 00 05 00 40 4d 1a 1a 00 00 00 60 00 00
10: 65 ef d3 5f a2 08 01 05 fa ff 0e 7f 0c 00 00 cf
can1 SJA1000 registers:
00: 02 00 0c 00 05 00 43 ff 1a 1a 00 00 00 60 00 00
10: 61 ff de 3d 80 00 10 45 d7 ef fb 4a 06 00 00 cf
can2 SJA1000 registers:
00: 02 00 0c 00 05 00 43 ff 1a 1a 00 00 00 60 00 00
10: 61 fb ee 87 a0 4a 80 10 76 ff da bd 00 00 00 cf
can3 SJA1000 registers:
00: 02 00 0c 00 05 00 40 4d 1a 1a 00 00 00 60 00 00
10: 61 ef 7f ff 21 1c 42 08 32 df 57 6f a1 00 00 cf

Driver reset: /proc/net/drivers/sja1000-xxx_reset

Reading this entry performs a reset of the SJA1000 CAN controller. As can be seen in the example, the number of 'restarts' is increased by 1.

hartko@pplinux1:~> cat /proc/net/drivers/sja1000-gw2_reset 
resetting can0 can1 can2 can3 done
hartko@pplinux1:~> cat /proc/net/drivers/sja1000-gw2
CAN bus device statistics:
       errwarn  overrun   wakeup   buserr   errpass  arbitr   restarts clock        baud
can0:        0        0        0        0        0        0        1   20000000      500
can0: bus status: OK, RXERR: 0, TXERR: 0
can1:        0        0        0        0        0        0        1   20000000      100
can1: bus status: OK, RXERR: 0, TXERR: 0
can2:        0        0        0        0        0        0        1   20000000      100
can2: bus status: OK, RXERR: 0, TXERR: 0
can3:        0        0        0        0        0        0        1   20000000      500
can3: bus status: OK, RXERR: 0, TXERR: 0

Test programs

tst-proc
Opens up to 800 raw sockets to provoke an overflow of the output of /proc/net/can/rcvlist_all.

Contact

This document should be read together with the test programs in src/test as a comprehensive introduction to the Low Level CAN Framework.

For questions, bug reports and suggestions the authors are always open and grateful. Therefore, the Group Research Volkswagen AG set up a special email address where the the authors can be reached: contact email: socketcan-users@lists.berlios.de Postal address:
Volkswagen AG
Oliver Hartkopp
Brieffach 1776
D-38426 Wolfsburg Oliver Hartkopp $<$oliver.hartkopp@volkswagen.de$>$
Dr. Urs Thürmann $<$urs.thuermann@volkswagen.de$>$
English translation from German: Daniele Venzano $<$venza@brownhat.org$>$