RPi CANBus

CAN-bus is a communication protocol used mainly in car and some industrial products.

The Raspberry pi doesn't have CANbus built in, but it can be added through USB or SPI converters.

This document presents how to enable CANbus support in the kernel, using a SPI to CANbus converter (MCP2515). The same can be done for other SPI converters, or for PeakCAN Usb.

Raspbian kernel doesn't come with modules needed, so the kernel must be compiled from source. Refer to http://elinux.org/RPi_Kernel_Compilation for more information on this. The following instructions present all steps requiered to build a kernel with the correct modules, and some useful commands to use it.

Please note:

The best way to compile a kernel is to do it on a Desktop-PC and not on a Raspberry Pi.

It takes about 2 or 3 hours on Desktop-PCs but much more (about 12 hours) on a Raspberry Pi.

Prerequisite
At least, a proper gcc installation is needed, and ncurses development package are used by kernel menuconfig. If you are using Ubuntu or Kubuntu, please use this command instead.

Kernel configuration and compilation
For this example, everything will be done in a directory "/opt/raspberrypi/". So first create it, and then checkout the last version of the kernel for the raspberrypi in the linux subdirectory.

At the time of writing, the current kernel trunk version is 3.2. To use the 3.6 kernel, an additional branch has to be fetch.

Then copy the default cutdown .config file, and run the "oldconfig" make to make it up to date.

From the default file, I only changed the two following lines (first is for cross-compiling the kernel), and pressed "enter" for all other (there are a lot...). Cross-compiler tool prefix (CROSS_COMPILE) [] (NEW) arm-rpi-linux-gnueabi- Default hostname (DEFAULT_HOSTNAME) [(none)] (NEW) raspberrypi

Then the CAN bus support must be added using "menuconfig" (see. http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=7027&start=50)

Activate the following lines: [*] Networking support ---> .... CAN bus subsystem support ---> ........ Raw CAN Protocol (raw access with CAN-ID filtering) ........ Broadcast Manager CAN Protocol (with content filtering) ............CAN Device Drivers ---> ................ Platform CAN drivers with Netlink support ................[*] CAN bit-timing calculation ................ Microchip MCP251x SPI CAN controllers ................[*] CAN devices debugging messages ....Device Drivers ---> ........[*] SPI support ---> ............ BCM2798 SPI controller driver (SPI0) ............ User mode SPI driver support .......-*- GPIO Support ---> ............[*] /sys/class/gpio/... (sysfs interface)

If another driver is used, activate it in place of the "MCP251x SPI CAN controllers". If using a USB controller, then SPI support is not needed, but USB must be correctly set up.

Then edit the board definition, to add the informations about the SPI bus, and to configure the interrupt pin of the MCP2515.

Note that the "IRQF_ONESHOT" flag is only required for kernel 3.6. For kernel 3.2 you should remove it. Adjust the GPIO pin used for interrupt (here 25), the SPI frequency (here 10MHz) and MCP2515 oscillator frequency (here 20MHz) to your setup.

Then compile the kernel. The example below is for cross compilation, using a 2 core x86 machine. For compiling on the Pi, just type "make".

Then install the tools from git.

Use the tools to generate an image from the build kernel, and copy that to a new "build" directory.

Then return to the linux directory, to compile the kernel modules, and copy them to the build directory.

Again from git, get the last firmware for the raspberrypi, and copy it to the build directory.

You should now have the complete new kernel/modules/firmware in the "/opt/raspberrypi/build" directory. If you want to use it, simply puts its contents to the root directory. It is possible to do it directly without using a temporary build directory, but this method has the advantage of being possible on a remote machine, and to allow easier save of the binary generated (simply archive this directory if you need to give it to someone else).

MCP2515 Asynchronous Driver
The standard MCP251x has some drawbacks with kernel 3.6. It happens that it hangs and stop receiving frames. It has something to do with the "IRQF_ONESHOT" flag. Refer to the Raspberry Pi forum, for latest discussions on this point : http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=7027.

However, another MCP2515 driver exists, and has been successfully tested with kernel 3.6. Please not that it only allows to use a MCP2515 and no MCP2510 like the MCP251x driver.

You can download it and activate it in your kernel like follows.

Activate the following lines. [*] Networking support ---> .... CAN bus subsystem support ---> ........ Raw CAN Protocol (raw access with CAN-ID filtering) ........ Broadcast Manager CAN Protocol (with content filtering) ............CAN Device Drivers ---> ................ Platform CAN drivers with Netlink support ................[*] CAN bit-timing calculation ................ Microchip MCP2515 SPI CAN controller ................[*] CAN devices debugging messages

Then go again through the kernel compilation (see above if some line is missing).

The build directory is updated with the kernel and module with MCP2515 driver support.

SPI low latency patch
Finally, the SPI adds a lot of latency, that can results in frame lost at high CANbus rate, due to the small receive buffer of the MCP2515 controller.

This can be reduced using the following patch. Refer to the discussion on the forum for more details : http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=19489.

Warning : following the commit of 22 January 2013 (https://github.com/raspberrypi/linux/commit/91a3be5b2b783b930b2d7cdbf38283b613bce7d4) the patch fails to apply. A new patch is in process, see the forum above to check the last patch.

These instructions download it from the forum and apply it.

Then a new compilation of the kernel is done.

The build directory is updated with the kernel patched SPI driver with low latency.