Skip to content

Commit

Permalink
nrf_rpc: Add initial protocol specification
Browse files Browse the repository at this point in the history
Add initial version of the nRF RPC protocol specification
that describes the nRF RPC packet format.

Signed-off-by: Damian Krolik <[email protected]>
  • Loading branch information
Damian-Nordic authored and nordicjm committed May 15, 2024
1 parent 7bf4f9b commit d7d48b6
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 9 deletions.
22 changes: 13 additions & 9 deletions nrf_rpc/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,29 @@
Remote procedure call library (nRF RPC)
#######################################

nRF RPC is a remote procedure call library for |NCS| enabling inter-processor communication on Nordic Semiconductor SoCs.
The library is RTOS-agnostic and implements serialization of function calls.
It is designed to be used with an underlying transport layer, for example `OpenAMP`_.
nRF RPC is a remote procedure call library for enabling inter-processor communication on Nordic Semiconductor SoCs.
The library provides a framework for function call serialization.
It is RTOS-agnostic and designed to be used with an underlying transport layer, such as one based on `OpenAMP`_.

The nRF RPC library allows for calling a function on remote processors from a local processor, in both synchronous and asynchronous way.
The nRF RPC library allows for calling a function on a remote processor from a local processor, in both synchronous and asynchronous way.
The library simplifies:

Depending on the transport layer, the remote processor is not limited to a single device.
It can also be a separate device of any type (for example, a PC), or another core on the same system.
* The serialization of user APIs, such as those of a Bluetooth stack.
* The execution of functions implementing those APIs on a remote processor.

The nRF RPC library simplifies the serialization of user APIs, such as a Bluetooth stack, and executing of functions implementing those APIs on a remote CPU.
The library is operating system independent so it can be used with any operating system after porting the OS-dependent layers of the library.
Depending on the transport layer, the local and remote processors are not confined to just one device.
The remote processor can be located on a separate device of any kind, such as a PC, or it can be another CPU core within the same device.

The API layer on top of the core nRF RPC API uses the `zcbor`_ library for serialization.
The library can be used with any operating system after porting the OS-dependent layers of the library.

The CBOR API layer on top of the core nRF RPC API uses the `zcbor`_ library for serializing the function arguments and return values.

.. toctree::
:maxdepth: 2
:caption: Subpages:

doc/architecture
doc/usage
doc/protocol_specification
CHANGELOG
doc/api
125 changes: 125 additions & 0 deletions nrf_rpc/doc/protocol_specification.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
.. _nrf_rpc_protocol_specification:

nRF RPC protocol specification
##############################

.. contents::
:local:
:depth: 2

Two processors that communicate with each other using the remote procedure call (nRF RPC) library follow the nRF RPC protocol.
The nRF RPC protocol specifies the binary format and rules for constructing packets that are exchanged within an nRF RPC communication.

The nRF RPC packets that are constructed by the nRF RPC core library are relayed to the selected transport layer, where they can be additionally encoded to ensure a reliable delivery of the packet to the other processor using the selected medium.
The nRF RPC transport's specification is outside the scope of this document.

The types of communication, threading model and other general concepts of the nRF RPC are described in :ref:`nrf_rpc_architecture`.

nRF RPC packet format
*********************

Each nRF RPC packet consists of a 5-byte header and an optional, variable-length payload:

.. table::
:align: center

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|0 |1 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|0 |1 |2 |3 |4 |5 |6 |7 |0 |1 |2 |3 |4 |5 |6 |7 |
+===+===+===+===+===+===+===+===+===+===+===+===+===+===+===+===+
| Type [\| Source Context ID] | Command ID |
+-------------------------------+-------------------------------+
| Destination Context ID | Source Group ID |
+-------------------------------+-------------------------------+
| Destination Group ID | [Payload...] |
+-------------------------------+-------------------------------+
| [...] |
+---------------------------------------------------------------+

A description of the various fields and their meaning:

``Type [| Source Context ID]``: 8 bits
The packet type determines the function of the packet and it can be one of the following values:

* ``0x00`` - event
* ``0x01`` - response
* ``0x02`` - event acknowledgment
* ``0x03`` - error report
* ``0x04`` - initialization packet
* ``0x80`` - command

If the packet type is ``0x80`` (command), this field is additionally bitwise ORed with the source context ID.

The source context ID is a numeric identifier of the conversation to which the packet is associated, chosen by the packet sender.

The source context ID is a feature of the nRF RPC protocol that facilitates concurrent conversations.
When two threads on the local processor want to start an nRF RPC conversation at the same time, they shall use distinct source context IDs when constructing a packet to the remote processor.
The remote processor is then obliged to use the source context ID as the destination context ID in the response packet.
This ensures that responses and any packets that follow within each conversation are correctly routed to the initiating thread.

The exact source context ID allocation pattern is implementation-defined, meaning that when the packet sender intiates a new conversation or responds to the initiating packet, it is free to allocate any unused source context ID for the new conversation.

``Command ID``: 8 bits
Identifies an individual command or event within an nRF RPC group.

If the packet is a **response** or an **initialization packet**, this field has no meaning and shall be set to ``0xff``.

``Destination Context ID``: 8 bits
A numeric identifier of the conversation to which the packet is associated, chosen by the packet receiver.

In a packet that starts a new conversation, this field shall be assigned the value ``0xff`` (indicating it is unknown).
In all subsequent packets within the conversation, the sender of the packet shall carry over the source context ID that was included in the last packet received from the peer.

``Source Group ID``: 8 bits
A numeric identifier of the nRF RPC group associated with the packet, chosen by the packet sender.

Each processor that uses the nRF RPC protocol chooses unique numeric identifiers for all nRF RPC groups that it supports.
During the nRF RPC protocol initialization, it then communicates its own mapping of the pre-shared string group identifiers to these unique numeric identifiers.

``Destination Group ID``: 8 bits
A numeric identifier of the nRF RPC group associated with the packet, chosen by the packet receiver.

The sender learns this identifier by receiving an **initialization packet** from the peer during the nRF RPC protocol initialization.

``Payload``: variable length
The payload format depends on the packet type:

* **event acknowledgment** - the payload is empty.
* **error report** - the payload is a 32-bit integer representing an error code, in little-endian byte order.
* **initialization packet** - the payload has the following format:

.. table::
:align: center

+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|0 |1 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|0 |1 |2 |3 |4 |5 |6 |7 |0 |1 |2 |3 |4 |5 |6 |7 |
+===+===+===+===+===+===+===+===+===+===+===+===+===+===+===+===+
| Max Version | Min Version | Group name.... |
+---------------+---------------+-------------------------------+
| ... |
+---------------------------------------------------------------+

The ``Min Version`` and ``Max Version`` fields indicate the minimum and maximum version of the nRF RPC protocol supported by the sender.
The ``Group name`` field has a variable length and contains the string identifier of the nRF RPC group to which this packet is associated with, without the null terminator.

* **event**, **response**, **command** - the payload contains remote procedure call arguments or return values, represented in an implementation-defined format.

If the nRF RPC protocol is used together with the CBOR encoding, then the arguments and return values are represented as a sequence of CBOR data items, terminated by the null data item (``0xf6``).

For example, if a packet is an nRF RPC command that represents the C function call ``foo(100, "bar")``, the packet might look as follows:

.. code-block:: none
80 01 ff 00 00 18 64 63 62 61 72 f6
80: Command | Source Context ID (0)
01: Command ID (1)
ff: Destination Context ID (unknown)
00: Source Group ID (0)
00: Destination Group ID (0)
18 64: CBOR unsigned int (100)
63 62 61 72: CBOR text string ("bar")
f6: CBOR null

0 comments on commit d7d48b6

Please sign in to comment.