A few months back I got hold of my first BeagleBone Black (BBB) with the intention of installing it in my car as a trackday data logger. First step in this endeavor was to get the CANBus working. I wrote this up here, but I'm shutting down that (poorly designed) site and have come up with a better way of enabling CAN so here goes.
First up, I'm assuming you are either running the latest Angstrom image (see here), or Ubuntu with the patched device tree compiler (see here). This ensures you have a device tree compiler which is capable of compiling overlays. So with that out of the way...
Enabling DCAN1
Update 26th August 2013: This original post focused on enabling dcan1, as these pins are available by default. If you'd like to enable dcan0 (At the expense of i2c2, possibly breaking any capes you have plugged in!), skip to the bottom of the post
To enable CAN (specifically dcan1), we need to write a device tree overlay which will enable the device and set the pin muxing. For those of you who just want the answer, here's the overlay.
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone", "ti,beaglebone-black";
/* identification */
part-number = "dcan1pinmux";
fragment@0 {
target = <&am33xx_pinmux>;
__overlay__ {
dcan1_pins_s0: dcan1_pins_s0 {
pinctrl-single,pins = <
0x180 0x12 /* d_can1_tx, SLEWCTRL_FAST | INPUT_PULLUP | MODE2 */
0x184 0x32 /* d_can1_rx, SLEWCTRL_FAST | RECV_ENABLE | INPUT_PULLUP | MODE2 */
>;
};
};
};
fragment@1 {
target = <&dcan1>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&dcan1_pins_s0>;
};
};
};
There are two important parts to the overlay, fragment@0 and fragment@1. We'll look at each of those in turn.
fragment@0 is responsible for setting the pin mux. The two lines of hex (15-16) represent pairs of 'pin' register and 'mode' value.
Update 20th August 2013: I've created a spreadsheet to simplify the determination of register offset and mode values so you no longer have to dig through datasheets. The dcan1 signals can be found on pins P9 _24 and P9_26, both Mode 2. Use the register value worksheet to determine the correct pinmux values (Fast slew, input for rx/output for tx, pull up, mode 2).
To find the correct register you first need to find out the name of the pins from the BBB SRM. Referring to Table 11 in the SRM, you can find the dcan1 signals are exposed on pins 24 (UART1_TXD) and 26 (UART1_RXD).
Now, diving in to the AM3359 Technical Reference Manual. In Table 9-10 (on page 759!) you can find the two registers conf_uart1_txd (0x980) and conf_uart1_rxd (0x984). These pin configuration registers start at 0x800, therefore the offset values are 0x180 and 0x184 respectively.
The detail of these registers can be found in Section 9.3.51, letting you calculate the correct values for dcan1.
Pin |
Slew Rate |
Input |
Pull Up |
Pull Up |
Mode |
Mode |
Mode |
In Hex |
d_can1_tx (0x180) |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0x12 |
d_can1_rx (0x184) |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
0x32 |
That's it for fragment@0, on to fragment@1. This section enables the CAN device. Firstly, on line 23, we identify the device we want to enable as dcan1. Then we specify that we want the device enabled by setting it's status to "okay" on line 28. Finally, we associate the pin mux created in fragment@0 with the device, line 30.
To compile this overlay, save it as BB-DCAN1-00A0.dts (the dts extension referring to a device tree source file). Then execute the following command.
dtc -O dtb -o BB-DCAN1-00A0.dtbo -b 0 -@ BB-DCAN1-00A0.dts
This will create the overlay binary BB-DCAN1-00A0.dtbo. If you get an error about the -@ option being unrecognised then you are likely on Ubuntu without the patched version of dtc (see here).
To use the overlay simply copy it to /lib/firmware
sudo cp BB-DCAN1-00A0.dtbo /lib/firmware
And execute the following (note you must be logged in as root to do this, sudo will not work!)
echo BB-DCAN1 > /sys/devices/bone_capemgr.*/slots
Check with dmesg to see if this worked, you should see something like this
dmesg | tail -n15
[ 17.878323] init: plymouth-stop pre-start process (796) terminated with status 1
[ 283.946706] bone-capemgr bone_capemgr.8: part_number 'BB-DCAN1', version 'N/A'
[ 283.946892] bone-capemgr bone_capemgr.8: slot #9: generic override
[ 283.946944] bone-capemgr bone_capemgr.8: bone: Using override eeprom data at slot 9
[ 283.946996] bone-capemgr bone_capemgr.8: slot #9: 'Override Board Name,00A0,Override Manuf,BB-DCAN1'
[ 283.947270] bone-capemgr bone_capemgr.8: slot #9: Requesting part number/version based 'BB-DCAN1-00A0.dtbo
[ 283.947323] bone-capemgr bone_capemgr.8: slot #9: Requesting firmware 'BB-DCAN1-00A0.dtbo' for board-name 'Override Board Name', version '00A0'
[ 283.951368] bone-capemgr bone_capemgr.8: slot #9: dtbo 'BB-DCAN1-00A0.dtbo' loaded; converting to live tree
[ 283.952035] bone-capemgr bone_capemgr.8: slot #9: #2 overlays
[ 283.953133] platform 481d0000.d_can: alias fck already exists
[ 283.962225] bone-capemgr bone_capemgr.8: slot #9: Applied #2 overlays.
[ 284.034183] CAN device driver interface
[ 284.071999] c_can_platform 481d0000.d_can: invalid resource
[ 284.078088] c_can_platform 481d0000.d_can: control memory is not used for raminit
[ 284.084553] c_can_platform 481d0000.d_can: c_can_platform device registered (regs=fa1d0000, irq=71)
If you have something to hook up to (don't forget to go through a transceiver, or bad things will happen), you can test everything is up and working with can-utils. First, make sure you have all the relevant modules loaded.
sudo modprobe can
sudo modprobe can-dev
sudo modprobe can-raw
Get and build can-utils
svn co svn://svn.berlios.de/socketcan/trunk
cd trunk/can-utils/
make
Set up the bus speed and enable it
sudo ip link set can0 up type can bitrate 500000
sudo ifconfig can0 up
Now you can use either cansend or candump to test your bus.
Unfortunately, I've discovered my car is more rust than chassis so the track days are going to have to wait. BBB has been repurposed to other projects, more details on these coming soon...
Enabling DCAN0
Update 26th August 2013: After the comment from Marco below, I've put this section in to enable DCAN0.
To enable dcan0, you'll need an overlay similar to that for dcan1. Marco posted one below, but it seems the comment system strips angled brackets for fear of HTML tags, so here is one I made.
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone", "ti,beaglebone-black";
/* identification */
part-number = "dcan0pinmux";
fragment@0 {
target = <&am33xx_pinmux>;
__overlay__ {
dcan0_pins_s0: dcan0_pins_s0 {
pinctrl-single,pins = <
0x178 0x12 /* d_can0_tx, SLEWCTRL_FAST | INPUT_PULLUP | MODE2 */
0x17C 0x32 /* d_can0_rx, SLEWCTRL_FAST | RECV_ENABLE | INPUT_PULLUP | MODE2 */
>;
};
};
};
fragment@1 {
target = <&dcan0>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&dcan0_pins_s0>;
};
};
};
We can build and install this in the same way
dtc -O dtb -o BB-DCAN0-00A0.dtbo -b 0 -@ BB-DCAN0-00A0.dts
sudo cp BB-DCAN0-00A0.dtbo /lib/firmware
However, if you try to enable dcan0 now you will get an error about the i2c pins (see Marco's comment). This is because the i2c2 pins are enabled by default and take precedence over any overlay. Before we continue I should mention that the i2c2 pins are used by the BBB to identify capes, and enable devices/pinmuxes appropriately, everything I do from here on is likely to stop any capes working!.
Another warning: This process involves modifying the default device tree binary. If you do this incorrectly, your BBB will not boot. If you're messing with the eMMC image, I can't guarantee it can be reflashed either (although I see no reason why it shouldn't be possible). You're following this guide at your own risk, if it breaks your BBB it's not my fault! I do all my hacking on an Ubuntu flashed SD card, so if it goes wrong (and it often does!) I can stick the card in my PC and undo any changes. eMMC users, continue at your own risk...
Unfortunately, we can't simply disable i2c2 with an overlay (I have tried, it crashed my BBB!). We also can't switch off the i2c2 device, because it is used by bone_capemgr and disabling it seems to make /sys/devices/bone_capemgr.*/slots disappear, meaning we can't enable overlays! So, my work around is simply to prevent the i2c2 device setting its pinmux and claiming the dcan0 pins. In this state, as far as bone_capemgr is concerned, the i2c2 pins are perpetually disconnected (but the device still exists in /dev/).
To stop i2c2 from setting its pinmux, we need to modify the default device tree binary, and to do this we need the source files. If you built your kernel from scratch you will have them lying around somewhere, but if not you can grab them from Derek Molloy's git repository (Note, I'm assuming the 3.8.13 kernel here).
git clone https://github.com/derekmolloy/boneDeviceTree.git
cd boneDeviceTree/DTSource3.8.13/
Open up am335x-bone-common.dtsi and go to line 401 (pass the -c flag to nano to show line numbers). This is the section concerning i2c2.
nano -c am335x-bone-common.dtsi
&i2c2 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&i2c2_pins>;
clock-frequency = <100000>;
cape_eeprom0: cape_eeprom0@54 {
compatible = "at,24c256";
reg = <0x54>;
};
cape_eeprom1: cape_eeprom1@55 {
compatible = "at,24c256";
reg = <0x55>;
};
cape_eeprom2: cape_eeprom2@56 {
compatible = "at,24c256";
reg = <0x56>;
};
cape_eeprom3: cape_eeprom3@57 {
compatible = "at,24c256";
reg = <0x57>;
};
};
To prevent the pinmux from being applied, simply comment out line 404
// pinctrl-0 = <&i2c2_pins>;
Save and exit, then build with (note, you're not building the file you just edited!)
dtc -O dtb -o am335x-boneblack.dtb -b 0 -@ am335x-boneblack.dts
Before overwriting your default device tree binary, back it up
sudo mv /boot/uboot/dtbs/am335x-boneblack.dtb /boot/uboot/dtbs/am335x-boneblack.orig.dtb
Now move your new binary in to place
sudo mv am335x-boneblack.dtb /boot/uboot/dtbs/
You'll get an error about preserving permissions, you can safely ignore this.
Now reboot your BBB and the i2c2 pinmux will not be applied. Now you should be able to enable dcan0 in much the same way as dcan1. As root (not sudo!)
echo BB-DCAN0 > /sys/devices/bone_capemgr.*/slots
Now grab can-utils and play around with the bus (see above for dcan1).
If you plan to use dcan0 and dcan1, I believe the device driver numbering is based on the order the devices are enabled. So enable dcan0 before dcan1 so that your calls to ip, ifconfig, candump, etc... all make sense!
Recent Comments