Control a CAN (Controller Area Network) device
canctl -uunit[,mailbox] [-bdeFhMnPrT] [-f 0x########] [-m 0x########] [-p 0x########] [-t 0x########] [-w 0xmid,mid_type,data_str] [-y 0xmid,mid_type,data_str]
QNX Neutrino
The form of the ID depends on whether or not the driver is using extended MIDs:
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:
canctl option | devctl() command |
---|---|
-d | CAN_DEVCTL_DEBUG_INFO, CAN_DEVCTL_DEBUG_INFO2 |
-e | CAN_DEVCTL_ERROR |
-F | CAN_DEVCTL_GET_MFILTER |
-f | CAN_DEVCTL_SET_MFILTER |
-M | CAN_DEVCTL_GET_MID |
-m | CAN_DEVCTL_SET_MID |
-P | CAN_DEVCTL_GET_PRIO |
-p | CAN_DEVCTL_SET_PRIO |
-r | CAN_DEVCTL_READ_CANMSG_EXT |
-T | CAN_DEVCTL_GET_TIMESTAMP |
-t | CAN_DEVCTL_SET_TIMESTAMP |
-w | CAN_DEVCTL_WRITE_CANMSG_EXT |
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:
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:
# slay dev-can-eg123 # dev-can-eg123 -t -x can1
# canctl -u1,rx0 -F MFILTER = 0x0 # canctl -u1,rx1 -F MFILTER = 0x0 # canctl -u1,tx5 -F MFILTER = 0x0
# canctl -u1,rx0 -M GET_MID = 0x100C0000 # canctl -u1,rx1 -M GET_MID = 0x101C0000 # canctl -u1,tx5 -M GET_MID = 0x100C0000
# 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
# echo testing > /dev/can1/tx5
# 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.
# canctl -u1,rx0 -f0xFFFFFFF0 # canctl -u1,rx1 -f0xFFFFFFF0
echo testing > /dev/can1/tx5
# 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.