Skip to main content Link Menu Expand (external link) Document Search Copy Copied

6. Device Firmware Integration

The reference integration is the sid_diagnostics application. Where it does not exist for your platform, this chapter is the porting contract. A port is typically one source file of 200 to 350 lines, plus build system changes.

Section 6.1 is for the engineer who adds ROW to a Factory Diagnostic Firmware. If an image with ROW support already exists for your platform, go straight to Section 6.2, which applies to every product.

The firmware reaches the line PC over one host interface, which is selected when the image is built: UART, or SEGGER RTT through a J-Link debug probe. Both interfaces carry the same wire protocol (Section 6.1.2), and the tool handles both in the same way. The reference application builds one image per host interface, and the RTT image is the default where both exist.

6.1 Factory Diagnostic Firmware

The Factory Diagnostic Firmware runs ROW on the factory line (Chapter 5). It is flashed first, and is replaced by the production firmware after registration.

6.1.1 Feature macros and libraries

Define the following for the Factory Diagnostic Firmware image:

# Compiles in the `register ...` CLI commands (default off); the stack itself is the three libraries linked below
target_compile_definitions(sid_on_dev_cert_cli
    PRIVATE SID_SDK_INTERNAL_CONFIG_ENABLE_SERIAL_REGISTRATION=1)

target_link_libraries(<your_app> PRIVATE
    sid_serial_registration
    sid_network_link_wired_ifc
    sid_network_link_wired)

6.1.2 Wire protocol

The host interface is one byte stream in each direction. On UART it is a serial port at 115200 baud, 8N1, no flow control. On RTT it is channel 0, the terminal channel, of the SEGGER RTT control block; no second RTT channel is used. In both cases the stream carries two kinds of traffic, which are separated on the first byte of each unit:

  • Text CLI. ASCII command lines (cert ..., register ...) terminated by \r or \n. The device answers them in text: {CERT ...} and {REGISTRATION ...} status lines. The cert ... commands are the same Factory Diagnostic Firmware certificate commands used in the existing mass production flow.
  • Binary frames. The format is identical in both directions: 0xAA | LEN (1 byte) | payload, with a payload of at most 255 bytes. The wired link MTU of 184 bytes keeps traffic within this limit. A host-to-device frame with a 1-byte payload is the registration-complete indication, and is consumed by the SDK. Payloads are opaque encrypted messages: the firmware only frames and deframes them.

Console output of the firmware, such as the CLI prompt, the command echo and log lines, may share the stream with this traffic. The tool treats every byte that is not part of a frame as console text. Console text must therefore be 7-bit ASCII, so that the sync byte 0xAA never occurs in it, and a frame must be written as one unit, so that no console output is inserted into it.

The framing is version-paired with the tool. Earlier releases used a 2-byte host-to-device length field. If the versions do not match, the tool and the device cannot communicate.

6.1.3 Serial interface callbacks

Implement all four callbacks of struct serial_ifc_context (sid_serial_ifc.h). The callbacks are called from task context.

Callback Contract
serial_init One-time initialization of the host interface (UART or RTT) and of the demultiplexer. It is called by sid_on_dev_cert_serial_registration_init() when the transport is registered, and must be idempotent
serial_read Non-blocking. Returns one complete deframed payload, or zero bytes. It must never return a partial frame
serial_write Emits 0xAA, the 1-byte length and the payload as one unit. It must reject a length greater than 255
serial_mfg_data_write Same as serial_write, preceded by a pacing delay of approximately 10 ms on UART. On RTT the delay is optional

The receive demultiplexer must behave as follows:

  • Accumulate CLI text only while waiting for the sync byte (0xAA).
  • Inside a frame, treat every byte as part of the frame.
  • Validate the length (0 < len ≤ buffer size). On an invalid length, drop the frame and return to waiting for the sync byte.
  • Hand completed CLI lines to the CLI runtime from the main loop, never from interrupt context. The reference backends either feed the demultiplexed text to the runtime through stdio, where sid_cli_process() reads and dispatches it, or pass each completed line to the CLI runtime directly from the main loop.

6.1.4 Integration and lifecycle

sid_cli_init();                                          /* CLI runtime, required */
sid_diagnostics_cli_init();                              /* reference diagnostics commands, optional */
sid_on_dev_cert_cli_init();                              /* cert ... commands, required */
sid_on_dev_cert_serial_registration_init(&serial_ifc);   /* register ... commands and the transport; calls serial_init() */

for (;;) {
    /* flush platform logs */
    sid_serial_registration_process();   /* no-op until the host starts registration */
    sid_cli_process();                   /* dispatches the command lines received on the host interface */
}

sid_cli_init() and sid_cli_process() are required: the command lines the tool sends arrive through the host interface backend (UART or RTT) and are handed to the CLI runtime as described in Section 6.1.3, and sid_cli_process() runs the CLI runtime and its event queue. sid_on_dev_cert_cli_init() registers the cert command set, and sid_on_dev_cert_serial_registration_init() registers the register command set together with the serial transport. sid_diagnostics_cli_init() adds the reference diagnostics commands and is optional.

  • The host tool drives the lifecycle. The tool sends register start and, at security-level-low, register commit_keys. Do not call sid_serial_registration_init() or sid_serial_registration_start() from application code. register start already calls them, and a second initialization fails with SID_ERROR_ALREADY_INITIALIZED.
  • Completion. The host tool determines completion from the Amazon Sidewalk cloud and sends the registration-complete indication (Section 6.1.2). The firmware needs no completion logic of its own; register get_state prints the device state for debugging.
  • Retry. A failed attempt leaves the stack initialized. Reset the device before retrying device register.

The following rules apply:

  • Exactly one reader owns the receive side of the host interface, and it feeds the demultiplexer. Console output and command echo may share the interface with the frames (Section 6.1.2), but the interface must pass bytes unchanged: disable LF-to-CRLF conversion and every other translation, keep console text to 7-bit ASCII, and write each frame as one unit so that no log line is inserted into it.
  • Process CLI commands outside interrupt context.
  • Never run ROW while the Sidewalk radio stack is started (sid_init and sid_start).
  • Size the buffers for the payload plus 2 framing bytes.

6.1.5 Bring-up steps

Bring up the integration in the following order. Each step isolates one layer.

  1. Send help from a terminal program: a serial terminal on the port (115200 baud, 8N1) for a UART image, or J-Link RTT Viewer on channel 0 for an RTT image. The response appears in the same terminal. This verifies the receive path of the host interface and the CLI demultiplexer. Close the terminal program before running the tool, because a serial port has one reader and a J-Link probe serves one host program at a time.
  2. Run device provision .... The first commands, cert init and cert smsn, are text round trips: the device answers {CERT OK} (preceded by the informational {CERT BASE64_MTU=32}), then the SMSN as {CERT <base64>} fragments followed by {CERT OK}. This verifies the CLI path in both directions. The following cert csr and the chunked cert chain write and cert app_key write commands verify the cryptography and the host-to-device text path. The tool errors identify the failing layer: <command>: no {CERT OK} / {CERT ERROR} within <N>s means that no reply reached the tool on the host interface it reads (the console output of the image goes to another interface, the image lacks the cert commands, or a second program reads the same port or probe), and device answered with a <N>-byte binary frame instead of {CERT ...} text means the firmware image predates the text replies.
  3. Run device register. The device answers register start with {REGISTRATION STARTED} and then sends the first 0xAA frames. This verifies the binary framing in both directions, the encrypted handshake and the registration-complete indication. UART: no sync byte (0xAA) within <N>s or RTT: no complete frame within <N>s means that the device sent no frame: the image has no ROW support, or serial_write writes to another interface. UART: read timed out after <N> bytes still pending or RTT: no complete frame within <N>s; incomplete frame, <N> byte(s) still pending means that a frame started but did not complete, which indicates a transmit framing or length problem.
  4. Run device onboard end to end. The tool reports Device registered over the wire.
  5. Send help again. This detects demultiplexer ownership defects that appear only after binary traffic.

6.1.6 UART and RTT backends

The reference application implements the callbacks of Section 6.1.3 in one backend per host interface, selected when the image is built (see the table at the start of this chapter). Both backends implement the wire protocol of Section 6.1.2 without change.

  • UART backend. One UART at 115200 baud, 8N1, no flow control, carries the frames and the console. The receive path feeds every received byte to the demultiplexer: frame bytes go to the ROW buffer, every other byte to the CLI. Automatic LF-to-CRLF conversion on the port is disabled, because it would alter frame bytes. The console output of the image uses the same port, so prompt, echo and replies are visible on the wire. The backend owns the UART; no other function of the image may use it.
  • RTT backend. SEGGER RTT channel 0, the terminal channel, carries the frames and the console. No second channel is configured, so the RTT configuration of the image does not change. The line PC reads and writes the channel through the J-Link probe over the debug port, so the backend claims no UART and leaves it available to other functions of the image. The receive path drains channel 0 in the main loop: frame bytes go to the ROW buffer, every other byte to a console ring from which the CLI reads through stdio. Bytes stay in the RTT down buffer while a frame is pending or the ring is full, so nothing is lost. A frame is written under the RTT lock, whole or not at all, with a retry of up to 200 ms for the host to drain the up buffer; a short write is reported as a failure, so that a log line from another context cannot be inserted into a frame. The RTT down buffer is small (16 bytes in the reference configuration), and the tool writes command lines and frames in pieces as the device drains it. The main loop must therefore run often enough to drain the buffer: the tool waits at most 2 seconds for the device to accept a write.

6.2 Production firmware

The production firmware is the image the device ships with. It contains no ROW or serial registration support. It runs the device as a factory-registered Sidewalk endpoint, including field activation and credential handling.

6.2.1 Feature macros

A factory-registered production image exists in two configurations, one per security level (Section 7.1). Both set SID_SDK_INTERNAL_CONFIG_IS_FACTORY_REGISTERED=1. They differ in the SDK variant, the advertised security level and the tool setting the device must be registered with. Choose one column and use it for both the firmware and the tool. The SDK variants themselves are described in the Amazon Sidewalk SID API Developer Guide, Section 2.15 (Reference 7). This section lists only the settings that ROW adds or constrains.

Setting Lite build (security-level-low) Full build (security-level-high)
SDK variant Lite, single link: sid_api_ble.c, sid_api_fsk.c or sid_api_lora.c Full, multi-link: sid_api.c
Reference build (sid_dut) BUILD_SID_SDK_LINK_TYPE=BLE_LITE, FSK_LITE or LORA_LITE (sets every macro below) BUILD_SID_SDK_LINK_TYPE=DEFAULT, BLE, FSK, BLE_FSK, BLE_LORA or FSK_LORA, plus BUILD_FACTORY_REGISTERED=1
CMake variant selector (own build system) set(SID_SDK_CONFIG_BUILD_BLE_ONLY ON), _FSK_ONLY or _LORA_ONLY, before include(sid_common.cmake) None. The default compiles sid_api.c
SID_SDK_CONFIG_ENABLE_LINK_TYPE_1/2/3 1 for the single link, 0 for the other two 1 for each link the product uses
SID_SDK_INTERNAL_CONFIG_IS_FACTORY_REGISTERED 1 1
SID_SDK_CONFIG_SECURITY_LEVEL SID_SDK_CONFIG_SECURITY_LEVEL_LOW Default (SID_SDK_CONFIG_SECURITY_LEVEL_HIGH)
SID_SDK_INTERNAL_CONFIG_ENABLE_GSK 0 Default (1)
SID_SDK_INTERNAL_CONFIG_ENABLE_CAPABILITIES_LITE_FRAMEWORK, SID_SDK_INTERNAL_CONFIG_ENABLE_METRICS_LITE_FRAMEWORK 1 Not set
Link-specific settings FSK: SID_SDK_CONFIG_ENABLE_LINK_TYPE_2_REGISTRATION=0 (removes the Sidewalk FFS registration path over FSK). LoRa: SID_SDK_ENABLE_LORA_BUILD=1 (bypasses the LoRa-only build assertion) None
Tool security_level (Chapter 4) low: register commit_keys is sent, and the credentials are also written to the manufacturing page high (default): commit_keys is skipped, and the credentials are stored in the KV store only

SID_SDK_INTERNAL_CONFIG_IS_FACTORY_REGISTERED enables the handling of factory-registered devices in the SDK. The FSK and LoRa links prompt the Amazon Sidewalk cloud for field activation, a LoRa-only device is allowed to start while factory-registered, and the build check that otherwise requires an over-the-air registration path is relaxed. Without this macro, a factory-registered device never performs field activation.

SID_SDK_CONFIG_SECURITY_LEVEL only sets the security level bit in the endpoint capability notification. The security-level-low behavior itself is built into the lite sid_api variant and is absent from the full variant. That behavior consists of restoring the manufacturing page credentials into the KV store at boot and carrying the live key across a factory reset. For this reason, the lite variant must advertise LOW and the full variant must advertise HIGH.

No serial registration macro belongs in the production image. Register every device with the tool setting that matches its production firmware:

  • A lite image registered at security-level-high never comes up registered. The boot-time restore finds no manufacturing page copy, and the lite variant has no over-the-air registration path.
  • A full image registered at security-level-low receives a manufacturing page copy that it never reads.

6.2.2 Storage layout continuity

Registration credentials are stored according to the build-time flash configuration. The Factory Diagnostic Firmware and the production firmware must use a compatible layout:

  • Always match the manufacturing page flash address.
  • At security-level-high, also match the KV region (address and size) and the Sidewalk KV group IDs (SID_PAL_STORAGE_KV_INTERNAL_*_GROUP_ID overrides). At security-level-low, the boot-time restore populates the KV layout of the production build.

A mismatch is not detected at the factory. It appears in the field as an unregistered device. Verify each production firmware release by flashing it onto a factory-registered bench unit and confirming field activation.

Lite SDK variants exclude the registration stack. On these variants, sid_init fails with SID_ERROR_NOSUPPORT unless the device is registered or factory-registered.


Back to top

©2023 Amazon.com, Inc. or its affiliates (collectively, “Amazon”). All Rights Reserved.