How to configure and use CAN bus

本文详细介绍了如何在AM35x EVM和OMAP35x平台上启用CAN总线,并提供了使用MCP2515 Bus Monitor板进行数据交换的步骤。此外,还包含了配置过程中的常见问题及解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

This article explains how to enable the CAN bus using as examples the AM35x EVM and 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.

If you are new to CAN, please spend 15 minutes reading the CAN bus protocol technical overview.

Contents

[hide]

References

Enable the CAN controller kernel driver

AM35x kernel

In the case of the 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 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

Send simple test packet

The socket-CAN tools include the cansend utility:

cansend <device> <can_frame>

where the device is the network interface name, typically can0, and a CAN frame is in the format:

<can_id>#{R|data}

with the can_id having 3 (SFF) or 8 (EFF) hex chars. and data in the format of zero to eight 8-bit hex-values that can optionally be separated by a period ('.') or use R for remote transmission request.

To send a CAN data frame message, with a can_id arbitration field value of 0x5A1 and a data field value 0x1122334455667788:

cansend can0 5A1#11.22.33.44.55.66.77.88

If you are using a CAN bus monitor, like the MCP2515 bus monitor, You will see (packet sent 3 times):

 

 

 

 

Dump received packets

The socket-CAN tools include the candump utility, which dumps all messages being exchanged on the CAN bus. To run candump, just specify the CAN interface:

candump can0

If a device on the CAN bus sends a packet with ID 0x456 and data 0x122345, the output would be

 # candump can0
  can0       456  [3] 12 23 45

The MCP2515 bus monitor allows you to send CAN bus packet. You can also telnet into the target hardware and use cansend to put a packet on the bus that can be monitiored with candump.


cansend can0 5A1#11.22.33.44.55.66.77.88

creates the following cumulative candump output

/ # candump can0
  can0       456  [3] 12 23 45
  can0  5A1  [8] 11 22 33 44 55 66 77 88

CAN protocol stack information

The CAN protocol implementation version:

cat /proc/net/can/version

The CAN bus statistics:

cat /proc/net/can/stats

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

fgrep 147 /sys/kernel/debug/gpio

with example output being:

gpio-147 (MCP251x CAN INT) in  hi irq-274 edge-falling

Which indicates GPIO 147 is configure as an input, currently has a high logic level, is mapped to IRQ 307, and causes an interrupt on the falling edge.

You can see if any interrupts have occurred using (for example GPIO 147 being mapped to IRQ 307):

fgrep 307 /proc/interrupts

with example output being:

307:  60        GPIO  mcp251x

which indicates 60 interrupts have been occurred.

With OMAP3, you also need to verify the pad where the signal leaves the chip is configured properly. For the OMAP3 in the CBB package (used on Gumstix Overo Water board) GPIO147 uses the uart2_rx pad.

cat /sys/kernel/debug/omap_mux/uart2_rx

with example output being:

name: uart2_rx.gpio_147 (0x4800217a/0x14a = 0x4104), b ad25, t NA
mode: OMAP_PIN_INPUT | OMAP_PIN_OFF_WAKEUPENABLE | OMAP_MUX_MODE4
signals: uart2_rx | mcbsp3_fsx | gpt8_pwm_evt | NA | gpio_147 | NA | NA | safe_mode

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.

NOHZ: local_softirq_pending 08

You are using an older version of the mcp2515 driver. The driver should call netif_rx() only from interrupt context. Update to a newer version of the driver and the warning will go away.

System files and command

Files

cat /proc/net/dev

Commands Examples

ip -details link show can0

References

### CAN2 Protocol, Interface, and Network Overview The term "CAN2" could refer to several aspects depending on the context, such as a protocol variant, an interface, or a network. Below is a detailed explanation of these terms based on the provided references and general knowledge. #### CAN2 Protocol The **CAN2 protocol** typically refers to enhancements or specific configurations of the standard Controller Area Network (CAN) protocol. In the context of CAN communication, the CAN protocol supports robust message-based communication for microcontrollers and devices in automotive and industrial applications. The CAN2 protocol might involve updated specifications or adaptations for specific use cases [^1]. For example, in the STM32 microcontroller series, the CAN protocol implementation includes features like error detection, message prioritization, and arbitration mechanisms. These are essential for ensuring reliable communication in noisy environments [^1]. #### CAN2 Interface A **CAN2 interface** generally refers to hardware or software components that enable communication over a CAN bus. For instance, the Arduino Due provides a CAN interface through its onboard SAM3X8E ARM Cortex-M3 CPU, which supports CAN communication protocols [^1]. Similarly, STM32 microcontrollers have dedicated CAN peripherals that facilitate interfacing with CAN networks [^1]. In more advanced systems, such as those adhering to AUTOSAR standards, the CAN State Management (CanSM) module plays a critical role in managing the state transitions of CAN networks. This includes handling various effects like `E_PRE_NOCOM`, `E_NOCOM`, and `E_FULL_COM` [^3]. These effects define how the system responds to different communication states, ensuring smooth transitions between modes like full communication, no communication, and silent communication. #### CAN2 Network A **CAN2 network** refers to a network configuration involving multiple nodes communicating via the CAN protocol. Such networks often include features like multiple simultaneous transmissions, where hosts have dedicated connections to switches. These networks leverage Ethernet-like protocols for packet buffering and full-duplex communication without collisions [^2]. For example, in modern automotive systems, CAN networks are designed to support various communication modes, including passive and active states. The CanSM module ensures that these modes are managed effectively by coordinating with other modules like BswM and ComM [^3]. This coordination involves invoking functions such as `BswM_CanSM_CurrentState()` and `ComM_BusSM_ModeIndication()` to report and manage state changes. ```python # Example of configuring a CAN interface in Python using the can package import can # Configure CAN bus bus = can.interface.Bus(channel='can0', bustype='socketcan') # Send a message message = can.Message(arbitration_id=0x123, data=[1, 2, 3, 4, 5, 6, 7, 8]) bus.send(message) ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值