Difference between revisions of "RPi CANBus"

From eLinux.org
Jump to: navigation, search
m (Kernel configuration and compilation)
m (added information for ubuntu / kubuntu users)
(5 intermediate revisions by 3 users not shown)
Line 6: Line 6:
  
 
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.
 
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:<br />
 +
The best way to compile a kernel is to do it on a Desktop-PC and not on a Raspberry Pi.<br />
 +
It takes about 2 or 3 hours on Desktop-PCs but much more (about 12 hours) on a Raspberry Pi.
  
 
== Prerequisite ==
 
== Prerequisite ==
Line 11: Line 15:
 
<source lang="bash">
 
<source lang="bash">
 
  sudo apt-get install gcc ncurses-dev
 
  sudo apt-get install gcc ncurses-dev
 +
</source>
 +
If you are using Ubuntu or Kubuntu, please use this command instead.
 +
<source lang="bash">
 +
sudo apt-get install gcc-arm-linux-gnueabi make ncurses-dev
 
</source>
 
</source>
  
Line 34: Line 42:
 
  cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
 
  cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- oldconfig -j 3
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- oldconfig -j 3
</source>  
+
</source>
 +
 
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
cp arch/arm/configs/bcmrpi_cutdown_defconfig .config
 +
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- oldconfig -j 3
 +
</source>
  
 
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...).
 
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...).
Line 42: Line 56:
  
 
Then the CAN bus support must be added using "menuconfig" (see. http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=7027&start=50)
 
Then the CAN bus support must be added using "menuconfig" (see. http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=7027&start=50)
<source>
+
<source lang="bash">
 
  cd  /opt/raspberrypi/linux
 
  cd  /opt/raspberrypi/linux
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- menuconfig
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- menuconfig
 +
</source>
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
cd  /opt/raspberrypi/linux
 +
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
 
</source>  
 
</source>  
 +
 +
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:
 
Activate the following lines:
Line 142: Line 163:
  
 
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 compile the kernel. The example below is for cross compilation, using a 2 core x86 machine. For compiling on the Pi, just type "make".
<source>
+
<source lang="bash">
 +
cd /opt/raspberrypi/linux
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3
 +
</source>
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
cd /opt/raspberrypi/linux
 +
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j 3
 
</source>  
 
</source>  
  
Line 166: Line 193:
 
  cp .config ../build/boot/
 
  cp .config ../build/boot/
 
</source>
 
</source>
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
cd ../../linux/
 +
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install INSTALL_MOD_PATH=/opt/raspberrypi/build/ -j3
 +
cp .config ../build/boot/
 +
</source>
  
 
Again from git, get the last firmware for the raspberrypi, and copy it to the build directory.
 
Again from git, get the last firmware for the raspberrypi, and copy it to the build directory.
Line 199: Line 232:
 
   
 
   
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- menuconfig
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- menuconfig
 +
</source>
 +
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
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
 
</source>  
 
</source>  
  
Line 216: Line 259:
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3
 
  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
 
  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
 +
</source>
 +
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
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
 
  cd ../tools/mkimage
 
  ./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
 
  ./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
Line 228: Line 281:
  
 
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.
 
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.
 +
 +
<font color="red">'''Warning'''</font> : 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.
 
These instructions download it from the forum and apply it.
Line 234: Line 290:
 
  wget http://www.raspberrypi.org/phpBB3/download/file.php?id=1492 -O spi-latency-branch3.6.y.patch.bz2
 
  wget http://www.raspberrypi.org/phpBB3/download/file.php?id=1492 -O spi-latency-branch3.6.y.patch.bz2
 
  bunzip2 spi-latency-branch3.6.y.patch.bz2  
 
  bunzip2 spi-latency-branch3.6.y.patch.bz2  
  patch -p1 << spi-latency-branch3.6.y.patch
+
  patch -p1 < spi-latency-branch3.6.y.patch
 
</source>  
 
</source>  
  
 
Then a new compilation of the kernel is done.
 
Then a new compilation of the kernel is done.
<source>
+
<source lang="bash">
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- -j3
 
  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
 
  make ARCH=arm CROSS_COMPILE=arm-rpi-linux-gnueabi- modules_install INSTALL_MOD_PATH=/opt/raspberrypi/build/modules -j3
Line 246: Line 302:
 
  cd ../../linux
 
  cd ../../linux
 
</source>
 
</source>
 +
For Ubuntu or Kubuntu users, please use this command instead.<br />
 +
<source lang="bash">
 +
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
 +
</source>
  
 
The build directory is updated with the kernel patched SPI driver with low latency.
 
The build directory is updated with the kernel patched SPI driver with low latency.
  
 
[[Category:RaspberryPi]]
 
[[Category:RaspberryPi]]

Revision as of 11:19, 27 August 2013

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.

 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.

 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-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)

 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 --->
........<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",
-		.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 2 core x86 machine. For compiling on the 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.

 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 raspberrypi, 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 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.

 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 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.

 cd /opt/raspberrypi/linux
 wget http://www.raspberrypi.org/phpBB3/download/file.php?id=1492 -O spi-latency-branch3.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.