1. Introduction
This document describes the NoCAN wire-level protocol as implemented in the NoCAN project.
NoCAN is a protocol that is built on top of CAN bus. It is designed to make communications between micro-controller based nodes simple and cheap. All nodes are connected together through a common shared bus. A special node called the network manager, is also connected to the shared bus and takes care of managing nodes in the network. The network manager typically runs on a PC or Raspberry Pi and communicates with the network through a specific interface (i.e. the Omzlo PiMaster HAT controller).
NoCAN is designed to optionally work without a network manager with degraded functionalities but this mode of operation is not currently described in this document.
NoCAN offers the following features:
- A publish/subscribe messaging system (pub/sub).
- The ability to send messages of up to 64 bytes (CAN bus messages are only 8 bytes max).
- Provisions for automated address assigned to each node in the network.
- Specialised messaging for micro-controller firmware update and bootloader control.
The publish/subscribe messaging system is based on the concept of channels.
A channel has an identifier channel_id
and a textual description is the form of an ascii string of up to 64 bytes.
When a node wants to receive data, it subscribes to a channel by performing the following operations:
- The node performs a channel lookup, providing the name of the channel it is interested in (e.g. "garden/temperature")
- The node manager responds with a
channel_id
corresponding to that channel (or an error code if the channel does not exist). - The node configures its internal CAN bus filters to accept all messages with the specific
channel_id
. - The node then waits for messages
When a node wants to send data, it publishes to a channel by performing the following operations:
- The node performs a channel registration, providing the textual name of the channel it wants to publish to (e.g. "garden/temperature")
- The node manager responds with a
channel_id
corresponding to that channel. - The node then sends messages with a channel identifier set to the
channel_id
provided in step 2.
All the steps above are supported by the NoCAN protocol though system messages and publish messages, as detailed in this document.
The rest of this specification is organized as follows:
- Section 2 describes how NoCAN uses CAN bus frames.
- Section 3 lists common messaging sequences used in NoCAN.
- Sections 4 and 5 specify all messages used in NoCAN.
2. CAN bus frame structure used in Nocan
Nocan uses CAN extended data frames exclusively. Such frames are composed of 3 main parts:
- eid: A 29 bit extended identifier,
- dlc: A data length code with a value between 0 and 8,
- data: 0 to 8 bytes of data, depending on the length specfied in the dlc.
While CAN frames are limited to 8 bytes of data, NoCAN allows creating messages of up to 64 bytes by combining up to 8 CAN frames together, as described below.
The 29 bits of the eid are used to carry both node address information and protocol parameters.
There are essentially two types of NoCAN messages:
- System messages: these messages are used to manage nodes and channel subscriptions. The eid notably contains a function identifier.
- Publish messages: these messages are used to send a message on a specific channel. The eid notably contains a channel identifier.
System messages and publish messages are distinguished by the 11th bit of the eid as described below.
2.1 The eid of a system CAN frame
The 29-bit eid of a system message has the following structure:
Position | Length | Field | Description |
---|---|---|---|
0 | 1 | first_packet_flag |
When set to 1, indicates that this is the first packet in a message. |
1 | 7 | node_id |
Node sending the message (0 to 127). 0 has a special meaning. |
8 | 1 | last_packet_flag |
When set to 1, indicates that this is the last packet in a message. |
1 | 1 | reserved | always 0 |
10 | 1 | sys_flag |
When set to 1 indicates that this is a "system" message |
11 | 2 | reserved | always 0 |
13 | 8 | function |
Function identifier (currently there are 27 function identifiers). |
21 | 8 | parameter |
Optional parameter, function dependent. |
The flags first_packet_flag
and last_packet_flag
are used to construct NoCAN messages that are composed of 1 to 8 CAN frames:
- The first frame in a message will have the
first_packet_flag
set to 1. - The last frame in a message will have the
last_packet_flag
set to 1. - Any intermediate frame that is neither the last nor the first will have both flags set to 0.
- Any message that is composed of a single CAN frame will have both flags set to 1.
The node_id
indicates the address of the node that has sent the message.
The value 0 has a special meaning when used as a node_id
and can only be used:
- By the node manager to send a message.
- By an ordinary node when it sends the NOCAN_SYS_ADDRESS_REQUEST system message
In all other cases, nodes should never use node_id=0
The flag sys_flag
is always set to 1 in system messages.
The function
field describes a request or response to a request, most frequently directed to the node manager.
The meaning of the function
field is described in detail in a dedicated section of this document.
The parameter
field complements the function
field in some situations or is used to carry a response code (by convention 0 means success, while 255 indicates a failure).
2.2 The eid of a publish CAN frame
The 29-bit eid of a publish message has the following structure:
Position | Length | Field | Description |
---|---|---|---|
0 | 1 | first_packet_flag |
When set to 1, indicates that this is the first packet in a message. |
1 | 7 | node_id |
Node sending the message (0 to 127). 0 has a special meaning. |
8 | 1 | last_packet_flag |
When set to 1, indicates that this is the last packet in a message. |
1 | 1 | reserved | always 0 |
10 | 1 | sys_flag |
When set to 0 indicates that this is a "publish" message |
11 | 2 | reserved | always 0 |
13 | 16 | channel_id |
Channel identifier (0 to 65534). The value 65535 indicates an error. |
The flags first_packet_flag
and last_packet_flag
are used to construct Nocan messages that are composed of 1 to 8 CAN frames, in the same way as they are used for system messages (see 2.1).
The node_id
indicates the address of the node that publishes the message.
The channel_id
field indicates the channel to which the message is published.
2.3 Data types and conventions
A node_id
represents a value between 0 and 127, where 0 has a special meaning described previously.
A channel_id
represents a value between 0 and 65534. The value 65535 is reserved to indicate an error.
A Nocan message can be composed of 1 to 8 CAN bus frames:
- This limit is enforced by software.
- Except for NOCAN_SYS_CHANNEL_REGISTER and NOCAN_SYS_CHANNEL_LOOKUP system messages (see section 5), which can contain up to 8 frames, all system messages are composed of 1 CAN frame.
- All CAN frames in a system message are expected to have the same value for the
function
andnode_id
fields. - All CAN frames in a publish message are expected to have the same value for the
channel_id
andnode_id
fields.
The number of channels a single node can subscribe to may be limited by software/hardware constraints. On the Omzlo One, each node can subscribe to up to 12 channels simultaneously.
3. Nocan protocol messaging sequences
This section presents a high-level view of the most common protocol sequences used in Nocan. Individual messages are detailed in section 4 and 5.
3.1 Address allocation
When a node wants to obtain a unique address (i.e. a node_id
), the following exchange takes place:
- The node sends a NOCAN_SYS_ADDRESS_REQUEST message with a unique 8-byte device identifier.
- The node manager responds with a NOCAN_SYS_ADDRESS_CONFIGURE message with the same unique 8 byte device identifier and a
parameter
value set to the new address allocated to the node. - The node responds with NOCAN_SYS_ADDRESS_CONFIGURE_ACK.
Note that in steps 1 and 2, node_id
is set to 0.
3.2 Registering a channel
When a node wants to create a new channel to publish data, the following exchanges take place:
- The node sends a NOCAN_SYS_CHANNEL_REGISTER message containing a textual description of the channel (e.g. "garden/temperature").
- The node manager responds with a NOCAN_SYS_CHANNEL_REGISTER_ACK message containing the
channel_id
corresponding to the channel name provided in step 1.
Note that if the channel defined in step 1 already exists, the node manager will not create a new channel_id
but will return the existing one.
A node can also perform a channel lookup using (NOCAN_SYS_CHANNEL_LOOKUP) and proceed to step 1 above only if the lookup fails (returning param=255).
3.3 Subscribing to a channel
When a node wants to subscribe to a channel, the following actions take place:
- The node sends a NOCAN_SYS_CHANNEL_LOOKUP message containing a textual description of the channel (e.g. "garden/temperature").
- The node manager responds with a NOCAN_SYS_CHANNEL_LOOKUP_ACK message containing the
channel_id
corresponding to the channel name provided in step 1. - The node sends an advisory NOCAN_SYS_CHANNEL_SUBSCRIBE message, specifying the
channel_id
it wants to subscribe to. - The node configures its CAN bus driver filters to accept 'publish' messages with an eid that contains
channel_id
.
In step 2, if the channel has not been previously registered (see 3.2), an error is returned by the node manager.
3.4 Publishing to a channel
When a node wants to publish data, the following exchanges will take place:
- The node sends a NOCAN_SYS_CHANNEL_LOOKUP message containing a textual description of the channel (e.g. "garden/temperature").
- The node manager responds with a NOCAN_SYS_CHANNEL_LOOKUP_ACK message containing the
channel_id
corresponding to the channel name provided in step 1. - The node sends a "publish" message with the data it wants to publish. That message will use the
channel_id
obtained in step 2.
Step 1 and 2 only need to be performed once. After that step 3 can be repeated indefinitely.
3.5 Rebooting a node
When the node manager wants to reboot a node, it sends a NOCAN_SYS_NODE_BOOT_REQUEST message to the target node.
On the CANZERO this message is captured by the NoCAN driver IC (STM32F042), which in turn performs a hard reset on the main IC (the SAMD21). This is designed to allow rebooting the main IC even if it is "stuck".
3.6 Node firmware upgrade over the network
When the node manager wants to update the flash or eeprom memory of a node, the following exchanges take place:
- The node manager reboots the node (see 3.5).
- The node starts in "bootloader mode". The node requests and obtains an address (see 3.1).
- The node sends a NOCAN_SYS_NODE_BOOT_ACK message to signify that it is in "bootloader mode".
- The node manager sends a NOCAN_SYS_BOOTLOADER_SET_ADDRESS with the memory type and address it wants to update.
- The node responds with a NOCAN_SYS_BOOTLOADER_SET_ADDRESS_ACK.
- The node manager sends a NOCAN_SYS_BOOTLOADER_WRITE message with up to 8 bytes of data to write, and
parameter
set 0. - The node responds with a NOCAN_SYS_BOOTLOADER_WRITE_ACK, stores the data in a temporary location.
- If there is still data to write in the memory block, we go back to step 6, otherwise, we continue to step 9.
- The node manager sends a NOCAN_SYS_BOOTLOADER_WRITE with
parameter
set to 1. - The node updates the memory block and responds with a NOCAN_SYS_BOOTLOADER_WRITE_ACK.
- If more memory needs to be updated, we go back to step 4, otherwise, we stop.
When updating flash memory, the steps 4 to 10 need to be repeated for each "page" of memory (one page is 128 bytes for the Atmega328pb).
4. NoCAN publish message
Publish messages have a specific eid described in 2.2 and are composed of 1 to 8 CAN frames. Publish messages are not acknowledged.
5. NoCAN system messages
This section describes system messages used in NoCAN, based on the value of the function
field.
5.1 NOCAN_SYS_ADDRESS_REQUEST (1)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
0 | 1 | - | 8 | 8 byte unique device identifier |
DESCRIPTION
The node sends this message with an 8-byte unique device identifier to request the attribution of an address (node_id
).
In the Omzlo One, this unique device identifier is derived from the serial number of the STM32F042 chip used as a CAN bus interface.
The node manager responds with a NOCAN_SYS_ADDRESS_CONFIGURE message containing the assigned node_id
.
5.2 NOCAN_SYS_ADDRESS_CONFIGURE (2)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
0 | 1 | 1 to 127 or 255 | 8 | 8 byte unique device identifier |
Parameter: 1 to 127 as the new node_id
assigned to the node or 255 (0xFF) for failure.
DESCRIPTION
This message attributes the value defined in parameter
as an address (i.e. a node_id
) to the node that has the 8-byte unique device identifier provided in data
.
This message is sent as a response to a NOCAN_SYS_ADDRESS_CONFIGURE message.
The node that receives this message should respond with a NOCAN_SYS_ADDRESS_CONFIGURE_ACK message to finalize the node identifier attribution.
5.3 NOCAN_SYS_ADDRESS_CONFIGURE_ACK (3)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 3 | - | 0 | - |
DESCRIPTION
This message is sent by a node to finalizes the attribution of an address to itself.
This message is sent as a response to a NOCAN_SYS_ADDRESS_CONFIGURE message.
5.4 NOCAN_SYS_ADDRESS_LOOKUP (4)
Not implemented.
5.5 NOCAN_SYS_ADDRESS_LOOKUP_ACK (5)
Not implemented.
5.6 NOCAN_SYS_NODE_BOOT_REQUEST (6)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 6 | 1 | 0 | - |
DESCRIPTION
Causes the node identified by node_id
to reboot.
On the Omzlo One, this message causes the STM32F042 to lower the reset pin of the Atmega328pb, causing a hardware reset.
NOCAN_SYS_NODE_BOOT_ACK (7)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 7 | - | 0 | - |
DESCRIPTION
This message is sent by the bootloader once it has received an address (see NOCAN_SYS_ADDRESS_CONFIGURE and other related messages), to indicate that it is ready to accept bootloader commands (e.g. firmware update).
On the Omzlo One, the bootloader is active for 10 seconds approximately before automatically booting to the main application.
NOCAN_SYS_NODE_PING (8)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 8 | - | 0 to 8 | 0 to 8 bytes |
DESCRIPTION
When a node receives this message it is expected to respond with NOCAN_SYS_NODE_PING_ACK message that contains a copy of the data
provided here.
On the Omzlo CANZERO this message is directly processed by the network driver IC (STM32F042) and is not passed along to the main microcontroller (SAMD21G18).
NOCAN_SYS_NODE_PING_ACK (9)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 9 | - | 0 to 8 | 0 to 8 bytes |
DESCRIPTION
This message is provided in response to a NOCAN_SYS_NODE_PING message.
NOCAN_SYS_CHANNEL_REGISTER (10)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 10 | - | 1-64 | 1 to 64 bytes, representing an ascii channel name |
DESCRIPTION
This message is sent by a node to register a channel with the name provided in data
.
The node manager will respond with a NOCAN_SYS_CHANNEL_REGISTER_ACK containing the channel_id
of the channel.
If a channel with a similar name has already been registered with a channel_id
that value will be provided in response.
Note that the channel name is not 0 terminated as strings are in the C language.
NOCAN_SYS_CHANNEL_REGISTER_ACK (11)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 11 | 0 or 255 | 2 | A 16 bit channel_id (MSB first) |
DESCRIPTION
This message is provided by the node manager to a node in reponse to a NOCAN_SYS_CHANNEL_REGISTER message.
Parameter is 0 in case of success and 255 in case of failure. The data contains a 16-bit channel id in case of success.
NOCAN_SYS_CHANNEL_UNREGISTER (12)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 12 | - | 2 | A 16 bit channel_id (MSB first) |
DESCRIPTION
This message is sent by a node to unregister the channel identified by the 16 bit channel_id
.
If there are no other nodes that have registered channel_id
, the channel manager will release internal resources associated with that channel.
The node manager will respond with a NOCAN_SYS_CHANNEL_UNREGISTER_ACK message.
NOCAN_SYS_CHANNEL_UNREGISTER_ACK (13)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 13 | 0 or 255 | 0 | - |
DESCRIPTION
This message is sent by the node manager in response to a NOCAN_SYS_CHANNEL_UNREGISTER message.
Parameter is 0 in case of success and 255 in case of failure.
NOCAN_SYS_CHANNEL_SUBSCRIBE (14)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 14 | - | 2 | A 16 bit channel_id (MSB first) |
DESCRIPTION
This message is sent by a node to signal that it is subscribing to the channel identified by channel_id
.
This message is only advisory and is not acknowledged by the node manager.
NOCAN_SYS_CHANNEL_UNSUBSCRIBE (15)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 15 | - | 2 | A 16 bit channel_id (MSB first) |
DESCRIPTION
This message is sent by a node to signal that it is stoping its subscription to the channel identified by channel_id
.
This message is only advisory and is not acknowledged by the node manager.
NOCAN_SYS_CHANNEL_LOOKUP (16)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 16 | - | 1 to 64 | 1 to 64 bytes, representing an ascii channel name |
DESCRIPTION
This message is sent by a node to request the value of channel_id
that corresponds to the provided channel name.
The node manager will respond with NOCAN_SYS_CHANNEL_LOOKUP_ACK, providing the channel_id
.
NOCAN_SYS_CHANNEL_LOOKUP_ACK (17)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 17 | 0 or 255 | 2 | A 16 bit channel_id (MSB first) |
DESCRIPTION
This message is sent by the node manager in response to a NOCAN_SYS_CHANNEL_LOOKUP message.
Parameter is 0 in case of success and 255 in case of failure. The data contains a 16 bit channel id in case of success.
NOCAN_SYS_BOOTLOADER_GET_SIGNATURE (18)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 18 | - | 0 | - |
DESCRIPTION
This message is sent by the node manager to request the device id of the main chip in the node.
The node is expected to respond with a NOCAN_SYS_BOOTLOADER_GET_SIGNATURE_ACK message. A node is only required to respond to this message when it is in bootloader mode.
NOCAN_SYS_BOOTLOADER_GET_SIGNATURE_ACK (19)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 19 | - | 1-8 | The device signature. |
DESCRIPTION
This message is sent by a node in response to a NOCAN_SYS_BOOTLOADER_GET_SIGNATURE message.
On the Omzlo One DLC=3 and data is 0x1E, 0x95, 0x16.
NOCAN_SYS_BOOTLOADER_SET_ADDRESS (20)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 20 | 'F' or 'E' | 4 | 32 bits address (MSB first). |
DESCRIPTION
This message is sent by the node manager to set the address of the next flash or eeprom memory that will be read or written.
Reaging or writing is performed by LL_SYS_BOOTLOADER_READ and LL_SYS_BOOTLOADER_WRITE.
Parameter is set to 'F' to indicate flash memory, and 'E' to indicate eeprom.
NOCAN_SYS_BOOTLOADER_SET_ADDRESS_ACK (21)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 21 | 0 or 255 | 0 | - |
DESCRIPTION
This message is sent by a node in response to a NOCAN_SYS_BOOTLOADER_SET_ADDRESS message.
NOCAN_SYS_BOOTLOADER_WRITE (22)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 22 | 0 or 1 | 0-8 | Data to be writen to flash or eeprom. |
DESCRIPTION
This message is sent by the node manager to request data to be written in flash or eeprom.
The memory address where data is written is set by a call to NOCAN_SYS_BOOTLOADER_SET_ADDRESS and is then incremented automatically by each call to NOCAN_SYS_BOOTLOADER_WRITE.
If parameter
is 0 the data is stored in a buffer and the flash/eeprom is not updated.
A parameter
set to 1 marks the final bytes of data in a block and the buffer is written to flash or eeprom.
NOCAN_SYS_BOOTLOADER_WRITE_ACK (23)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 23 | 0, 1 or 255 | 0 | - |
DESCRIPTION
This message is sent by a node in response to a NOCAN_SYS_BOOTLOADER_WRITE message.
In case of success parameter
takes the same value (0 or 1) as in the NOCAN_SYS_BOOTLOADER_WRITE message.
In case of failure parameter
is set to 255.
NOCAN_SYS_BOOTLOADER_READ (24)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
id > 0 | 24 | 0 to 8 | 0 | - |
DESCRIPTION
This message is sent by the node manager to request data to be read from flash or eeprom.
The memory address where data is read is set by a call to NOCAN_SYS_BOOTLOADER_SET_ADDRESS and is then incremented automatically by each call to NOCAN_SYS_BOOTLOADER_READ.
The value of parameter
indicates the number of bytes to read.
NOCAN_SYS_BOOTLOADER_READ_ACK (25)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
0 > id | 25 | 0 or 255 | 0 to 8 | Data read from flash or eeprom. |
DESCRIPTION
This message is sent by a node in response to a NOCAN_SYS_BOOTLOADER_READ message.
Parameter is 0 in case of success and 255 in case of failure.
NOCAN_SYS_BOOTLOADER_LEAVE (26)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
0 > id | 26 | - | 0 | - |
DESCRIPTION
This message is sent by the node manager to request a node to leave bootloader mode and start the main application.
On the Omzlo One, the bootloader is active for 10 seconds approximately before automatically booting to the main application: this message allows to shorten this delay by explicitly requesting the node to launch the application.
The node is expected to acknowledge this message with a NOCAN_SYS_BOOTLOADER_LEAVE_ACK message.
NOCAN_SYS_BOOTLOADER_LEAVE_ACK (27)
STRUCTURE
node_id | function | parameter | DLC | data |
---|---|---|---|---|
0 > id | 27 | - | 0 | - |
DESCRIPTION
This message is sent by a node in response to a NOCAN_SYS_BOOTLOADER_LEAVE message.