Quick start
This section shows you how to create a loopback connection by connecting the two CAN channels (connect CAN0-H to CAN1-H and CAN0-L to CAN1-L).
The tutorial below assumes that you're using a Raspberry Pi 4 with a Waveshare 2-channel CAN HAT as a CAN controller (for more information, refer to the "2-CH CAN HAT" section in the Waveshare wiki).
To operate properly, you may require a 120 ohm resistor between the CAN-Hn and CAN-Ln terminals on both ends, as described in the Nuts and Volts article, Take a CAN bus for a spin.
Building the project
To build the project:
Ensure you have the QNX Software Development Platform (SDP) 8 installed on your computer. Refer to steps 1-4 of the "Quick start instructions" section in the Quick Start Target Image (QSTI) Guide.
Clone the can-mcp2515 project using the
gitcommand:git clone https://gitlab.com/qnx/projects/drivers/can-mcp2515.gitExecute the build by using QNX recursive make:
- Activate the QNX SDP 8 environment and execute
makein the project directory. - Specify
hinstall(header install) andinstall(library/binary install) as targets. - Specify the local output directory using INSTALL_ROOT_nto and USE_INSTALL_ROOT environment variables.
- Specify your QNX SDP 8 installation path and change the current directory to wherever you cloned the project to.
For example:
. ~/qnx800/qnxsdp-env.sh cd can-mcp2515 make INSTALL_ROOT_nto=${PWD}/build USE_INSTALL_ROOT=1 hinstall install- Activate the QNX SDP 8 environment and execute
Installing the driver
To install the driver, copy the appropriate executable to the target device:
TARGET=192.168.1.12 # Use IP or address of your target device
scp build/aarch64le/bin/can-mcp2515 root@${TARGET}:/system/binConfiguring the driver
To configure the driver:
Modify the SPI configuration file, /system/etc/config/spi/spi.conf, to ensure that SPI bus #0 and the two devices, #0 and #1, on the bus are configured as follows:
[bus] busno=0 name=spi0 base=0xfe204000 irq=150 input_clock=500000000 bs=rpanic=48,tpanic=16 dma_attach_opts=num_cbs=256,range_min=0,range_max=14,typed_mem=sysram&below1G dma_thld=4 [dev] parent_busno=0 devno=0 name=dev0 clock_rate=10000000 cpha=0 cpol=0 bit_order=msb word_width=8 idle_insert=1 [dev] parent_busno=0 devno=1 name=dev1 clock_rate=10000000 cpha=0 cpol=0 bit_order=msb word_width=8 idle_insert=1Reboot your target device, wait for the reboot to complete, and log in. Verify that there are two SPI devices available with the following paths:
- /dev/io-spi/spi0/dev0
- /dev/io-spi/spi0/dev1
Running the driver
To run the driver:
Start the can-mcp2515 driver for each CAN channel on the board:
can-mcp2515 --mid=eid -s /dev/io-spi/spi0/dev0 -c 16000000 -g 23 can-mcp2515 --mid=eid -s /dev/io-spi/spi0/dev1 -c 16000000 -g 25 -u 1You can add the
-voption to increase driver logging verbosity and repeat thevup to seven times.Use the
slog2infocommand to view the logs.Verify that two new CAN devices are present:
- /dev/can0
- /dev/can1
Each CAN device should have two receive mailboxes,
rx0andrx1, and three transmit mailboxes,tx2,tx3, andtx4.Each mailbox has a different MID (CAN message ID) set. Given that you started the driver with the
--mid=eidoption, the IDs forrx0,rx1,tx2,tx3, andtx4are0,1,2,3, and4, respectively. If you set--midtosid, then the IDs would be0x0,0x40000,0x80000,0xC0000, and0x100000, respectively.Send data using /dev/can0/tx2 and receive data using /dev/can1/rx0. The receive mailboxes use a combination of filter and MID to determine whether to capture the message. To capture all messages, set both to
0using thecanctlcommand:canctl -u 1,rx0 -m 0 canctl -u 1,rx0 -f 0
Receiving data
You can receive data using one of the methods listed below:
Use the
canctlcommand. For example, to continuously read CAN messages from /dev/can1/rx0 with a 100 ms delay between reads, execute:canctl -u 1,rx0 -R 100Use the devctl() function with one of the following commands:
Read /dev/can1/rx0 using the open(), read(), and close() functions, or the
catcommand (this only returns the CAN frames' payload data):cat /dev/can1/rx0
Sending data
You can send data using one of the methods listed below:
Use the
canctlcommand. For example, to send a CAN message to /dev/can0/tx2, execute:canctl -u 0,tx2 -w 0x12345,1,testingUse the devctl() function with the CAN_DEVCTL_WRITE_CANMSG_EXT or CAN_DEVCTL_TX_FRAME_RAW command.
Write to /dev/can0/tx2 using the open(), write(), and close() functions, or the
echocommand. Since you can only specify a payload this way, the MID of the frame is set to the MID of the TX device. As specified below, the payload contains the new-line character:echo TESTING > /dev/can0/tx2
Send and receive data
To send and receive messages using the command line simultaneously, execute the receive and send commands in separate terminals, or execute the receive command in the background, and then execute the send command:
canctl -u 1,rx0 -R 100 &
canctl -u 0,tx2 -w 0x12345,1,testingThe output displayed represents data from both the send and the receive commands. For example:
mid = 0x12345
dat = testing
dat len = 8
mid type = extended
WRITE_CANMSG_EXT: OK
READ_CANMSG_EXT 2:
mid = 0x12345
timestamp = 0xE92AD1A1
dat len = 8
dat = 74 65 73 74 69 6e 67 00
testing.When reading multiple messages using the canctl command with the -R argument, the data displayed in the dat field contains all bytes received since the receive command was started; however, only the first 106 bytes are displayed. This is a bug in the canctl command, and has nothing to do with libcan or the driver. The following lines contains the text representation of the currently received message.
