How to configure and use CAN bus
This article explains how to enable the CAN bus using as examples the AM35x EVM and [[:Category:OMAP35x OMAP35x], but can be applied to other platforms as well. In addition, steps to exchange data with a MCP2515 Bus Monitor board is also documented.
Enable the CAN controller kernel driver
AM35x kernel
In the case of the Category:AM35x platform the configuration is:
Linux Kernel Configuration Networking support CAN bus subsystem support CAN device drivers Platform CAN drivers with Netlink support CAN bit-timing calculation TI High End CAN controller (HECC)
OMAP3x kernel
In the case of the Category:OMAP3x platform with a MCP2515 chip the configuration is:
Linux Kernel Configuration Networking support CAN bus subsystem support CAN device drivers Platform CAN drivers with Netlink support CAN bit-timing calculation Microchip MCP251x SPI CAN controller
Enable socketcan and ip tools
Working with the CAN bus requires enabling the 'ip' tools from iproute2 package (the 'ip' tool from busybox won't work). The socketcan package is optional and provide you with tools to debug your can bus.
These packages are available for selection from the RidgeRun SDK in the configuration menu.
File System Configuration Select target's file system software iproute2-2.6.34 socketcan utils
Setup the networking rules
Edit your /etc/networking/interfaces on the target file system and add the following rules (required to setup the bit-rate of the bus):
auto can0 iface can0 inet manual #pre-up ip link set $IFACE type can bitrate 125000 listen-only off pre-up /ip link set $IFACE type can bitrate 125000 triple-sampling on up /sbin/ifconfig $IFACE up down /sbin/ifconfig $IFACE down
Verifying CAN support configuration
Linux boot
Look for the following in the Linux boot output
Run
dmesg | fgrep -i mcp
Expected output:
mcp251x spi1.0: setup: speed 750000, sample leading edge, clk normal mcp251x spi1.0: setup mode 0, 8 bits/w, 1000000 Hz max --> 0 mcp251x spi1.0: CANSTAT 0x80 CANCTRL 0x07 mcp251x spi1.0: probed
Run
dmesg | fgrep -i can
Expected output:
PM: Adding info for No Bus:can0 CAN device driver interface can: controller area network core (rev 20090105 abi 8)
sysfs entries
Verify the CAN host driver is registered correctly (meaning properly added to kernel arch/arm/mach-*/board-*.c file).
MC2515
Run:
ls -d /sys/bus/spi/drivers/mcp251x cat /sys/devices/platform/omap2_mcspi.1/spi1.0/modalias ls /sys/class/net/
Expect:
/sys/bus/spi/drivers/mcp251x mcp2515 can0 eth0 lo
Power on CAN hardware
ip link set can0 type can bitrate 125000 triple-sampling on ifconfig can0 up
MCP251x interrupt signal
MCP251x Platform Bus Data
In the architecture specific board file, such as arch/arm/mach-omap2/board-overo.c, first define the platform data:
#include <linux/can/platform/mcp251x.h> static int overo_mcp2515_setup(struct spi_device *sdev) { printk(KERN_DEBUG "overo_mcp2515_setup: Entry\n"); return 0; } static int overo_mcp2515_transceiver_enable(int enable) { printk(KERN_DEBUG "overo_mcp2515_transceiver_enable: Entry %d\n", enable); return 0; } static struct mcp251x_platform_data overo_mcp2515_pdata = { .oscillator_frequency = 32*1000*1000, .board_specific_setup = overo_mcp2515_setup, .model = CAN_MCP251X_MCP2515, .power_enable = overo_mcp2515_transceiver_enable, }; <pre> Then add the logic to initialize the GPIO used as the incoming mcp251x interrupt signal: <pre> static void __init overo_mcp251x_init(void) { printk(KERN_DEBUG "overo_mcp251x_init: Entry\n"); if ((gpio_request(OVERO_GPIO_CAN_INT, "MCP251x CAN INT") == 0) && (gpio_direction_input(OVERO_GPIO_CAN_INT) == 0)) { gpio_export(OVERO_GPIO_CAN_INT, 0); set_irq_type(OMAP_GPIO_IRQ(OVERO_GPIO_CAN_INT), IRQ_TYPE_EDGE_FALLING); } else { printk(KERN_ERR "could not obtain gpio for MCP251x CAN bus interrupt\n"); return; } }
Add the SPI information to the SPI board info array:
{ .modalias = "mcp251x", .platform_data = &overo_mcp2515_pdata, .irq = OMAP_GPIO_IRQ(114), .max_speed_hz = 1*1000*1000, .bus_num = 1, .mode = SPI_MODE_0, .chip_select = 0, },
Finally call the GPIO interrupt initialization function right before registering SPI board info:
overo_mcp251x_init(); spi_register_board_info(overo_spi_board_info, ARRAY_SIZE(overo_spi_board_info));
GPIO MCP251x interrupt verification
You can use debugfs to monitor the GPIO used for the MCP251x interrupt signal.
Configure the kernel to enable debugfs:
Symbol: DEBUG_FS [=y] Prompt: Debug Filesystem Defined at lib/Kconfig.debug:77 Depends on: SYSFS Location: -> Kernel configuration -> Kernel hacking
Boot the target hardware and mount debugfs:
mount -t debugfs none /sys/kernel/debug
Check the current value and configuration for the GPIO of interest (for example GPIO 114):
fgrep 114 /sys/kernel/debug/gpio
with example output being:
gpio-114 (MCP251x CAN INT) in hi irq-274 edge-falling
Which indicates GPIO 114 is configure as an input, currently has a high logic level, is mapped to IRQ 274, and causes an interrupt on the falling edge.
You can see if any interrupts have occurred using (for example GPIO 114 being mapped to IRQ 274):
fgrep 274 /proc/interrupts
with example output being:
274: 60 GPIO mcp251x
which indicates 60 interrupts have been occurred.
Problems and how to resolve them
The titles of the following sections are text that gets displayed when a problem occurs. Each section describes how to resolve the issue.
No can0 interface
If you have problems with network interface can0 not being created, enable
kernel -> Device Drivers -> Generic Driver Options -> Driver Core verbose debug messages
and
kernel -> Networking support -> CAN bus subsystem support -> CAN Device Drivers -> CAN devices debugging messages
bit-timing calculation not available
Enable CAN bit-timing calculation in the Linux kernel.
kernel -> Networking support -> CAN bus subsystem support -> CAN Device Drivers -> CAN bit-timing calculation
bit-timing not yet defined
First run
ip link set can0 type can bitrate 125000 triple-sampling on
then run
ifconfig can0 up
MCP251x didn't wake-up
If the response to ifconfig can0 up is
mcp251x spi1.0: MCP251x didn't wake-up mcp251x spi1.0: CNF: 0x03 0xf5 0x01
Then there is a problem with the interrupt signal from the MCP251x chip back to the driver. Check the arch/arm/mach-*/board-*.c file for your hardware along with any jumpers on your hardware design.
ip command says link/[280] instead of link/can
You need to enable and build iproute2 to get an up-to-date ip command that supports the can bus.
System files and command
Files
cat /proc/net/dev
Commands Examples
ip -details link show can0