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

Amazon Sidewalk MCU SDK Migration Guide

This guide covers migration from Amazon Sidewalk MCU SDK 1.19 to Amazon Sidewalk MCU SDK 2.0.

Table of Contents

1. Introduction

Amazon Sidewalk MCU SDK 2.0 adds registration over a wired serial link, keep-alive payloads and acknowledgement events, a medium data rate (MDR) on the SubG-CSS (LoRa) link, Bluetooth LE (BLE) bonding, FSK beacon events, Gateway Session Key (GSK) security, regulatory-region reporting, an extended Location Library with GPS-assisted positioning, and a security-level build setting. Registration over Wire also introduces three lite build variants. This guide uses the short forms BLE, FSK (SubG-FSK) and LoRa (SubG-CSS). Most of these additions are optional. A small number of changes alter existing types or defaults and require action.

This guide lists every change an application or platform developer must make to move an SDK 1.19 integration to SDK 2.0.

2. Scope

This guide covers the Amazon Sidewalk Endpoint MCU SDK and applies to:

  • Application developers using the Sid API (sid_ifc/ headers) on an endpoint.
  • Platform developers maintaining an endpoint Platform Abstraction Layer (PAL) port (sid_pal_ifc/ headers).

Out of scope: the Amazon Sidewalk Gateway MCU SDK (including the gateway configuration header and radio co-processor interfaces), the Amazon Sidewalk Gateway SDK, the Amazon Sidewalk Mobile SDK, and cloud-side configuration. Error codes (sid_error.h) are unchanged between 1.19 and 2.0.

The SDK version string is set by the release build. Read it from your SDK package or from the build information embedded in the library (strings libsidewalk_sdk.a | grep SID_SDK_.*_VERSION), not from this document.

Each change in this guide carries one of three labels:

Label Meaning
Breaking (compile) SDK 1.19 code fails to build unchanged.
Breaking (behavior) Code builds, but runtime behavior or data layout differs.
Additive (optional) New symbols only. No action unless you adopt the feature.

A struct that gains a trailing field is Additive when you use designated initializers (.field = value) and Breaking (compile) or Breaking (behavior) when you use positional initializers. Each affected struct is called out below.

3. If you only read one section

Change Who Label What you do
SID_SDK_CONFIG_RF_POWER_TABLE and SID_SDK_CONFIG_RF_POWER_MAX_TABLE removed App / platform Additive (removal; no runtime effect) Delete any -D override or #define. See §5.2.
SID_SDK_CONFIG_ENABLE_GSK defaults to 1 App Breaking (behavior) Decide whether to keep GSK enabled; zero-initialize struct sid_config (new gsk_config pointer); LoRa links run at MDR while a GSK is active. See §4.6, §5.1, §6.1.1.
sid_msg_desc_tx_attributes.resolve_location is now a uint8_t flag mask App (Location) Breaking (behavior) Replace true with SID_TX_LOCATION_LINK_RESOLVE. See §6.3.1.
sid_dlrv_config.nwsync_time widened to uint16_t App (FSK/LoRa) Breaking (behavior) Re-check any code that stores or compares it as uint8_t. See §6.3.2.
Location Library result and run-config structs reshaped; SID_LOCATION_METHOD_BLE_GATEWAY renamed; sid_location_update_almanac() removed App (Location) Breaking (compile) Follow §6.3.4.
SID_BULK_DATA_TRANSFER_FILE_DESCRIPTOR_MAX_SIZE 128 → 200 App (SBDT) Breaking (behavior) Resize buffers sized by this constant. See §6.3.5.
sid_pal_radio_is_channel_free() signature changed; two LoRa helper functions removed Platform Breaking (compile) Follow §7.1.
sid_pal_radio_data_rate_t values renumbered Platform Breaking (behavior) Rebuild any table indexed by data rate. See §7.1.
Region reporting (SID_DEVICE_INFO_TYPE_REGION) App Additive (optional); gates sub-GHz bring-up in sid_start() once you report a region See §6.2.3.
request_fast_adv in struct sid_pal_ble_adapter_interface Platform (BLE PAL) Breaking (compile) for positional initializers; Breaking (behavior) otherwise Append request_fast_adv as the final member; implement it as a one-shot force-fast latch; the PAL now owns the fast→slow transition. See §7.2.1.
Everything else (registration over wire and lite builds, keep-alive payload/ACK, MDR, BLE bonding, beacon events, GSK config, GPS assist) App / platform Additive (optional) Adopt as needed. See §4.

4. New features in 2.0

Each feature below has its own application note or developer guide. This section states what the feature is and which public symbols it adds; the referenced documents describe how to use it.

4.1 Registration over Wire and Factory-Registered Devices

An Endpoint can now be registered at the factory over a serial connection, using the new wired link type SID_LINK_TYPE_8 and the serial registration API (sid_serial_registration_init, sid_serial_registration_start, sid_serial_registration_process, sid_serial_registration_deinit). The wired link is brought up by that API, not by sid_init/sid_start, and is required in the diagnostics firmware used at the factory. A device registered this way is factory-registered and is field-activated by the Amazon Sidewalk stack on its first contact with the network. Three lite build variants (SID_SDK_CONFIG_BUILD_BLE_ONLY, SID_SDK_CONFIG_BUILD_FSK_ONLY, SID_SDK_CONFIG_BUILD_LORA_ONLY) restrict the stack to one link type and rely on factory registration: in these variants sid_init returns SID_ERROR_NOSUPPORT if the device is neither registered nor factory-registered, and a factory reset returns the device to the factory-registered state instead of the pre-registration state. For details, please refer to Sections 2.3.4, 2.15 and 3.30 to 3.33 of the Amazon Sidewalk API Developer Guide and to the Amazon Sidewalk Registration over Wire Application Note.

Supplementary notes:

  • New headers: sid_serial_ifc.h (transport callbacks the application provides) and sid_serial_registration.h (sid_serial_registration_init(), _start(), _process(), _deinit()).
  • SID_LINK_TYPE_8 = 1 << 7 is documented as “Wired (serial/UART) link.” Do not include it in sid_config.link_mask: sid_init() and sid_start() do not bring up a wired link.
  • Platform obligation: the manufacturing store must persist eight new credential records (SID_PAL_MFG_STORE_* values 4001 – 4008) so a factory-registered device keeps its registration across a reflash of the key-value store. See §7.4.
  • The three lite build variants are CMake options (default OFF, mutually exclusive; configuring more than one is a CMake error). In such a build sid_init() also returns SID_ERROR_NOSUPPORT for any link_mask other than exactly that link, and APIs that have no meaning for the link return SID_ERROR_NOSUPPORT.
  • Breaking (behavior) for products that ship a lite build: the factory reset wipes the persisted Sidewalk state and session keys, then restores the factory-provisioned credentials, so the device keeps its registration and can rejoin without a new registration flow. A product that relies on a factory reset to de-register the device must account for this.

Reference: Amazon Sidewalk Registration over Wire Application Note (overview, factory diagnostic firmware, production firmware, security levels); SID API Developer Guide, serial registration API section; https://docs.sidewalk.amazon/manufacturing/.

4.2 Keep-alive payload and acknowledgement status

On the SubG-FSK link, and on the SubG-CSS (LoRa) link in Profile B or Profile C, the application can attach up to SID_KA_PAYLOAD_MAX_SIZE (19) bytes to each keep-alive frame and is told whether the keep-alive was acknowledged. SID_KA_PAYLOAD_MAX_SIZE (19) is the largest keep-alive payload that fits on both sub-GHz links; it equals the LoRa link MTU.

  • struct sid_sub_ghz_links_config has a new trailing member struct sid_ka_payload_config ka_payload (const uint8_t *data; uint8_t len;, in sid_900_cfg.h). Set it in the configuration passed to sid_init(). The stack does not copy the buffer; it reads it on every keep-alive, so the buffer must stay valid until sid_deinit(). You may change the buffer, data or len at run time; the next keep-alive uses the new values. data == NULL or len == 0 sends the default payload. sid_init() returns SID_ERROR_INVALID_ARGS if len exceeds SID_KA_PAYLOAD_MAX_SIZE.
  • SID_CONTROL_EVENT_KA_ACK_STATUS delivered through on_control_event_notify; event_data points to struct sid_ka_ack_status { enum sid_link_type link_type; bool ack_received; }. This event is emitted only for the SubG-FSK link and for the SubG-CSS (LoRa) link in Profile B or Profile C.
  • sid_dlrv_config.nwsync_time now also sets the FSK keep-alive interval, up to MAX_FSK_KA_INTERVAL_MINS (1440). See §6.3.2.

Reference: SID API Developer Guide, keep-alive payload and control events sections.

4.3 LoRa medium data rate (MDR) and RX-window interval

The application can request a medium data rate on the LoRa link. MDR is honored only in regions that support it; otherwise the link runs at the low data rate (LDR). No error is returned and no public API reports the active data rate when MDR is not honored.

  • enum sid_link3_data_rate { SID_LINK3_DATA_RATE_LDR = 0, SID_LINK3_DATA_RATE_MDR = 1 } and sid_sub_ghz_links_config.link3_data_rate (trailing field; default LDR).
  • sid_device_profile_unicast_params.l3_mdr_rx_window_interval_ms (trailing field) selects the RX-window interval in MDR mode. Accepted values: 0 (no MDR-specific interval; the link uses its default; continuous RX cannot be requested through this field, use Profile C), SID_LINK3_RX_WINDOW_SEPARATION_5 (500 ms), SID_LINK3_RX_WINDOW_SEPARATION_2 (1000 ms) and SID_LINK3_RX_WINDOW_SEPARATION_3 (5000 ms); other values make sid_option(SID_OPTION_900MHZ_SET_DEVICE_PROFILE) return SID_ERROR_INCOMPATIBLE_PARAMS. SID_LINK3_RX_WINDOW_SEPARATION_4 (10000 ms) is declared in the enum but is not accepted for this field.

Reference: Gateway Session Key (GSK) Application Note (LoRa data rate and RX-window interval); SID API Developer Guide, LoRa data rate section.

4.4 Bluetooth LE bonding

  • Build flag: SID_SDK_CONFIG_ENABLE_BLE_BONDING (default 0).
  • SID_LINK_MODE_BONDED = 1 << 2 is reported in sid_status_detail::supported_link_modes when the connected mobile peer is the bonded owner. It is status-only and must not be used as a send-mode selector.
  • SID_BLE_BOND_TRIGGER_UUID (sid_ble_config_ifc.h): a characteristic whose encrypted value forces the peer to pair.
  • PAL: optional bond_control and get_advertiser_addr entries in struct sid_pal_ble_adapter_interface, and bond_callback in sid_pal_ble_adapter_callbacks_t. See §7.2.

4.5 FSK beacon events

SID_CONTROL_EVENT_BEACON_RECEIVED = 4 and SID_CONTROL_EVENT_BEACON_MISSED = 5 report FSK (Link Type 2) beacon reception through on_control_event_notify. These are distinct from SID_SDK_CONFIG_ENABLE_BEACON_DATA (default 0), which controls a Bluetooth LE connectionless beacon payload.

Reference: Gateway Discovery and Selection Application Note, control events section.

4.6 Gateway Session Key (GSK)

GSK lets an endpoint and the gateways in its area share a session key, so a gateway can verify the sender of an uplink locally. Payload encryption and authentication keys are unchanged. GSK establishment is governed by the Amazon Sidewalk Cloud; the application only tunes three parameters (two timeouts and one threshold).

  • Build flag: SID_SDK_CONFIG_ENABLE_GSK (default 1). See §5.1.
  • Configuration: struct sid_gsk_config in sid_gsk_config.h, passed through sid_config.gsk_config. NULL, or a field set to 0, selects the defaults. See §6.1.1.
Field Type Range Default Meaning
idle_timeout_sec uint32_t 10 – 600 s 240 TX and RX idle window before GSK establishment is attempted.
app_ack_miss_threshold uint32_t 3 – 10 6 Consecutive uplinks sent with an acknowledgement request that go unacknowledged while GSK is active; reaching the threshold falls back to legacy security. The count resets when any downlink is received under GSK.
retry_interval_sec uint32_t 43200 – 129600 s (12 – 36 h) 86400 (24 h) Minimum time after a fallback before GSK establishment is attempted again; the attempt itself still waits for the idle window (idle_timeout_sec).

Values outside a range are clamped. No other GSK parameter is exposed through the public API.

On the LoRa link an active GSK runs the link at the medium data rate (MDR, §4.3) even if the application configured LDR, and a later GSK fallback restarts the LoRa link, which the application observes as a link status change through on_status_changed.

Reference: Gateway Session Key (GSK) Application Note (per-link effects and lifecycle, configuration fields, interacting settings, sizing); SID API Developer Guide, GSK configuration section.

4.7 Regulatory region reporting

sid_device_information.h adds SID_DEVICE_INFO_TYPE_REGION = 4, enum sid_device_region, and sid_device_information_is_region_registerable(). The SDK calls the latter from sid_start(); when the module is not initialized or the application reports no region, it returns true and 1.19 behavior is preserved. See §6.2.3.

Reference: Sidewalk Internationalization Application Note (region values, configuring and reporting a region, unsupported regions); SID API Developer Guide, device information section.

4.8 Location Library: typed results, effort levels L5/L6, GPS assist

The Location Library now returns typed Wi-Fi and GNSS results, accepts a caller-ordered list of effort levels, adds FSK-gateway and LoRa multilateration methods, and supports cloud-initiated GPS-assisted positioning.

  • Build flags: SID_SDK_CONFIG_ENABLE_GNSS, SID_SDK_CONFIG_ENABLE_WIFI, SID_SDK_CONFIG_ENABLE_GPS_ASSIST (all default 0).
  • sid_msg_desc_tx_attributes.resolve_location becomes a flag mask (SID_TX_LOCATION_LINK_RESOLVE, SID_TX_LOCATION_GPS_ASSIST). See §6.3.1.
  • New PAL header sid_pal_gps_assist_ifc.h, required only when SID_SDK_CONFIG_ENABLE_GPS_ASSIST = 1. See §7.5.
  • Existing 1.19 location code requires changes. See §6.3.4.

Reference: SID API Developer Guide, Location Library and location-resolution sections. Effort levels in 2.0: L1 BLE gateway, L2 FSK gateway, L3 Wi-Fi scan, L4 GNSS scan, L5 LoRa multilateration, L6 GPS assist.

4.9 Security level

SID_SDK_CONFIG_SECURITY_LEVEL advertises the endpoint security level to the cloud. Values: SID_SDK_CONFIG_SECURITY_LEVEL_HIGH (0, default) or SID_SDK_CONFIG_SECURITY_LEVEL_LOW (1). Override at build time, for example -DSID_SDK_CONFIG_SECURITY_LEVEL=SID_SDK_CONFIG_SECURITY_LEVEL_LOW. The SDK headers do not define the criteria for each level; keep the default unless your qualification process directs otherwise (see the Amazon Sidewalk Registration over Wire Application Note, security levels section).

5. Stack configuration changes

5.1 New SID_SDK_CONFIG_* flags — Additive (optional), except ENABLE_GSK

sid_sdk_config.h adds the following flags. Only SID_SDK_CONFIG_ENABLE_GSK changes default behavior.

Flag Default Effect
SID_SDK_CONFIG_ENABLE_GSK 1 Gateway Session Key support. Breaking (behavior): a 1.19 application rebuilt on 2.0 advertises GSK capability and establishes a GSK when the cloud enables it. On LoRa an active GSK runs the link at MDR (§4.3) and a later GSK fallback restarts the LoRa link. Set to 0 to keep 1.19 behavior.
SID_SDK_CONFIG_ENABLE_BLE_BONDING 0 BLE adapter exposes bond_control and fires bond_callback.
SID_SDK_CONFIG_ENABLE_BEACON_DATA 0 Connectionless beacon data payload in BLE advertisements.
SID_SDK_CONFIG_ENABLE_GNSS 0 Location Library GNSS capability.
SID_SDK_CONFIG_ENABLE_WIFI 0 Location Library Wi-Fi capability.
SID_SDK_CONFIG_ENABLE_GPS_ASSIST 0 Cloud-initiated GPS-assisted location; requires the GPS-assist PAL (§7.5).
SID_SDK_CONFIG_SECURITY_LEVEL SID_SDK_CONFIG_SECURITY_LEVEL_HIGH (0) Endpoint security level advertised to the cloud; SID_SDK_CONFIG_SECURITY_LEVEL_LOW is 1.
// Updated (2.0) — sid_sdk_config.h
#ifndef SID_SDK_CONFIG_ENABLE_GSK
#define SID_SDK_CONFIG_ENABLE_GSK 1
#endif

#define SID_SDK_CONFIG_SECURITY_LEVEL_HIGH 0
#define SID_SDK_CONFIG_SECURITY_LEVEL_LOW 1
#ifndef SID_SDK_CONFIG_SECURITY_LEVEL
#define SID_SDK_CONFIG_SECURITY_LEVEL SID_SDK_CONFIG_SECURITY_LEVEL_HIGH
#endif

5.2 Removed RF power tables — Additive (removal, no runtime effect)

SID_SDK_CONFIG_RF_POWER_MAX_TABLE and SID_SDK_CONFIG_RF_POWER_TABLE are removed. The 1.19 stack did not read them (only a developer command-line tool did), so a build that still defines them compiles and nothing changes at runtime.

// Previous (1.19) — removed in 2.0
#ifndef SID_SDK_CONFIG_RF_POWER_MAX_TABLE
#define SID_SDK_CONFIG_RF_POWER_MAX_TABLE { 20, 20, 20, 20, 20, 20 }
#endif
#ifndef SID_SDK_CONFIG_RF_POWER_TABLE
#define SID_SDK_CONFIG_RF_POWER_TABLE { 20, 20, 20, 20, 20, 20 }
#endif

What you do: delete any override of these macros. Transmit power is configured through sid_sub_ghz_links_config.link2_max_tx_power_in_dbm / link3_max_tx_power_in_dbm and the radio PAL configuration, as in 1.19.

5.3 Lite build options — Additive (optional)

See §4.1.

5.4 Exported utility headers — Additive (optional)

The SDK now installs utility headers under sid_utility_ifc/ (event queue, clock, list, endian and memory-pool helpers, among others). Several PAL headers include them. If your build already includes same-named headers from a private copy, remove the private copy to avoid duplicate definitions. No application call site changes.

6. SID API changes

6.1 Data structures added

# Item Header Description Label
1 struct sid_gsk_config sid_gsk_config.h GSK tunables (§4.6). Additive
2 enum sid_msg_desc_tx_location_flags sid_api.h SID_TX_LOCATION_NONE = 0, SID_TX_LOCATION_LINK_RESOLVE = 1u << 0, SID_TX_LOCATION_GPS_ASSIST = 1u << 1. Additive
3 struct sid_ka_payload_config, SID_KA_PAYLOAD_MAX_SIZE, sid_sub_ghz_links_config.ka_payload, struct sid_ka_ack_status sid_900_cfg.h (payload), sid_api.h (ACK status) Keep-alive payload configuration and ACK status (§4.2). Additive
4 enum sid_link3_data_rate sid_900_cfg.h SID_LINK3_DATA_RATE_LDR = 0, SID_LINK3_DATA_RATE_MDR = 1. Additive
5 enum sid_device_region sid_device_information.h UNSET = 0, NORTH_AMERICA = 1, EUROPE = 2, JAPAN = 3, AUSTRALIA_NZ = 4, NOT_SUPPORT = 0xFF. Additive
6 struct sid_serial_registration_config, struct serial_ifc_context and callback typedefs sid_serial_registration.h, sid_serial_ifc.h Registration over Wire (§4.1). Additive
7 Location result types: enum sid_location_result_type, struct sid_location_wifi_result, struct sid_location_gnss_result, union sid_location_data, struct sid_location_wifi_ap, struct sid_location_gnss_info, struct sid_location_gnss_pseudorange, struct sid_location_gnss_pseudoranges sid_location.h Typed location payloads (§6.3.4). Additive
8 SID_BLE_BOND_TRIGGER_UUID sid_ble_config_ifc.h Bonding trigger characteristic UUID (§4.4). Additive

6.1.1 Pass sid_gsk_config through sid_config

sid_api.h does not include sid_gsk_config.h, and the sid_api CMake target does not propagate its include directory. Include the header yourself and link the sid_gsk_config CMake interface target (or add sid_ifc/sid_gsk_config to your include path).

// Updated (2.0) — struct sid_config tail
    const struct sid_time_sync_config *time_sync_config;

    /**
     *  Gateway Session Key (GSK) configuration; see struct sid_gsk_config for the
     *  individual tunables. If not provided (NULL), defaults are used.
     */
    const struct sid_gsk_config *gsk_config;
};

Breaking (behavior) for non-zeroed configs: with SID_SDK_CONFIG_ENABLE_GSK = 1, sid_init() reads gsk_config whenever it is not NULL. A struct sid_config built field by field on a non-zeroed stack object leaves the new trailing pointer uninitialized and sid_init() dereferences it. Zero-initialize the struct (designated initializer or memset) or set .gsk_config = NULL explicitly.

#include <sid_gsk_config.h>

static const struct sid_gsk_config gsk_cfg = {
    .idle_timeout_sec = 240,
    .app_ack_miss_threshold = 6,
    .retry_interval_sec = 86400,
};

struct sid_config config = {
    /* ... existing fields ... */
    .gsk_config = &gsk_cfg,   /* or NULL for defaults */
};
sid_error_t err = sid_init(&config, &handle);
if (err != SID_ERROR_NONE) { /* handle error */ }

6.2 APIs added

# API Header Description Label
1 sid_serial_registration_init(), sid_serial_registration_start(), sid_serial_registration_process(), sid_serial_registration_deinit() sid_serial_registration.h Factory registration over a serial transport (§4.1, §6.2.4). on_registration_done runs inside the receive path and must only set a flag. Additive
2 sid_device_information_is_region_registerable() sid_device_information.h Returns whether the reported region permits radio bring-up (§6.2.3). Additive
3 sid_location_parse_wifi(), sid_location_parse_gnss(), sid_location_parse_pseudoranges(), sid_location_send_pseudoranges(), sid_location_send_pseudoranges_raw() sid_location.h Typed result parsers and GPS-assist pseudorange uplink (§6.3.4). Additive
4 SID_CONTROL_EVENT_BEACON_RECEIVED = 4, SID_CONTROL_EVENT_BEACON_MISSED = 5, SID_CONTROL_EVENT_KA_ACK_STATUS = 6 sid_api.h New control events (§4.2, §4.5). Additive

6.2.1 Set a keep-alive payload

static uint8_t ka_buf[SID_KA_PAYLOAD_MAX_SIZE] = { /* ... */ };
static struct sid_sub_ghz_links_config sub_ghz_cfg = {
    /* ... existing members ... */
    .ka_payload = { .data = ka_buf, .len = sizeof(ka_buf) },
};
/* pass &sub_ghz_cfg as sid_config.sub_ghz_link_config */
sid_error_t err = sid_init(&config, &handle);
if (err != SID_ERROR_NONE) { /* SID_ERROR_INVALID_ARGS if len > SID_KA_PAYLOAD_MAX_SIZE */ }

To change the payload later, edit ka_buf or sub_ghz_cfg.ka_payload; the next keep-alive uses the new values.

6.2.2 Handle new control events

Extend your on_control_event_notify handler. Unknown event types should still be ignored, as before.

case SID_CONTROL_EVENT_KA_ACK_STATUS: {
    const struct sid_ka_ack_status *s = data->event_data;
    /* s->link_type, s->ack_received */
    break;
}
case SID_CONTROL_EVENT_BEACON_RECEIVED:
case SID_CONTROL_EVENT_BEACON_MISSED:
    break;

6.2.3 Report the regulatory region (optional)

Report SID_DEVICE_INFO_TYPE_REGION through the device information API. Once you report a region, sid_start() consults sid_device_information_is_region_registerable(). SID_DEVICE_REGION_NORTH_AMERICA, SID_DEVICE_REGION_EUROPE and SID_DEVICE_REGION_AUSTRALIA_NZ are accepted; SID_DEVICE_REGION_UNSET, SID_DEVICE_REGION_JAPAN and SID_DEVICE_REGION_NOT_SUPPORT are refused. When the region is refused, sid_start() drops the sub-GHz links from the requested mask and starts Bluetooth LE only; if no Bluetooth LE link was requested it returns SID_ERROR_INVALID_STATE. Applications that report no region keep 1.19 behavior. See the Sidewalk Internationalization Application Note for the regions supported by a given release.

6.2.4 Serial registration APIs

Factory registration over a wired link (SID_LINK_TYPE_8):

struct sid_serial_registration_config {
    const struct serial_ifc_context *ifc;        /* application serial transport, already initialized */
    void (*on_registration_done)(void *ctx);     /* completion callback; may only set a flag */
    void *ctx;
};

sid_error_t sid_serial_registration_init(const struct sid_serial_registration_config *cfg);
sid_error_t sid_serial_registration_start(void);
void        sid_serial_registration_process(void);
sid_error_t sid_serial_registration_deinit(void);

These APIs do not use sid_init()/sid_start(). Please refer to Sections 2.3.4 and 3.30 to 3.33 of the Amazon Sidewalk API Developer Guide.

6.3 Updates to existing data structures

6.3.1 sid_msg_desc_tx_attributes.resolve_location — Breaking (behavior)

// Previous (1.19)
struct sid_msg_desc_tx_attributes {
    /* ... */
    uint16_t ttl_in_seconds;
    bool resolve_location;
};

// Updated (2.0)
struct sid_msg_desc_tx_attributes {
    /* ... */
    uint16_t ttl_in_seconds;
    uint8_t resolve_location;   /* bit mask of enum sid_msg_desc_tx_location_flags */
};

What you do: replace .resolve_location = true with .resolve_location = SID_TX_LOCATION_LINK_RESOLVE. true still evaluates to SID_TX_LOCATION_LINK_RESOLVE (1), so existing code keeps working, but any code that reads the field as a bool must treat it as a mask. Add SID_TX_LOCATION_GPS_ASSIST only with SID_SDK_CONFIG_ENABLE_GPS_ASSIST = 1.

6.3.2 sid_dlrv_config.nwsync_time — Breaking (behavior)

// Previous (1.19)
struct sid_dlrv_config {
    uint16_t time;
    uint8_t nwsync_time;   /* LoRa Profile B NW sync time, mins */
    bool is_set;
};

// Updated (2.0)
struct sid_dlrv_config {
    uint16_t time;
    uint16_t nwsync_time;  /* KA / NW-sync interval, mins. LoRa Profile B: 1-240. FSK: up to 1440. 0 = link default. */
    bool is_set;
};

What you do: update any variable, storage record or comparison that assumed an 8-bit value. 0 (SID_NWSYNC_TIME_NOT_SET) now means “use the link default”. sizeof(struct sid_dlrv_config) changes.

// Updated (2.0) — trailing members
struct sid_sub_ghz_links_config {
    /* ... existing fields ... */
    struct sid_link_type_2_registration_config registration_config;
    enum sid_link3_data_rate link3_data_rate;                       /* new, default LDR */
    struct sid_ka_payload_config ka_payload;                        /* new, default keep-alive payload */
};

struct sid_device_profile_unicast_params {
    /* ... existing fields ... */
    uint32_t l2_rx_duration_sec;
    enum sid_link3_rx_window_separation_ms l3_mdr_rx_window_interval_ms;  /* new */
};

Zero-initialized or designated-initialized instances keep 1.19 behavior. Positional initializers must add the new members.

6.3.4 Location Library — Breaking (compile)

Any 1.19 application that uses the Location Library must change:

1.19 symbol 2.0 replacement
SID_LOCATION_METHOD_BLE_GATEWAY SID_LOCATION_METHOD_GATEWAY (same value 1u << 0).
sid_location_run_config.buffer, .size .payload_type (enum sid_location_result_type) + .payload (union sid_location_data); the library copies the bytes during sid_location_run(). New optional .levels[SID_LOCATION_MAX_LEVELS] / .num_levels (0 keeps 1.19 behavior).
sid_location_result.payload[], .size, .raw_gnss_data[], .raw_gnss_data_size .result_type + .parsed (union sid_location_data); pointers are valid only during on_update. Use sid_location_parse_wifi() / sid_location_parse_gnss() to decode.
sid_location_update_almanac() Removed. No replacement in the public API.
SID_LOCATION_EFFORT_INVALID (5), SID_LOCATION_EFFORT_DEFAULT (6) Now 7 and 8; SID_LOCATION_EFFORT_L5 and SID_LOCATION_EFFORT_L6 are inserted. Do not persist or compare these numerically.
// Previous (1.19)
struct sid_location_run_config {
    enum sid_location_effort_mode mode;
    enum sid_location_run_type type;
    uint8_t *buffer;
    size_t size;
};

// Updated (2.0)
struct sid_location_run_config {
    enum sid_location_effort_mode mode;
    enum sid_location_run_type type;
    enum sid_location_result_type payload_type;
    union sid_location_data payload;
    enum sid_location_effort_mode levels[SID_LOCATION_MAX_LEVELS];
    uint8_t num_levels;
};
// Previous (1.19)
struct sid_location_result {
    enum sid_location_status status;
    sid_error_t err;
    enum sid_location_effort_mode mode;
    enum sid_link_type link;
    uint8_t payload[SID_LOCATION_MAX_PAYLOAD_SIZE];
    size_t size;
    uint8_t raw_gnss_data[SID_LOCATION_MAX_PAYLOAD_SIZE];
    size_t raw_gnss_data_size;
};

// Updated (2.0)
struct sid_location_result {
    enum sid_location_status status;
    sid_error_t err;
    enum sid_location_effort_mode mode;
    enum sid_link_type link;
    enum sid_location_result_type result_type;
    union sid_location_data parsed;
};

sid_location_config gains a trailing void *gps_assist_pal_config (additive). New method bits SID_LOCATION_METHOD_FSK_GATEWAY = 1u << 3 and SID_LOCATION_METHOD_LORA_MLAT = 1u << 4 are included in SID_LOCATION_METHOD_ALL.

6.3.5 SID_BULK_DATA_TRANSFER_FILE_DESCRIPTOR_MAX_SIZE — Breaking (behavior)

The constant grows from 128 to 200. Buffers and structures sized by it grow by 72 bytes. Re-check static allocations and any persisted layout.

6.3.6 sid_config.gsk_config — Additive (trailing field)

See §6.1.1.

6.3.7 sid_device_dyn_info.region — Additive (new union member)

See §6.2.3.

6.4 Enumerator additions — Additive

  • enum sid_link_type: SID_LINK_TYPE_8 = 1 << 7 (wired; not used with sid_init() / sid_start()).
  • enum sid_link_mode: SID_LINK_MODE_BONDED = 1 << 2 (status-only).
  • enum sid_link3_rx_window_separation_ms: SID_LINK3_RX_WINDOW_SEPARATION_2 = 1000, _4 = 10000 (declared; not accepted for l3_mdr_rx_window_interval_ms), _5 = 500.
  • enum sid_dl_route_validity_time_mins: DEF_DL_ROUTE_VALIDITY_TIME_MINS_FSK = 1080.
  • enum sid_link3_profile_b_nw_sync_time_mins: SID_NWSYNC_TIME_NOT_SET = 0, MAX_FSK_KA_INTERVAL_MINS = 1440.
  • enum sid_on_dev_cert_print_fileds: SID_ODC_PRINT_SMSN.
  • SID_CONTROL_EVENT_LAST moves accordingly. enum sid_option is unchanged from 1.19.

7. PAL interface changes

7.1 Radio PAL (sid_pal_radio_ifc.h, sid_pal_radio_lora_defs.h) — Breaking (compile and behavior)

Every radio PAL port must change.

Signature change:

// Previous (1.19)
int32_t sid_pal_radio_is_channel_free(uint32_t freq, int16_t threshold, uint32_t delay_us, bool *is_channel_free);

// Updated (2.0)
struct sid_phy_multi_channel_data {
    int16_t threshold;     /* RSSI threshold in dBm */
    uint32_t delay_us;     /* per-sub-band sense time in microseconds */
    uint8_t scan_num;      /* number of frequencies in freq */
    const uint32_t *freq;  /* array of scan_num frequencies in Hz */
};
int32_t sid_pal_radio_is_channel_free(const struct sid_phy_multi_channel_data *scan_data, bool *is_channel_free);

The channel is busy if any sub-band’s RSSI exceeds the threshold. A single-channel check is a one-element sweep (scan_num = 1).

Removed functions: sid_pal_radio_lora_mod_params_to_data_rate() and sid_pal_radio_lora_data_rate_to_mod_params(). Remove their implementations and any callers.

Renumbered enum — Breaking (behavior):

Enumerator 1.19 2.0
SID_PAL_RADIO_DATA_RATE_1_76KBPS — 6 (new)
SID_PAL_RADIO_DATA_RATE_5_47KBPS — 7 (new)
SID_PAL_RADIO_DATA_RATE_12_5KBPS 6 8
SID_PAL_RADIO_DATA_RATE_CUSTOM 7 9
SID_PAL_RADIO_DATA_RATE_MAX_NUM 7 9

Rebuild any table indexed by sid_pal_radio_data_rate_t and any array sized by SID_PAL_RADIO_DATA_RATE_MAX_NUM. Do not persist these values.

Other additions: SID_PAL_RADIO_RC_ANZ = 4 (so SID_PAL_RADIO_RC_MAX is now 5; region tables grow by one); RADIO_ERROR_FW_NOT_UP_TO_DATE (-11) and RADIO_ERROR_FW_TYPE_NOT_SUPPORTED (-12); trailing field sid_pal_radio_packet_cfg_t.side_sf_enabled; in sid_pal_radio_lora_defs.h, SID_PAL_RADIO_LORA_SF_INVALID 0x0, trailing fields sid_pal_radio_lora_modulation_params_t.side_sf and sid_pal_radio_lora_rx_packet_status_t.side_detect. The 2.0 headers do not document the semantics of side_sf, side_detect and side_sf_enabled; zero them unless your radio PAL vendor documents otherwise. Each struct gains a one-byte trailing member and sizeof changes.

7.2 BLE adapter PAL (sid_pal_ble_adapter_ifc.h) — Additive (optional)

Two optional entries are appended to struct sid_pal_ble_adapter_interface after get_mac_addr. The SDK also adds bond_callback to the sid_pal_ble_adapter_callbacks_t it passes to your set_callback:

typedef void (*sid_pal_ble_bond_callback_t)(bool bonded, uint8_t *addr);
enum sid_pal_ble_bond_cmd { SID_PAL_BLE_BOND_CMD_ENABLE = 0, SID_PAL_BLE_BOND_CMD_DISABLE, SID_PAL_BLE_BOND_CMD_DELETE_ALL,
                            SID_PAL_BLE_BOND_CMD_DELETE_PEER, SID_PAL_BLE_BOND_CMD_IS_BONDED, SID_PAL_BLE_BOND_CMD_IS_CONN_BONDED };

/* struct sid_pal_ble_adapter_interface, appended: */
sid_error_t (*bond_control)(enum sid_pal_ble_bond_cmd cmd, void *data, size_t size);
sid_error_t (*get_advertiser_addr)(uint8_t *addr);
/* sid_pal_ble_adapter_callbacks_t (populated by the SDK), appended: */
sid_pal_ble_bond_callback_t bond_callback;

The SDK checks bond_control for NULL before calling it; get_advertiser_addr is not called by the stack. Implement them or leave them NULL; return SID_ERROR_NOSUPPORT if your platform does not support an operation. Ports using positional initializers for struct sid_pal_ble_adapter_interface must append the new members. When a bonding procedure completes or fails, call callbacks->bond_callback(bonded, addr) (addr = NULL on failure); the SDK always sets this pointer, and with SID_SDK_CONFIG_ENABLE_BLE_BONDING = 0 it is a no-op.

7.2.1 Advertising phase: request_fast_adv — Breaking (compile) for positional initializers; Breaking (behavior) otherwise

Before 2.0, the SAL selected the BLE advertising phase on every start, and re-hinted on every TX-ID rotation (every ADV_ROTATION_TIMEOUT_SEC, 900 s). A device that had settled into the slow phase could be pulled back into a periodic fast burst on each rotation — a power and discoverability-latency regression, and on some platforms a correctness bug (see the Nordic note below).

2.0 inverts this ownership. The SAL now only forces the fast phase on a genuine discoverable event — fresh start, reconnect, connection request, factory reset, GCS time request, D2D config — and never on a TX-ID rotation restart. The PAL owns the fast→slow transition through its own fast-window timer, and must preserve its phase across a stop/start. That is why the hint is now one-way (force fast) with a void return rather than a bool fast selector: the SAL has no view of the PAL’s fast-window deadline and must not reset a device mid-transition. A wrong phase is a power/latency matter, not a functional one, so the hint is advisory.

// Updated (2.0) — one-way force-fast hint, appended as the FINAL interface member
/**
 * Request that advertising (re)enter the FAST phase now. Optional (may be
 * NULL); when NULL start_adv keeps its default behavior of always beginning
 * fast. The SAL calls this only on an external "make me discoverable" event
 * (fresh start, reconnect, connection request, factory reset, GCS time
 * request, D2D config) -- never on a TX-ID rotation restart.
 */
void (*request_fast_adv)(void);

The member is appended last in struct sid_pal_ble_adapter_interface (after get_advertiser_addr, §7.2), consistent with the ABI-stability rule for this struct: new members always go last, so a prebuilt SAL module or an out-of-tree positional-initializer PAL does not call the wrong vtable slot. In-tree PALs use designated initializers (.request_fast_adv = ...) and compile unchanged if you don’t adopt it — Additive. Ports using positional initializers for struct sid_pal_ble_adapter_interface must append the new member — Breaking (compile) for them. The SAL checks request_fast_adv for NULL before calling it; a NULL member keeps the default “always begin fast” behavior at start_adv.

The contract. A conforming PAL honors three invariants:

  1. request_fast_adv forces the fast phase for the next start_adv. Implement it as a one-shot latch consumed and reset by start_adv — do not leave it latched across subsequent starts.
  2. The PAL owns the fast→slow transition: arm your own fast-window timer and step the device from fast to slow yourself. The SAL will not hint slow and will not re-hint on rotation.
  3. Preserve the phase across a PAL-internal stop/start. Any restart the PAL does on its own — a disconnect-while-advertising re-advertise, a config-update restart — bypasses the SAL hint, so the PAL must set the force-fast latch itself if (and only if) that restart is a genuine come-up-discoverable event. A plain rotation restart must not force fast.

Make the PAL self-contained on deinit/init: reset the phase state on deinit to the cold-boot default (fast), matching first-boot behavior, so a deinit→init cycle does not inherit the last rotation’s phase. A single-mode PAL that has no slow phase (for example, a port delegating to a fixed-interval adapter) should implement request_fast_adv as an explicit, documented no-op rather than leaving it NULL, so the interface is visibly complete across all ports.

Per-platform notes. Each in-tree PAL carries the fast→slow transition in its own mechanism:

PAL Fast→slow mechanism Notes
Nordic (ble_adapter_native.c) SDK ble_advertising module FAST→SLOW→IDLE ladder Correctness-critical: requesting SLOW with ble_adv_slow_enabled == false degrades straight to IDLE while ble_advertising_start() still returns NRF_SUCCESS — advertising goes dark while the adapter reports success. Select FAST whenever slow is disabled so a real fallback ladder is always underneath. Phase state lives in ctx (ctx.start_adv_fast).
Nordic IoT-BLE (ble_adapter_iot_ble.c) None — single advertising mode via Amazon FreeRTOS BTBleAdapter (pxStartAdv) No fast/slow phase; request_fast_adv is an explicit no-op. Always effectively fast.
Silabs (ble_adapter.c) fast_timeout timer —
TI (ble_adapter.c) enableSlowIntvAdv + last_set_adv_interval, stepped in sid_pal_ble_adapter_handle_adv_terminated_cb No FAST→SLOW→IDLE ladder; a slow request puts the radio on air at the slow interval unconditionally (sid_pal_set_adv_param + pxStartAdv), so it cannot hit the Nordic silent-stop.
Telink (sid_ble_adapter.c) fast-window work item sid_ble_advert_start consumes and resets the force-fast latch within itself on every start.

7.3 GNSS and Wi-Fi PAL (sid_pal_gnss_ifc.h, sid_pal_wifi_ifc.h) — Additive

sid_pal_gnss_config and sid_pal_wifi_config gain a trailing struct sid_event_queue *event_queue (may be NULL). Both headers now include sid_event_queue_ifc.h from sid_utility_ifc/; make sure that directory is on the include path.

7.4 Manufacturing store PAL (sid_pal_mfg_store_ifc.h) — Additive, with a collision check

Eight value identifiers 4001 – 4008 and their sizes are added above SID_PAL_MFG_STORE_CORE_VALUE_MAX (4000), in the range the 1.19 header described as available to applications:

Identifier Value Size
SID_PAL_MFG_STORE_WAN_MASTER_KEY 4001 16
SID_PAL_MFG_STORE_WAN_KEY_PARAMS 4002 6
SID_PAL_MFG_STORE_APP_MASTER_KEY 4003 16
SID_PAL_MFG_STORE_APP_KEY_PARAMS 4004 2
SID_PAL_MFG_STORE_TSYNC_COUNTER_SEED 4005 4
SID_PAL_MFG_STORE_TX_UUID_PARAMS 4006 2
SID_PAL_MFG_STORE_CONFIGURATION_COMPLETE 4007 1
SID_PAL_MFG_STORE_SIDEWALK_ID 4008 7

What you do: if your application already uses identifiers 4001 – 4008, move them. If you use Registration over Wire, your manufacturing store must be able to write and read these records; the set is treated as complete only when all eight are present. No existing identifier or size changed.

7.5 GPS-assist PAL (sid_pal_gps_assist_ifc.h) — New, opt-in

Required only when SID_SDK_CONFIG_ENABLE_GPS_ASSIST = 1. Implement sid_pal_gps_assist_init(), _deinit(), _inject_ephemeris(), _start_acquisition(), _abort_acquisition(), _get_pseudoranges() and _get_power_state(); configure through struct sid_pal_gps_assist_config (event callback, acquisition timeout, event queue, memory pool, platform config). See the Amazon Sidewalk Location Library Developer Guide.

8. Migration checklist

Application:

  1. Delete any SID_SDK_CONFIG_RF_POWER_TABLE / SID_SDK_CONFIG_RF_POWER_MAX_TABLE definitions (§5.2).
  2. Decide on SID_SDK_CONFIG_ENABLE_GSK (default 1). Make sure struct sid_config is zero-initialized or set .gsk_config = NULL explicitly (NULL selects defaults); optionally include sid_gsk_config.h, link the sid_gsk_config target and point gsk_config at a struct sid_gsk_config (§6.1.1). LoRa products: note the MDR and link-restart effects (§4.6).
  3. Replace .resolve_location = true with SID_TX_LOCATION_LINK_RESOLVE; treat the field as a mask (§6.3.1).
  4. Re-check code that handles sid_dlrv_config.nwsync_time as an 8-bit value (§6.3.2).
  5. Location Library users: rename SID_LOCATION_METHOD_BLE_GATEWAY, migrate run_config and result to the typed payload/parsed unions, remove sid_location_update_almanac() calls, stop comparing effort enumerators numerically (§6.3.4).
  6. Bulk data transfer users: resize buffers for SID_BULK_DATA_TRANSFER_FILE_DESCRIPTOR_MAX_SIZE = 200 (§6.3.5).
  7. Convert positional initializers of sid_config, sid_sub_ghz_links_config and sid_device_profile_unicast_params to designated initializers (§6.3.3, §6.3.6).
  8. Optional: set sid_sub_ghz_links_config.ka_payload and handle SID_CONTROL_EVENT_KA_ACK_STATUS, _BEACON_RECEIVED, _BEACON_MISSED (§6.2.1, §6.2.2).
  9. Optional: request MDR with link3_data_rate = SID_LINK3_DATA_RATE_MDR and set l3_mdr_rx_window_interval_ms (§4.3).
  10. Optional: report the regulatory region; note that sid_start() then enforces it (§6.2.3).
  11. Optional: set SID_SDK_CONFIG_SECURITY_LEVEL (§4.9).
  12. Do not pass SID_LINK_TYPE_8 to sid_init() / sid_start(); use the serial registration API instead (§4.1).

Platform (PAL):

  1. Update sid_pal_radio_is_channel_free() to the struct sid_phy_multi_channel_data signature; delete sid_pal_radio_lora_mod_params_to_data_rate() / sid_pal_radio_lora_data_rate_to_mod_params() (§7.1).
  2. Rebuild data-rate-indexed tables for the renumbered sid_pal_radio_data_rate_t; add SID_PAL_RADIO_RC_ANZ; handle the new radio error codes; zero the new side_sf / side_detect / side_sf_enabled members unless documented otherwise (§7.1).
  3. Implement bond_control and get_advertiser_addr (or leave them NULL) in struct sid_pal_ble_adapter_interface; invoke callbacks->bond_callback from your bonding event handler (§7.2).
  4. Add sid_utility_ifc/ to the include path; set or NULL the new event_queue fields in GNSS/Wi-Fi configs (§7.3, §5.4).
  5. Check manufacturing-store identifiers 4001 – 4008 for collisions; support them if you use Registration over Wire (§7.4).
  6. GPS assist users: implement sid_pal_gps_assist_ifc.h (§7.5).
  7. Rebuild with the lite build CMake options if you ship a one-link product (§4.1).
  8. Lite builds: review any flow that relies on a factory reset to de-register the device; in these builds a factory reset restores the factory-registered state (§4.1).
  9. Added request_fast_adv(void) in your BLE adapter PAL’s interface initializer (or add the member if your port never implemented the old one); positional initializers must append it as the final member (§7.2.1).
  10. Implement request_fast_adv as a one-shot force-fast latch consumed by start_adv, or leave it NULL to keep “always begin fast” (§7.2.1).
  11. Move your fast-window timer into the PAL so it carries the device fast→slow; stop expecting a slow hint from the SAL on rotation (§7.2.1).
  12. Preserve the advertising phase across a PAL-internal stop/start; force fast only on a genuine discoverable restart, never on a rotation restart (§7.2.1).
  13. Reset the phase state in deinit to the fast cold-boot default so the PAL is self-contained across a deinit→init cycle (§7.2.1).
  14. Single-mode BLE PALs: implement request_fast_adv as an explicit no-op, not NULL (§7.2.1).
  15. Nordic BLE PAL: select FAST when slow is disabled to avoid the SLOW→IDLE silent-stop (§7.2.1).

8.1 Retest after migrating

  • LoRa: data rate actually in use and RX-window interval after setting a device profile; link restart behavior when a GSK is established or falls back.
  • FSK: keep-alive interval (DLRV minus 5 minutes unless set through sid_dlrv_config.nwsync_time); beacon events.
  • Keep-alive payload from sid_sub_ghz_links_config.ka_payload (including a run-time change to the buffer) and SID_CONTROL_EVENT_KA_ACK_STATUS handling.
  • Bulk data transfer with descriptors up to 200 bytes.
  • Location Library result parsing (result_type / parsed) and effort-level ordering.
  • BLE status bits, including SID_LINK_MODE_BONDED if bonding is enabled.
  • Region gate in sid_start() if your application reports a region.
  • Manufacturing-store identifiers 4001 – 4008 and Registration over Wire, if used.
  • Factory reset on lite builds: confirm the device returns to its factory-registered state and rejoins.
  • Fresh BLE advertising start comes up fast, then transitions to slow on the PAL’s own timer and stays slow across rotations (no periodic fast burst).
  • Reconnect, connection request, factory reset, GCS time request and D2D config each force the BLE advertising phase back to fast.
  • A disconnect-while-advertising re-advertise comes up fast.
  • A BLE config-update restart (sid_option(SID_OPTION_BLE_USER_CONFIG...) or a connection-policy change) comes up fast, not a stale slow.
  • BLE deinit → init behaves like a cold boot (comes up fast), not inheriting the last rotation’s phase.
  • Nordic: BLE advertising is actually on air with slow_enabled == false (no silent IDLE stop).

9. References

  • Gateway Session Key (GSK) Application Note
  • Amazon Sidewalk Registration over Wire — Application Note
  • Gateway Discovery and Selection Application Note
  • Sidewalk Internationalization Application Note
  • Amazon Sidewalk Location Library Developer Guide
  • Amazon Sidewalk SID API Developer Guide — https://docs.sidewalk.amazon/sid-api-dg/

10. Glossary

Term Meaning
Endpoint A Sidewalk-enabled device running the MCU SDK.
Gateway A Sidewalk bridge that relays traffic between endpoints and the Amazon Sidewalk Cloud.
Uplink A message from an endpoint toward the cloud.
Downlink A message from the cloud toward an endpoint.
GSK Gateway Session Key: a session key shared between an endpoint and the gateways in its area.
KA Keep-alive frame sent periodically on SubG-FSK links and on SubG-CSS links in Profile B or Profile C.
LDR / MDR Low / medium data rate on the SubG-CSS (LoRa) link.
PAL Platform Abstraction Layer: the hardware interface a platform port implements.
SBDT Sidewalk Bulk Data Transfer.

11. Change history

Version Summary of Changes
1 First release, covering migration from SDK 1.19 to SDK 2.0.
2 Add BLE advertising phase PAL change (request_fast_adv) in §7.2.1.

Back to top

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