You are on page 1of 7

RPi CANBus - eLinux.

org

Personal tools
Create account
Log in

Namespaces

RPi CANBus

Page

Views
Read

Discussion
View source
CAN
bus is a communication protocol used mainly in cars and some industrial products.View history
Community portal
Variants
Main Page

Current events
The
Raspberry Pi doesn't have CAN bus built in, but it can be added through USB or
SPI converters.
More
Recent changes

Search
Helpdocument presents how to enable CAN bus support in the kernel, using a SPI-to-CAN
This
bus converter
Volunteering
Search
(MCP2515). The same can be done for other SPI converters, or for PeakCAN USB. Search
Popular Pages

Go

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

Please
note:
Special
pages
version
ThePrintable
best way
to compile a kernel is to do it on a desktop PC and not on a Raspberry Pi.
Permanent
link
It takes about 2 or 3 hours on desktop PCs, but much more (about 12 hours) on a Raspberry Pi.
Page information

Contents[hide]
1 Prerequisite
2 Kernel configuration and compilation
2.1 MCP2515 Asynchronous Driver
2.2 SPI low latency patch

Prerequisite
At least, a proper GCC installation is needed, and ncurses development package are used by kernel
menuconfig.
sudo apt-get install gcc ncurses-dev

If you are using Ubuntu or Kubuntu, please use this command instead:
sudo apt-get install gcc-arm-linux-gnueabi make ncurses-dev

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.

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

RPi CANBus - eLinux.org

cd /opt
sudo mkdir raspberrypi
cd raspberrypi
sudo chmod og+w .
git clone --depth 1 https://github.com/raspberrypi/linux/
cd linux

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.
git fetch --depth=1 git://github.com/raspberrypi/linux.git
rpi-3.6.y:refs/remotes/origin/rpi-3.6.y
git checkout rpi-3.6.y

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

cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- oldconfig -j 3

For Ubuntu or Kubuntu users, please use this command instead:

cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- oldconfig -j 3

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-gnueabiDefault 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 )
cd /opt/raspberrypi/linux
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- menuconfig

For Ubuntu or Kubuntu users, please use this command instead:


cd /opt/raspberrypi/linux
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig

Notice: Please make the changes first in the "Device Drivers ---> SPI support --->". After that you can
make the changes in "Networking support --->", because only now you can see the entry "<M> Microchip
MCP251x SPI CAN controllers".
Activate the following lines:
[*] Networking support --->
....<M> CAN bus subsystem support --->

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

RPi CANBus - eLinux.org

........<M> Raw CAN Protocol (raw access with CAN-ID filtering)


........<M> Broadcast Manager CAN Protocol (with content filtering)
............CAN Device Drivers --->
................<M> Platform CAN drivers with Netlink support
................[*] CAN bit-timing calculation
................<M> Microchip MCP251x SPI CAN controllers
................[*] CAN devices debugging messages
....Device Drivers --->
........[*] SPI support --->
............<M> BCM2798 SPI controller driver (SPI0)
............<M> 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.
vi arch/arm/mach-bcm2708/bcm2708.c
#apply patch

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.
diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c
index 838e0f2..10026ec 100644
--- a/arch/arm/mach-bcm2708/bcm2708.c
+++ b/arch/arm/mach-bcm2708/bcm2708.c
@@ -54,6 +54,12 @@
#include <mach/vcio.h>
#include <mach/system.h>

+#include <linux/can/platform/mcp251x.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+
+#define MCP2515_CAN_INT_GPIO_PIN 25
+
#include <linux/delay.h>

#include "bcm2708.h"
@@ -586,11 +592,21 @@ static struct platform_device bcm2708_spi_device = {
.resource = bcm2708_spi_resources,
};

+static struct mcp251x_platform_data mcp251x_info = {


+
.oscillator_frequency
= 20000000,
+
.board_specific_setup
= NULL,
+
.irq_flags
= IRQF_TRIGGER_FALLING|IRQF_ONESHOT,
+
.power_enable
= NULL,
+
.transceiver_enable
= NULL,
+};
+
#ifdef CONFIG_SPI
static struct spi_board_info bcm2708_spi_devices[] = {
{
.modalias = "spidev",

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

RPi CANBus - eLinux.org

+
+
+
+

.max_speed_hz = 500000,
.modalias = "mcp2515",
.max_speed_hz = 10000000,
.platform_data = &mcp251x_info,
/* .irq = unknown , defined later thru bcm2708_mcp251x_init */
.bus_num = 0,
.chip_select = 0,
.mode = SPI_MODE_0,
@@ -602,6 +618,13 @@ static struct spi_board_info bcm2708_spi_devices[] = {
.mode = SPI_MODE_0,
}
};
+
+static void __init bcm2708_mcp251x_init(void) {
+
bcm2708_spi_devices[0].irq = gpio_to_irq(MCP2515_CAN_INT_GPIO_PIN);
+
printk(KERN_INFO " BCM2708 mcp251x_init: got IRQ%d for MCP2515\n",
bcm2708_spi_devices[0].irq);
+
return;
+};
+
#endif

static struct resource bcm2708_bsc0_resources[] = {


@@ -749,6 +772,7 @@ void __init bcm2708_init(void)
system_serial_low = serial;

#ifdef CONFIG_SPI
+
bcm2708_mcp251x_init();
spi_register_board_info(bcm2708_spi_devices,
ARRAY_SIZE(bcm2708_spi_devices));
#endif

Then compile the kernel. The example below is for cross compilation, using a two-core x86 machine. For
compiling on the Raspberry Pi, just type "make".
cd /opt/raspberrypi/linux
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3

For Ubuntu or Kubuntu users, please use this command instead:


cd /opt/raspberrypi/linux
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j 3

Then install the tools from Git.


cd /opt/raspberrypi/
git clone --depth 1 git://github.com/raspberrypi/tools.git

Use the tools to generate an image from the build kernel, and copy that to a new "build" directory.
cd tools/mkimage
./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
mkdir -p /opt/raspberrypi/build/boot
mv kernel.img /opt/raspberrypi/build/boot

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

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

RPi CANBus - eLinux.org

cd ../../linux/
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- modules_install
INSTALL_MOD_PATH=/opt/raspberrypi/build/ -j3
cp .config ../build/boot/

For Ubuntu or Kubuntu users, please use this command instead.


cd ../../linux/
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install
INSTALL_MOD_PATH=/opt/raspberrypi/build/ -j3
cp .config ../build/boot/

Again from Git, get the last firmware for the Raspberry Pi, and copy it to the build directory.
cd ..
git clone --depth 1 git://github.com/raspberrypi/firmware.git
cd firmware
git fetch --depth 1 git://github.com/raspberrypi/firmware.git next:refs/remotes/origin/next
git checkout next

cp boot/bootcode.bin /opt/raspberrypi/build/boot
cp boot/fixup.dat /opt/raspberrypi/build/boot
cp boot/start.elf /opt/raspberrypi/build/boot

mkdir -p /opt/raspberrypi/build/opt
cp -r hardfp/opt/vc /opt/raspberrypi/build/opt

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 it 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.
cd /opt/raspberrypi/linux
wget http://clientes.netvisao.pt/anbadeol/linux-mcp2515-20101018.patch.gz
gunzip linux-mcp2515-20101018.patch.gz
patch -p1 < linux-mcp2515-20101018.patch

make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- menuconfig

For Ubuntu or Kubuntu users, please use this command instead.

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

RPi CANBus - eLinux.org

cd /opt/raspberrypi/linux
wget http://clientes.netvisao.pt/anbadeol/linux-mcp2515-20101018.patch.gz
gunzip linux-mcp2515-20101018.patch.gz
patch -p1 < linux-mcp2515-20101018.patch

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig

Activate the following lines.


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

Then go again through the kernel compilation (see above if some line is missing).
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- modules_install
INSTALL_MOD_PATH=/opt/raspberrypi/build/modules -j3
cd ../tools/mkimage
./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
mv kernel.img /opt/raspberrypi/build/boot
cd ../../linux

For Ubuntu or Kubuntu users, please use this command instead.


make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j3
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install
INSTALL_MOD_PATH=/opt/raspberrypi/build/modules -j3
cd ../tools/mkimage
./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
mv kernel.img /opt/raspberrypi/build/boot
cd ../../linux

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 CAN bus rates, 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.

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

RPi CANBus - eLinux.org

cd /opt/raspberrypi/linux
wget http://www.raspberrypi.org/phpBB3/download/file.php?id=1492 -O spi-latencybranch3.6.y.patch.bz2
bunzip2 spi-latency-branch3.6.y.patch.bz2
patch -p1 < spi-latency-branch3.6.y.patch

Then a new compilation of the kernel is done.


make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3
make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- modules_install
INSTALL_MOD_PATH=/opt/raspberrypi/build/modules -j3
cd ../tools/mkimage
./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
mv kernel.img /opt/raspberrypi/build/boot
cd ../../linux

For Ubuntu or Kubuntu users, please use this command instead.


make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j3
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install
INSTALL_MOD_PATH=/opt/raspberrypi/build/modules -j3
cd ../tools/mkimage
./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
mv kernel.img /opt/raspberrypi/build/boot
cd ../../linux

The build directory is updated with the kernel patched SPI driver with low latency.
Category: RaspberryPi
This page was last modified on 22 June 2014, at 20:14.
This page has been accessed 29,625 times.
Content is available under a Creative Commons Attribution-ShareAlike 3.0 Unported License unless otherwise noted.
Privacy policy

About eLinux.org

http://elinux.org/RPi_CANBus[9/10/2014 3:10:13 PM]

Disclaimers

You might also like