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:

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

  2. Clone the can-mcp2515 project using the git command:

    git clone https://gitlab.com/qnx/projects/drivers/can-mcp2515.git
  3. Execute the build by using QNX recursive make:

    • Activate the QNX SDP 8 environment and execute make in the project directory.
    • Specify hinstall (header install) and install (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

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/bin

Configuring the driver

To configure the driver:

  1. 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=1
  2. Reboot 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:

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

    You can add the -v option to increase driver logging verbosity and repeat the v up to seven times.

  2. Use the slog2info command to view the logs.

  3. Verify that two new CAN devices are present:

    • /dev/can0
    • /dev/can1

    Each CAN device should have two receive mailboxes, rx0 and rx1, and three transmit mailboxes, tx2, tx3, and tx4.

    Each mailbox has a different MID (CAN message ID) set. Given that you started the driver with the --mid=eid option, the IDs for rx0, rx1, tx2, tx3, and tx4 are 0, 1, 2, 3, and 4, respectively. If you set --mid to sid, then the IDs would be 0x0, 0x40000, 0x80000, 0xC0000, and 0x100000, respectively.

  4. 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 0 using the canctl command:

    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:

Sending data

You can send data using one of the methods listed below:

  • Use the canctl command. For example, to send a CAN message to /dev/can0/tx2, execute:

    canctl -u 0,tx2 -w 0x12345,1,testing
  • Use 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 echo command. 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,testing

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

Page updated: