canctl

Control a CAN (Controller Area Network) device

Syntax:

canctl -uunit[,mailbox] [-bdeFhMnPrT] [-f 0x########]
       [-m 0x########] [-p 0x########] [-t 0x########]

Runs on:

QNX Neutrino

Options:

-b
Use blocking mode.
-d
Print debugging information. If you specify a receive or transmit mailbox in the -u option, you get information for that mailbox; otherwise, you get information for all of them. The information depends on the driver, but could include the values of the driver's registers and mailboxes.
-e
Print error information.
-F
Get the current message filter. The -u option must specify a receive mailbox.
-f 0x########
Set the message filter. The -u option must specify a receive mailbox.
-h
Print the usage message.
-M
Get the message ID. The -u option must specify a receive mailbox.
-m 0x########
Set the message ID. The -u option must specify a receive mailbox.

The form of the ID depends on whether or not the driver is using extended MIDs:

  • In standard 11-bit MIDs, bits 18–28 define the MID.
  • In extended 29-bit MIDs, bits 0–28 define the MID.
-n
Use nonblocking mode.
-P
Get the tx message priority. The -u option must specify a transmit mailbox.
-p 0x########
Set the tx message priority. The -u option must specify a transmit mailbox, and the priority must not exceed the maximum for the device (usually defined as a constant whose name is in the form board_CANMCF_TPL_MAXVAL).
-r
Read an extended CAN message.
-T
Get the device's timestamp.
-t 0x########
Set the device's timestamp.
-uunit[,mailbox]
Specify the CAN device to operate on. The mailbox name consists of rx or tx followed by the mailbox number. The default is /dev/can1/rx0.

Description:

The canctl utility lets you control a Controller Area Network (CAN) device through its driver, whose name is in the form dev-can-board. This utility provides a command-line interface to the following devctl() commands, which are described in the Devctl and Ioctl Commands reference:

The -u option becomes the file descriptor that's passed to devctl().

The information that's displayed depends on the hardware. Here are some abbreviations that you might see in the output:

LAM
Local area mask
MB
Mailbox name
MCF
Message control field
MDH
Message data high word
MDL
Message data low word
MID
Message ID
MOTS
Message object timestamp

Let's use examples to illustrate what you can use canctl for. In these examples, we'll use a fictitious board, the Exempli Gratia 123, or EG123. First, let's start the CAN driver in self-test mode:

# dev-can-eg123 -t eg123can1

# ls /dev/can1
rx0  rx1  rx2  rx3  rx4  tx5  tx6  tx7  tx8  tx9

In this mode, the transmitter and receiver of the CAN device are looped back. Let's assume that the message IDs (MIDs) of the transmit and receive mailboxes are configured by default as follows:

Mailbox MID
RX0, TX5 0x100C0000
RX1, TX6 0x101C0000
RX2, TX7 0x102C0000
RX3, TX8 0x103C0000
RX4, TX9 0x104C0000

All messages transmitted with MID 0x101C0000 (TX6) are received by any receivers with a filter for MID 0x101C0000, which is RX1 in this case. The CAN drivers let you configure the number of RX and TX devices, as well as the MIDs.

You can use cat to read CAN messages from a receive mailbox:

# cat /dev/can1/rx0 &

and use echo, directed at a transmit mailbox, to transmit a CAN message. The receive mailbox that uses the same message ID receives the message; in this case, RX0 gets the message, and the cat utility displays it:

# echo testing > /dev/can1/tx16
testing

Now, let's examine how you can use canctl to send devctl() commands to the CAN driver to take advantage of various driver features.

Getting and setting the message ID

You can use the -M option or the CAN_DEVCTL_GET_MID devctl() command to obtain the message ID (MID) for a given device:

# canctl -u1,rx0 -M
GET_MID = 0x100C0000

and the -m option or the CAN_DEVCTL_SET_MID devctl() command to specify a new MID. Here we set this for a TX device and the corresponding RX device:

# canctl -u1,rx1 -m0x11CC0000
# canctl -u1,tx6 -m0x11CC0000

You can also specify the starting MID value when you start the driver.

The form of the message ID depends on whether or not the driver is using extended MIDs:

Extended CAN message data

You can get additional information with each received CAN message, but this feature must be enabled in the driver:

# dev-can-eg123 -t -M can1

Then, if you transmit a CAN message:

# echo tstdat1 > /dev/can1/tx5

you can read it with the extended information:

# canctl -u1,rx0 -r
READ_CANMSG_EXT:
mid = 0x100C0000
timestamp = 0xE74
dat len = 8
dat = tstdat1

You can also use the CAN_DEVCTL_READ_CANMSG_EXT devctl() command to get the extended information.

Normal reads still work, but the extended information is discarded.

Device timestamps

You can specify the timestamp when you start the driver:

# dev-can-eg123 -t -m0x123456 -M can1

(We've also enabled extended messaging in this case.) You can use canctl or the CAN_DEVCTL_GET_TIMESTAMP and CAN_DEVCTL_SET_TIMESTAMP devctl() commands to get or set the timestamp:

# canctl -u1 -T
GET_TIMESTAMP = 0x1BD9FC
# canctl -u1 -t0xAAAAAA
# canctl -u1 -T
GET_TIMESTAMP = 0xAAEBEC

If extended message information is enabled, the information includes the timestamp:

# echo testing > /dev/can1/tx5
# canctl -u1,rx0 -r
READ_CANMSG_EXT:
mid = 0x100C0000
timestamp = 0xAED57A
dat len = 8
dat = testing

Message priorities

Priorities can be associated with CAN transmit messages. The hardware uses these priorities to determine which CAN message to transmit first if there are multiple messages waiting to be transmitted. The default priorities depend on the driver.

To read the current priorities, use the -P or the CAN_DEVCTL_GET_PRIO devctl() command:

# canctl -u1,tx1 -P
GET_PRIO = 16

To set a new device priority, use the -p or the CAN_DEVCTL_SET_PRIO devctl() command:

# canctl -u1,tx1 -p5

Message filtering

You can use masks on the receive mailboxes to further modify the filtering provided by the message IDs (MID). The mask specifies which bits in the MID are to be ignored. By default, the mask is disabled, but you can enable and modify it by using the -f option or the CAN_DEVCTL_SET_MFILTER devctl() command:

  1. Start the driver with extended MIDs enabled:
    # slay dev-can-eg123
    # dev-can-eg123 -t -x can1
    
  2. Get the initial mask values:
    # canctl -u1,rx0 -F
    MFILTER = 0x0
    
    # canctl -u1,rx1 -F
    MFILTER = 0x0
    
    # canctl -u1,tx5 -F
    MFILTER = 0x0
    
  3. Get the initial MID values:
    # canctl -u1,rx0 -M
    GET_MID = 0x100C0000
    
    # canctl -u1,rx1 -M
    GET_MID = 0x101C0000
    
    # canctl -u1,tx5 -M
    GET_MID = 0x100C0000
    
  4. Set new MID values for rx0, rx1, and tx5
    # canctl -u1,rx0 -m0x100C0001
    # canctl -u1,rx1 -m0x100C0002
    # canctl -u1,tx5 -m0x100C0002
    
    # canctl -u1,rx0 -M
    GET_MID = 0x100C0001
    
    # canctl -u1,rx1 -M
    GET_MID = 0x100C0002
    
    # canctl -u1,tx5 -M
    GET_MID = 0x100C0002
    
  5. Transmit a CAN message from tx5:
    # echo testing > /dev/can1/tx5
    
  6. Determine which RX device received that message:
    # cat /dev/can1/rx0
    [Ctrl+C]
    
    # cat /dev/can1/rx1
    testing
    [Ctrl+C]
    

    RX1 received the message because its MID exactly matched that of TX5.

  7. Use the -f option (or the CAN_DEVCTL_SET_MFILTER devctl() command) to set the local area mask (LAM) filter on RX0 and RX1:
    # canctl -u1,rx0 -f0xFFFFFFF0
    # canctl -u1,rx1 -f0xFFFFFFF0
    
  8. Transmit a CAN message from tx5:
    echo testing > /dev/can1/tx5
    
  9. Determine which RX device received that message:
    # cat /dev/can1/rx1
    [Ctrl+C]
    
    # cat /dev/can1/rx0
    testing
    

    RX0 and RX1 now appear to have the same MID since the last nibble is now ignored for both devices because they have the last nibble of the LAM filter cleared. Therefore, RX0 received the message because it is the first message buffer with the most matching MID bits.