Silicon Labs documentation on Wi-SUN version 2.12.0.

Documentation source: https://docs.silabs.com/wisun/2.12.0

# Wi-SUN

## Developing with Silicon Labs Wi-SUN

Wireless Smart Ubiquitous Network (Wi-SUN) is the leading IPv6 sub-GHz mesh technology
for smart city and smart utility applications. Silicon Labs' Wi-SUN SDK includes
industry-leading software stacks and development tools for Wi-SUN end nodes and border routers.
In conjunction with SoCs and reference applications for Wi-SUN, developers can
use software and tools from Silicon Labs to quickly and reliably:

- Develop multi-node mesh networks
- Monitor and debug multiple nodes simultaneously
- Visually analyze system performance

![wi-sun network](/wisun-start/0.2/images/wi-sun-network.png)

The content on these pages is intended for those are developing a Wi-SUN application using the Silicon Labs Wi-SUN SDK.

**For details about this release**: Links to release notes are available on the [silabs.com SiSDK page](https://www.silabs.com/developers/simplicity-software-development-kit).

**For Silicon Labs' Wi-SUN product information**: See the [product pages on silabs.com](https://www.silabs.com/wireless/wi-sun).

**For background about the Wi-SUN protocol**: The [introductory materials on silabs.com](https://www.silabs.com/wireless/wi-sun?tab=learn)
is a good place to start.

**To get started with development with the Wi-SUN stack**: See the [Getting Started page](/wisun/2.12.0/wisun-getting-started-development) to get started working with sample applications.

**If you are already in development with the stack**: See the specific material on this page for details or go directly to the [API Reference](/wisun/2.12.0/wisun-stack-api).

**If you are primarily interested in working directly with the Wi-SUN PHY and system,** without using the Silicon Labs stack, see the [Wi-SUN PHY section](/wisun/2.12.0/wisun-phy-overview).

## Wi-SUN SDK Version 2.12.0 - Release Notes (Jun 23, 2026)

Wireless Smart Ubiquitous Network (Wi-SUN) is the leading IPv6 sub-GHz mesh technology for smart city and smart utility applications. Wi-SUN brings Smart Ubiquitous Networks to service providers, utilities, municipalities/local government, and other enterprises by enabling interoperable, multi-service, and secure wireless mesh networks. Wi-SUN can be used for large-scale outdoor IoT wireless communication networks in a wide range of applications covering both line-powered and battery-powered nodes.

Silicon Labs' Wi-SUN hardware is certified by the Wi-SUN Alliance, a global industry association devoted to seamless LPWAN connectivity. Wi-SUN builds upon open standard internet protocols (IP) and APIs, enabling developers to extend existing infrastructure platforms to add new capabilities. Built to scale with long-range capabilities, high-data throughput, and IPv6 support, Wi-SUN simplifies wireless infrastructure for industrial applications and the evolution of smart cities.

### Release Summary

[Key Features](#key-features) | [API Changes](#api-changes) | [Bug Fixes](#bug-fixes) | [Chip Enablement](#chip-enablement)

#### Key Features

- Added automatic connection parameter selection. The stack can now automatically optimize connection parameters based on the PAN size, and adapt the parameters as the size changes. This replaces the fixed legacy connection parameter configurations and predefined parameter sets.
- Introduced an optional component to allocate a separate heap for critical Wi-SUN functions. The component reserves a separate configurable heap for critical Wi-SUN stack and cryptographic allocations, allowing the Wi-SUN connection to be maintained even when the system heap is exhausted.
- Added support for Direct Connect client. The application can now act as a Direct Connect client with scanning capabilities, complementing the existing server role.  
  - The client opens a secure, single-hop IPv6 wireless link to a Direct Connect server.  
  - The client is available as a standalone stack variant or together with FFN; it is not supported with LFN or Border Router (BR). When used with FFN, the DC link can run alongside an active or in-progress Wi-SUN mesh connection.
- Added support for First Breath mode. First Breath enables an FFN to send expedited upstream application data after a network outage before the node reaches full operational connectivity.
- Added support for Last Gasp mode. FFNs can enter a low-energy Last Gasp mode to deliver a final burst of traffic before power loss.
- Expanded RF test component with TX and RX modes. RF test component now supports dedicated transmission and reception test modes for high-volume production testing.

#### API Changes

- Added new APIs for fine-tuning the automatic parameter selection
- Added new APIs for Direct Connect client
- Added an API to insert vendor-specific data into DHCPv6 Solicit messages
- Added an API to control First Breath mode
- Added an API to control Last Gasp mode
- Deprecated a few legacy configuration parameters
- Deprecated a few API flags related to certificate configuration

#### Bug Fixes

- Enhanced processing of malformed channel-mask IEs for better interoperability with third-party devices
- Fixed various LFN multicast issues
- Fixed several LFN stability and scheduling issues
- Fixed routing, forwarding, and DAO-related edge cases
- Fixed socket error propagation after connection teardown

#### Chip Enablement

None.

### Key Features

[New Features](#new-features) | [Enhancements](#enhancements) | [Removed Features](#removed-features) | [Deprecated Features](#deprecated-features)

#### New Features

- Automatic connection parameter selection: By default, the stack will optimize connection parameters based on the PAN size, and adapt the parameters as the size changes. Parameters that are not automatically adapted can be fine-tuned using `sl_wisun_set_option()`, otherwise they will utilize the fixed default values. The application can override the adapted parameters by specifying explicit values using `sl_wisun_set_ffn_advanced_parameters()`, `sl_wisun_set_lfn_advanced_parameters()`, or `sl_wisun_br_set_advanced_parameters()`.  
  It's possible to revert back to the legacy fixed configuration by using `sl_wisun_set_connection_parameters()`, `sl_wisun_set_lfn_parameters()`, or `sl_wisun_br_set_connection_parameters()`. While the legacy configuration parameters are not deprecated, developers are encouraged to adapt the new configuration APIs.
- Separate Wi-SUN heap: The application can include an optional `wisun_alloc` component during project generation. This reserves a separate, application-configurable heap used for critical features needed to maintain the Wi-SUN connection even when the system heap is exhausted. Care should be taken to size the heap correctly since any cryptographic operations performed by the application will also utilize this heap.
- Direct Connect client: This client allows a device to establish a secure, single-hop wireless link to a Direct Connect server, enabling fast, direct IPv6 communication outside of the Wi-SUN network. The client is supported only as a standalone library or together with FFN; it is not available in LFN or BR. When used with FFN, the DC client and Wi-SUN mesh connection operate independently without disturbing each other. As part of the enhanced Direct Connect support, the DC server has been extended to advertise a DC server identity. This allows the client to search for a unique server identity or identify a particular server when multiple servers are available.
- First Breath mode: First Breath is a feature that allows a Wi-SUN FFN to rapidly deliver critical application data upstream following a network outage or a device reboot, before the node completes full joining process. This enables applications to expedite high-priority messages (such as alerts or maintenance signals) without waiting for the full operational state. The feature is controlled using `sl_wisun_set_first_breath()` and the application receives `SL_WISUN_MSG_FB_READY_IND` event when the node is ready for expedited traffic.
- Last Gasp mode: When an FFN detects imminent power failure, Last Gasp mode enables the node to temporarily maintain network connectivity and send a final burst of high-priority messages, such as alerts or telemetry, before shutting down. This capability boosts the reliability of critical event reporting in power-constrained scenarios. The feature is managed with the `sl_wisun_set_last_gasp()` API.
- Vendor-specific data in DHCPv6 Solicit messages: `sl_wisun_set_dhcpv6_vendor_data()` allows the application to insert vendor-specific data into the DHCPv6 Solicit messages that are sent when joining a Wi-SUN network and when DHCP lease is renewed.
- Event Task: Wi-SUN event processing has been moved to a separate `wisun_event_task` component that's included by default. The application can override this by including `wisun_disable_event_task` component which allows the application to consume events directly from the underlying [Event System](https://docs.silabs.com/gecko-platform/latest/platform-common/event-system) instead of `sl_wisun_on_event()` callback.
- Channel Mask for Explicit Channel Plans: Added a `channel_mask` field to `sl_wisun_phy_config_explicit_t` to restrict the set of channels on which the device is permitted to transmit. The mask applies to asynchronous, unicast, and broadcast frames, and is advertised in both US-IE and BS-IE.
- Expanded RF Test Component: Extended the `wisun_rf_test` component with dedicated TX and RX test modes to support high-volume production testing. The PHY configuration can be selected from the command line.

#### Enhancements

- LFN improvements  
  - LFN adapts listening strategy based on measured parent drift  
  - Improved LFN recovery after parent reboot  
  - Increased LFN multicast group enrollment support up to 8 groups
- Improved asynchronous frame TX fairness between nodes
- Improved key rotation reliability by retrying key fetches through the rotation window
- Persisted RPL DODAG ID and DAO sequence in NVM to reduce route instability
- Optimized the size of stack release libraries by removing unnecessary strings
- Improved socket POSIX compatibility  
  - Reorganized socket header placement to better align with POSIX  
  - Updated IPV6_TCLASS socket option to make it RFC3542 compliant
- Optimized authenticator heap usage to support larger networks on memory-constrained SoC Border Routers

#### Removed Features

None.

#### Deprecated Features

None.

### API Changes

[New APIs](#new-ap-is) | [Modified APIs](#modified-ap-is) | [Removed APIs](#removed-ap-is) | [Deprecated APIs](#deprecated-ap-is)

#### New APIs

|New API Signature|Deprecated API replaced by this (if any)|
|---|---|
|[sl_wisun_set_option()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-option)|None|
|[sl_wisun_set_ffn_advanced_parameters()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-ffn-advanced-parameters)|None|
|[sl_wisun_set_lfn_advanced_parameters()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-lfn-advanced-parameters)|None|
|[sl_wisun_br_set_advanced_parameters()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-br-api#sl-wisun-br-set-advanced-parameters)|None|
|[sl_wisun_reset_parameters()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-reset-parameters)|None|
|[sl_wisun_advert_direct_connect_server_id()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-advert-direct-connect-server-id)|None|
|[sl_wisun_start_direct_connect_client()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-start-direct-connect-client)|None|
|[sl_wisun_stop_direct_connect_client()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-stop-direct-connect-client)|None|
|[sl_wisun_start_direct_connect_scan()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-start-direct-connect-scan)|None|
|[sl_wisun_stop_direct_connect_scan()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-stop-direct-connect-scan)|None|
|[sl_wisun_connect_to_direct_connect_server()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-connect-to-direct-connect-server)|None|
|[sl_wisun_set_dhcpv6_vendor_data()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-dhcpv6-vendor-data)|None|
|[sl_wisun_set_last_gasp()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-last-gasp)|None|
|[sl_wisun_set_first_breath()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-first-breath)|None|
|[SL_WISUN_MSG_DIRECT_CONNECT_ID_SOLICIT_IND](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-msg-direct-connect-id-solicit-ind#sl-wisun-msg-direct-connect-id-solicit-ind)|None|
|[SL_WISUN_MSG_DIRECT_CONNECT_ID_RECEIVED_IND](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-msg-direct-connect-id-received-ind#sl-wisun-msg-direct-connect-id-received-ind)|None|
|[SL_WISUN_MSG_DIRECT_CONNECT_CLIENT_STATE_CHANGED_IND](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-msg-direct-connect-client-state-changed-ind#sl-wisun-msg-direct-connect-client-state-changed-ind)|None|
|[SL_WISUN_MSG_FB_READY_IND](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-msg-fb-ready-ind-id#sl-wisun-msg-fb-ready-ind)|None|

#### Modified APIs

|Modified API / Type|Change Description|
|---|---|
|[sl_wisun_set_lfn_parameters()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-lfn-parameters)|Added `lpas_interval_s` for configuring the interval between LPAS.|
|[sl_wisun_trigger_frame()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-trigger-frame)|Added `SL_WISUN_FRAME_TYPE_LPAS` to trigger an LPAS frame.|
|[Socket API](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-socket-api)|Reorganized socket header includes for POSIX compatibility. Existing `socket/socket.h` and `socket/select.h` remain as compatibility wrappers.|
|[sl_wisun_phy_config_explicit_t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-phy-config-explicit-t)|Added `channel_mask` field to specify the set of channels on which the device is permitted to transmit when using an explicit channel plan.|

#### Removed APIs

None.

#### Deprecated APIs

|Deprecated API Name|Planned Removal Date|
|---|---|
|[sl_wisun_br_set_network_size()](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-br-api#sl-wisun-br-set-network-size)|Not before June, 2027|
|[SL_WISUN_CERTIFICATE_OPTION_IS_REF](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-types#sl-wisun-certificate-option-t)|Not before June, 2027|
|[SL_WISUN_CERTIFICATE_OPTION_HAS_KEY](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-types#sl-wisun-certificate-option-t)|Not before June, 2027|
|[dhcp_address_lifetime_s](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-br-params-dhcp-s#dhcp-address-lifetime-s)|Not before June, 2027|
|[temp_link_min_timeout_s](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-misc-s#temp-link-min-timeout-s)|Not before June, 2027|

### Bug Fixes

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Issue Description</th>
            <th>GitHub / Salesforce Reference (if any)</th>
            <th>Affected Software Variants, Hardware, Modes, Host Interfaces</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1639610</td>
            <td>RPL: Fixed leaf nodes accepting children if leaf mode was configured before connection start.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1639535</td>
            <td>RPL: Fixed FFN being unable to switch to the secondary parent if the primary parent rejected NA(ARO).</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1582395</td>
            <td>RPL: Fixed the only parent candidate being temporarily ignored on failure.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1581677</td>
            <td>RPL: Fixed an issue where post-reboot DAOs could be dropped by the border router, preventing route establishment. The RPL DODAG ID and DAO sequence are now persisted in NVM.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1593305</td>
            <td>RPL: Fixed a node getting stuck in Join State 4 (Parent Selection) and failing to select a parent until PAN timeout.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1456996</td>
            <td>RPL: Fixed original datagram Hop Limit not taken into account when generating SRH.</td>
            <td></td>
            <td>BR</td>
        </tr>
        <tr>
            <td>1646935</td>
            <td>LFN: Fixed slow LPCS retry interval.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1647721</td>
            <td>LFN: Fixed incorrectly calculated FFN BC slot on initial parent sync.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1578988</td>
            <td>LFN: Fixed an infinite loop when queueing too many message for LFNs.</td>
            <td></td>
            <td>BR, FFN</td>
        </tr>
        <tr>
            <td>1606615</td>
            <td>LFN: Fixed LFN accepting frames with invalid LCP-IE.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1635839</td>
            <td>LFN: Fixed excessively long MAC timeouts for frames destined to an LFN.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1619734</td>
            <td>LFN: Fixed invalid processing of multicast group registration failure.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1619747</td>
            <td>LFN: Fixed an issue where multicast group registrations were not refreshed upon reconnection.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1571629</td>
            <td>LFN: Fixed missed LPA reception due to early parent transmission and overlapping unicast schedule offsets.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1570736</td>
            <td>LFN: Fixed unnecessary full authentication after reboot despite valid credentials in NVM, which could delay reconnection.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1608913</td>
            <td>LFN: Fixed delayed detection of a parent disconnection, which could delay reconnection.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1632686</td>
            <td>MAC: Fixed nodes ignoring POM-IE in EAPOL frames.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1631647</td>
            <td>MAC: Fixed incorrect broadcast slot number when using a fixed channel.</td>
            <td></td>
            <td>BR, FFN</td>
        </tr>
        <tr>
            <td>1582393</td>
            <td>MAC: Fixed FAN 1.0 EDFE response frames being dropped when MAC address filtering was enabled.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1613180</td>
            <td>MAC: Fixed Transmit Flow Control calculation in FC-IE when using mode switch.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1568217</td>
            <td>MAC: Fixed inability to clear the MAC address filtering table after it became full.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1143702</td>
            <td>MAC: Fixed LFN parent selection failures caused by an incorrect LFN PAN Advertisement (LPA) frame timeout.</td>
            <td></td>
            <td>BR, FFN</td>
        </tr>
        <tr>
            <td>1590250</td>
            <td>MAC: Fixed newly added neighbors not using the configured default rate algorithm.</td>
            <td></td>
            <td>BR, FFN</td>
        </tr>
        <tr>
            <td>1631596</td>
            <td>Security: Fixed frame counters unnecessarily being incremented when going back to join state 1.</td>
            <td></td>
            <td>FFN, LFN</td>
        </tr>
        <tr>
            <td>1616467</td>
            <td>Security: Fixed supplicant incorrectly relaying authenticator retries after parent change.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1563032</td>
            <td>Security: Fixed incorrect validation of Wi-SUN certificate extensions.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1516872</td>
            <td>Security: Fixed connection setup ignoring supplicant/authenticator initialization failure.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1640018</td>
            <td>Security: Fixed Key-Request frames incorrectly containing NR and LGTKL KDEs when operating in FAN 1.0.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1606527</td>
            <td>Security: Fixed active supplicants being removed from the neighbor table during congestion.</td>
            <td></td>
            <td>BR</td>
        </tr>
        <tr>
            <td>1606120</td>
            <td>Security: Fixed an authenticator crash if a supplicant context was removed early.</td>
            <td></td>
            <td>BR</td>
        </tr>
        <tr>
            <td>1614265</td>
            <td>Security: Fixed LFNs mistakenly including GTKL KDE in Key-Request frames.</td>
            <td></td>
            <td>LFN</td>
        </tr>
        <tr>
            <td>1614265</td>
            <td>Security: Fixed incorrect KDE ordering in Key-Request frames.</td>
            <td></td>
            <td>FFN, LFN</td>
        </tr>
        <tr>
            <td>1564487</td>
            <td>Security: Fixed occasional reconnection delays when changing PAN due to repeated unnecessary authentication attempts.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1638246</td>
            <td>Multicast: Fixed router incorrectly inserting non-LFN multicast into MPL domain.</td>
            <td></td>
            <td>BR, FFN</td>
        </tr>
        <tr>
            <td>1630831</td>
            <td>Socket: Fixed socket close not aborting a blocking sendmsg request.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1630689</td>
            <td>Socket: Fixed deadlock and incorrect abort handling when closing a socket during blocking socket I/O.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1627089</td>
            <td>Socket: Fixed a heap buffer overflow when reading incoming socket data into a socket data indication event.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1589325</td>
            <td>PHY: Fixed connection failures with certain OFDM PHY configurations generated by the Simplicity Studio radio configurator.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1639375</td>
            <td>RCP: Fixed LPA transmission being blocked by long unicast retry queues after LFN reboot.</td>
            <td></td>
            <td>RCP</td>
        </tr>
        <tr>
            <td>1613156</td>
            <td>RCP: Fixed FC-IE TX field value not being properly set if data was in the initial EDFE frame.</td>
            <td></td>
            <td>RCP</td>
        </tr>
        <tr>
            <td>1631703</td>
            <td>RCP: Fixed a rare invalid HIF status code being reported in CNF_DATA_TX.</td>
            <td></td>
            <td>RCP</td>
        </tr>
        <tr>
            <td>1639795</td>
            <td>Misc: Fixed nodes being stuck in join state 4 after a power cycle.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1596083</td>
            <td>Misc: Fixed stack always using PRS channel 7 for RAIL timer synchronization.</td>
            <td></td>
            <td>BR</td>
        </tr>
        <tr>
            <td>1520149</td>
            <td>Misc: Fixed a neighbor from a non-preferred PAN instantly being selected as an EAPOL target.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1396010</td>
            <td>API: Fixed <code>sl_wisun_get_network_info()</code> reporting an incorrect PAN ID when the device is disconnected.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1617238</td>
            <td>API: Fixed <code>sl_wisun_get_join_state()</code> returning DISCONNECTED during transient connection losses instead of maintaining the correct join state.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1562929</td>
            <td>API: Fixed <code>sl_wisun_get_join_state()</code> to not return an error during disconnection events.</td>
            <td></td>
            <td>FFN, LFN</td>
        </tr>
        <tr>
            <td>1572906</td>
            <td>IPv6: Fixed incorrect hop limit handling when a router forwarded its own multicast packets to LFN children.</td>
            <td></td>
            <td>BR, FFN</td>
        </tr>
        <tr>
            <td>1619125</td>
            <td>IPv6: Fixed an issue where a node would not unregister its IPv6 address from its former secondary parent when switching parents.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1565796</td>
            <td>IPv6: Fixed loopback (self-addressed) IPv6 traffic being dropped (e.g., self-ping).</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1596009</td>
            <td>6LoWPAN: Fixed a rare crash/memory corruption in fragmentation error handling.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1572790</td>
            <td>6LoWPAN: Fixed an incorrect fragment reassembly timeout that could prevent LFNs from receiving fragmented packets.</td>
            <td></td>
            <td>BR, FFN, LFN</td>
        </tr>
        <tr>
            <td>1630069</td>
            <td>Direct Connect: Fixed invalid Direct Connect link teardown on frame counter error.</td>
            <td></td>
            <td>FFN</td>
        </tr>
        <tr>
            <td>1565526</td>
            <td>RF Test: Fixed assertion failures when switching channels or starting RF tests on non-default radio configurations.</td>
            <td></td>
            <td>FFN, LFN</td>
        </tr>
        <tr>
            <td>1620925</td>
            <td>CoAP: Fixed resource leaks in CoAP packet handler.</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>1620929</td>
            <td>CoAP: Fixed memory leaks in CoAP notification error handling.</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>1625090</td>
            <td>CoAP: Fixed CoAP not being usable with Border Router examples.</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>1606270</td>
            <td>CoAP: Fixed CoAP discarding received messages due to 'Request-tags' option.</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>1639504</td>
            <td>CoAP: Fixed resource leaks in CoAP service management.</td>
            <td></td>
            <td></td>
        </tr>
    </tbody>
</table>

### Chip Enablement

None.

### Application Example Changes

[New Examples](#new-examples) | [Modified Examples](#modified-examples) | [Removed Examples](#removed-examples) | [Deprecated Examples](#deprecated-examples)

#### New Examples

<table>
    <thead>
        <tr>
            <th>Example Name</th>
            <th>Description</th>
            <th>Supported Software Variants (if applicable)</th>
            <th>Supported Modes</th>
            <th>Supported OPNs / Boards / OPN Combinations</th>
            <th>Supported Host Interfaces</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Wi-SUN - SoC DC CIU</p>
                <p><a href="https://github.com/SiliconLabsSoftware/sisdk-release/blob/sisdk-2026.6/wisun_cli_app/wisun_dc_ciu/readme.md">Application Readme</a></p>
            </td>
            <td>
                The Wi-SUN Direct Connect (DC) Control Interface Unit (CIU) sample application demonstrates a low-power wireless control interface to a Wi-SUN node, such as an electric meter. It uses the Wi-SUN Direct Connect client to communicate with a Direct Connect server on the node, without joining the Wi-SUN network or disturbing the node’s existing Wi-SUN connection.</td>
            <td>
                N/A
            </td>
            <td>
                SoC
            </td>
            <td>
                <ul>
                    <li>Parts: EFR32FG23, EFR32FG25, EFR32xG28</li>
                    <li>Boards: BRD4204D BRD4210A BRD4263C BRD4264C BRD4270A BRD4270B BRD4271A BRD4272A BRD4276A BRD4400A BRD4400B BRD4400C BRD4401A BRD4401B BRD4401C</li>
                </ul>
            </td>
            <td>
                N/A
            </td>
        </tr>
    </tbody>
</table>

#### Modified Examples

<table>
    <thead>
        <tr>
            <th>Example Name</th>
            <th>Changes</th>
            <th>Supported Software Variants if applicable </th>
            <th>Supported Modes</th>
            <th>Supported OPNs / Boards / OPN Combinations</th>
            <th>Supported Host Interfaces</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Wi-SUN - SoC CoAP Meter</p>
            </td>
            <td>Added support for the new temperature SHT4x sensor of brd4002B.</td>
            <td>N/A</td>
            <td>SoC</td>
            <td>
                <ul>
                    <li>All supported parts</li>
                    <li>All supported boards</li>
                </ul>
            </td>
            <td>N/A</td>
        </tr>
        <tr>
            <td>
                <p>Wi-SUN - SoC CLI</p>
            </td>
            <td>Updated RF test CLI commands to support the expanded <code>wisun_rf_test</code> TX and RX modes.</td>
            <td>N/A</td>
            <td>SoC</td>
            <td>
                <ul>
                    <li>All supported parts</li>
                    <li>All supported boards</li>
                </ul>
            </td>
            <td>N/A</td>
        </tr>
    </tbody>
</table>

#### Removed Examples

None.

#### Deprecated Examples

None.

### Known Issues and Limitations

None.

### Impact of Release Changes

[Impact Statements](#impact-statements) | [Migration Guide](#migration-guide)

#### Impact Statements

None.

#### Migration Guide

`sl_wisun_regdb.c` is generated only once at project creation and is not automatically regenerated when upgrading the SDK. Because the file is user-modifiable, any fixes or updates introduced in newer SDK versions within `sl_wisun_regdb.c` are not applied automatically after migration. When upgrading, manually compare your project's `sl_wisun_regdb.c` with the latest version shipped in the SDK and merge the required changes to ensure all fixes are included.

### Using This Release

#### What's in the Release?

This release contains the following:

- Wi-SUN stack library
- Wi-SUN sample applications
- Wi-SUN border router and RCP pre-compiled demos
- Documentation

If you are a first-time user, see the [Wi-SUN Getting Started Guide](https://docs.silabs.com/wisun/latest/wisun-getting-started-overview/).

#### Compatible Software

<table>
    <thead>
        <tr>
            <th>Software</th>
            <th>Compatible Version or Variant</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><a href="https://github.com/SiliconLabs/wisun-br-linux">Wi-SUN Linux Border Router (wsbrd)</a></td>
            <td>v2 and more recent.</td>
        </tr>
        <tr>
            <td><a href="https://github.com/SiliconLabs/wisun-br-linux">Wi-SUN Linux Router (wsrd)</a></td>
            <td>v2.2 and more recent.</td>
        </tr>
    </tbody>
</table>

#### Installation and Use

The Wi-SUN SDK is distributed as part of the Simplicity SDK, Silicon Labs' unified software development kit suite. To get started quickly, install [Simplicity Studio 6](https://www.silabs.com/developers/simplicity-studio), which provides a complete development environment, including project and resource management, software configuration tools, a full IDE with GNU toolchain, and analysis utilities. Step-by-step installation instructions are available in the [Simplicity Studio 6 User’s Guide](https://docs.silabs.com/ssv6ug/latest/ssv6ug-overview/).

Documentation for each SDK version is included with the SDK installation.

For information about Secure Vault Integration, see [Secure Vault](https://www.silabs.com/security/secure-vault).

To review Security and Software Advisory notifications and manage your notification preferences, complete the following steps:

1. Go to [https://community.silabs.com/](https://community.silabs.com/).
2. Sign in with your account credentials.
3. Click on your profile icon in the upper-right corner of the page.
4. Select **Notifications** from the dropdown menu.
5. In the Notifications section, go to the **My Product Notifications** tab to review historical Security and Software Advisory notifications.
6. To manage your preferences, use the **Manage Notifications** tab to customize which product updates and advisories you receive.

#### Help and Feedback

- Contact [Silicon Labs Support](https://www.silabs.com/support).
- To try our **Ask AI** tool to get answers, use the search field at the top of the [Silicon Labs Developer Documentation](https://docs.silabs.com/) page.  
  > **Note:** **Ask AI** is experimental.
- Get help from our [developer community](https://community.silabs.com/s/?language=en_US).

### SDK Release and Maintenance Policy

See our [SDK Release and Maintenance Policy](https://www.silabs.com/developer-tools/sdk-release-and-maintenance-policy).

## Getting Started

### Introducing Wi-SUN Development

Wireless Smart Ubiquitous Network (Wi-SUN) is the leading IPv6 sub-GHz mesh technology for smart city and smart utility applications. Wi-SUN brings Smart Ubiquitous Networks to service providers, utilities, municipalities/local government, and other enterprises, by enabling interoperable, multi-service, and secure wireless mesh networks. Wi-SUN can be used for large-scale outdoor IoT wireless communication networks in a wide range of applications covering both line-powered and battery-powered nodes.

Silicon Labs provides a complete set of hardware and software solutions to help developers design their Wi-SUN wireless products:

- [Certified hardware platforms](https://wi-sun.org/product/wsa0258-efr32fg12/)
- [Certified Wi-SUN FAN router stack](https://wi-sun.org/product/wsa0266-silicon-labs-wi-sun-sdk/)
- [Certified Wi-SUN FAN border router solution (GitHub)](https://github.com/SiliconLabs/wisun-br-linux)

Silicon Labs has enhanced Wi-SUN to work with Silicon Labs hardware. The Wi-SUN stack library is available as a software development kit (SDK) installed as part of the SiSDK, the suite of Silicon Labs SDKs. The two primary elements to getting started with Wi-SUN development are the **Silicon Labs Wi-SUN SDK** and **Simplicity Studio 5**:

#### Prerequisites

Before following the procedures in this document, you must have:

- Purchased one of the Wireless Gecko (EFR32) Portfolio Wireless Kits with compatible radio boards, listed on [https://www.silabs.com/wireless/wi-sun](https://www.silabs.com/wireless/wi-sun).
- Downloaded SSv5 and the SiSDK and be generally familiar with the SSv5 Launcher perspective. SSv5 installation and getting started instructions along with a set of detailed references can be found in the online [Simplicity Studio 5 User's Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/).
- Obtained a compatible compiler (see the Wi-SUN SDK’s release notes for the compatible versions):  
  - Simplicity Studio comes with a free GCC C-compiler.  
  - IAR Embedded Workbench for ARM (IAR-EWARM) can also be used as the compiler for Silicon Labs Wi-SUN projects. Once IAR-EWARM is installed, the next time Simplicity Studio starts, it will automatically detect and configure the IDE to use IAR-EWARM. Refer to [IAR IDE License](/wisun/2.12.0/wisun-getting-started-going-further/02-development-tools#iar-ide) on the Development Tools page to get an IAR IDE trial of 30 days.

#### The Silicon Labs Wi-SUN SDK

The Silicon Labs Wi-SUN SDK is composed of the Wi-SUN FAN stack and sample applications as well as the addition of metadata to allow for the seamless integration into Simplicity Studio 5. The Silicon Labs Wi-SUN SDK contains the Wi-SUN stack in a library format.

The Silicon Labs Wi-SUN SDK is based on the Simplicity Platform component-based design, where each component provides a specific function. Components are made up of a collection of source files and properties. The component-based design enables customization by adding, configuring, and removing components. The application developer can use SSv5’s Project Configurator and Component Editor to easily assemble the desired features by including those components that match the required functionality and by configuring the various properties associated with those components.

For details on the Wi-SUN stack version included within the Silicon Labs Wi-SUN SDK, refer to the [Wi-SUN SDK release notes](/wisun/2.12.0/sisdk-wisun-release-notes).

#### Simplicity Studio 5 (SSv5)

The Silicon Labs Wi-SUN SDK is downloaded through SSv5. SSv5 is the core development environment designed to support the Silicon Labs IoT portfolio of system-on-chips (SoCs) and modules. It provides access to target device-specific web and SDK resources; software and hardware configuration tools; an integrated development environment (IDE) featuring industry-standard code editors, compilers and debuggers; and advanced, value-add tools for network analysis and code-correlated energy profiling.

SSv5 is designed to simplify developer workflow. It intelligently recognizes all Silicon Labs evaluation and development kit parts and, based on the selected development target, presents appropriate software development kits (SDKs) and other development resources.

The GNU Compiler Collection (GCC) is provided with SSv5. Other important development tools provided with SSv5 are reviewed in [Development Tools](/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-overview/).

#### Starting Development

Install [Simplicity Studio 5](http://www.silabs.com/simplicity) (SSv5), which will set up your development environment and walk you through SiSDK installation. Installation instructions are provided in the [Simplicity Studio 5 online User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/). This is the recommended method for getting started with development.

Alternatively, SiSDK may be installed manually by downloading or cloning the latest from GitHub. See [https://github.com/SiliconLabsSoftware/sisdk-release](https://github.com/SiliconLabsSoftware/sisdk-release) for more information.

Using Simplicity Studio, you have easy access to the [sample applications and demos](02-wisun-sample-apps). Instructions for quickly beginning to use these to create a Wi-SUN network as well as information about other development tools are included in these 2 sections:

- [**Wi-SUN Sample Applications**](02-wisun-sample-apps): Introduces the list of Wi-SUN Demos and Sample applications to start creating a Wi-SUN Network and evaluate the Silicon Labs Wi-SUN solution.
- [**Creating a Wi-SUN Network**](03-wisun-network): Provides instructions to compile and load a simple **Wi-SUN Ping** application on a node and a **Wi-SUN Border Router** demo image on another node. You can then use these to create a network.

#### Support

Access the Silicon Labs support portal at [https://www.silabs.com/support](https://www.silabs.com/support) through SSv5’s Welcome view under Learn and Support. Use the support portal to contact Customer Support for any questions you might have during the development process.

![Technical Support](/wisun-getting-started-development/0.3/images/sld124-image1.png)

#### Documentation

Relevant documentation is available through SSv5. It is filtered based on the device selected in either the Debug Adapters view or the My Product view. Hardware-specific documentation for the device can be accessed through links on the OVERVIEW tab.

![Hardware documentation](/wisun-getting-started-development/0.3/images/sld124-image2.png)

SDK documentation and other references are available through the DOCUMENTATION tab. Filter with the Wi-SUN Technology Type checkbox to see documentation most closely related to the Wi-SUN SDK. To see documents specific to Wi-SUN, select ‘Wi-SUN’ under **Wireless Technology**.

![The documentation tab](/wisun-getting-started-development/0.3/images/sld124-image3.png)

SSv5 and its tools are documented in the online [Simplicity Studio 5 User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/).

![Simplicity Studio 5 Users Guide](/wisun-getting-started-development/0.3/images/sld124-image4.png)

### About Sample Applications and Demos

Because starting application development from scratch is difficult, the Silicon Labs Wi-SUN SDK comes with a number of built-in sample applications and demos covering the most frequent use cases designed to illustrate common application functions. Silicon Labs strongly recommends starting development from one of the sample applications.

Like everything in SSv5, the examples and the demos shown on the **EXAMPLE PROJECTS & DEMOS** tab are filtered based on the part you have connected or selected.

#### Demos

Demos are prebuilt firmware images that are ready to download to a compatible device. The quickest way to find if a demo is available for your part is by adding the part or board information in the My Products view and then navigating to the **EXAMPLE PROJECTS & DEMOS** tab in the **Launcher** perspective. Disable the Example Projects filter. The Solution Examples filter is provided for future use.

![Examples and Demos tab](/wisun-getting-started-development/0.3/images/sld124-image5.png)

Precompiled demo application images provided with the Wi-SUN SDK are compatible with the [Wi-SUN Wireless SoCs](https://www.silabs.com/wireless/wi-sun?tab=hardware) listed Silicon labs web page.

#### Software Examples

When you work with examples, the process is:

- Select an example
- Change the example configuration (if needed)
- Build the example
- Load the example to the target device

Since typically you will finish by flashing a compiled application image to a device, connect a device to your computer and select it in the Debug Adapters view. In the **EXAMPLE PROJECTS & DEMOS** tab on the **Launcher** perspective, enter ‘wi-sun’ as a keyword. A number of other filters are provided. To see the examples only, turn off **Demos**.

![Examples and demos tab with no demos shown](/wisun-getting-started-development/0.3/images/sld124-image6.png)

Each example has its own documentation accessible by clicking **View Project Documentation** below the example description. The HTML document covers the steps to set up the example and run the associated demonstration.

The sample applications provided with the Silicon Labs Wi-SUN SDK are as follows.

**Wi-SUN - SoC Border Router**: Acts as a Wi-SUN Border Router in a network, and provides an interface device functionality.

**Wi-SUN – CLI example**: Acts as a Wi-SUN router node in a network, and provides an interface device functionality.

**Wi-SUN - LFN CLI example**: Acts as a Wi-SUN Limited Function Node in a network, and provides an interface device functionality.

**Wi-SUN – SoC CoAP Collector**: Collects data from other devices configured as meters using CoAP.

**Wi-SUN – SoC CoAP Meter**: Provides basic meter functionality to communicate with a collector using CoAP.

**Wi-SUN – SoC Empty**: Provides a basic framework to begin adding custom functionality.

**Wi-SUN – SoC Network Measurement**: Provides a tool to measure the Wi-SUN solution performance.

**Wi-SUN – SoC Ping**: Provides simple connectivity testing.

**Wi-SUN – SoC Socket**: Enables TCP/UDP socket communication between nodes.

**Wi-SUN – RCP**: Radio co-processor border router implementation that pairs with a Linux host running the Wi-SUN stack upper layers.

**Wi-SUN - DDP**: Provides support for run-time provisioning of device-specific Wi-SUN data, such as private keys and certificates.

### Creating a Wi-SUN Network

In these instructions, you compile and load a simple **Wi-SUN Ping** application on a node and a **Wi-SUN Border Router** demo image on another node. The [Creating a Network](#creating-a-network) section describes how to use the examples to create a network.

When working with an example application in Simplicity Studio, execute the steps in the following order:

1. Create a project based on an example.
2. Configure the project.
3. Build the application image and flash it to your device.

These steps are described in detail in the following sections. These procedures are illustrated for a mainboard with an EFR32MG12. Note: Your SDK version may be later than the version shown in the figures.

You should have your mainboard connected.

> For best performance in Simplicity Studio 5, be sure that the power switch on your mainboard is in the Advanced Energy Monitoring or **AEM** position, as shown in the following figure.

![Wireless starter kit with power switch](/wisun-getting-started-development/0.3/images/sld124-image7.png)

#### Flashing the Wi-SUN Border Router

Every Wi-SUN example requires a Wi-SUN Border Router to create and manage a Wi-SUN network for the Wi-SUN devices to join. It provides an easy and quick medium to evaluate the Silicon Labs Wi-SUN stack solution without deploying an expensive and cumbersome production-grade Wi-SUN Border Router. A CLI (Command-Line Interface) is exposed to facilitate the configuration.

Note: Make sure your mainboard has the latest “Adapter FW” to avoid any issue when using the example CLI. To do so:

1. In the **Launcher** perspective, click the radio board listed in the Debug Adapters view.
2. In the **OVERVIEW** tab, verify the Adapter FW version in the **General Information** card.
3. If Simplicity Studio 5 proposes to update the firmware, do so.

The [Wi-SUN SoC Border Router](/wisun/2.12.0/wisun-soc-border-router) demonstration is delivered in a binary format for an out-of-the-box experience. The implementation scales for a production-grade SoC Border Router maintaining several hundreds of Wi-SUN nodes. For a production-grade Linux border router solution, refer to the [Wi-SUN Linux Border Router](/wisun/2.12.0/wisun-linux-border-router) section to get started.

![Examples and demos tab showing border router example](/wisun-getting-started-development/0.3/images/sld124-image8.png)

1. In the **Debug Adapters** view, select the device that will be the Wi-SUN border router. Note: To rename the device so that you know which device is the Border Router, right-click it and select **Rename** on the context menu.
2. Navigate to the **EXAMPLE PROJECTS & DEMOS** tab and turn off the **Example Projects** filter. Click **RUN** next to **Wi-SUN – SoC Border Router** demo.
3. Start the Wi-SUN Border Router with the CLI interface. In the Debug Adapters view, right-click the Border Router device and click Launch Console, as shown. Alternatively, click Tools in the Simplicity IDE menu and select 'Device Console'.  
   ![Project menu launch console option](/wisun-getting-started-development/0.3/images/sld124-image9.png)
4. To get a prompt on the Console, go to the Serial 1 tab and press **Enter**. To start the Wi-SUN Border Router with default FAN 1.1 PHY, enter:  
   ```c  
   > wisun start_fan11  
   ```

#### Creating a Project Based on an Example

Simplicity Studio 5 (SSv5) offers a variety of ways to begin a project using an example application. The online [Simplicity Studio 5 User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/) describes them all. This guide uses the **File > New > Silicon Labs Project Wizard** method because it takes you through all three of the Project Creation Dialogs. Details on each creation dialog option may be found in the _Simplicity Studio 5 User’s Guide_.

1. In the **Debug Adapters** view, select the target part for the application node. This should be a different part than the one used for the border router in the previous section.
2. Open SSv5’s File menu and select **New > Silicon Labs Project Wizard**. The Target, SDK, and Toolchain Selection dialog opens. Do not change the default **Simplicity IDE / GNU ARM v<version>** toolchain supported by Wi-SUN. Click **NEXT**.  
   ![Target, SDK, and Toolchain selection](/wisun-getting-started-development/0.3/images/sld124-image10.png)
3. The Example Project Selection dialog opens. Use the ‘Wi-SUN’ Technology Type and Keyword filters to search for a specific example, in this case **Wi-SUN – SoC Ping**. Select it and click **NEXT**.  
   ![Example Project Selection](/wisun-getting-started-development/0.3/images/sld124-image11.png)
4. The Project Configuration dialog opens. Here you can rename your project, change the default project file location, and determine if you will link to or copy project files. Note that if you change any linked resource, it is changed for any other project that references it. Click **FINISH.**  
   ![Project Configuration](/wisun-getting-started-development/0.3/images/sld124-image12.png)
5. The Simplicity IDE Perspective opens with the project documentation (readme.md). Click the <project>.slcp tab to see the Project Configurator OVERVIEW tab. See the online [Simplicity Studio 5 User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-overview/) for details about the functionality available through the Simplicity IDE perspective and the Project Configurator.

![Project Configurator Overview tab](/wisun-getting-started-development/0.3/images/sld124-image13.png)

#### Configuring the Project

Silicon Labs Wi-SUN applications are built on a Simplicity Platform component structure. Click the **SOFTWARE COMPONENTS** tab to see a complete list of component categories.

![Software components](/wisun-getting-started-development/0.3/images/sld124-image14.png)

The project is configured by installing and uninstalling components and configuring installed components. Installed components are shown with a circled checkmark on their left. Click **Installed Components** to see a filtered list of components installed by the example application.

Configurable components have a gear symbol on their right. Select a component to see information about it.

![Configurable components](/wisun-getting-started-development/0.3/images/sld124-image15.png)

If the component is configurable, click **CONFIGURE** to open the Component Editor in a new tab.

For example, in the Ping component you can configure various parameters that change the way the wisun-ping application behaves.

![Ping component configuration](/wisun-getting-started-development/0.3/images/sld124-image16.png)

Any changes you make are autosaved, and project files are autogenerated.

![Ping configuration with autosave banner](/wisun-getting-started-development/0.3/images/sld124-image17.png)

In addition to the Project Configurator tab (<project>.slcp), a Wi-SUN Configurator tab is also available. For more information about using the Wi-SUN Configurator and how to change the default Wi-SUN PHY, see [Wi-SUN Configurator](/wisun/2.12.0/wisun-configurator/).

![Wi-SUN configurator](/wisun-getting-started-development/0.3/images/sld124-image18.png)

If you make changes, the Wi-SUN Configurator tab has an asterisk to the left. Save changes (CTRL-S) when you are finished updating Wi-SUN Configurator settings. If you build the project without saving changes, the changes are saved automatically.

#### Building the Project

You can either compile and flash the application automatically, or manually compile it and then flash it.

##### Automatically Compile and Flash

1. You can automatically compile and flash the application to your connected development hardware in the Simplicity IDE, and open a Debug interface. Click **Debug** ![debug icon](/wisun-getting-started-development/0.3/images/sld124-image19.png).
2. Progress is displayed in the console and a progress bar in the lower right.  
   ![Console with build progress](/wisun-getting-started-development/0.3/images/sld124-image20.png)  
   The project should build without error.  
   ![Console showing successful build](/wisun-getting-started-development/0.3/images/sld124-image21.png)
3. When building and flashing are complete a Debug perspective is displayed. Click **Resume** (![resume icon](/wisun-getting-started-development/0.3/images/sld124-image22.png)) to start the application running on the WSTK.

Next to the Resume control are **Suspend**, **Terminate**, **Disconnect**, and **stepping** controls. Click **Disconnect** (![Disconnect icon](/wisun-getting-started-development/0.3/images/sld124-image23.png)) when you are ready to exit Debug mode.

##### Manually Compile and Flash

1. After you generate your project files, instead of clicking Debug, click **Build** (![Build icon](/wisun-getting-started-development/0.3/images/sld124-image24.png)) in the top tool bar.
2. You can load the binary image through Project Explorer view.

Locate the <project>.bin, .hex, or .s37 file in the Binaries subdirectory.

![Project explorer view](/wisun-getting-started-development/0.3/images/sld124-image25.png)

Right-click the file and select **Flash to Device..**. If you have more than one device connected, select a device to program. The Flash Programmer opens with the file path populated. Click **PROGRAM** to flash the image to the device.

![Flash Programmer](/wisun-getting-started-development/0.3/images/sld124-image26.png)

#### Flashing a Bootloader

All Silicon Labs examples require that a bootloader be installed. A bootloader is a program stored in reserved flash memory that can initialize a device, update firmware images, and possibly perform some integrity checks. Silicon Labs networking devices use bootloaders that perform firmware updates in two different modes: standalone (also called standalone bootloaders) and application (also called application bootloaders). An application bootloader performs a firmware image update by reprogramming the flash with an update image stored in internal or external memory. By default, a new device is factory-programmed with a bootloader, which remains installed until you erase the device. The Gecko Bootloader is a code library configurable through Simplicity Studio’s IDE to generate bootloaders that can be used with a variety of Silicon Labs protocol stacks. The Gecko Bootloader is used with all EFR32xG parts. For more information about bootloaders see [Bootloader Fundamentals](/wisun/2.12.0/bootloader-fundamentals).

By default, a new device is factory-programmed with a bootloader. If you have a new device, haven’t cleared the bootloader region for your part or have a supported bootloader image already flashed on your device, skip this step and continue with the next section.

With Silicon Labs Wi-SUN, the bootloader serves to start the application code within the image you created and flashed in the previous procedure. Once you have installed a bootloader image, it remains installed until you erase the device.

To flash a bootloader, first select one of the bootloader examples, such as **SPI Flash Storage Bootloader (single image)**, and build and flash it as described above. For more information see [Silicon Labs Gecko Bootloader User’s Guide for SiSDK 4.0 and Higher (series 1 and 2 devices)](/wisun/2.12.0/bootloader-user-guide-gsdk-4) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](/wisun/2.12.0/bootloader-user-guide-series3-and-higher).

If you are working with the Gecko Bootloader, bootloader images must be formatted as GBL files. To create a GBL file from an .s37 or binary, follow the instructions in the _GBL File Creation_ section of the [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-commands/gbl-commands). The exact format of the GBL file depends on the hardware you selected.

#### Creating a Network

Depending on the example application, you may be able to interact with it through your development environment’s Console interface using a CLI (command-line interface). The console interface allows you to form a network and send data using the border router device created in section [Flashing the Wi-SUN Border Router](#flashing-the-wi-sun-border-router) and the application node.

To launch the Console interface, in the Simplicity IDE perspective right-click the application node in the Debug Adapters View. Select **Launch Console**. Alternatively, click Tools in the Simplicity IDE menu and select Device Console.

![Launch Console menu option](/wisun-getting-started-development/0.3/images/sld124-image27.png)

To get a prompt on the Console, go to the **Serial 1** tab and press Enter.

> **TIP**: The prompt input and output are managed via UART over a virtual COM port (VCOM). The communication parameters are configured as follows: Baud Rate 115200 bps, Parity None, Stop Bits 1, Flow Control None.

##### Connect the Wi-SUN Ping WSTK

The Wi-SUN Ping application automatically starts by connecting to the Border Router. If the connection is successful, the application should output the traces below in the console.

```c
[Connecting to "Wi-SUN Network"]
> [Join state: Authenticate (2)]
[Join state: Acquire PAN Config (3)]
[Join state: Configure Routing (4)]
[Join state: Operational (5)]

Addresses:

[GLOBAL        : fd00:7283:7e00:0:5e02:72ff:fe96:ca9c]
[LINK_LOCAL    : fe80::5e02:72ff:fe96:ca9c]
[BORDER_ROUTER : fd00:6172:6d00:0:b6e3:f9ff:fea6:3aa]
[170 s]
```

The following is an illustration of connecting the Wi-SUN SoC Border Router application to the Wi-SUN SoC Ping Example Application. This setup allows showing the Border Router and the device consoles side by side, where Wi-SUN settings can be compared. If these do not match, the connection will fail. When using a Linux Border Router, use 'wsbrd_cli status' to check the Border Router settings.

![Connection illustration](/wisun-getting-started-development/0.3/images/sld124-image28.png)

The two Wi-SUN devices (Border Router and Wi-SUN SoC Ping) are now part of the same Wi-SUN network.

##### Ping the Wi-SUN Border Router

To check the commands exposed in the Wi-SUN Ping application, enter:

`wisun help`

To retrieve the Border Router IPv6 address, enter:

`wisun get wisun.ip_address_border_router`

The Wi-SUN Ping application has a specific command: `wisun ping [IPv6 address]`. Use the command to ping the Border Router.

`wisun ping [Border Router Global IPv6 address]`

If the ping command is successful, the pong message size and latency are output on the console.

```c
> wisun ping fd00:6172:6d00:0:20d:6fff:fe20:bd95`
PING fd00:6172:6d00:0:20d:6fff:fe20:bd95: 40 data bytes
> [40 bytes from fd00:6172:6d00:0:20d:6fff:fe20:bd95: icmp_seq=1 time=196.231 ms]
```

In this case, the ping took 196 milliseconds to come back to the Wi-SUN device. The ping command can be used to communicate with other Wi-SUN devices in the same Wi-SUN network.

###### Disconnect and Reconnect the Ping WSTK

You need to disconnect the WSTK and reconnect it to apply new network settings, if you modified them on the Border Router (check these on the Linux Border Router using ‘wsbrd_cli status’).

> **Note**: It may be worth going through this in situations where the Wi-SUN device does not connect to the Border Router.

To disconnect the WSTK, enter:

`wisun disconnect`

Check the Wi-SUN settings using:

`wisun get wisun`

Set the new Wi-SUN settings using:

`wisun set wisun.<parameter> <value>`

Use the online help or refer to the readme.md file (at the root of you project) to check what parameters are required for your FAN configuration, using:

`wisun set wisun help`

If you want to preserve your settings following a power cycle or reset, use:

`wisun save`

Depending on the FAN configuration, use one of the commands below to connect with your new settings:

`wisun join_fan10`

`wisun join_fan11`

`wisun join_explicit` (only for the Wi-SUN SoC CLI application)

#### Next Steps

Some next steps:

- Explore the functions available through the Wi-SUN CLI example. In the Serial 1 console connected to a device running the example, enter wisun help to see a list of commands.  Enter wisun get wisun to see a list of Wi-SUN network parameters.
- Compile and flash different sample applications and explore the functionality they provide.
- Explore configuring one of the sample applications to meet your needs.
- Explore the documentation provided in this site.

[Going Further](/wisun/2.12.0/wisun-getting-started-development/04-wisun-going-further) provides other suggestions once you have created a network.

### Going Further

After creating a Wi-SUN Network, this section is a guide toward the next steps in exploring the Silicon Labs Wi-SUN solution.

- [**Wi-SUN Border Router GUI**](/wisun/2.12.0/wisun-border-router-gui): Under Wi-SUN Border Router, this section presents the Wi-SUN Border Router Dashboard that can be used to configure the Wi-SUN Linux Border router and visualize the Wi-SUN Network.
- **Development Tools**: The development tools below are provided within Simplicity Studio as well as third party.

#### Simplicity Platform

The Simplicity Platform is a set of drivers and other lower layer features that interact directly with Silicon Labs chips and modules. Simplicity Platform components include EMLIB, EMDRV, RAIL Library, NVM3, and MbedTLS. For more information about Simplicity Platform, see release notes that can be found in SSv5’s Documentation tab, as well as online API documentation at [https://docs.silabs.com/](https://docs.silabs.com/).

#### Simplicity Commander

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple Command Line Interface (CLI) that is also scriptable. Simplicity Commander enables customers to complete essential tasks such as configuring and building applications and bootloaders and flashing images to their devices. Simplicity Commander is available through Simplicity Studio or can be downloaded through [system-specific installers](https://www.silabs.com/developers/mcu-programming-options#programming). The [**Simplicity Commander Reference Guide**](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) provides more information.

![Simplicity Commander](/wisun-getting-started-development/0.3/images/sld124-image33.png)

#### Pin Tool

Simplicity Studio 5 offers a Pin Tool that allows you to easily configure new peripherals or change the properties of existing ones. In the Project Configurator **SOFTWARE COMPONENTS** tab, expand the **Advanced Configurators** group and open the Pin Tool. The graphical view differs based on the chip.

![The pin tool view 1](/wisun-getting-started-development/0.3/images/sld124-pintool-start.png)

The pin, function, and peripheral tabs in the configuration pane provide different modes of access. A search function is also provided.

Use the Pin Tool to modify the pin configuration of the device. Software components control behavior in the project but must be associated with a peripheral, and generally need pin or function assignments. These pin or function assignments are most easily edited in the Component Editor for that component. The Pin Tool allows you to assign functions to pins. On all three dialogs, click **EDIT** next to a software component to go directly to the Component Editor for that component. Click **NEW** to go to the Project Configurator's SOFTWARE COMPONENTS tab, where you can install a component in the project so that it can be selected in the dialog.

For more information, see the [Simplicity Studio 5 User's Guide Pin Tool section](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-developing-with-project-configurator/pin-tool).

#### Developer's Guide

The [Wi-SUN Developer's Guide](/wisun/2.12.0/wisun-developers-guide) explores the different Wi-SUN roles and IP communication concepts, combining theory and practice through various examples. It also demonstrates several tools used to visualize and debug Wi-SUN networks.

#### Silicon Labs Configurator (SLC)

SLC offers command-line access to application configuration and generation functions. [**Software Project Generation and Configuration with SLC-CLI**](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-slc-cli/) provides instructions on downloading and using the SLC-CLI tool.

#### IAR IDE

To get a 30-day evaluation license for IAR-EWARM:

1. Go to the Silicon Labs support portal at [https://www.silabs.com/support](https://www.silabs.com/support).
2. Scroll down to the bottom of the page, and click **Contact Support**.
3. If you are not already signed in, sign in.
4. Click the **Software Releases** tab. In the View list, select **Development Tools**. Click **Go**. In the results is a link to the IAR-EWARM version named in the release notes.
5. Download the IAR package (takes approximately 1 hour).
6. Install IAR.
7. In the IAR License Wizard, click **Register with IAR Systems to get an evaluation license**.
8. Complete the registration and IAR will provide a 30-day evaluation license.
9. Once IAR-EWARM is installed, the next time Simplicity Studio starts, it will automatically detect and configure the IDE to use IAR-EWARM.

## Wi-SUN Developer's Guide

### Overview

Silicon Labs provides a certified **Wi-SUN FAN 1.1** solution, delivered as a precompiled stack library (available for GCC and IAR).

|**Profile (Library)**|**Linux Border Router**|**Soc Border Router**|**FFN**|**LFN**|
|---|---|---|---|---|
|Border Router (`libwisun_border_router_efr32xg2x_xxx.a`)| |✔️| | |
|FFN (`libwisun_ffn_efr32xg2x_xxx.a`)| | |✔️| |
|Full (`libwisun_full_efr32xg2x_xxx.a`)| | |✔️|✔️|
|LFN (`libwisun_lfn_efr32xg2x_xxx.a`)| | | |✔️|
|MAC Co-Processor (`libwisun_mac_efr32xg2x_xxx.a`)|✔️| | | |
|RCP Co-Processor (`libwisun_rcp_efr32xg2x_xxx.a`)|✔️| | | |

> **Note:** The **MAC** and **RCP** libraries target the EFR32 Radio Co-Processor (RCP). When combined with a **Linux host** running the Wi-SUN stack, they form a **Linux Border Router**.

This developer guide offers step-by-step instructions to set up and configure different Wi-SUN node types using the provided examples.<br />It also demonstrates communication over the network using various transport and application layer protocols (**UDP/TCP** and **COAP**).

![Wi-SUN Architecture](/wisun-developers-guide/0.1/images/sld871-wisun-archi.png)

> **Note**: The Wi-SUN stack depends on the **RAIL** library, which is responsible in interfacing the Hardware Radio and upper layer. It also depends on **Mbed TLS** third party enabling security with PSA and hardware acceleration.

#### Summary

- [**Border Router**](/wisun/2.12.0/wisun-border-router-overview)

The **Border Router** section explains how to set up and configure both **Linux-based** and **SoC-based Border Routers**.

- [**Router (FFN)**](/wisun/2.12.0/wisun-router-ffn)

This section covers how to set up and configure a **Router (FFN)** to extend coverage and manage traffic.

- [**LFN**](/wisun/2.12.0/wisun-lfn)

For low-power device use cases, this section provides a guide to set up and configure a **Limited Function Node (LFN)**.

- [**Platform Resources**](/wisun/2.12.0/wisun-platform-resources-overview)

This section focuses on **hardware resources and system utilities** used by the Wi-SUN stack and applications.

- [**Network Performance**](/wisun/2.12.0/wisun-performance-overview)

To help developers optimize deployments, this section describes tools and methodologies for **measuring PAN performance** and testing with the **Wi-SUN Network Measurement Application**.

- [**Silabs Tools**](/wisun/2.12.0/wisun-configurator)

A dedicated section highlighting tools that accelerate development and debugging workflows.

- [**Development Walkthrough**](/wisun/2.12.0/wisun-dev-walkthrough-overview)

A practical **step-by-step workflow** that bridges the gap between architecture and hands-on implementation.

- [**FAN Certification**](/wisun/2.12.0/wisun-fan-node-certification)

**Guide** to help certify Silicon Labs devices for Wi-SUN FAN 1.1.

### Router (FFN)

#### Introduction

The Wi-SUN FAN stack supports router nodes, which are a type of Full Function Node (FFN). As described in the specification, a router must support the following functionalities:

- Join network and communicate with other nodes securely through authentication, encryption, and key management.
- Forward packets between nodes and toward the border router following RPL protocol.
- Maintain links with neighboring nodes and manage network topology with self-healing capabilities.
- Extend the network by enabling parent-child relationships with other nodes.

##### Architecture

Once router nodes have joined the network, they enable parent-child relationships with other nodes both inside and outside the network. A router advertises network information and can establish parent-child links with new routers and/or LFNs (starting from FAN 1.1), provided they meet authentication requirements.

![Sample Routed FAN](/wisun-router-ffn/0.1/images/sld979-pan1-1.png)

##### Router Characteristics

- Router evaluates the overall link quality with the Border Router and switches to a new parent in the network if necessary. Router can also transmit this information to potential new child, allowing them to choose the best parent following RPL protocol.
- Router performs continuous listening with channel hopping following Wi-SUN PAN PHY configuration. Since the router is always listening, it cannot enter deep sleep mode and achieve the ultra-low power capabilities of an LFN.
- Router receives and transmits multicast message following broadcast interval imposed by Border Router. It includes forward multicast messages to neighbors following MPL protocol.
- The main difference between a Router and a Border Router is that the Router does not maintain source routing tables for all nodes within its PAN. Instead, it maintains a limited routing table containing its child nodes and its primary and secondary parents. To communicate with unknown address, the router forwards packets upward to the border router, which maintains routing information for all nodes in the network. Then the packet is forwarded downward to the targeted node on the FAN network or outside FAN depending of address.

#### Supported Hardware

Router feature is supported on all the Wi-SUN capable devices listed at [Wi-SUN Wireless SoCs](https://www.silabs.com/wireless/wi-sun).

#### Router Node in Silicon Labs Wi-SUN Stack

The Wi-SUN Stack fully supports Router FFN.

On the latest SiSDK, Router nodes are supported on the following sample apps by default:

- **Wi-SUN – CLI example**
- **Wi-SUN – SoC Coap Collector**
- **Wi-SUN – SoC Coap Meter**
- **Wi-SUN – SoC Network Measurement**
- **Wi-SUN – SoC Ping**
- **Wi-SUN – SoC Socket**
- **Wi-SUN – SoC Empty**

##### Router Configuration

The **Wi-SUN - CLI example** supports changing the device settings using the command line interface. Router can also be settled through the **Wi-SUN configurator** and API.

> **Note**: In your project, ensure that **Wi-SUN Stack FFN Support** component is installed.![Sample Routed FAN](/wisun-router-ffn/0.1/images/sld979-stack-ffn-support-component.png)

###### Device Type

By default, the device type is configured as FFN. To change the device type, use the following command that allows setting the device type to either **LFN** or **FFN**:

```c
wisun set wisun.device_type FFN
```

```C
#Related API: 
sl_status_t sl_wisun_set_device_type(sl_wisun_device_type_t device_type);
```

> **Note**: For this command to take effect after a join either as an FFN or an LFN, a board reset is mandatory.

###### Network Size

The Network Size can also be set through the command line, using the following command that allows choosing between three sizes:

- **small**: Less than 100 nodes.
- **medium**: 100 to 800 nodes.
- **large**: 800 to 1500 nodes.

```c
wisun set wisun.network_size small
```

```C
#Related API: 
sl_status_t sl_wisun_set_connection_parameters(const sl_wisun_connection_params_t *params);
```

> **Note**: The Network Size parameter allows automatic customization of connection settings. Depending on the number of devices in the network, these parameters should be adjusted to maintain reliable connection. All devices in the network must use the same Network Size (same connection parameters) value to ensure consistency and stability. The Larger the network is, the longer the join time is.

###### Unicast Dwell Interval

Dwell interval refers to the amount of time a device stays on a specific frequency channel before hopping to the next one in a frequency-hopping sequence.

```c
CLI:
[interval] = [15,255] ms
wisun set wisun.unicast_dwell_interval [interval]
```

```C
#Related API: 
sl_status_t sl_wisun_set_unicast_settings(uint8_t dwell_interval_ms);
```

###### Routers LFN Parenting

To support LFN parenting introduced in FAN1.1, Router should belong FAN1.1 PAN with LFN parenting enabled over PAN (set by Border Router).

On the SiSDK 2025.6.0 and later, LFN parenting is supported by all FFN and Border Router devices.

The number of supported LFNs by each FFN is 10 by default on all applications supporting LFN parenting.

```c
CLI:
wisun set_lfn_support [Max number of LFNs]
```

```C
#Related API: 
sl_status_t sl_wisun_set_lfn_support(uint8_t lfn_limit);
```

The maximum number of LFN nodes that can be supported by an FFN is 10.

##### Using Wi-SUN Configurator

Except for the **Wi-SUN - SoC CLI example**, the other sample applications support the [Wi-SUN Configurator Application panel](/wisun/2.12.0/wisun-configurator).

- Router's available configuration  
  - Network Name  
  - Network Size  
  - Unicast Dwell Interval  
  - TX output Power  
  - Broadcast Retransmissions

### Wi-SUN Limited Function Nodes (LFN)

#### Introduction

The Wi-SUN FAN stack supports Limited Function Node (LFN) functionalities specified in the Wi-SUN FAN Technical Profile Specification version 1.1v06. The Limited Function Nodes as described in the specification must support low power operations:

- The MAC must allow for LFN battery life of 20 years.
- The MAC must support a less than 2 minute response for LFNs.
- Multicast operations must minimize LFN power consumption.

##### Architecture

LFNs provide minimum capabilities like discovering/joining a PAN and sending/receiving IPv6 packets. LFNs also implement the same communication stack as a Full Function Node (FFN) with a limited listening schedule to conserve power. But it can only operate within a PAN rooted at a FAN 1.1 Border Router (LFN is not part of the FAN 1.0 specification) as a child of a FAN 1.1 Router and not a parent to any other node. See the following figure.

![Sample Routed FAN](/wisun-lfn/0.2/images/pan1-1.png)

##### LFN Characteristics

An LFN employs different mechanisms than those used by an FFN to communicate, do routing, and secure the association with the border router.

- An LFN operates as an RPL Unaware Leaf (RUL) node, which differs from an FFN in that an LFN does not implement RPL routing and relies on a parent RPL Router to provide routing capability.
- LFNs employ a sampled listening technique rather than the continuous listening performed by an FFN.
- LFN’s security associations with the Border Router are substantially longer lived than those of an FFN because FFNs and LFNs use separate sets of group keys (GTK / LGTK, respectively), with longer lifetimes for the LFN group keys.

Those characteristics help an LFN meet the required low power capabilities described in the Wi-SUN FAN Specification.

#### Supported Hardware

LFN feature is supported on all the Wi-SUN capable devices listed at [Wi-SUN Wireless SoCs](https://www.silabs.com/wireless/wi-sun). However, the power optimization capabilities are only supported on the **EFR32FG28** (BRD4401C) and **EFR32ZG28** (BRD4400C) as the other Wi-SUN Wireless SoCs have low energy consumption limitations in EM2 DeepSleep energy mode.

#### LFN in Silicon Labs Wi-SUN Stack

The Wi-SUN Stack implements all the necessary mechanisms for an LFN to be able to join a Wi-SUN Network. Also, it supports Multicast and the power optimization capabilities.

On the latest SiSDK, LFNs are supported on the following sample apps by default:

- **Wi-SUN – LFN CLI example**
- **Wi-SUN – CLI example**
- **Wi-SUN – SoC Coap Meter**
- **Wi-SUN – SoC Network Measurement**
- **Wi-SUN – SoC Ping**
- **Wi-SUN – SoC Socket**
- **Wi-SUN – SoC Empty**

##### LFN Power Management

The Wi-SUN stack supports LFN power management capabilities in SiSDK 4.3.1 and later. This feature allow the LFNs to go into sleep in EM2 mode, with an average consumption of **5.23 µA** with the **EFR32FG28** (BRD4401C) and **EFR32ZG28** (BRD4400C).

> **Note**: The EFR32FG28 version BRD4401B and the EFR32ZG28 version BRD4400B have hardware limitations that keep them from entering sleep mode EM2.

This power optimization level comes with some challenges, especially the CLI UART clock that we use in our sample applications. For the **Wi-SUN – LFN CLI example**, the project configures the CLI UART to use the Low-Frequency clock to be able to use the CLI in a low speed of 9600 Bauds without preventing the LFN from entering the sleep mode EM2.

For the rest of the examples, this configuration has to be done manually on the software component perspective after creating the project. Follow the next steps to disable the UART high frequency clock and enable the power management capabilities:

1. Open the slcp file and click the **SOFTWARE COMPONENTS**. Then use the search bar to look for the **Power Manager** component and click **Install**.  
   ![Power Manager Component ](/wisun-lfn/0.2/images/power-manager-component.png)
2. Use the search bar to look for **IO Stream: EUSART** and click the on the configuration icon in front of _vcom_:  
   - Switch off **Enable High Frequency mode**.  
   - Set the Baud rate to 9600.  
   - Switch off **Restrict the energy mode to allow the reception** if enabled.  
   ![IO Stream: EUSART Configuration ](/wisun-lfn/0.2/images/io-stream-configuration.png)
3. Search for the **Micrium OS Kernel** component and click the configuration icon:  
   - Switch off **Enable Round-Robin scheduling**.  
   - Switch off **Enable statistics gathering task**.  
   - Switch off **Enable task profiling instrumentation**.

After configuring the project to enter the sleep mode EM2, configure the WPK to use 9600 vcom baud rate speed following the next steps:

1. On the Debug Adapter perspective, right-click on your board and click **Launch Console**.
2. Click the **Admin** tab of the Console panel.
3. Enter the command `serial vcom config speed 9600`.

> **Note**: This is a persistent configuration and it might be necessary to restore the previous value if the same WPK is used with any other CLI application. To do that, enter the command `serial vcom config speed 115200`.

##### LFN Configuration Using the CLI

The **Wi-SUN - SoC CLI example** supports changing the device type and the device profile using the command line interface. By default, the device type is configured as FFN. To change the device type, use the following command that allows setting the device type to either **LFN** or **FFN**:

```c
wisun set wisun.device_type LFN
```

> Note: For this command to take effect after a join either as an FFN or an LFN, a board reset is mandatory.

The device profile can also be set through the command line, using the following command that allows choosing between three profiles:

- **Test:** Used for testing the LFNs performance.
- **Balanced:** Balance between LFNs performance and battery life.
- **Eco:** Profile for high battery life performance.

```c
wisun set wisun.device_profile balanced
```

> **Note**: The profiles defined above focus on defining different time slots and intervals for the [LFN parameters](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-lfn-params-t) to optimize performance and battery life. These three predefined modes are just for reference, and it is up to the customer to fine tune the parameters to adapt the LFN behavior to the application use case. The three profiles are defined under [protocol/wisun/stack/inc/sl_wisun_lfn_params_api.h](https://github.com/SiliconLabsSoftware/sisdk-release/blob/sisdk-2025.12/wisun/stack/inc/sl_wisun_lfn_params_api.h).

##### Enabling LFN Using Wi-SUN Configurator

Except for the **Wi-SUN - LFN CLI example** and **Wi-SUN - SoC CLI example**, the other sample applications supporting LFN, by default, use **Wi-SUN Configurator** to enable LFN device type.

Once the project is created, the device type is set by default to FFN. To change the device type to LFN, go to the **Application** panel on the **Wi-SUN Configurator** and, under the **Device information** section, change the **Device Type** of the node to **LFN**.

![LFN Device Type](/wisun-lfn/0.2/images/lfn-device.png)

> **Note**: if you cannot select LFN in device type, ensure component **Wi-SUN Stack LFN Support** is installed. This component is currently marked as Evaluation quality.

###### LFN Device Profiles

When LFN is selected in the **Device Type** dropdown, a dropdown named **Device Profile** is exposed on the Wi-SUN Configurator Application's panel to allow choosing from three device profiles: **Test**, **Balanced**, and **Eco**.

#### LFN Parenting

An LFN operates as an RPL Unaware Leaf (RUL) node, which means that an LFN does not implement RPL routing and relies on its parent Border Router or FFN to provide routing capability. In other words, LFNs won't be able to join the Network in the following cases:

- If the Border router doesn't support LFN parenting.
- If the Border router supports LFN parenting and the LFN parent does not support LFN parenting.
- If the Border router doesn't support LFN direct parenting and there is no router that supports LFN parenting which the LFN can join.

##### Routers LFN Parenting

On the SiSDK 2025.6.0 and later, LFN parenting is supported by all FFN and Border Router devices.

The number of supported LFNs by each FFN is 10 by default on all the applications supporting LFN parenting. On **Wi-SUN - CLI example**, this number can be changed using the following command:

```c
wisun set_lfn_support [Max number of LFNs]
```

Note that `Max number of LFNs` will be accepted as-is, but the actual LFN capacity will always be capped by the neighbor's table size. Ensure that `sl_wisun_config_neighbor_table` is configured appropriately to support the desired number of LFNs.

##### Border Routers LFN Parenting

###### Wi-SUN - SoC Border Router

LFN parenting is enabled by default on **Wi-SUN SoC Border Router**. To disable LFN support on the PAN, set _**lfn_support_pan**_ to _**0**_ using the following command:

```c
wisun set_lfn_support [lfn_limit] [lfn_support_pan]
```

The `lfn_limit` argument defines the number of LFNs that the Border Router SoC can support locally. By default, it is set to 10, but you can request higher values if your neighbor table configuration supports it.

For a better LFN device battery performance and synchronization with the Border Router SoC, the LFN device profiles have to be set also on the Border Router side using the following command:

```c
wisun set wisun.lfn_profile [device profile]
```

###### Wi-SUN Border Router Linux

The wisun-br-linux version 1.6 and later supports LFN direct parenting by default. And it has no option to set a maximum number of LFN devices that can connect directly to the border router.

###### LFN Support in The PAN Network (heading level 7)

In version 1.7, a new configuration option was added to the configuration file [wsbrd.conf](https://github.com/SiliconLabs/wisun-br-linux/blob/main/examples/wsbrd.conf) named `enable_lfn` to allow enabling or disabling LFN devices support in the PAN Network, hence disabling the LFN parenting.

###### LFN Profiles (heading level 7)

Unlike the **Wi-SUN - SoC Border Router** that has predefined LFN device profiles, the **Wi-SUN Border Router Linux** introduces two configuration options, `lfn_broadcast_interval` and `lfn_broadcast_sync_period` in [wsbrd.conf](https://github.com/SiliconLabs/wisun-br-linux/blob/main/examples/wsbrd.conf) to allow synchronizing the LFN broadcast listening windows and the number of LFN broadcast intervals to optimize the power consumption by the LFN devices.

> **Note**: The [wisun-br-linux](https://github.com/SiliconLabs/wisun-br-linux) supports LFN parenting by default with a limitation of not supporting direct parenting of LFNs on the wisun-br-linux versions 1.5 to 1.5.4. To connect an LFN to wisun-br-linux using one of those versions, an FFN connected to the network and supporting LFN parenting is mandatory.

### Wi-SUN FAN 1.1 Node Certification

#### Introduction

This page provides a guide to help certify Silicon Labs devices for Wi-SUN FAN 1.1.<br />For details about the certification process itself, see the [Wi-SUN Alliance Certification Process page](https://wi-sun.org/certification-process/).

Silicon Labs recommended versions for certification:

| |**FAN 1.1**|**FAN 1.0**|
|---|---|---|
|Stack Version|2.8.0 or later|2.10.0 or later|
|Linux Border Router Tag|v2.7.1 or later|v2.7.1 or later|

Wi-SUN FAN 1.1 nodes must be certified as **FAN 1.1 Core**, with optional certification features for **High Performance (HP)** and **Low Energy (LE)** (LE certification not yet available).

- **FAN 1.1 Core (FAN 1.0+)**: Addition of the FFN-wide, PAN-wide Information Elements.  
  |**FAN 1.1 Core**|**BR**|**R**|**LFN**|  
  |---|---|---|---|  
  |PAN-wide IE|M|M|-|  
  |MAC-Command Mode Switch|O|O|-|  
  |PHY Mode Switch|O|O|-|  
  |LFN Parenting|-|-|-|  
  |LFN features|-|-|-|  
  |FSK|M*|M*|-|  
  |OFDM|-|-|-|
- **FAN 1.1 Core + HP**: Adds SUN-OFDM PHYs and PHY Mode Switch.  
  |**FAN 1.1 Core + HP**|**BR**|**R**|**LFN**|  
  |---|---|---|---|  
  |PAN-wide IE|M|M|-|  
  |MAC-Command Mode Switch|O|O|-|  
  |PHY Mode Switch|M|M|-|  
  |LFN Parenting|-|-|-|  
  |LFN features|-|-|-|  
  |FSK|M*|M*|-|  
  |OFDM|M*|M*|-|
- **FAN 1.1 Core + LE**: Introduces Limited Function Nodes (LFNs). Border Routers and Routers must support LFN parenting. LFNs act as leaf nodes only and cannot serve as routers.  
  |**FAN 1.1 Core + HP**|**BR**|**R**|**LFN**|  
  |---|---|---|---|  
  |PAN-wide IE|M|M|O|  
  |MAC-Command Mode Switch|O|O|O|  
  |PHY Mode Switch|O|O|O|  
  |LFN Parenting|M|M|-|  
  |LFN features|-|-|M|  
  |FSK|M*|M*|M*|  
  |OFDM|O|O|O|

> * At least the mandatory data rate modes

#### Certification Test Configuration

Wi-SUN Alliance define several settings for certification test DUT (Device under test):

- Keys and certificates
- Network Name
- Network Size
- PHY settings: Depending on the test, the DUT must adapt its configuration to match one of the **channel plans** according to the **tested region**.

**Channel Plan 0 Fixed Channel**

|Region|Operating Class|FSK Operating Mode|Channel|
|---|---|---|---|
|NA|1|1b|10|
|BZ|1|1b|10|
|JP|2|2b|10|

**Channel Plan 0 DH1CF**

|Region|Operating Class|FSK Operating Mode|
|---|---|---|
|NA|2|3|
|BZ|2|3|
|JP|2|2b|

**Channel Plan 2 Fixed Channel**

|Region|Channel Plan ID|PHYModeID|Channel|
|---|---|---|---|
|NA|1|2 (FSK 1b)|10|
|BZ|1|2 (FSK 1b)|10|
|JP|22|4 (FSK 2b)|10|

**Channel Plan 2 DH1CF**

|Region|Channel Plan ID|PHYModeID|
|---|---|---|
|NA|2|5 (FSK 3)|
|BZ|2|5 (FSK 3)|
|JP|22|4 (FSK 2b)|

**Channel Plan HP Mode Switch**: (optional only for **High Performance (HP)**)

|Region|Mode|Base PhyModeID|Base ChanPlanID|Base Channel|Switched PhyModeID|Switched ChanPlanID|Switched Channel|
|---|---|---|---|---|---|---|---|
|NA|FSK-FSK|2 (FSK 1b)|1|24|5 (FSK 3)|2|12|
|BZ|FSK-FSK|2 (FSK 1b)|1|12|5 (FSK 3)|2|5|
|NA|FSK-OFDM|2 (FSK 1b)|1|24|38 (OFDM Option 1 MCS 6)|5|3|
|JP|FSK-OFDM|4 (FSK 2b)|22|4|86 (OFDM Option 4 MCS 6)|21|10|
|BZ|FSK-OFDM|2 (FSK 1b)|1|12|38 (OFDM Option 1 MCS 6)|5|0|
|NA|OFDM-OFDM|86 (OFDM Option 4 MCS 6)|1|7|84 (OFDM Option 4 MCS 4)|1|7|
|JP|OFDM-OFDM|86 (OFDM Option 4 MCS 6)|21|9|84 (OFDM Option 4 MCS 4)|21|9|
|BZ|OFDM-OFDM|86 (OFDM Option 4 MCS 6)|1|7|84 (OFDM Option 4 MCS 4)|1|7|

#### Router Certification

##### Installing Wi-SUN FAN Certification Component

To help certify your product, the **Wi-SUN FAN Certification** component can only be used with the **Wi-SUN - CLI example**, which sets up the Wi-SUN Alliance certification configuration.

Follow these steps to add the **Wi-SUN FAN Certification** component to your application:

1. Open Simplicity Studio 5 and choose your board in **Debug Adapter**.
2. In the **Launcher** perspective, click **EXAMPLE AND PROJECT**.
3. Filter by _Wi-SUN_ under **Wireless Technology** and create the **Wi-SUN - CLI example** app.  
   ![Screenshot highlighting the create button for the Wi-SUN CLI Example](/wisun-fan-node-certification/0.1/images/sld985-sample-app-creation.png)
4. After creating the project, open _wisun_soc_cli.slcp_ and click **Software Component**.
5. Enter _wisun_ in the search bar to filter the components and install the **Wi-SUN FAN Certification** component.  
   ![Screenshot highlighting the Install button for Wi-SUN FAN Certification](/wisun-fan-node-certification/0.1/images/sld985-component-instalation.png)
6. Build the project and flash it to the board.

##### Add PHY with Wi-SUN Configurator

Depending on the tested region and the optional certification features, the DUT must support different PHY settings as described in the channel plans in [Certification Test Configuration](#certification-test-configuration).

To switch between PHY settings, they must first be added in the [Wi-SUN Configurator](/wisun/2.12.0/wisun-configurator/#radio-panel).

##### Changing the Connection Settings and Run Tests

The Wi-SUN Conformance Tests specification defines tests to pass the **Wi-SUN FAN 1.1 Certification**, and describes the required settings for each test.

The **Wi-SUN FAN Certification** component sets by default the network name, network size, keys and certificates compatible with test bed. Some settings change between tests like PHY settings. Review the advice below to modify settings and join network as router.

**Before each test:**

- Ensure DUT is disconnected​:  
  ```c  
  > wisun disconnect​  
  ```
- Reset previous configuration​:  
  ```c  
  > wisun reset  
  ```
- Clear DUT’s cache memory​:  
  ```c  
  > wisun ccc​  
  ```
- Set the DUT’s settings as described in the test, for example:  
  ```c  
  > wisun set wisun.network_name "WiSUN PAN"  
  > wisun set wisun.keychain_index 0  
  ```  
  - By default, the component installs Wi-SUN Alliance Test certificates but for test case 6.4.2 SEC-TLS-TERMINATE-2, select the Silabs Certificate Chain with​:    
    ```c    
    > wisun set wisun.keychain_index 1​    
    ```
- Set DUT’s PHY settings as described in the test and join:  
  - For a test requiring **Channel Plan 0 Fixed Channel** and DUT testing NA regulatory:    
    ```c    
    > wisun set wisun.regulatory_domain NA    
    > wisun set wisun.operating_class 1    
    > wisun set wisun.operating_mode 0x1b    
    > wisun set wisun.allowed_channels "10"    
    > wisun join_fan10    
    ```  
  - For a test requiring **Channel Plan 0 DH1CF** and DUT testing BZ regulatory:    
    ```c    
    > wisun set wisun.regulatory_domain BZ    
    > wisun set wisun.operating_class 2    
    > wisun set wisun.operating_mode 0x3    
    > wisun set wisun.allowed_channels "0-255"    
    > wisun join_fan10    
    ```  
  - For a test requiring **Channel Plan 2 Fixed Channel** and DUT testing NA regulatory:    
    ```c    
    > wisun set wisun.regulatory_domain NA    
    > wisun set wisun.chan_plan_id 0x1    
    > wisun set wisun.phy_mode_id 2    
    > wisun set wisun.allowed_channels "10"    
    > wisun join_fan11    
    ```  
  - For a test requiring **Channel Plan 2 DH1CF** and DUT testing NA regulatory:    
    ```c    
    > wisun set wisun.regulatory_domain NA    
    > wisun set wisun.chan_plan_id 0x2    
    > wisun set wisun.phy_mode_id 5    
    > wisun set wisun.allowed_channels "0-255"    
    > wisun join_fan11    
    ```  
  - (Optional HP) For a test requiring **Channel Plan HP Mode Switch**:    
    The DUT’s settings must be configured with the `wisun set $Parameter$` command, according to the appropriate tables for the tested region:    
    **Region NA**    
    |Parameter|Channel Plan 2 Fixed Channel|Channel Plan 2 DH1CF|FSK-FSK Mode Switch|FSK-OFDM Mode Switch|OFDM-OFDM Mode Switch|    
    |---|---|---|---|---|---|    
    |**wisun.regulatory_domain**|NA|NA|NA|NA|NA|    
    |**wisun.chan_plan_id**|1|2|1|1|1|    
    |**wisun.phy_mode_id**|2|5|2|2|86|    
    |**wisun.allowed_channels**|10|0-255|24|24|7|    
    |**wisun.rx_mdr_capable**|0|0|1|1|1|    
    |**wisun.rx_phy_mode_ids**| | |5|38|84|    
    **Region BZ**    
    |Parameter|Channel Plan 2 Fixed Channel|Channel Plan 2 DH1CF|FSK-FSK Mode Switch|FSK-OFDM Mode Switch|OFDM-OFDM Mode Switch|    
    |---|---|---|---|---|---|    
    |**wisun.regulatory_domain**|BZ|BZ|BZ|BZ|BZ|    
    |**wisun.chan_plan_id**|1|2|1|1|1|    
    |**wisun.phy_mode_id**|2|5|2|2|86|    
    |**wisun.allowed_channels**|10|0-255|12|12|7|    
    |**wisun.rx_mdr_capable**|0|0|1|1|1|    
    |**wisun.rx_phy_mode_ids**| | |5|38|84|    
    **Region JP**    
    |Parameter|Channel Plan 2 Fixed Channel|Channel Plan 2 DH1CF|FSK-FSK Mode Switch|FSK-OFDM Mode Switch|OFDM-OFDM Mode Switch|    
    |---|---|---|---|---|---|    
    |**wisun.regulatory_domain**|JP|JP|N/A|JP|JP|    
    |**wisun.chan_plan_id**|22|22|N/A|22|21|    
    |**wisun.phy_mode_id**|4|4|N/A|4|86|    
    |**wisun.allowed_channels**|10|0-255| |4|9|    
    |**wisun.rx_mdr_capable**|0|0| |1|1|    
    |**wisun.rx_phy_mode_ids**| | | |86|84|    
    Then join network with `wisun join_fan11` command.

> **Note**: If an error is returned after the join command, ensure that your PHY setting configuration is added. Check [Add PHY with Wi-SUN Configurator](#add-phy-with-wi-sun-configurator).

**After this step device should join the certification network.**

- Test case 6.3.1.4.1 MULTICAST-ORIGINATOR-1 asks the DUT to send a multicast frame​

```c
> wisun ping ff03::1​
```

- Stop the DUT​:

```c
> wisun disconnect
```

#### Border Router Certification

##### Linux Border Router Certification

Follow this [Linux BR DUT guide](https://github.com/SiliconLabs/wisun-br-linux/blob/main/tools/dut/README.md).

### Border Router

#### Wi-SUN Border Router

A Wi-SUN Border Router oversees network management (authentication, routing, and so on). Border Router also connects a Wi-SUN mesh network to other IP-based networks (for example Ethernet). It provides routing and network services for Wi-SUN devices and can be implemented in several ways depending on hardware and deployment needs.

Below is a brief overview and quick index of available Border Router solutions.

- [**Linux Border Router (wsbrd)**](/wisun/2.12.0/wisun-linux-border-router): Production-grade Linux implementation using a Raspberry Pi (or similar) paired with an RCP device. Includes wsbrd, configuration and deployment notes.
- [**SoC Border Router**](/wisun/2.12.0/wisun-soc-border-router): Standalone Border Router running on an EFR32 SoC, useful for embedded deployments without a separate host.
- [**SoC Border Router — Backhaul Options**](/wisun/2.12.0/wisun-soc-border-router-backhaul): Details on backhaul interfaces (Ethernet, cellular, etc.) and how to connect the SoC Border Router to external networks.
- [**Wi‑SUN IP Communication**](/wisun/2.12.0/wisun-ip-communication): Guidelines for IP-level operations with the Linux Border Router (pinging Wi‑SUN nodes, routing checks, diagnostics).  
  Production-grade Linux implementation using a Raspberry Pi (or similar) paired with an RCP device. Includes wsbrd, configuration and deployment notes.
- **[SoC Border Router](/wisun/2.12.0/wisun-soc-border-router)**  
  Standalone Border Router running on an EFR32 SoC — useful for embedded deployments without a separate host.
- **[SoC Border Router — Backhaul Options](/wisun/2.12.0/wisun-soc-border-router-backhaul)**  
  Details on backhaul interfaces (Ethernet, cellular, etc.) and how to connect the SoC Border Router to external networks.
- **[Wi‑SUN IP Communication](/wisun/2.12.0/wisun-ip-communication)**  
  Guidelines for IP-level operations with the Linux Border Router (pinging Wi‑SUN nodes, routing checks, diagnostics).

#### Wi-SUN SoC Border Router

The Silicon Labs Wi-SUN SoC Border Router provides a production-grade Wi-SUN Border Router implementation running entirely on the EFR32. This solution enables an efficient and cost-effective way to evaluate and deploy the Silicon Labs Wi-SUN stack, eliminating the need for expensive and complex external hardware. A Command Line Interface (CLI) is available to facilitate easy configuration and management.

![Wi-SUN SoC Border Router Demonstration](/wisun-soc-border-router/0.1/images/sld994-image1.png)

##### Getting Started with the Solution

The Wi-SUN SoC Border Router project creates a Wi-SUN network that the Wi-SUN nodes can connect to. For an out-of-the-box experience, use the **Wi-SUN – SoC Border Router** Demo instead of creating and building the **Wi-SUN – SoC Border Router** project.

To get started with the demonstration, follow these steps:

1. In the Debug Adapters view, select the device to be used as the Border Router.
2. Navigate to the **EXAMPLE PROJECTS & DEMOS** tab and turn off the Example Projects filter.
3. Click **RUN** next to the **Wi-SUN – SoC Border Router** project. The project is flashed to your board.
4. In the Debug Adapter view, right click your chosen device, and click **Launch Console**.  
   ![Screenshot of Launch Console option](/wisun-soc-border-router/0.1/images/sld994-image2.png)
5. Start the Border Router with default FAN 1.1 PHY using the following command:

```c
> wisun start_fan11
```

##### Wi-SUN SoC Border Router Configuration

The application provides a command-line interface to control basic configurations. To see the available commands, enter the following command in the console:

```C
> wisun help
```

The list of available commands is output on the console with the associated help. Wi-SUN SoC Border Router comes with a list of default PHYs. To add other PHYs to the application, create the **Wi-SUN – SoC Border Router** project and use the Wi-SUN Configurator.

##### Going Further

For more customization and to adapt the application to your specific use case, use the **Wi-SUN – SoC Border Router** project instead of the demo. This allows you to modify, extend, and tailor the features of the Wi-SUN SoC Border Router to meet your unique requirements effectively.

For an advanced SoC Border router solution with Wi-Fi backhaul connection support, see [SoC Border Router Wi-Fi Backhaul](/wisun/2.12.0/wisun-soc-border-router-backhaul).

#### SoC Border Router with Wi-Fi Backhaul

The Wi-SUN SoC Border router supports backhaul connection, using the two APIs `sl_wisun_br_set_ipv6_up_handler()` and `sl_wisun_br_ipv6_down()`. With `sl_wisun_br_set_ipv6_up_handler()` API, a host can register a callback to handle IPv6 packets from the Wi-SUN Network to forward them to internet. And with the `sl_wisun_br_ipv6_down()` API, the host can inject IPv6 packets to the Wi-SUN Network.

For the purpose of demonstrating this feature, a standalone project has been added to the list of Wi-SUN applications. The **Wi-SUN - SoC Border Router - with SiWx917 Wi-Fi backhaul** as its name indicates, relies on the **SiWx917** Wi-Fi board to open a backhaul interface on the Wi-SUN SoC Border Router. The LwIP stack is used as the host IP stack of this project because of its integration, ease-of-use, and most importantly, the IPv6 packet forwarding.

The SoC Border Router with backhaul connectivity enables the use of an external DHCPv6 server. So in addition to the support of the internal DHCPv6 server that makes from the SoC Border router an out-of-the-box solution that can be evaluated on the fly, it also becomes possible to scale the border to a production-grade solution that can fit in larger and complex networks, thanks to the external DHCPv6 server feature support.

The demonstration relies on having a Wi-Fi access point with IPv6 support and DHCPv6 server, configured to forward the Wi-SUN packets through the SiWx917 Wi-Fi interface and have the right IPv6 addresses range that will be assigned to the Wi-SUN nodes.

> **Note**: Silicon Labs considers the configuration of the access point out of scope for this demonstration.

![SoC BR with backhaul Setup](/wisun-soc-border-router-backhaul/0.1/images/sld995-image1.png)

##### Demo Prerequisites

This demonstration, as shown in the previous figure, relies on four main entities:

- A Wi-SUN Node running on one of the [Wi-SUN Development Kits](https://www.silabs.com/wireless/wi-sun?tab=kits).
- The Border router running on an [FG25-RB4270B](https://www.silabs.com/development-tools/wireless/proprietary/fg25-rb4270b-efr32fg25-radio-board?tab=overview) or an [FG25-RB4271A](https://www.silabs.com/development-tools/wireless/proprietary/fg25-rb4271a-efr32fg25-radio-board?tab=overview).
- The Wi-Fi module [SiWx917-RB4346A](https://www.silabs.com/development-tools/wireless/wi-fi/siwx917-rb4346a-wifi-6-bluetooth-le-soc-4mb-flash-radio-board?tab=overview) plus the [Si-EB8045A](https://www.silabs.com/development-tools/wireless/wi-fi/expansion-adapter-board-for-co-processor-radio-boards?tab=overview) expansion board.
- An access point with IPv6 and DHCPv6 server support, which is a Raspberry Pi in this demo.

Software used in this demonstration:

- [Simplicity Studio v5](https://www.silabs.com/developer-tools/simplicity-studio)
- SiSDK v2024.12.0 or later
- [WiseConnect 3 Extension](https://docs.silabs.com/wiseconnect/latest/wiseconnect-getting-started/getting-started-with-ncp-mode-with-efr32#install-the-wi-se-connect-3-extension) latest version

##### Setup Preparation

###### Wi-SUN Node

On the Wi-SUN node, flash the **Wi-SUN - CLI Example**. For details on how to create a project and flash it to your board using Simplicity Studio v5, refer to [Creating a Project Based on an Example](/wisun/2.12.0/wisun-getting-started-development/03-wisun-network#creating-a-project-based-on-an-example).

###### SiWx91x Connectivity Firmware

The SiWx91x has to be updated with the latest Connectivity Firmware. Refer to [Update SiWx91x Connectivity Firmware](https://docs.silabs.com/wiseconnect/latest/wiseconnect-getting-started/getting-started-with-ncp-mode-with-efr32#update-siwx91x-connectivity-firmware) for detailed steps.

###### Wi-SUN Border Router

First start by creating the project **Wi-SUN - SoC Border Router - with SiWx917 Wi-Fi backhaul** in Studio. The project supports, by default, the internal DHCPv6 server. In case of a setup that relies on the internal DHCPv6 server, you can directly build the project and flash it to the board. If the setup has an external DHCPv6 server, follow the next steps to install the **DHCPv6 Relay for Wi-SUN Border Router** component.

1. In the _wisun_soc_brcli_wifi.slcp_, click **[SOFTWARE COMPONENTS]**.
2. Type "DHCPv6" in the search bar, and click **DHCPv6 Relay for Wi-SUN Border Router**.
3. Click **[Install]** and, in the prompt window, choose the option to replace the internal DHCPv6 server with the DHCPv6 Relay for Wi-SUN Border Router.

Once the DHCPv6 Relay component is installed, you can build and flash the project.

##### Demo Configuration and Launch

After flashing all the binaries to the boards, launch the consoles of the Wi-SUN node board and the SoC Border router. In the **Debug Adapters** view, right-click the desired board and select **Launch Console**. To get a prompt on the Console, go to the Serial 1 tab and press **Enter**.

###### Wi-Fi Configuration

On the console of the Wi-SUN Border router, use the following commands to configure the access point SSID and passphrase:

```bash
> wisun set wifi.ssid "BRSoCDemo"
wifi.ssid = BRSoCDemo
> wisun set wifi.passphrase "Silabs_BRSoC"
wifi.passphrase = Silabs_BRSoC
```

After configuring the right ssid and passphrase, connect to the access point using the following command:

```bash
> wifi connect
[wifi: connecting to BRSoCDemo]
[wifi: connection successful]
```

The IPv6 address of the Wi-Fi interface and other details can be checked by the command `wisun get wifi`:

```bash
>wisun get wifi
wifi.ssid = "BRSoCDemo"
wifi.security = WPA2_CCMP (3)
wifi.passphrase = "Silabs_BRSoC"
wifi.wlan_state = connected
wifi.channel_number = 7
wifi.mac_address = ec:f6:4c:a0:43:20:02:08
wifi.ipv6_address = fd00:1234::eef6:4cff:fea0:4320
```

###### SoC Border Router Configuration

The Border Router configuration differs depending on whether it is the internal DHCPv6 server that is being used, or if the setup has an external DHCPv6 server.

With the two configurations, it is essential to set the Wi-SUN Network IPv6 prefix that is recommended to be different from the WAN IPv6 prefix to ease the routing configuration on the access point. Use the following command to set the IPv6 prefix:

```bash
> wisun set wisun.ipv6_prefix "fdc0:114f:d751:1::/64"
wisun.ipv6_prefix = fdc0:114f:d751:1::/64
```

> **Note**: Now that the IPv6 prefix of the Wi-SUN Network is known, the access point can be configured to route all the packets destined to the wisun.ipv6_prefix via the wifi.ipv6_address. This configuration is essential to have a working backhaul.

###### DHCPv6 Relay Configuration (heading level 7)

In case of using the DHCPv6 relay, the address of the DHCPv6 server should be provided to the SoC Border Router. To set the DHCPv6 server address, use the following command:

```bash
> wisun set wisun.dhcpv6_server "fd00:1234::1"
wisun.dhcpv6_server = fd00:1234::1
```

> **Note**: The IPv6 addresses range with the wisun.ipv6_prefix should be configured on the external DHCPv6 server. It is important that the external DHCPv6 Server generates IPv6 addresses for Wi-SUN nodes with the same IPv6 prefix that was configured on the Border Router side. If not, IPv6 routing protocol (RPL) will not work within the Wi-SUN Network.

###### Start The SoC Border Router (heading level 7)

The SoC Border Router can be started with the default PHY configuration. In case of changing the default PHY configuration, make sure to have the same configuration on the node side. To start the SoC Border Router, use the following command:

```bash
> wisun start_fan11
[Using built-in trusted CA #0]
[Using built-in device credentials]
[Border router started]
```

###### Node Configuration

If the Node Radio Board is on the same frequency band of the Border Router SoC Radio Board, the node can be started with the default PHY configuration. In case the boards have different frequency bands, check that the node PHY configuration matches the SoC Border Router PHY configuration and make the necessary adjustment in case the configurations are different before starting the node.

```bash
> wisun join_fan11
[Using built-in trusted CA #0]
[Using built-in device credentials]
[Connecting to "Wi-SUN Network"]
[Join state 1: Select PAN]
[Join state 2: Authenticate]
[Join state 3: Acquire PAN Config]
[Join state 4: Configure Routing - parent selection]
[Join state 4: Configure Routing - DHCP]
[Join state 4: Configure Routing - address registration]
[Join state 4: Configure Routing - DAO registration]
[Join state 5: Operational]
[Connected: 173 s]
[IPv6 address: fdc0:114f:d751:1::6c9b]
```

##### Local Ping Test

To test that the backhaul functions correctly, try to ping the node from a Smartphone connected to the access point.

On the phone side, [PingTools](https://pingtools.org/) is used to perform the ping. The following screenshot shows a successful ping of the node IP address `fdc0:114f:d751:1::6c9b`.

![Ping from phone](/wisun-soc-border-router-backhaul/0.1/images/sld995-image2.png)

From the node, use the following command to ping the phone. Make sure to change the IP address in the example.

```bash
> wisun ping fd00:1234::b473:7aff:fe9b:a804
PING fd00:1234::b473:7aff:fe9b:a804: 40 data bytes
40 bytes from fd00:1234::b473:7aff:fe9b:a804: icmp_seq=1 time=350 ms
```

#### Linux Border Router

##### Linux Border Router Overview

The border router oversees the network management (authentication, routing, and so on) and provides internet connectivity to the Wi-SUN devices part of the network.

Because of the standalone RCP connectivity features, the Linux border router solution offers an easy-to-use and scalable solution to address various Wi-SUN network deployments. This implementation relies on an external Silicon Labs EFR32 device flashed with a dedicated Wi-SUN RCP firmware. As a result, the EFR32 is connected to the host with a serial link. The EFR32 runs the time constrained low-level layers while the Linux host handles the memory-intensive computing of the Wi-SUN stack upper-layers.

As an accessible and well-spread Linux platform, the Raspberry Pi is used as a default platform for the solution demonstration (which can also run on a different Linux host), and will run the  Wi-SUN Border Router Linux daemon, which is responsible for running the Wi-SUN protocol high-level layers. The demonstration communications and connections are described in the following figure.

![Wi-SUN Linux Border Router Demonstration](/wisun-linux-border-router/0.1/images/sld993-image1.png)

As an alternative, Silicon Labs also provides a border router demonstration running on a standalone EFR32. It provides a quicker way to evaluate the solution but does not scale into production.

###### Hardware Requirements

To create a Wi-SUN Network with a Wi-SUN Linux border router and one Wi-SUN Node, you need the following hardware:

- A Raspberry Pi 3 Model B+ or above with an Internet connection (another Linux host should also work)
- An SD card (4 GB or more) and SD card slot/dongle
- 2 WTSK/WPK boards
- 2 EFR32 radio boards with matching RF bands from the Wi-SUN capable devices listed on the [Silicon Labs Wi-SUN Products](https://www.silabs.com/wireless/wi-sun) page.

###### Software Requirements

You need the following software to complete the steps in this application note:

- [Simplicity Studio 5](https://www.silabs.com/developers/simplicity-studio)
- [Raspberry Pi imager](https://www.raspberrypi.org/software/)
- [wsbrd source code repository](https://github.com/SiliconLabs/wisun-br-linux)

##### Linux Border Router (WSBRD)

The Silicon Labs Wi-SUN Linux Border Router solution “wsbrd” provides a daemon that is responsible for running the Wi-SUN protocol high-level layers. It is paired with an RF device (RCP) handling the low-level layers and radio activities. The Silicon Labs RCP devices currently supported are listed under [Wi-SUN Wireless SoCs](https://www.silabs.com/wireless/wi-sun).

###### Software Architecture

The Silicon Labs Linux border router solution has two distinct software components:

- **wsbrd**: the solution running on a Linux host. It supports high-level Wi-SUN FAN protocols such as 6LoWPAN, RPL, and MPL. The solution is available in source code on GitHub: [https://github.com/SiliconLabs/wisun-br-linux](https://github.com/SiliconLabs/wisun-br-linux).
- **Wi-SUN RCP**: the solution running on an EFR32. It provides a low-level Wi-SUN implementation meant to be paired with a Linux host running wsbrd. Silicon Labs provides the Wi-SUN RCP application in the SiSDK and Simplicity Studio 5.

The two solutions exchange messages using a serial link between the Linux host and the EFR32. UART is the currently supported protocol. The solution relies on Linux services for the IPv6 communication with external IP devices. The complete architecture of the solution is provided in the following figure.

![Wi-SUN Linux Border Router Architecture](/wisun-linux-border-router/0.1/images/sld993-image4.png)

###### Getting Started with the Solution

To use the Wi-SUN Border Router Linux, install wsbrd on a Raspberry Pi (Silicon Labs recommends this platform but you can use another Linux host if desired) and use the solution as it would be in production. This method allows you to access the Wi-SUN devices from the Linux host (Wi-SUN border router and the devices connected to it). However, there is no automatic IPv6 configuration to allow another IP device (other than the Linux host) to access the Wi-SUN network. You must configure the Linux host and the IP routing to match his external IP network configuration.

###### Flashing the Wi-SUN RCP (heading level 7)

A mandatory step to evaluate the Silicon Labs Wi-SUN Linux border router solution is to flash the Wi-SUN RCP image on an EFR32. The first possibility is to use the image or project delivered through Simplicity Studio 5. Create the **Wi-SUN – RCP** project, compile, and flash it in your mainboard. To do so, complete the following steps:

1. In the **Debug Adapters** view, select the device to be used as the Wi-SUN RCP.
2. Navigate to the **EXAMPLE PROJECTS & DEMOS** tab and turn off the **Example Projects** filter.
3. Click **RUN** next to the **Wi-SUN – RCP** project.  
   ![Screenshot showing the Wi-SUN - RCP Project](/wisun-linux-border-router/0.1/images/sld993-image5.png)

###### wsbrd (heading level 7)

To install and run wsbrd on your hardware:

1. Connect the EFR32 flashed with the RCP image to the Raspberry Pi through USB.
2. Download the wsbrd software on your Linux device.
3. Follow the guidelines provided in the repository readme ([Wi-SUN Linux Border Router repository](https://github.com/SiliconLabs/wisun-br-linux)).

When starting wsbrd and if it is running as expected, you should see a similar trace on the terminal.

```C
$ sudo wsbrd -F examples/wsbrd.conf -u /dev/ttyACM0

Silicon Labs Wi-SUN border router v1.0.0

Connected to RCP "0.12.0" (0.12.0), API 0.12.0

[DBG ][core]: Allocate Root Tasklet

[DBG ][6lo ]: P.Init

Successfully registered to system DBus

[DBG ][core]: NS Root task Init

[DBG ][sck ]: Socket Tasklet Generated

[INFO][wsbs]: WS tasklet init
```

In the traces, the wsbrd, RCP, and API versions are output. The wsbrd automatically checks the RCP and API versions to confirm they are valid and supported by the wsbrd version running.

If the default configuration is used, a new border router is advertising a network with the name **Wi-SUN Network**. On the Raspberry Pi, a new IP interface is created with the name **tun0**. Below is an example of the IP configuration once wsbrd is running.

```C
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500

        inet6 fd12:3456::7c3f:f8e7:55c5:e07f  prefixlen 64  scopeid 0x0<global>

        inet6 fe80::d0a6:c144:ad24:9b1d  prefixlen 64  scopeid 0x20<link>

        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 500  (UNSPEC)

        RX packets 10  bytes 752 (752.0 B)

        RX errors 0  dropped 0  overruns 0  frame 0

        TX packets 3  bytes 144 (144.0 B)

TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
```

The **tun0** interface can be natively used to interact with the Wi-SUN devices connected to the Linux border router.

###### Interact with a Running wsbrd Instance

###### wsbrd Command Line Interface (heading level 7)

wsbrd provides a command line interface to interact with the Linux border router when it is running. The interface can be used to retrieve configurations like the network name, Wi-SUN PHY configuration, PAN ID, GAK/GTK and LGAK/LGTK keys, and the MAC Addresses of the border router and the connected nodes. You can use the `wsbrd_cli status` command to view the list of configurations. For help, use the `wsbrd_cli help` command.

```shell
$   wsbrd_cli status
network_name: Wi-SUN Network
fan_version: FAN 1.1
domain: NA
phy_mode_id: 2
chan_plan_id: 1
panid: 0x3f48
size: SMALL
GAK[0]: 0f:a7:bc:8e:fa:1f:a3:22:6b:15:30:80:dd:06:6d:e7
GAK[1]: 95:03:54:82:78:c2:01:69:79:96:96:72:9a:f9:08:b9
GAK[2]: 95:03:54:82:78:c2:01:69:79:96:96:72:9a:f9:08:b9
GAK[3]: 95:03:54:82:78:c2:01:69:79:96:96:72:9a:f9:08:b9
GTK[0]: e9:a6:e0:19:00:8d:ae:12:4a:1d:73:93:ee:53:c6:6b
GTK[1]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
GTK[2]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
GTK[3]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
LGAK[0]: a5:01:bf:df:aa:fa:da:84:a5:9d:9c:41:53:31:03:9e
LGAK[1]: 95:03:54:82:78:c2:01:69:79:96:96:72:9a:f9:08:b9
LGAK[2]: 95:03:54:82:78:c2:01:69:79:96:96:72:9a:f9:08:b9
LGTK[0]: 61:ff:86:39:6c:ec:00:52:c9:fd:27:90:f1:db:f7:f5
LGTK[1]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
LGTK[2]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
38:39:8f:ff:fe:99:9b:e4
```

###### DBus Interface (heading level 7)

The DBus interface can also interact with the Linux border router when it’s running and retrieve static configurations. It is also able to trigger actions like adding or revoking root certificates and revoking a Wi-SUN device access to the network. You can execute the command `busctl introspect com.silabs.Wisun.BorderRouter /com/silabs/Wisun/BorderRouter` to see the list of all the properties that can be retrieved within the DBus interface and the methods that can be used. For example, to read a DBus property execute the following command:

```C
$ busctl get-property com.silabs.Wisun.BorderRouter /com/silabs/Wisun/BorderRouter com.silabs.Wisun.BorderRouter WisunNetworkName

s "Wi-SUN Network"
```

For additional information on the interface usage, refer to the [D-Bus API documentation](https://github.com/SiliconLabs/wisun-br-linux/blob/main/DBUS.md#d-bus-api-documentation).

###### Raspberry Pi Adapter BRD8016A

BRD8016A is an excellent solution to build a Wi-SUN Linux Border Router on top of a Raspberry Pi, together with a Wi-SUN Radio Board used as the Wi-SUN device. The Wi-SUN Linux Border Router is ultimately made of 3 boards stacked together:

- Raspberry Pi (Linux host)
- BDR8016A (Adapter Board)  
  ![Photograph of Adapter Board](/wisun-linux-border-router/0.1/images/sld993-image13.png)
- Radio Board (RCP: Radio Co-Processor)

This setup is an alternative to connecting the Raspberry Pi to the Radio Board over USB via a WSTK/WPK mainboard, as initially described in the Wi-SUN Linux Border Router README.

###### wsbrd configuration

This setup uses the _Normal UART_ instead of _UART over USB_ usually used with the WSTK/WPK. For the wsbrd to use the _Normal UART_, change the following option in the wsbrd.conf file:

```C
uart_device = /dev/ttyAMA0
```

###### Raspberry Pi Boot Configuration

To use the _Normal UART_ by the Raspberry Pi, change the configuration in `/boot/config.txt`. Because of the way Raspberry Pi 2/3/4 are wired, to get a good UART clock, it is required to disable Bluetooth and use GPIOs 14 and 15 for /dev/ttyAMA0. See the [Raspberry Pi documentation](https://www.raspberrypi.com/documentation/computers/configuration.html#configuring-uarts) for details. To achieve this, the following changes need to be added at the end of `/boot/config.txt`:

```C
[all]

dtoverlay=disable-bt

enable_uart=1

gpio=23=op,dh
```

It is required to reboot the Raspberry Pi following such changes:

```C
sudo reboot
```

After rebooting your Raspberry Pi, follow these steps to enable shell messages on the serial connection and disable the login shell over serial:

- Open Raspberry Pi configuration GUI:

```C
sudo raspi-config
```

- Select  `3 Interface Options    Configure connections to peripherals`
- Select `I6 Serial Port    Enable/disable shell messages on the serial connection`
- Answer **No** to the question “Would you like a login shell to be accessible over serial?”
- Answer **Yes** to the question  “Would you like the serial port hardware to be enabled?”
- Choose to reboot your Raspberry Pi

Now that the Raspberry Pi is configured, connect the RCP to the adapter and start wsbrd.

Note that the switch on the adapter (BRD8016A) must be on _High Power (LDO)_ to use 5V from the Raspberry Pi to generate a regulated 3.3V supply.

###### CPC

Co-Processor Communication (CPC) enables a host system to communicate with a Network Co-Processor (NCP) through physical transports such as UART or SPI.<br />While plain UART allows easier integration for simple setups, CPC provides several additional features:

- Support for UART and SPI buses
- Support for encrypted communication with the RCP
- Support for Dynamic Multiprotocol (DMP), allowing CPCd to share the RCP between multiple network stacks such as Bluetooth, Zigbee, OpenThread, and Wi-SUN.

To start CPC integration check these sections:

- [CPC SPI on Linux Border Router](cpcd-spi-with-wsbrd)
- [CPC UART on Linux Border Router](cpcd-uart-with-wsbrd)

###### Border Router GUI

A companion tool for configuring the Linux Border Router and visualizing the network topology graphically can be installed by following instructions in [Border Router GUI](/wisun/2.12.0/wisun-border-router-gui).

##### Using Co-Processor Communication Daemon with wsbrd

###### Overview

Co-Processor Communication (CPC) enables one host system to communicate with a Network co-processor device (NCP), by physical transport (UART, SPI, and so on). In CPC, data transfers between processors are segmented in sequential packets. Transfers are guaranteed to be error-free and sent in order. Multiple applications can send or receive on the same endpoint without worrying about collisions. A CPC daemon (CPCd) is provided to allow applications on Linux to interact with a secondary running CPC.

For the purpose of having Silicon Labs Wi-SUN stack running in harmony with other services such as Bluetooth, ZigBee, or others on the same Co-Processor, Silicon Labs added support of CPCd to wsbrd.

The next sections explain how to install and configure CPCd and wsbrd, and also how to set up an RCP with the CPC Secondary Service component in Simplicity Studio v5. This chapter only covers UART communication between a WSTK and Raspberry Pi. SPI communication using CPC is described in [CPC SPI on Linux Border Router](cpcd-spi-with-wsbrd)

![Diagram showing host to co-processor communication](/wisun-linux-border-router/0.1/images/sld993-image6.png)

###### Setting Up the RCP with CPC Secondary Service

This part is the RCP project creation and configuration in Simplicity Studio.

To use the **Wi-SUN – RCP** sample application as CPC secondary device, users should enable the Co-Processor Communication components in the **Wi-SUN – RCP** project in Simplicity Studio v5.

###### Components Installation (heading level 7)

After creating a **Wi-SUN – RCP** project, open the slcp file and select the **Software Component** tab. In the search box, enter _secondary_ to filter the components and install the following components:

![Screenshot showing installation of CPC Secondary Device Component](/wisun-linux-border-router/0.1/images/sld993-image7.png)

1. Install **Services/Co-Processor Communication/Secondary Device (Co-Processor)**.
2. By default, the **CPC SECURITY** component will be installed automatically after installing the **Secondary Device (Co-Processor)** component. If you wish to disable security on the CPC link, install **CPC SECURITY NONE**.
3. The **Wi-SUN/Application/Wi-SUN RCP/Wi-SUN Border Router RCP - CPC Interface** will be automatically added to your project.

###### Secondary Device Configuration (heading level 7)

###### CPC Secondary - UART (EUSART) Component (heading level 8)

After installing all the components, configure the created instance with the desired Flow control and Baud rate. Select your created instance in the slcp perspective, and then click **Configure**.

![Screenshot showing selection of CPC Secondary - UART (EUSART) Configuration](/wisun-linux-border-router/0.1/images/sld993-image14.png)

In the configuration perspective, the recommended **EUSART Baudrate** value is 921600. Concerning the **Flow Control**, it is set by default to **CTS/RTS**. Silicon Labs recommends this default; do not set it to **None**.

![Screenshot showing CPC Secondary - UART (EUSART) Configuration](/wisun-linux-border-router/0.1/images/sld993-image15.png)

###### WSTK Configuration

The WSTK boards are factory programmed to support 115200bps with no flow control. To align the WSTK configuration with the chosen CPC EUSART Baudrate configuration, follow the next steps:

1. In **Debug Adapters**, right-click your device and click **Launch Console…**.
2. On the console, select the **Admin** tab, and enter the following commands:

```C
serial vcom config speed 921600
serial vcom config handshake rtscts
```

The following figure shows the resulting console output.

![Screenshot of resulting output](/wisun-linux-border-router/0.1/images/sld993-image8.png)

After finishing these steps, you can **Build** your project and flash it to the device.

###### CPCd Installation and Configuration

This part is to be executed on the linux host.

###### CPCd Installation (heading level 7)

CPCd is delivered as a CMake project. The minimum version of CMake required to generate the project is 3.10. CPCd requires MbedTLS to encrypt the endpoints. The minimal version required for Mbed-TLS is 2.7.0. libmbedtls-dev must be installed to compile from sources.

Refer to [cpc-deamon readme](https://github.com/SiliconLabs/cpc-daemon/blob/main/readme.md), sections _**Compiling CPCd**_ and _**Installing CPCd and CPC library**_ to install CPCd.

###### Checking `cpcd` / `libcpc` Installs (heading level 7)

```bash
$ ls -al /usr/local/bin | grep cpc
-rwxr-xr-x  1 root root   748024 May 29 11:01 cpcd
```

```bash
$ ls -al /usr/local/lib/arm-linux-gnueabihf/ | grep libcpc
lrwxrwxrwx 1 root root    11 May 29 11:01 libcpc.so -> libcpc.so.3
lrwxrwxrwx 1 root root    17 May 29 11:01 libcpc.so.3 -> libcpc.so.4.4.2.0
-rw-r--r-- 1 root root 87776 May 29 11:01 libcpc.so.4.4.2.0
```

```bash
$ cpcd --version
4.4.2.0
GIT commit: 37bc19f2dfffa8cd954162bb42b8f80755e31e99
GIT branch: refs/heads/main
Sources hash: bbf8593d1941a71988883e18e2bfeb85ec27aaffbb84aadbf12a50a7e0c2a226
```

###### CPCd Configuration (heading level 7)

After installing CPCd, a configuration file can be found under _/usr/local/etc/cpcd.conf_. This file can be accessed using the following command:

```C
sudo nano /usr/local/etc/cpcd.conf
```

The modifications that need to be applied to this file to configure CPCd for a secured UART communication between a WSTK and Raspberry Pi are:

```C
instance_name: cpcd_0

bus_type: UART

uart_device_file: /dev/ttyACM0

uart_device_baud: 921600

disable_encryption: false

multicast_endpoints: []
```

Note that the `uart_device_file` and `uart_device_baud` values above are examples and can be changed to suit your use case. The `uart_device_file` must match what is visible in `dmesg` after plugging the WSTK/WPK on the host.

If security was disabled on the secondary device (the RCP) by installing the **CPC SECURITY NONE** component, the value of **disable_encryption** must be set to **true**.

The `multicast_endpoints: []` setting disables multicasting for all endpoints, ensuring that only a single client can open and use an endpoint at a time. This is a precautionary measure to prevent issues that may occur if another process accidentally connects to the same endpoint used by wsbrd.

Refer to [CPC SPI on Linux Border Router](cpcd-spi-with-wsbrd) for CPC over SPI (SPI provides higher bandwidth than UART).

###### wsbrd Configuration

CPC is supported by `wsbrd` version 1.4 and above. Make sure to update and re-build `wsbrd` if you are running an older version. In case of reinstalling `wsbrd`, make sure to delete the `/wisun-br-linux/CMakeCache.txt` file.

In the **/etc/wsbrd.conf** file (copied from [**wisun-br-linux/examples/wsbrd.conf**](https://github.com/SiliconLabs/wisun-br-linux/blob/main/examples/wsbrd.conf)), comment-out `cpc_instance` and give it the same value as `instance_name` in **/usr/local/etc/cpcd.conf** and comment the `uart_device` option.

```bash
cpc_instance = cpcd_0
#uart_device = /dev/ttyACM0
```

###### Setup Cross-check (heading level 7)

```bash
$ cat /etc/wsbrd.conf | grep cpc_instance
cpc_instance = cpcd_0
$ cat /usr/local/etc/cpcd.conf | grep instance_name
instance_name: cpcd_0
$ cat /usr/local/etc/cpcd.conf | grep uart_device_baud
uart_device_baud: 921600
```

The `uart_device_baud` value must match the WSTK `Stored port speed` when calling `serial vcom` in the 'Admin' console tab.

###### Launching CPDC and wsbrd

###### Starting `cpcd` before starting `wsbrd` (heading level 7)

If `cpcd` is not running when `wsbrd` is launched, the following error will occur:

```bash
 $ sudo wsbrd -F /etc/wsbrd.conf
Silicon Labs Wi-SUN border router...
cpc_init: Connection refused
```

###### Manually starting cpcd (heading level 7)

Before starting CPCd and wsbrd, connect the RCP to your Raspberry Pi. Then you can manually start the CPCd.

When CPC security is enabled, the key should be bound a single time.

```bash
sudo cpcd --conf /usr/local/etc/cpcd.conf --bind ecdh
```

For more information about CPC encryption refere to this [Readme](https://github.com/SiliconLabs/cpc-daemon/blob/main/readme.md#encrypted-serial-link).

After that, you can start CPCd.

```C
$sudo cpcd --conf /usr/local/etc/cpcd.conf
..
..
Info : Daemon startup was successful. Waiting for client connections
```

###### Manually Starting wsbrd (heading level 7)

After the line indicating that the CPC deamon startup was successful appears in the logs, use a separate terminal to manually launch wsbrd using the command:

```C
sudo wsbrd -F /etc/wsbrd.conf
```

###### Starting cpcd as a Service (heading level 7)

Starting cpcd as a service is a better option once the system has been tested using a manual start. With the `Restart=on-failure`, cpcd will be restarted automatically in case of failure.

This requires:

- Creating a service file for cpcd

```bash
sudo nano /usr/local/lib/systemd/system/cpcd.service
```

```bash
##### SPDX-License-Identifier: GPL-2.0 or APACHE-2.0
[Unit]
Description=Silicon Labs CPC Service
Documentation=file:////usr/local/etc/cpcd.conf
After=network.target
After=freeradius.service
##### If you rely on an external DHCP server, don't forget to add a dependency here

[Service]
ExecStart=cpcd --conf /usr/local/etc/cpcd.conf
#Restart=on-failure

[Install]
WantedBy=multi-user.target
```

- reloading the system services

```bash
sudo systemctl daemon-reload
```

###### Checking `cpcd` Service Status (heading level 8)

```bash
 $ sudo systemctl status cpcd.service
● cpcd.service - Silicon Labs CPC Service
     Loaded: loaded (/usr/local/lib/systemd/system/cpcd.service; disabled; vendor preset: enabled)
     Active: active (running) since Mon 2023-11-06 15:45:08 CET; 2min 48s ago
       Docs: file:////usr/local/etc/cpcd.conf
   Main PID: 7608 (cpcd)
      Tasks: 5 (limit: 1595)
        CPU: 62ms
     CGroup: /system.slice/cpcd.service
             └─7608 cpcd --conf /usr/local/etc/cpcd.conf

Nov 06 15:47:56 rns-md-wisun-br cpcd[7608]: [2023-11-06T14:47:56.882099Z] Core : Endpoint #10: rxd data frame queued
Nov 06 15:47:56 rns-md-wisun-br cpcd[7608]: [2023-11-06T14:47:56.882121Z] Core : Endpoint #10 sent ACK: 6
Nov 06 15:47:56 rns-md-wisun-br cpcd[7608]: [2023-11-06T14:47:56.882147Z] Core : Pushed frame to driver : 14:0A:00:00:86:B9:14
. . .
```

###### Starting wsbrd as a Service (heading level 7)

Starting wsbrd as a service is a good option once the system has been tested using a manual start. With the `Restart=on-failure`, wsbrd will be restarted automatically in case of failure.

This requires:

- Creating a service file for wsbrd

```bash
nano $ sudo nano /usr/local/lib/systemd/system/wisun-borderrouter.service
```

```bash
##### SPDX-License-Identifier: GPL-2.0 or Apache-2.0
[Unit]
Description=Wi-SUN Border Router Service
Documentation=file:///usr/local/share/doc/wsbrd/examples/wsbrd.conf
After=network.target
After=freeradius.service
##### If you rely on an external DHCP server, don't forget to add a dependency here

[Service]
BusName=com.silabs.Wisun.BorderRouter
ExecStart=/usr/local/bin/wsbrd -F /etc/wsbrd.conf
Restart=on-failure
##### Files created by wsbrd contain secrets, so remove read permissions
UMask=0066

[Install]
WantedBy=multi-user.target
```

- reloading the system services

```bash
sudo systemctl daemon-reload
```

###### CPC/wsbrd Communication (heading level 7)

A log of CPC/wsbrd communication can be obtained adding `cpc` trace to `/etc/wsbrd.conf`. Once CPC is working, removing the `cpc` trace is recommended.

If the `Connected to RCP "x.y.z" (x.y.z), API t.u.v` message is present, everything is working as expected (the RCP version string comes from the RCP binary, not from `wsbrd`, so it validates proper communication between the host and the RCP over CPC).

###### Error Messages and Corrections

As a general rule, always check the traces from `cpcd` and `wsbrd` in case of issues. These can be obtained directly from the command line is the applications are manually started from a command line, and using `journalctl` if started as services:

```bash
tail -f sudo journalctl -u cpcd.service -f
tail -f sudo journalctl -u wisun-borderrouter.service.service -f
```

###### `'support for CPC is disabled'` (heading level 7)

- `cpcd` has been installed after `wsbrd` had already been compiled.
- You need to rebuild `wsbrd` following `cpcd` installation.
- Make sure to delete the `/wisun-br-linux/CMakeCache.txt` file and the `/wisun-br-linux/CMakeFiles` folder before rebuilding `wsbrd`.

###### `'cpc_init: Connection refused'` (heading level 7)

- `cpcd` is not running yet when starting `wsbrd`.
- Make sure `cpcd` is started first and the `cpcd` traces contain `Info : Daemon startup was successful. Waiting for client connections`
- You may need to disconnect/reconnect the RCP is some cases.

###### `'cpc_init: No such file or directory'` (heading level 7)

See [RCP not communicating](#rcp-not-communicating)

###### `Failed to connect, secondary seems unresponsive` (heading level 7)

See [RCP not communicating](#rcp-not-communicating)

###### RCP Not Communicating (heading level 7)

When communication issues appear with the RCP, check cpc status to know more:

```bash
sudo systemctl status cpcd.service
```

Possible causes are:

- There is no WSTK/WPK plugged in, if the setup has been running before. Unplug/Replug the WSTK/WPK. Check `dmesg` for the `USB ACM device` name.
- There is a mismatch between the `uart_device_file` in `/usr/local/etc/cpcd.conf`. Start `dmesg -w` then unplug/plug the WSTK/WPK to check the `USB ACM device` name and update the `uart_device_file` to match.
- There is an invalid binary running on the RCP. Make sure you flash it with a RCP project with CPC enabled and the correct UART baudrate.
- The serial vcom speed on the WSTK/WPK is incorrect. Refer to [WSTK Configuration](#wstk-configuration).

##### Using CPC SPI on Linux Border Router

This document refers to a setup build using:

- [BRD4271A](https://www.silabs.com/documents/public/schematic-files/BRD4271A-A06-schematic.pdf) as the Silicon Labs Radio Board
- [BRD8016A](https://www.silabs.com/documents/public/schematic-files/BRD8016A-A01-schematic.pdf) as the Silicon Labs Raspberry Pi Adapter Board
- A Raspberry Pi as the host

![Border Router](/wisun-linux-border-router/0.1/images/sld993-brd4x71-brd8016-a-rpi.png)

> **Note**: Pin mapping will need to be adapted to any custom hardware.

###### RCP SPI Connections

SPI signals need to be allocated to pins connected to the host via the Radio Board connectors and the BRD8016A Raspberry Pi connector shown below.

###### xG25 Software Configuration (heading level 7)

|SPI signal|`sl_cpc_drv_secondary_spi_eusart_exp_config.h`|RCP values|xG25 GPIO|
|---|---|---|---|
|IRQ|SL_CPC_DRV_SPI_EXP_IRQ_PORT / SL_CPC_DRV_SPI_EXP_IRQ_PIN|SL_GPIO_PORT_A / 5|EFR32_PA5|
|CS|SL_CPC_DRV_SPI_EXP_CS_PORT / SL_CPC_DRV_SPI_EXP_CS_PIN|SL_GPIO_PORT_B / 4|EFR32_PB4|
|(MISO)CIPO/RX|SL_CPC_DRV_SPI_EXP_CIPO_PORT / SL_CPC_DRV_SPI_EXP_CIPO_PIN|SL_GPIO_PORT_C / 1|EFR32_PC1|
|(MOSI)COPI/TX|SL_CPC_DRV_SPI_EXP_COPI_PORT / SL_CPC_DRV_SPI_EXP_COPI_PIN|SL_GPIO_PORT_C / 0|EFR32_PC0|
|SCLK|SL_CPC_DRV_SPI_EXP_SCLK_PORT / SL_CPC_DRV_SPI_EXP_SCLK_PIN|SL_GPIO_PORT_C / 2|EFR32_PC2|

###### xG25 Pins (heading level 7)

|SPI signal|xG25 GPIO|xG25 Pin|WSTK signal|
|---|---|---|---|
|IRQ|EFR32_PA5|34|WSTK_P4|
|CS|EFR32_PB4|24|WSTK_P7|
|(MISO)CIPO/RX|EFR32_PC1|2|WSTK_P3|
|(MOSI)COPI/TX|EFR32_PC0|1|WSTK_P1|
|SCLK|EFR32_PC2|3|WSTK_P5|

###### BRD4271A Pins (heading level 7)

|SPI signal|BRD4271A signal|Radio Board Pin|
|---|---|---|
|IRQ|WSTK_P4|P201_7|
|CS|WSTK_P7|P201_10|
|(MISO)CIPO/RX|WSTK_P3|P201_6|
|(MOSI)COPI/TX|WSTK_P1|P201_4|
|SCLK|WSTK_P5|P201_8|

###### BRD8016A Pins (heading level 7)

|SPI signal|Radio Board Pin|BRD8016A signals|RPi GPIO|
|---|---|---|---|
|IRQ|P201_7|RADIO_P4|RPI_GPIO22|
|CS|P201_10|RADIO_P7|RPI_GPIO8|
|(MISO)CIPO/RX|P201_6|RADIO_P3|RPI_GPIO9|
|(MOSI)COPI/TX|P201_4|RADIO_P1|RPI_GPIO10|
|SCLK|P201_8|RADIO_P5|RPI_GPIO11|

###### Raspberry Header Pins (heading level 7)

|SPI signal|RPi GPIO|RPi Header pin|RPi SPI signal|
|---|---|---|---|
|IRQ|RPI_GPIO22|15| |
|CS|RPI_GPIO8|24|RPI_SPI_CS|
|(MISO)CIPO/RX|RPI_GPIO9|21|RPI_SPI_MISO|
|(MOSI)COPI/TX|RPI_GPIO10|19|RPI_SPI_MOSI|
|SCLK|RPI_GPIO11|23|RPI_SPI_SCLK|

###### Raspberry Software Settings (heading level 7)

|SPI signal|RPi SPI signal|RPi Software settings|RPi Value|
|---|---|---|---|
|IRQ| |`cpcd.conf` `spi_rx_irq_gpio`|22|
|CS|RPI_SPI_CS|device tree `spi0_cs_pins[0]`|0x08|
|(MISO)CIPO/RX|RPI_SPI_MISO|device tree `spi0_pins[0]`|0x09|
|(MOSI)COPI/TX|RPI_SPI_MOSI|device tree `spi0_pins[1]`|0x0a|
|SCLK|RPI_SPI_SCLK|device tree `spi0_pins[2]`|0x0b|

###### RCP Project

###### CPC Addition to Wi-SUN RCP Project (heading level 7)

Add Wi-SUN / Application / Wi-SUN RCP / Wi-SUN Border Router RCP - CPC Interface.

By default, this component uses UART. Follow the steps below to add CPC to your Wi-SUN project.

1. Install the Services / Co-Processor Communication / Secondary Device / Driver / CPC Secondary - SPI: Recommended SPI interface.  
   ![CPC SPI](/wisun-linux-border-router/0.1/images/sld993-cpc-spi-eusart.png)  
   This creates the default `exp` CPC instance under Services / Co-Processor Communication / Secondary Device / Driver / CPC Secondary - SPI (EUSART) / exp.  
   ![CPC SPI](/wisun-linux-border-router/0.1/images/sld993-cpc-spi-eusart-exp.png)
2. Click **Configure** to check the SPI pin configuration, making sure it matches the [RCP SPI connections for BRD4271A/BRD8016A/RPi hardware](#rcp-spi-connections).  
   ![CPC SPI](/wisun-linux-border-router/0.1/images/sld993-cpc-spi-eusart-exp-config.png)
3. Press the **Pin Tool** button and filter on 'SPI' to get a pin view of SPI signals.  
   ![CPC SPI](/wisun-linux-border-router/0.1/images/sld993-cpc-spi-eusart-exp-pintool.png)
4. Build your CPC project.
5. Flash it on the RCP, clearing the flash before flashing (to get rid of any remaining NVM data).
6. Insert the RCP Radio Board on the BRD8016A Adapter Board.
7. Make sure that the expansion board switch is set to the **High Power (LDO)** mode.
8. Insert the BRD8016A on the Raspberry Pi header.

###### Border Router

> **Note**: As from 23Q4/SiSDK V4.3.2, the CPC component in the SiSDK will use the **CPC Protocol v5**, so the `cpcd` installation on the Border Router also needs to use this version.

First of all CPC needs to be able to communicate with the RCP, independently from wsbrd.

To achieve this, `cpcd` needs to be compiled with the **CPC Protocol v5**, as follows:

###### Removing previous `cpcd` / `libcpc` Installs (heading level 7)

```bash
sudo rm -rf /usr/local/lib/arm-linux-gnueabihf/*
```

###### Installing cpcd with Protocol V6 (heading level 7)

```bash
git clone https://github.com/SiliconLabs/cpc_daemon.git cpc_daemon
cd cpc_daemon/
cat CMakeLists.txt | head
mkdir build
cd build/
cmake ../
make
sudo make install
sudo ldconfig
```

###### Checking `cpcd` Protocol Version (heading level 7)

```bash
$ cat ~/cpc_daemon*/CMakeLists.txt | grep CPC_PROTOCOL_VERSION
set(CPC_PROTOCOL_VERSION "6")
```

###### Checking `cpcd` / `libcpc` Installs (heading level 7)

```bash
$ ls -al /usr/local/lib/arm-linux-gnueabihf/
total 188
drwxr-xr-x 3 root root  4096 Jul  9 11:35 .
drwxr-xr-x 6 root root  4096 Apr 18  2024 ..
lrwxrwxrwx 1 root root    11 Apr 19  2024 libcpc.so -> libcpc.so.3
lrwxrwxrwx 1 root root    17 Jul  9 11:35 libcpc.so.3 -> libcpc.so.4.7.0.0
-rw-r--r-- 1 root root 87776 Jun  7  2024 libcpc.so.4.4.2.0
-rw-r--r-- 1 root root 88160 Jul  9 11:34 libcpc.so.4.7.0.0
drwxr-xr-x 2 root root  4096 Jul  9 11:35 pkgconfig
```

```bash
 $ cpcd --version
4.7.0.0
GIT commit: 4ff183d9d1ec888812bff3c3562e4961594e5bb5
GIT branch: refs/heads/main
```

###### Enabling SPI via the Device Tree (heading level 7)

In `/boot/config.txt`, comment the UART line and add the SPI overlay as follows:

```bash
[all]
###### Disable WiFi and Bluetooth, both potentially using UART
dtoverlay=disable-bt
dtoverlay=disable-wifi

##### Disable UART
#enable_uart=1

##### Enable SPI for CPC host/RCP communication
dtoverlay=spi0-1cs

##### Generate a reset on GIPO 23, keep the level high after reset
gpio=23=op,dh
```

> Note: A reboot is required after modifying `/boot/config.txt`.

- Reboot the Raspberry Pi

###### `cpcd` SPI configuration file (heading level 7)

(only active lines are shown)

The default configuration file is `/usr/local/etc/cpcd.conf`. To use another, use the `--conf` option.

```bash
$ cat /usr/local/etc/cpcd.conf | grep -v ^$ | grep -v ^#
instance_name: cpcd_0
bus_type: SPI
spi_device_file: /dev/spidev0.0
spi_rx_irq_gpio_chip: gpiochip0
spi_rx_irq_gpio: 22
spi_device_bitrate: 1000000
bootloader_recovery_pins_enabled: false
bootloader_wake_gpio_chip: gpiochip0
bootloader_wake_gpio: 24
bootloader_reset_gpio_chip: gpiochip0
bootloader_reset_gpio: 23
stdout_trace: false
trace_to_file: false
traces_folder: /tmp/
enable_frame_trace: false
rlimit_nofile: 2000
disable_encryption: true
binding_key_file: ~/.cpcd/binding.key
```

###### `wsbrd` Configuration File for CPC (heading level 7)

The changes are similar for UART and SPI mode, since the bus mode is selected in the `cpcd` configuration file (shown here with traces enabled).

```bash
$ cat ~/wsbrd.conf | grep -v ^$ | grep -v ^#
user = wsbrd
group = wsbrd
cpc_instance = cpcd_0
ipv6_prefix = fd12:3456::/64
network_name = Linux_spi_EU_33_5
domain = EU
chan_plan_id = 33
phy_mode_id = 5
phy_operating_modes = auto
key = /home/pi/wisun-br-linux/examples/br_key.pem
certificate = /home/pi/wisun-br-linux/examples/br_cert.pem
authority = /home/pi/wisun-br-linux/examples/ca_cert.pem
color_output = no
pcap_file = /tmp/dump.pcapng
trace = hif
```

The only line relevant to using CPC is (on top of commenting out UART-related lines):

```bash
cpc_instance = cpcd_0
```

###### Setup Cross-Check (heading level 7)

Using the BRD8016A Wireless Expansion board: you will need to mount the expansion board on the Raspberry Pi and make sure that the expansion board switch is set to the high power mode.

```bash
$ cat /etc/wsbrd.conf | grep cpc_instance
cpc_instance = cpcd_0
$ cat /usr/local/etc/cpcd.conf | grep instance_name
instance_name: cpcd_0
```

###### SPI Signals Allocation Checks (heading level 7)

###### Raspberry Pi Device Tree Check (heading level 8)

```bash
dtc -I fs /sys/firmware/devicetree/base
```

gives (abstracts) `spi0` information (comment lines added for clarity):

```c
                        spi0_pins {
                                brcm,function = <0x04>;
                                phandle = <0x0e>;
                                #            MISO MOSI SCLK
                                brcm,pins = <0x09 0x0a 0x0b>;
                        };
```

```c
                        spi0_cs_pins {
                                brcm,function = <0x01>;
                                phandle = <0x0f>;
                                #            CS0
                                brcm,pins = <0x08>;
                        };
```

###### Raspberry Pi GPIOs Check (heading level 8)

These are controlled by the device tree.

> **Note**: Remember that changes to the device tree require a reboot to be taken into account

```bash
cat /sys/kernel/debug/gpio | grep SPI

 gpio-7   (SPI_CE1_N           )
 gpio-8   (SPI_CE0_N           |spi0 CS0            ) out hi ACTIVE LOW
 gpio-9   (SPI_MISO            )
 gpio-10  (SPI_MOSI            )
 gpio-11  (SPI_SCLK            )
 gpio-43  (SPIFLASH_CE_N       )
```

###### Communication Checks

###### `cpcd`/RCP communication (without wsbrd) (heading level 7)

> **Note**: A reboot is required after modifying `/boot/config.txt`, so reboot if you haven't done so yet.

###### `cpcd` manual start (heading level 8)

Use `ps -C cpcd` to make sure no cpcd process is running. Use `sudo kill <cpcd PID>` to kill it if it's running.

A full log (with traces enabled) is provided below.

[Click to expand and view the full log]
```bash
 $ sudo cpcd --conf /usr/local/etc/cpcd.conf
WARNING in function 'main' in file /home/pi/cpc_daemon/main.c at line #68 : Running CPCd as 'root' is not recommended. Proceed at your own risk.
[2025-07-09T13:10:44.177112Z] Info : [CPCd v4.7.0.0] [Library API v3] [RCP Protocol v6]
[2025-07-09T13:10:44.177422Z] Info : Git commit: 4ff183d9d1ec888812bff3c3562e4961594e5bb5 / branch: refs/heads/main
[2025-07-09T13:10:44.177487Z] WARNING : In function 'main' in file /home/pi/cpc_daemon/main.c at line #68 : Running CPCd as 'root' is not recommended. Proceed at your own risk.
[2025-07-09T13:10:44.177578Z] Info : Reading cli arguments
[2025-07-09T13:10:44.177657Z] Info : cpcd --conf /usr/local/etc/cpcd.conf
[2025-07-09T13:10:44.178256Z] Info : Reading configuration
[2025-07-09T13:10:44.178275Z] Info :   file_path = /usr/local/etc/cpcd.conf
[2025-07-09T13:10:44.178291Z] Info :   instance_name = cpcd_0
[2025-07-09T13:10:44.178305Z] Info :   socket_folder = /dev/shm
[2025-07-09T13:10:44.178319Z] Info :   operation_mode = MODE_NORMAL
[2025-07-09T13:10:44.178333Z] Info :   use_encryption = false
[2025-07-09T13:10:44.178347Z] Info :   binding_key_file = /root/.cpcd/binding.key
[2025-07-09T13:10:44.178362Z] Info :   stdout_tracing = true
[2025-07-09T13:10:44.178375Z] Info :   file_tracing = false
[2025-07-09T13:10:44.178389Z] Info :   lttng_tracing = false
[2025-07-09T13:10:44.178402Z] Info :   enable_frame_trace = true
[2025-07-09T13:10:44.178416Z] Info :   traces_folder = /tmp
[2025-07-09T13:10:44.178430Z] Info :   bus = SPI
[2025-07-09T13:10:44.178445Z] Info :   spi_file = /dev/spidev0.0
[2025-07-09T13:10:44.178458Z] Info :   spi_bitrate = 10000000
[2025-07-09T13:10:44.178473Z] Info :   spi_irq_chip = gpiochip0
[2025-07-09T13:10:44.178487Z] Info :   spi_irq_pin = 22
[2025-07-09T13:10:44.178500Z] Info :   fwu_recovery_pins_enabled = false
[2025-07-09T13:10:44.178515Z] Info :   fwu_connect_to_bootloader = false
[2025-07-09T13:10:44.178529Z] Info :   fwu_enter_bootloader = false
[2025-07-09T13:10:44.178542Z] Info :   restart_cpcd = false
[2025-07-09T13:10:44.178556Z] Info :   application_version_validation = false
[2025-07-09T13:10:44.178569Z] Info :   print_secondary_versions_and_exit = false
[2025-07-09T13:10:44.178583Z] Info :   use_noop_keep_alive = false
[2025-07-09T13:10:44.178597Z] Info :   reset_sequence = true
[2025-07-09T13:10:44.178610Z] Info :   stats_interval = 0
[2025-07-09T13:10:44.178624Z] Info :   rlimit_nofile = 2000
[2025-07-09T13:10:44.178638Z] Info : ENCRYPTION IS DISABLED
[2025-07-09T13:10:44.178754Z] Gpio : Opening gpio #22 on chip gpiochip0. Direction : IN, edge : FALLING
[2025-07-09T13:10:44.180595Z] Info : Starting daemon in normal mode
[2025-07-09T13:10:44.180653Z] Gpio : Opening gpio #22 on chip gpiochip0. Direction : IN, edge : FALLING
[2025-07-09T13:10:44.181266Z] Driver : Thread start
[2025-07-09T13:10:44.181352Z] Driver : Opening spi file /dev/spidev0.0
[2025-07-09T13:10:44.181371Z] Driver : Init done
[2025-07-09T13:10:44.181511Z] Core : Changing ep#0 state from SLI_CPC_STATE_CLOSED to SLI_CPC_STATE_CONNECTED
[2025-07-09T13:10:44.181558Z] Core : open ep #0
[2025-07-09T13:10:44.181613Z] Server : Cleaning up socket folder /dev/shm/cpcd/cpcd_0
[2025-07-09T13:10:44.181707Z] Server : Removing /dev/shm/cpcd/cpcd_0/reset.cpcd.sock
[2025-07-09T13:10:44.181770Z] Server : Removing /dev/shm/cpcd/cpcd_0/ctrl.cpcd.sock
[2025-07-09T13:10:44.182031Z] Info : Connecting to Secondary...
[2025-07-09T13:10:44.182262Z] Core : Pushed frame to driver : 14:00:0E:00:C4:95:0F:03:00:08:00:02:02:00:00:00:00:00:00:91:A0
[2025-07-09T13:10:44.182330Z] Core : txd transmit completed
[2025-07-09T13:10:44.182347Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.182363Z] System : Submitted command_id #3 command_seq #0
[2025-07-09T13:10:44.182378Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.182418Z] System : property-set (id #3) sent with property #514
[2025-07-09T13:10:44.182424Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.182436Z] Reset Sequence : Reboot mode sent
[2025-07-09T13:10:44.182661Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.183050Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.183075Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.183262Z] Driver : Clocked in this header : 14:00:0E:00:C4:95:0F
[2025-07-09T13:10:44.183549Z] Driver : Sent frame to core : 14:00:0E:00:C4:95:0F:06:00:08:00:02:02:00:00:00:00:00:00:30:AE
[2025-07-09T13:10:44.183635Z] Core : rxd frame : 14:00:0E:00:C4:95:0F:06:00:08:00:02:02:00:00:00:00:00:00:30:AE
[2025-07-09T13:10:44.183663Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.183684Z] System : Processing command seq#0 of type 3
[2025-07-09T13:10:44.183747Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.183763Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.183858Z] Core : Pushed frame to driver : 14:00:06:00:C4:34:A6:01:01:00:00:84:41
[2025-07-09T13:10:44.183899Z] Core : txd transmit completed
[2025-07-09T13:10:44.183916Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.183931Z] System : Submitted command_id #1 command_seq #1
[2025-07-09T13:10:44.183980Z] System : reset (id #1) sent
[2025-07-09T13:10:44.183996Z] Reset Sequence : Reboot mode reply received, reset request sent
[2025-07-09T13:10:44.184034Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.184060Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.184337Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.184708Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.184735Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.184903Z] Driver : Clocked in this header : 14:00:0A:00:C4:55:D3
[2025-07-09T13:10:44.185145Z] Driver : Sent frame to core : 14:00:0A:00:C4:55:D3:01:01:04:00:00:00:00:00:13:F9
[2025-07-09T13:10:44.185199Z] Core : rxd frame : 14:00:0A:00:C4:55:D3:01:01:04:00:00:00:00:00:13:F9
[2025-07-09T13:10:44.185224Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.185242Z] System : Processing command seq#1 of type 3
[2025-07-09T13:10:44.185284Z] System : on_final_reset()
[2025-07-09T13:10:44.185300Z] Reset Sequence : Reset request response received : 0
[2025-07-09T13:10:44.185316Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.185330Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.185344Z] Reset Sequence : Reset request acknowledged, waiting for device to reset
[2025-07-09T13:10:44.479121Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.479174Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.479370Z] Driver : Clocked in this header : 14:00:0E:00:C0:11:4F
[2025-07-09T13:10:44.479678Z] Driver : Sent frame to core : 14:00:0E:00:C0:11:4F:06:00:08:00:00:00:00:00:73:00:00:00:DC:98
[2025-07-09T13:10:44.479747Z] Core : rxd frame : 14:00:0E:00:C0:11:4F:06:00:08:00:00:00:00:00:73:00:00:00:DC:98
[2025-07-09T13:10:44.479775Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.479794Z] System : Unsolicited uframe received
[2025-07-09T13:10:44.479811Z] Reset Sequence : Received reset reason : 115
[2025-07-09T13:10:44.479825Z] Reset Sequence : Reset sequence: 3
[2025-07-09T13:10:44.479839Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.479853Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.479868Z] Reset Sequence : Waiting for reset reason
[2025-07-09T13:10:44.479881Z] Reset Sequence : Reset reason received
[2025-07-09T13:10:44.479920Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:02:04:00:20:00:00:00:AA:DE
[2025-07-09T13:10:44.479957Z] Core : txd transmit completed
[2025-07-09T13:10:44.479974Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.479989Z] System : Submitted command_id #2 command_seq #2
[2025-07-09T13:10:44.480044Z] System : property-get (id #2) sent with property 0x20
[2025-07-09T13:10:44.480086Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.480111Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.480290Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.480692Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.480717Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.480902Z] Driver : Clocked in this header : 14:00:0C:00:C4:F5:61
[2025-07-09T13:10:44.481161Z] Driver : Sent frame to core : 14:00:0C:00:C4:F5:61:06:02:06:00:20:00:00:00:F6:07:9B:C9
[2025-07-09T13:10:44.481217Z] Core : rxd frame : 14:00:0C:00:C4:F5:61:06:02:06:00:20:00:00:00:F6:07:9B:C9
[2025-07-09T13:10:44.481241Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.481260Z] System : Processing command seq#2 of type 3
[2025-07-09T13:10:44.481315Z] Reset Sequence : Received RX capability of 2038 bytes
[2025-07-09T13:10:44.481331Z] Info : RX capability is 2038 bytes
[2025-07-09T13:10:44.481348Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.481361Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.481375Z] Reset Sequence : Obtained RX capability
[2025-07-09T13:10:44.481388Z] Info : Connected to Secondary
[2025-07-09T13:10:44.481421Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:03:04:00:01:00:00:00:31:27
[2025-07-09T13:10:44.481540Z] Core : txd transmit completed
[2025-07-09T13:10:44.481558Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.481588Z] System : Submitted command_id #2 command_seq #3
[2025-07-09T13:10:44.481634Z] System : property-get (id #2) sent with property 0x1
[2025-07-09T13:10:44.481677Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.481704Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.481939Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.482261Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.482387Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.482631Z] Driver : Clocked in this header : 14:00:0B:00:C4:65:E4
[2025-07-09T13:10:44.482874Z] Driver : Sent frame to core : 14:00:0B:00:C4:65:E4:06:03:05:00:01:00:00:00:06:CD:21
[2025-07-09T13:10:44.482928Z] Core : rxd frame : 14:00:0B:00:C4:65:E4:06:03:05:00:01:00:00:00:06:CD:21
[2025-07-09T13:10:44.482952Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.482971Z] System : Processing command seq#3 of type 3
[2025-07-09T13:10:44.483015Z] Info : Secondary Protocol v6
[2025-07-09T13:10:44.483033Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.483048Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.483062Z] Reset Sequence : Obtained Protocol version
[2025-07-09T13:10:44.483095Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:04:04:00:02:00:00:00:A9:A5
[2025-07-09T13:10:44.483133Z] Core : txd transmit completed
[2025-07-09T13:10:44.483149Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.483164Z] System : Submitted command_id #2 command_seq #4
[2025-07-09T13:10:44.483204Z] System : property-get (id #2) sent with property 0x2
[2025-07-09T13:10:44.483243Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.483267Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.483442Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.483758Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.483783Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.483952Z] Driver : Clocked in this header : 14:00:0E:00:C4:95:0F
[2025-07-09T13:10:44.484233Z] Driver : Sent frame to core : 14:00:0E:00:C4:95:0F:06:04:08:00:02:00:00:00:00:00:00:00:94:9F
[2025-07-09T13:10:44.484284Z] Core : rxd frame : 14:00:0E:00:C4:95:0F:06:04:08:00:02:00:00:00:00:00:00:00:94:9F
[2025-07-09T13:10:44.484307Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.484324Z] System : Processing command seq#4 of type 3
[2025-07-09T13:10:44.484360Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.484377Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.484391Z] Reset Sequence : Obtained Capabilities
[2025-07-09T13:10:44.484418Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:05:04:00:03:00:00:00:7C:6B
[2025-07-09T13:10:44.484455Z] Core : txd transmit completed
[2025-07-09T13:10:44.484471Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.484496Z] System : Submitted command_id #2 command_seq #5
[2025-07-09T13:10:44.484531Z] System : property-get (id #2) sent with property 0x3
[2025-07-09T13:10:44.484568Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.484593Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.484770Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.485219Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.485248Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.485455Z] Driver : Clocked in this header : 14:00:16:00:C4:57:E5
[2025-07-09T13:10:44.485954Z] Driver : Sent frame to core : 14:00:16:00:C4:57:E5:06:05:10:00:03:00:00:00:04:00:00:00:07:00:00:00:00:00:00:00:D4:FB
[2025-07-09T13:10:44.486013Z] Core : rxd frame : 14:00:16:00:C4:57:E5:06:05:10:00:03:00:00:00:04:00:00:00:07:00:00:00:00:00:00:00:D4:FB
[2025-07-09T13:10:44.486040Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.486061Z] System : Processing command seq#5 of type 3
[2025-07-09T13:10:44.486105Z] Info : Secondary CPC v4.7.0
[2025-07-09T13:10:44.486191Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.486207Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.486221Z] Reset Sequence : Obtained Secondary CPC version
[2025-07-09T13:10:44.486258Z] Core : Pushed frame to driver : 14:00:0E:00:C4:95:0F:03:06:08:00:60:00:00:00:04:07:00:00:F9:7C
[2025-07-09T13:10:44.486298Z] Core : txd transmit completed
[2025-07-09T13:10:44.486314Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.486329Z] System : Submitted command_id #3 command_seq #6
[2025-07-09T13:10:44.486371Z] System : property-set (id #3) sent with property #96
[2025-07-09T13:10:44.486412Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.486437Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.486615Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.487000Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.487025Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.487191Z] Driver : Clocked in this header : 14:00:0A:00:C4:55:D3
[2025-07-09T13:10:44.487413Z] Driver : Sent frame to core : 14:00:0A:00:C4:55:D3:06:06:04:00:60:00:00:00:9D:7E
[2025-07-09T13:10:44.487465Z] Core : rxd frame : 14:00:0A:00:C4:55:D3:06:06:04:00:60:00:00:00:9D:7E
[2025-07-09T13:10:44.487487Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.487504Z] System : Processing command seq#6 of type 3
[2025-07-09T13:10:44.487539Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.487555Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.487570Z] Reset Sequence : Obtained Set Primary Version Reply
[2025-07-09T13:10:44.487596Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:07:04:00:40:00:00:00:DF:FE
[2025-07-09T13:10:44.487632Z] Core : txd transmit completed
[2025-07-09T13:10:44.487649Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.487663Z] System : Submitted command_id #2 command_seq #7
[2025-07-09T13:10:44.487696Z] System : property-get (id #2) sent with property 0x40
[2025-07-09T13:10:44.487733Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.487758Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.487931Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.488258Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.488283Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.488449Z] Driver : Clocked in this header : 14:00:0E:00:C4:95:0F
[2025-07-09T13:10:44.488729Z] Driver : Sent frame to core : 14:00:0E:00:C4:95:0F:06:07:08:00:40:00:00:00:00:00:00:00:18:9E
[2025-07-09T13:10:44.488780Z] Core : rxd frame : 14:00:0E:00:C4:95:0F:06:07:08:00:40:00:00:00:00:00:00:00:18:9E
[2025-07-09T13:10:44.488803Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.488820Z] System : Processing command seq#7 of type 3
[2025-07-09T13:10:44.488852Z] Info : Secondary bus bitrate is 0
[2025-07-09T13:10:44.488870Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.488895Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.488922Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:08:04:00:50:00:00:00:91:6F
[2025-07-09T13:10:44.489166Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.489407Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.489472Z] Core : txd transmit completed
[2025-07-09T13:10:44.489491Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.489507Z] System : Submitted command_id #2 command_seq #8
[2025-07-09T13:10:44.489779Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.489545Z] System : property-get (id #2) sent with property 0x50
[2025-07-09T13:10:44.490154Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.490181Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.490431Z] Driver : Clocked in this header : 14:00:0E:00:C4:95:0F
[2025-07-09T13:10:44.490721Z] Driver : Sent frame to core : 14:00:0E:00:C4:95:0F:06:08:08:00:50:00:00:00:80:96:98:00:7C:AE
[2025-07-09T13:10:44.490777Z] Core : rxd frame : 14:00:0E:00:C4:95:0F:06:08:08:00:50:00:00:00:80:96:98:00:7C:AE
[2025-07-09T13:10:44.490802Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.490821Z] System : Processing command seq#8 of type 3
[2025-07-09T13:10:44.490866Z] Info : Secondary max bus bitrate is 10000000
[2025-07-09T13:10:44.490883Z] Info : The negotiated SPI bitrate will be 10000000
[2025-07-09T13:10:44.490900Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.490915Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.490949Z] Core : Pushed frame to driver : 14:00:0A:00:C4:55:D3:02:09:04:00:04:00:00:00:3A:68
[2025-07-09T13:10:44.490987Z] Core : txd transmit completed
[2025-07-09T13:10:44.491003Z] Core : Endpoint #0: frame transmit submitted
[2025-07-09T13:10:44.491018Z] System : Submitted command_id #2 command_seq #9
[2025-07-09T13:10:44.491124Z] System : property-get (id #2) sent with property 0x4
[2025-07-09T13:10:44.491165Z] Driver : Init of a transaction caused by the core
[2025-07-09T13:10:44.491191Z] Driver : Primary has a frame to send
[2025-07-09T13:10:44.491240Z] Driver : Clocked in this header : 00:00:00:00:00:00:00
[2025-07-09T13:10:44.491472Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.491497Z] Driver : Secondary signaled a frame to send
[2025-07-09T13:10:44.491538Z] Driver : Clocked in this header : 14:00:11:00:C4:C7:60
[2025-07-09T13:10:44.491647Z] Driver : Sent frame to core : 14:00:11:00:C4:C7:60:06:09:0B:00:04:00:00:00:32:2E:31:30:2E:30:00:18:4D
[2025-07-09T13:10:44.491697Z] Core : rxd frame : 14:00:11:00:C4:C7:60:06:09:0B:00:04:00:00:00:32:2E:31:30:2E:30:00:18:4D
[2025-07-09T13:10:44.491721Z] Core : Endpoint #0: rxd unnumbered frame
[2025-07-09T13:10:44.491739Z] System : Processing command seq#9 of type 3
[2025-07-09T13:10:44.491795Z] Info : Secondary APP v2.10.0
[2025-07-09T13:10:44.491814Z] Core : Endpoint #0: unnumbered frame processed
[2025-07-09T13:10:44.491828Z] Core : rxd uframe with valid header checksum
[2025-07-09T13:10:44.491842Z] Reset Sequence : Obtained Secondary APP version
[2025-07-09T13:10:44.492150Z] Security : Encryption is disabled
[2025-07-09T13:10:44.492169Z] Core : Security changed state: 0 -> 1
[2025-07-09T13:10:44.492185Z] Info : Daemon startup was successful. Waiting for client connections
```

An abstract is:

```bash
 $ sudo cpcd --conf /usr/local/etc/cpcd.conf
WARNING in function 'main' in file /home/pi/cpc_daemon/main.c at line #68 : Running CPCd as 'root' is not recommended. Proceed at your own risk.
[2025-07-09T13:10:44.177112Z] Info : [CPCd v4.7.0.0] [Library API v3] [RCP Protocol v6]
. . .
[2025-07-09T13:10:44.177487Z] WARNING : In function 'main' in file /home/pi/cpc_daemon/main.c at line #68 : Running CPCd as 'root' is not recommended. Proceed at your own risk.
[2025-07-09T13:10:44.177578Z] Info : Reading cli arguments
[2025-07-09T13:10:44.177657Z] Info : cpcd --conf /usr/local/etc/cpcd.conf
[2025-07-09T13:10:44.178256Z] Info : Reading configuration
[2025-07-09T13:10:44.178275Z] Info :   file_path = /usr/local/etc/cpcd.conf
[2025-07-09T13:10:44.178291Z] Info :   instance_name = cpcd_0
. . .
[2025-07-09T13:10:44.178430Z] Info :   bus = SPI
[2025-07-09T13:10:44.178445Z] Info :   spi_file = /dev/spidev0.0
[2025-07-09T13:10:44.178458Z] Info :   spi_bitrate = 10000000
[2025-07-09T13:10:44.178473Z] Info :   spi_irq_chip = gpiochip0
[2025-07-09T13:10:44.178487Z] Info :   spi_irq_pin = 22
. . .
[2025-07-09T13:10:44.178597Z] Info :   reset_sequence = true
. . .
[2025-07-09T13:10:44.178638Z] Info : ENCRYPTION IS DISABLED
. . .
[2025-07-09T13:10:44.181352Z] Driver : Opening spi file /dev/spidev0.0
[2025-07-09T13:10:44.181371Z] Driver : Init done
. . .
[2025-07-09T13:10:44.182031Z] Info : Connecting to Secondary...
. . .
[2025-07-09T13:10:44.182436Z] Reset Sequence : Reboot mode sent
. . .
[2025-07-09T13:10:44.183996Z] Reset Sequence : Reboot mode reply received, reset request sent
. . .
[2025-07-09T13:10:44.184735Z] Driver : Secondary signaled a frame to send
. . .
[2025-07-09T13:10:44.185199Z] Core : rxd frame : 14:00:0A:00:C4:55:D3:01:01:04:00:00:00:00:00:13:F9
. . .
[2025-07-09T13:10:44.185284Z] System : on_final_reset()
[2025-07-09T13:10:44.185300Z] Reset Sequence : Reset request response received : 0
. . .
[2025-07-09T13:10:44.185344Z] Reset Sequence : Reset request acknowledged, waiting for device to reset
[2025-07-09T13:10:44.479121Z] Driver : Init of a transaction caused by the IRQ line
[2025-07-09T13:10:44.479174Z] Driver : Secondary signaled a frame to send
. . .
[2025-07-09T13:10:44.481315Z] Reset Sequence : Received RX capability of 2038 bytes
[2025-07-09T13:10:44.481331Z] Info : RX capability is 2038 bytes
. . .
[2025-07-09T13:10:44.481375Z] Reset Sequence : Obtained RX capability
[2025-07-09T13:10:44.481388Z] Info : Connected to Secondary
. . .
[2025-07-09T13:10:44.492150Z] Security : Encryption is disabled
[2025-07-09T13:10:44.492169Z] Core : Security changed state: 0 -> 1
[2025-07-09T13:10:44.492185Z] Info : Daemon startup was successful. Waiting for client connections
```

**When you get the `Daemon startup was successful. Waiting for client connections` message, you're ready to start `wsbrd`.**

###### Starting `cpcd` before starting `wsbrd`

If `cpcd` is not running when `wsbrd` is launched, the following error will occur:

```bash
 $ sudo wsbrd --conf /etc/wsbrd.conf
Silicon Labs Wi-SUN border router v2.2
cpc_init: Connection refused
```

###### Starting `cpcd` as a Service (heading level 7)

This is an option. Probably the best, with `Restart=on-failure`.

```bash
nano $ sudo nano /usr/local/lib/systemd/system/cpcd.service
```

```bash
$ cat /usr/local/lib/systemd/system/cpcd.service
##### SPDX-License-Identifier: GPL-2.0 or APACHE-2.0
[Unit]
Description=Silicon Labs CPC Service
Documentation=file:////usr/local/etc/cpcd.conf
After=network.target
After=freeradius.service
##### If you rely on an external DHCP server, don't forget to add a dependency here

[Service]
ExecStart=cpcd --conf /usr/local/etc/cpcd.conf
Restart=on-failure

[Install]
WantedBy=multi-user.target
```

###### Checking `cpcd` Service Status (heading level 7)

```bash
 $ sudo systemctl status cpcd.service
● cpcd.service - Silicon Labs CPC Service
     Loaded: loaded (/usr/local/lib/systemd/system/cpcd.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2025-07-09 15:15:24 CEST; 2s ago
       Docs: file:////usr/local/etc/cpcd.conf
   Main PID: 2110 (cpcd)
      Tasks: 4 (limit: 1595)
        CPU: 19ms
     CGroup: /system.slice/cpcd.service
             └─2110 cpcd --conf /usr/local/etc/cpcd.conf

Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668762Z] Core : rxd frame : 14:00:11:00:C4:C7:60:06:09:0B:00:04:00:00:00:32:2E:31:30:2E:30:00:18:4D
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668788Z] Core : Endpoint #0: rxd unnumbered frame
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668808Z] System : Processing command seq#9 of type 3
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668872Z] Info : Secondary APP v2.10.0
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668892Z] Core : Endpoint #0: unnumbered frame processed
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668906Z] Core : rxd uframe with valid header checksum
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.668921Z] Reset Sequence : Obtained Secondary APP version
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.669204Z] Security : Encryption is disabled
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.669224Z] Core : Security changed state: 0 -> 1
Jul 09 15:15:25 rns-md-wisun-direct-connect cpcd[2110]: [2025-07-09T13:15:24.669239Z] Info : Daemon startup was successful. Waiting for client connections
```

###### CPC/wsbrd Communication (heading level 7)

A full log is provided below, obtained with `sudo wsbrd --conf /etc/wsbrd.conf -T cpc`.

[Click to expand and view the full log]
```bash
$ sudo wsbrd --conf /etc/wsbrd.conf -T cpc
Silicon Labs Wi-SUN border router v2.2
[2025-04-25T14:36:36.166444Z] libcpc(cpcd_0:1673) [cpc_init:732]: libcpc version: v4.4.2.0
[2025-04-25T14:36:36.166722Z] libcpc(cpcd_0:1673) [cpc_init:733]: libcpc API version: v3
[2025-04-25T14:36:36.167622Z] libcpc(cpcd_0:1673) [get_secondary_app_version:403]: secondary application is v2.6.1
[2025-04-25T14:36:36.168110Z] libcpc(cpcd_0:1673) [cpc_init:841]: cpc lib initialized
[2025-04-25T14:36:36.168184Z] libcpc(cpcd_0:1673) [cpc_open_endpoint:1107]: opening EP #10
[2025-04-25T14:36:36.170290Z] libcpc(cpcd_0:1673) [cpc_open_endpoint:1238]: opened EP #10
1745591796.170425: hif tx: REQ_RESET 00
[2025-04-25T14:36:36.170481Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.170530Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
[2025-04-25T14:36:36.171476Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1439]: reading from EP #10
[2025-04-25T14:36:36.171532Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1459]: read from EP #10
1745591796.171573: hif rx: IND_RESET 01 06 00 02 00 05 00 02 32 2e 35 2e 30 00 60 a4 23 ff fe 37 ac 96
Connected to RCP "2.5.0" (2.5.0), API 2.6.1
1745591796.171699: hif tx: SET_HOST_API 00 00 00 02
[2025-04-25T14:36:36.171733Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.171780Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.171819: hif tx: REQ_RADIO_LIST
[2025-04-25T14:36:36.171841Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.171886Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
[2025-04-25T14:36:36.171925Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1439]: reading from EP #10
[2025-04-25T14:36:36.173445Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1459]: read from EP #10
1745591796.173504: hif rx: CNF_RADIO_LIST 0f 01 00 00 01 60 dc 71 33 a0 86 01 00 45 00 91 ff 01 00 03 60 dc 71 33 40 0d 03 00 23 00 94 ff ff 01 50 60 dc 71 33 40 0d 03*
1745591796.185361: hif tx: SET_RADIO_TX_POWER 00
[2025-04-25T14:36:36.185454Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.185709Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
[INFO][addr]: Address added to IF 1: fe80::62a4:23ff:fe37:ac96
[DBG ][addr]: LL64 Register OK!
[INFO][rout]: Added route:
[DBG ][rout]:                 fe80::/64 if:1 src:'Static' id:0 lifetime:infinite
[DBG ][rout]:      On-link (met 128)
[INFO][rout]: Added route:
[DBG ][rout]:                  ff00::/8 if:1 src:'Static' id:0 lifetime:infinite
[DBG ][rout]:      On-link (met 192)
[INFO][addr]: Address added to IF 1: fd12:3456::62a4:23ff:fe37:ac96
[INFO][rout]: Added route:
[DBG ][rout]:  fd12:3456::62a4:23ff:fe37:ac96/128 if:1 src:'Loopback' id:0 lifetime:infinite
[DBG ][rout]:      On-link (met 128)
1745591796.187886: tkl RPL DIO  reset: t=492s I[525,1049]=584s k=0
Successfully registered to system DBus
[INFO][wsbs]: Wi-SUN packet congestion minTh 150, maxTh 300, drop probability 10 weight 32, Packet/Seconds 5
[INFO][wspc]: Read GTK frame counter: index 0 value 10000000
[INFO][wspc]: Read LGTK frame counter: index 0 value 10000000
PAN version number update
1745591796.198983: tkl (null)   reset: t=38s I[60,960]=60s k=1
1745591796.200975: hif tx: SET_FHSS_UC ff 02 20 ff ff ff 27 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-04-25T14:36:36.201199Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.201488Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.201544: hif tx: SET_FHSS_FFN_BC fc 03 00 55 e3 ff 02 20 ff ff ff 27 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-04-25T14:36:36.201662Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.201780Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.201901: hif tx: SET_FHSS_LFN_BC 60 ea 00 55 e3 02 20 ff ff ff 27 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-04-25T14:36:36.203242Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.203362Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.203467: hif tx: SET_FHSS_ASYNC f4 01 00 00 20 ff ff ff 27 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[2025-04-25T14:36:36.203579Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.203625Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.203665: hif tx: SET_RADIO 01 00 01
[2025-04-25T14:36:36.203699Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.203821Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.203875: hif tx: SET_FILTER_PANID 28 97
[2025-04-25T14:36:36.203904Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.203944Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.204013: hif tx: REQ_RADIO_ENABLE
[2025-04-25T14:36:36.204036Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.204090Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
  domain: EU
  channel plan id: 33
  phy mode id: 0x03
  phy operating modes: 1, 84, 85, 86
  RCP configuration index: 1
  channel 0 frequency: 863.1MHz
  channel spacing: 200kHz
  channel count: 35
  channel masks:
               advertised      effective
     unicast   --              00:00:00:d8:fb
     broadcast --              00:00:00:d8:fb
     async     --              00:00:00:d8:fb

Nodes join ability:
  rank    FFN1.0    FFN1.1    LFN
    1     no        yes       yes
   >1     no        yes       can[1]
  [1]: neighboring routers must use a channel plan 2 (reg. domain & ChanPlanId)

[INFO][wspc]: GTK hash set 60:95:a3:eb:29:24:a1:8a 00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00
[INFO][wspc]: NW key set: 0, hash: 60:95:a3:eb:29:24:a1:8a
1745591796.207604: hif tx: SET_SEC_KEY 01 dd cd bb 4f ba 43 76 2f 64 07 10 01 11 5c be 9d 80 96 98 00
[2025-04-25T14:36:36.207731Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.207799Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
[INFO][wspc]: LGTK hash set 65:93:0e:11:4e:fd:de:72 00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00
[INFO][wspc]: NW key set: 4, hash: 65:93:0e:11:4e:fd:de:72
1745591796.209030: hif tx: SET_SEC_KEY 05 21 42 c1 b4 59 97 51 53 e8 30 bb ef 13 e9 ae 15 80 96 98 00
[2025-04-25T14:36:36.209105Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.209172Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
[INFO][wspc]: NW send key index set: 0
[INFO][wspc]: NW send key index set: 4
1745591796.209661: tkl ADV      reset: t=536s I[60,960]=797s k=1
1745591796.209700: tkl CFG      reset: t=170s I[60,960]=259s k=1
1745591796.210187: tx-15.4 adv       dst:00:00:00:00:00:00:00:00
1745591796.210566: hif tx: REQ_DATA_TX 00 4b 00 01 e3 28 97 96 ac 37 fe ff 23 a4 60 05 15 01 00 00 00 00 00 3f 34 a0 06 88 ff ff 00 12 03 21 05 04 00 00 00 00 43 17*
[2025-04-25T14:36:36.210693Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.210771Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
1745591796.211121: tx-15.4 cfg       dst:00:00:00:00:00:00:00:00
1745591796.211223: hif tx: REQ_DATA_TX 01 7f 00 09 e3 28 97 96 ac 37 fe ff 23 a4 60 0e aa aa aa aa 01 05 15 01 02 00 00 00 06 15 02 00 00 00 00 00 05 15 c0 60 ea 00*
[2025-04-25T14:36:36.211343Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1524]: writing to EP #10
[2025-04-25T14:36:36.211404Z] libcpc(cpcd_0:1673) [cpc_write_endpoint:1540]: wrote to EP #10
Wi-SUN Border Router is ready
1745591796.211758: drop tun      : unsupported ICMPv6 type 133
1745591796.211821: drop tun      : unsupported dst=ff02::16
[2025-04-25T14:36:36.568841Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1439]: reading from EP #10
[2025-04-25T14:36:36.568918Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1459]: read from EP #10
1745591796.568940: hif rx: CNF_DATA_TX 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
1745591796.820307: drop tun      : unsupported dst=ff02::16
1745591797.160343: drop tun      : unsupported dst=ff02::16
[2025-04-25T14:36:38.241676Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1439]: reading from EP #10
[2025-04-25T14:36:38.241783Z] libcpc(cpcd_0:1673) [cpc_read_endpoint:1459]: read from EP #10
1745591798.241823: hif rx: CNF_DATA_TX 01 00 00 00 00 00 00 00 00 00 00 00 00 00 98 96 98 00 00 00 00 00 00
```

> **Note**: Once CPC is working, removing `-T cpc` is recommended.

If the `Connected to RCP "x.y.z" (x.y.z), API t.u.v` message is present, everything is working as expected (the RCP version string comes from the RCP binary, not from `wsbrd`).

##### External Servers

Silicon Labs provides external DHCPv6 and authentication servers with configuration examples to give you the possibility of managing your network at a large scale, and to avoid using the internal default server that is meant for an out-of-the-box experience, and doesn’t allow too much flexibility in configuration.

The external DHCPv6 servers can help you unify the IPv6 routing around all your nodes, instead of having different prefixes set by each of your border routers. And having an external authentication server, will let you manage authentication on all your network using one server.

![Wi-SUN Field Area Network connected to external servers](/wisun-linux-border-router/0.1/images/sld993-image11.png)

Refer to the [Wi-SUN Linux Border Router repository](https://github.com/SiliconLabs/wisun-br-linux) Readme and follow the guidelines to use the configuration examples.

#### IP Communication

##### IP Communication

This section provides guidelines to ping a Wi-SUN device from the Raspberry Pi running wsbrd. These guidelines assume that wsbrd has been configured and is running on the Raspberry Pi.

- [**Ping and UDP**](/wisun/2.12.0/wisun-ip-communication/02-ping-and-udp): Detailed guidelines to ping the nodes after they are connected to the Border Router and perform UDP communication between using Netcat.
- [**CoAP**](/wisun/2.12.0/wisun-ip-communication/03-coap): Get the Wi-SUN Meter temperature and humidity values and control the boards LEDs using CoAP.
- [**Wi-SUN Multicast**](/wisun/2.12.0/wisun-ip-communication/04-multicast): Silicon Labs Wi-SUN stack implements Multicast Protocol for Low-Power and Lossy Networks (MPL) as described in RFC7731, to support multicast packets messaging specified in the Wi-SUN FAN Technical Profile Specification version 1.1v06.

##### Ping and UDP

To complete the following steps correctly, you need a Wi-SUN node running the **Wi-SUN – SoC Ping** application on the network. For more information, see the [Quick Start Guide](/wisun/2.12.0/wisun-getting-started-development) for details on how to bring-up the Wi-SUN Ping project.

###### Connect a Wi-SUN Node to the Border Router

After the project is flashed and running on the Wi-SUN device, connect to the CLI interface. From this interface, retrieve the Wi-SUN border router IP address and the Wi-SUN node IP address by executing **wisun get wisun**. They are available only if the device is successfully connected. If this is not the case, wait for the connection process to complete. If the connection is not successful, verify the border router and router configurations match (network name, Wi-SUN PHY, certificates, and so on). You should get the following trace on the console.

```C
> wisun get wisun
wisun.network_name = Wi-SUN Network
wisun.phy_config_type = FAN 1.1 (1)
wisun.network_size = small (1)
wisun.tx_power = 20
wisun.regulatory_domain = NA (1)
wisun.operating_class = 0 (unused)
wisun.operating_mode = 0x0 (unused)
wisun.chan_plan_id = 1
wisun.phy_mode_id = 2
wisun.ch0_frequency = 0 (unused)
wisun.number_of_channels = 0 (unused)
wisun.channel_spacing = 100kHz (0) (unused)
wisun.join_state = Operational (5)
wisun.ip_address_global = fd12:3456::be33:acff:fef6:3161
wisun.ip_address_link_local = fe80::be33:acff:fef6:3161
wisun.ip_address_border_router = fd12:3456::86fd:27ff:fefe:55bd
wisun.ip_address_primary_parent = fd12:3456::86fd:27ff:fefe:55bd
wisun.regulation = none (0)
wisun.regulation_warning_threshold = 85
wisun.regulation_alert_threshold = 95
```

The Wi-SUN border router IP address is fd12:3456::86fd:27ff:fefe:55bd (wisun.ip_address_border_router value). The Wi-SUN node IP address is fd12:3456::be33:acff:fef6:3161 (wisun.ip_address_global value). These IP addresses are used in the following steps to address the devices.

###### Check the Communication Between the Raspberry Pi and the Node

From the same Linux terminal, ping the Wi-SUN node.

```C
$ ping fd12:3456::be33:acff:fef6:3161

PING fd12:3456::be33:acff:fef6:3161(fd12:3456::be33:acff:fef6:3161) 56 data bytes
64 bytes from fd12:3456::be33:acff:fef6:3161: icmp_seq=1 ttl=64 time=675 ms
64 bytes from fd12:3456::be33:acff:fef6:3161: icmp_seq=2 ttl=64 time=680 ms
64 bytes from fd12:3456::be33:acff:fef6:3161: icmp_seq=3 ttl=64 time=705 ms
64 bytes from fd12:3456::be33:acff:fef6:3161: icmp_seq=4 ttl=64 time=925 ms
64 bytes from fd12:3456::be33:acff:fef6:3161: icmp_seq=5 ttl=64 time=281 ms
64 bytes from fd12:3456::be33:acff:fef6:3161: icmp_seq=6 ttl=64 time=149 ms
```

This communication goes through the Linux IP interface to the communication bus. It is then received by the EFR32 running the RCP image and sent over the air using the Wi-SUN protocol. Finally, the packet is received by the Wi-SUN node which replies with its own packet. The new packet takes the same route the other way round. The latency is the accumulation of all the step durations.

You have successfully opened an upstream communication between the Wi-SUN network and a device in the backhaul network. To go further, you can use this new communication link to open TCP/UDP sockets between a Wi-SUN node and the Linux host.

###### Send and Receive UDP Data

Assuming that you have retrieved the iPv6 addresses of the border router and the node, as explained in the beginning of this page. And you have a Wi-SUN node running **Wi-SUN – SoC CLI** project. You can send and receive UDP data using netcat server.

###### Send UDP data (heading level 7)

To send data, make sure to open a UDP server port on your node first, using the following command:

```C
wisun udp_server [port]
```

And on your Linux host, use netcat command to send UDP data:

```C
$nc -u [Wi-SUN node IP address] [port]
```

###### Receive UDP Data (heading level 7)

To receive data on your Linux host, open a UDP server port using netcat command:

```C
$nc -6 -lu [port]
```

Then you can send data from your node with the following commands:

```C
wisun udp_client [Wi-SUN border router IP address] [port]

wisun socket_write [Socket ID] [Wi-SUN border router IP address] [Port] [Message]
```

Note that the Socket ID value, will be returned with command `wisun udp_client`.

##### CoAP Communication

###### Get the Metering Data

The Raspberry Pi gets CoAP metering data from the CoAP meter node using the libcoap client, if you have a node running **Wi-SUN SoC CoAP Meter** in the same network with the Linux Border Router. Follow the steps below to get CoAP metering data on your Raspberry Pi:

1. Install the libcoap library.  
   ```c  
    $sudo apt-get install libcoap2  
     
    $sudo apt-get install libcoap2-bin  
   ```

> On more recent linux kernels, use libcoap3 and the commands with the `-notls` suffix to keep it simple (without TLS authentication), considering that your Wi-SUN network already supports encryption.

1. From the node cli, make sure that you are connected to the network.  
   ```c  
   > wisun get wisun.join_state  
     
   wisun.connection_state = Operational (5)  
   ```
2. Get your node global address.  
   ```C  
   > wisun get wisun.ip_address_global  
     
   wisun.ip_address_global = fd12:3456::be33:acff:fef6:3161  
   ```

###### Discover the Available Resources

The CoAP protocol supports an interoperable discovery feature. A CoAP client can request the attributes hosted by a CoAP server. In the case of the CoAP Meter application, the available resources can be retrieved using the libcoap GET method with the standard discovery entry-point. The following command shows the sensor and LED resources.

```c
$coap-client -m get -N coap://[fd12:3456::be33:acff:fef6:3161]:5683/.well-known/core

</gpio>;ct=40,</sensor>;ct=40,</gpio/led>;rt="led";if="gpio",</sensor/light>;rt="light";if="sensor",</sensor/humidity>;rt="humidity";if="sensor",</sensor/temperature>;rt="temperature";if="sensor",</sensor/all>;rt="all";if="sensor"
```

###### Get the CoAP Meter Sensor Data

On your raspberry Pi, get the CoAP meter sensor data using libcoap with the following command:

```c
$coap-client -m get -N coap://[fd12:3456::be33:acff:fef6:3161]:5683/sensor/all

  {
    "id": 0,
    "temp": 28.18,
    "hum": 46.36,
    "lx": 512
  }
```

Each sensor data value can be retrieved alone if you specify the corresponding resource in the libcoap command. To retrieve the humidity value, the user can use the following command:

```c
$coap-client -m get -N coap://[fd12:3456::be33:acff:fef6:3161]:5683/sensor/humidity

46.59 %
```

Note that any machine that has a CoAP client and an IPv6 connectivity with the CoAP Meter node can get the metering data.

###### Get Help on CoAP Meter Capabilities

```c
$coap-client -t text -m put -N -B 1 coap://[fd12:3456::be33:acff:fef6:3161]:5683/meter/help
```

```c
Command example:
coap-client -m get -N -B 10 -t text coap://[$METER_IPV6_ADDR]:5683/$URI_PATH -e "$PAYLOAD"

Requests:
  [PUT/POST/GET] sensor/all:
    - no payload or "async": GET request to get measurement data
    - "register": POST/PUT request to register collector
    - "remove": POST/PUT request to remove collector
  [GET]       sensor/temperature: Request to get temperature
  [GET]       sensor/humidity: Request to get humidity
  [GET]       sensor/light: Request to get light
  [PUT/POST]  gpio/led: Toggle LED0/LED1. Payload is index of the LED: "0" or "1"
```

###### Toggle the LEDs

The libcoap PUT method allows you to toggle the CoAP Meter node LEDs remotely. Use the following command to toggle the LED0.

```c
$coap-client -t text -m put -N -B 1 coap://[fd12:3456::be33:acff:fef6:3161]:5683/gpio/led -e "0"
```

LED1 can also be toggled with changing the payload to “1”.

##### Wi-SUN Multicast

Silicon Labs Wi-SUN stack implements Multicast Protocol for Low-Power and Lossy Networks (MPL) as described in RFC7731, to support multicast packets messaging specified in the Wi-SUN FAN Technical Profile Specification version 1.1v06.

This page goes over the different aspects of Wi-SUN multicast aspects to allow users sending multicast messages over their Wi-SUN Network.

###### Wi-SUN Multicast Scopes

A **scope zone** as described by [RFC 4007] is a topological span within which the address may be used as a unique identifier for an interface or set of interfaces.

The Wi-SUN FAN Specification requires subscription to a couple of multicast addresses which covers two different scopes:

- **The Link Local scope (`FF02::`)**:  which includes all neighbors in the limit of 1 hop.
- **The Realm Local scope (`FF03::`)**: which includes all the network nodes at any limit of hops.

With the Silicon Labs Wi-SUN FAN Stack, FFNs are able to originate multicast messages destined for the required scopes listed above or any other scope. They are also able to forward multicast messages, whether they originate from the same PAN or from another host.

As the figure below shows, other hosts can send multicast packets destined to multicast groups to which PAN nodes are subscribed. The border router must join those multicast groups to enable forwarding the multicast packets of other hosts into the PAN.

![Wi-SUN Required Scopes](/wisun-ip-communication/0.3/images/wisun-required-scopes.png)

###### Wi-SUN Multicast Addresses

By default, all the Wi-SUN devices subscribe to the ALL_MPL_FORWARDERS address with a realm-local scope: `FF03::FC` as shown in the figure below.

In addition to the ALL_MPL_FORWARDERS address, the Border Router and the FFNs join their FAN interface to several predefined IPv6 multicast groups by default:

- **ff02::1 :** targets all the nodes in the link local scope.
- **ff02::2 :** targets all the routers in the link local scope.
- **ff03::1 :** targets all the nodes in a Realm local scope.
- **ff03::2 :** targets all the routers in a Realm local scope.

The Border Router and FFNs are also able to join other specific Multicast groups different than the ones joined by default.

###### Sending a Multicast Packet in Wi-SUN Network

This section explains how to send a multicast message from the Wi-SUN Linux Border Router ([wsbrd](https://github.com/SiliconLabs/wisun-br-linux)) to the FFN nodes, using a socket created by the python script at the end of this section.

###### Setting Up The Nodes (heading level 7)

1. Run the **Wi_SUN - SoC CLI example** sample application on your nodes.
2. Start a UDP server on the nodes.  
   ```bash  
       wisun  udp_server 1234  
   ```

> For multicast addresses other than the default ones listed in the section [Wi-Sun Multicast Addresses](#wi-sun-multicast-addresses), run the command below to join a multicast group.

```bash
    wisun socket_set_option [socket id] join_multicast_group [multicast address]
```

###### Setting Up The Border Router (heading level 7)

For multicast addresses other than the default ones listed in the section [Wi-Sun Multicast Addresses](#wi-sun-multicast-addresses), run the command below to join a multicast group _(eg: ff03::db8:0:0)_. Check [D-Bus API documentation](https://github.com/SiliconLabs/wisun-br-linux/blob/main/DBUS.md) for more information.

```bash
sudo busctl --system call com.silabs.Wisun.BorderRouter /com/silabs/Wisun/BorderRouter com.silabs.Wisun.BorderRouter JoinMulticastGroup "ay" 16 0xff 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0d 0xb8 0x00 0x00 0x00 0x00
```

> The multicast socket must be bound to the wsbrd interface in order to reach the Wi-SUN PAN. The script used in this document binds the socket to interface tun0 using the socket option [SO_BINDTODEVICE](https://man7.org/linux/man-pages/man7/socket.7.html#:~:text=since%20Linux%204.6.-,SO_BINDTODEVICE,-Bind%20this%20socket).

###### Allow multicast on `tun0` (heading level 8)

```bash
sudo ip link set tun0 multicast on
```

###### Route multicast traffic to `tun0` for common multicast scopes (heading level 8)

```bash
##### Link local Nodes
sudo ip -6 route add ff02::1 dev tun0 table local

##### Link local Routers
sudo ip -6 route add ff02::2 dev tun0 table local

##### Realm Local Nodes
sudo ip -6 route add ff03::1 dev tun0 table local

##### Realm Local Routers
sudo ip -6 route add ff03::2 dev tun0 table local
```

###### Send the Multicast Message (heading level 7)

Run the following command to send a message to all the routers in the Realm Local scope of the Border Router using the script [multicast_packet_send.py](#multicast_packet_sendpy).

```bash
python3 multicast_packet_send.py ff03::2 1234 "Hello World!!"
```

> The script sets the socket limit to 10 hops being that the default value on Linux is 1 hop. The number of hops can be changed by setting the socket option **IPV6_MULTICAST_HOPS** to a different value.

###### multicast_packet_send.py (heading level 8)

```python
import socket
import sys
import time

if len(sys.argv) != 3:
    print(
        'Usage: python3 multicast_packet_send.py [dest IPv6] [dest port] [message]' )
    exit(1)

sock = socket.socket(socket.AddressFamily.AF_INET6,
                     socket.SocketKind.SOCK_DGRAM)
sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 10)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, bytes("tun0", 'ascii'))
sock.sendto(sys.argv[3], (sys.argv[1], int(sys.argv[2])))

print('packet sent')
```

### Platform Resources

#### Platform Resources

When you develop in the Silicon Labs SiSDK, you have additional resources available to you through the Simplicity Platform. This section includes information on the following topics.

- [**Bootloading**](/wisun/2.12.0/wisun-bootloading-overview): Bootloading allows you to update application firmware images on Wi-SUN devices. This section provides background information about bootloading using the Silicon Labs Gecko Bootloader.
- [**Non-Volatile Memory Use**](/wisun/2.12.0/wisun-memory-use-overview): This section offers an introduction to non-volatile data storage and describes how to use NVM3 data storage.
- [**Security**](/wisun/2.12.0/wisun-security-overview): Silicon Labs offers a range of security features depending on the part you are using and your application and production needs. As well as the security features available, this section describes Wi-SUN-specific security design considerations.

#### Bootloading

##### Bootloading Wi-SUN Applications

Bootloading allows you to update application firmware images on Wi-SUN devices. This section provides background information about bootloading using the Silicon
Labs Gecko Bootloader.

- [**Bootloader Fundamentals**](/wisun/2.12.0/bootloader-fundamentals): Introduces bootloading for Silicon Labs networking devices. Discusses the Gecko Bootloader and bootloader file formats.
- [**Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher**](/wisun/2.12.0/bootloader-user-guide-series3-and-higher): Describes the high-level implementation of the Silicon Labs Gecko Bootloader for Series 3 microcontrollers, SoCs (System on Chips), and NCPs (Network Co-Processors), and provides information on different aspects of configuring the Gecko Bootloader.
- [**Silicon Labs Gecko Bootloader User's Guide for SiSDK 4.0 and Higher (series 1 and 2 devices)**](/wisun/2.12.0/bootloader-user-guide-gsdk-4): Describes the high-level implementation of the Silicon Labs Gecko Bootloader for EFR32 SoCs and NCPs, and provides information on how to get started using the Gecko Bootloader with Silicon Labs wireless protocol stacks in SiSDK 4.0 and higher.

##### Bootloader Fundamentals

###### Bootloader Fundamentals

> **Note: This section replaces _UG103.06: Bootloader Fundamentals_. Further updates to this user guide will be provided here**.

This guide introduces bootloading for Silicon Labs networking devices. It describes the concepts of standalone and application bootloaders and discusses their relative strengths and weaknesses. In addition, it looks at design and implementation details for each method. Finally, it describes the bootloader file format.

Silicon Labs’ _Fundamentals_ series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs Bluetooth, and associated development tools. These guides can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

###### Introduction

The bootloader is a program stored in reserved flash memory that can initialize a device, update firmware images, and possibly perform some integrity checks. Firmware image update occurs on demand, either by serial communication or over the air. Production-level programming is typically done during the product manufacturing process yet it is desirable to be able to reprogram the system after production is complete. More importantly, it is valuable to be able to update the device's firmware with new features and bug fixes after deployment. The firmware image update capability makes that possible.

Silicon Labs supports devices that do not use a bootloader, but this requires external hardware such as a Debug Adapter (Silicon Labs ISA3 or Wireless Starter Kit (WSTK)) or third-party SerialWire/JTAG programming device to update the firmware. Devices without a bootloader have no supported way of updating the firmware once they are deployed, which is why Silicon Labs strongly advocates implementing a bootloader.

In March of 2017, Silicon Labs introduced the Gecko Bootloader, a code library configurable through Simplicity Studio’s IDE to generate bootloaders that can be used with a variety of Silicon Labs protocol stacks. The Gecko Bootloader can be used with EFM32 and EFR32 Series 1 and later devices. The Gecko Bootloader was restructured into a component-based design and released with Gecko SDK Suite (GSDK) 4.0 in December of 2021. This new version is documented in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/), along with other documents. Documentation for older versions is installed with their respective SDKs.

The Gecko Bootloader uses a customized update image file format. The update image file consumed by a Gecko Bootloader-generated application bootloader is a GBL (Gecko BootLoader) file, and is described in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

Bootloading a firmware update image can be accomplished in two ways. The first is Over-The-Air (OTA), that is, through the wireless network, as shown in the following figure.

![OTA Bootloading Use Case](/bootloader-fundamentals/0.1/images/ota-bootloading-use-case.jpg)

The second is through a hardwired link to the device. The following figure represents the serial bootloader use cases for SoCs (System on Chips) using either a UART (Universal Asynchronous Receiver/Transmitter), SPI (Serial Protocol Interface), or USB (Universal Serial Bus) interface, and for NCPs (Network Coprocessors) using either UART or SPI.

![Serial Bootloading Use Cases](/bootloader-fundamentals/0.1/images/serial-bootloading-use-cases.jpg)

Silicon Labs networking devices use bootloaders that perform firmware updates in two different modes: standalone (also called standalone bootloaders) and application (also called application bootloaders). Application bootloaders are further divided into those that use external storage for the download update image, and those that use local storage. These bootloader types are discussed in the next two sections.

The firmware update situations described in this document assume that the source node (the device sending the firmware image to the target through a serial or OTA link) acquires the new firmware through some other means. For example, if a device on the local Zigbee network has an Ethernet gateway attached, this device could get or receive these firmware updates over the Internet. This necessary part of the firmware update process is system-dependent and beyond the scope of this document.

###### Standalone Bootloader (heading level 7)

A standalone bootloader is a program that uses an external communication interface, such as UART or SPI, to get an application image. Standalone firmware update is a single-stage process that allows the application image to be placed into flash memory, overwriting the existing application image, without the participation of the application itself. Very little interaction occurs between the standalone bootloader and the application running in flash. In general, the only time that the application interacts with the bootloader is when it requests a reboot into the bootloader. Once the bootloader is running, it receives firmware update packets containing the (new) firmware image either by physical connections such as UART or SPI, or by the radio (over-the-air).

When the firmware update process is initiated, the new code overwrites the existing stack and application code. If any errors occur during this process, the application cannot be recovered, and the process must start over. For information about configuring the Gecko Bootloader as a standalone bootloader, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

###### Application Bootloader (heading level 7)

An application bootloader begins the firmware update process after the running application has completely downloaded the update image file. The application bootloader expects that the image either lives in external memory accessible by the bootloader or in a portion of main flash memory (if the chip has sufficient memory to support this local storage model).

The application bootloader relies on the application to acquire the new firmware image. This image can be downloaded by the application in any way that is convenient (UART, over-the-air, etc.) but it must be stored into a region referred to as the download space. The download space is typically an external memory device such as an EEPROM or dataflash, but it can also be a section of the chip’s internal flash when using a local storage variant of the application bootloader. Once the new image has been stored, the application bootloader is then called to validate the new image and copy it from the download space to flash.

Since the application bootloader does not participate in acquiring the image, and the entire image is downloaded before the firmware update process is started, download errors do not adversely affect the running image. The download process can be restarted or paused to acquire the image over time. The integrity of the downloaded update image can be verified before initiating the firmware update process, to prevent a corrupt or non-functional image from being applied.

The Gecko Bootloader can be configured to accept a list of multiple upgrade images to attempt to verify and apply. This allows the Gecko Bootloader to store what is in effect a backup copy of the update image, which it can access if the first image is corrupt.

Note that the EmberZNet NCP platform does not utilize an application bootloader because the application code resides on the host rather than on the NCP directly. Instead a device acting as a serial coprocessor would utilize a standalone bootloader designed to accept code over the same serial interface as the expected NCP firmware uses. However, the host application (residing on a separate MCU from the NCP) can utilize whatever bootloading scheme is appropriate.

For more information on application bootloaders, see [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

###### About the Gecko Bootloader

The Silicon Labs Gecko Bootloader is a configurable code library that can be used with all the newer Silicon Labs Gecko MCUs and wireless MCUs. It uses a specially-formatted update image file called a GBL file. The Gecko Bootloader has a two-stage design on Series 1 devices, where a minimal first stage bootloader is used to update the main bootloader. On Series 2 devices, the first stage bootloader is replaced by a Secure Engine and the Gecko Bootloader consists only of the main bootloader. The Secure Engine may be hardware-based, or virtual (software). If hardware-based, the implementation may be either with or without Secure Vault. Throughout this document, the following conventions will be used.

- **HSE**: Hardware Secure Engine, either with or without Secure Vault if not specified
- **VSE**: Virtual Secure Engine
- **SE**: Secure Engine (either HSE or VSE, in general)

Having a first stage bootloader or SE allows for field updates of the main bootloader, including adding new capabilities, changing communication protocols, adding new security features and fixes, and so on. The Gecko Bootloader consists of three component parts:

**Core:** The bootloader core contains the main function of both bootloader stages. It also contains functionality to write to the internal main flash, to perform a bootloader update, and to reset into the application flagging applicable reset reasons.

**Driver:** Different bootloading applications require different hardware drivers for use by the other components of the bootloader.

**Component/Plugin:** All parts of the main bootloader that are either optional or selectable for different configurations are implemented as components (in GSDK 4.0 and higher) or previously in plugins. Each component/plugin has a generic header file, and one or more implementations. The current release contains components for functionality like UART and SPI communication protocols, SPI flash storage, internal flash storage, and different cryptographic operations.

###### Features (heading level 7)

Gecko Bootloader features include:

- Field-updatable
- Secure boot
- Signed GBL firmware update image file
- Encrypted GBL firmware update image file

These features are summarized in the following sections and described in more detail in [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/). Protocol-specific information about using the Gecko Bootloader may be found in the following documents:

- [Using the Gecko Bootloader with EmberZNet](https://docs.silabs.com/zigbee/latest/using-gecko-bootloader-with-zigbee/)
- [Bootloading and OTA with Silicon Labs Connect SDK v3.x](https://docs.silabs.com/connect-stack/latest/bootloading-and-ota-with-connect-v3x)
- [Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/)

###### Field-Updatable (heading level 8)

###### Series 1 (heading level 9)

On EFM32 and EFR32 Series 1 devices, field update capability for the Gecko bootloader is provided by a two-stage design where the bootloader has a first stage and a main stage. The minimal first stage of the bootloader is not field updatable, and can only update the main bootloader by reading from and writing to fixed addresses in internal flash memory. To perform a main bootloader update, the running main bootloader verifies the integrity and authenticity of the bootloader update image, writes it to internal flash, and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader update image before copying it to the main bootloader location, completing the update

###### Series 2 (heading level 9)

On Series 2 devices, field update capability for the Gecko bootloader is provided by the SE. To perform a main bootloader update, the running main bootloader verifies the integrity and authenticity of the bootloader update image, writes it to internal flash, and requests that the SE installs the update. The SE optionally verifies the authenticity of the main bootloader update image before copying it to the main bootloader location, completing the update. The same mechanism can be used to update the SE itself.

###### Secure Boot (heading level 8)

Secure boot is designed to prevent an untrusted application from running on the device. When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot using asymmetric cryptography. The signature algorithm used is ECDSA-P256-SHA256. The public key is written to the device during manufacturing, while the private key is kept secret. This ensures that the application was created and signed by a trusted party.

###### Signed GBL Update Image File (heading level 8)

The Gecko Bootloader supports enforcing cryptographic signature verification of the update image file in addition to Secure Boot. This allows the bootloader and application to verify that the application or bootloader update comes from a trusted source before starting the update process. The signature algorithm used is ECDSA-P256-SHA256. The public key is the same key as for secure boot, written to the device during manufacturing, while the private key is never distributed. This ensures that the GBL file was created and signed by a trusted party.

###### Encrypted GBL Update File (heading level 8)

The GBL update file can also be encrypted, to prevent eavesdroppers from getting hold of the plaintext firmware image. The encryption algorithm used is AES-CTR-128, and the encryption key is written to the device during manufacturing.

###### Memory Space for Bootloading

The first stage of the Gecko Bootloader on Series 1 devices takes up a single flash page. On devices with 2 kB flash pages, like EFR32MG1, this means that the first stage takes 2 kB.

The size of the main bootloader is dependent on the functionality required. With a typical bootloader configuration, the main bootloader for Series 1 devices takes up 14 kB of flash, bringing the total bootloader size to 16 kB.

Silicon Labs recommends reserving 16 kB for the bootloader for Series 1 and EFR32xG21 devices and 24 kB for EFR32xG22 devices.

On EFR32xG1 devices (Mighty Gecko, Flex Gecko, and Blue Gecko families), the bootloader resides in main flash.

- First stage bootloader @ 0x0
- Main bootloader @ 0x800
- Application @ 0x4000

On EFR32xG12 and later Series 1 devices, the bootloader resides in the bootloader area in the Information Block.

- Application @ 0x0
- First stage bootloader @ 0x0FE10000
- Main bootloader @ 0x0FE10800

On EFR32xG21, the main bootloader resides in main flash:

- Main bootloader @ 0x0
- Application @ 0x4000

On EFR32xG22, the main bootloader resides in main flash:

- Main bootloader @ 0x0
- Application @ 0x6000

On EFR32xG23, the main bootloader resides in main flash:

- Main bootloader @ 0x08000000
- Application @ 0x08006000

On EFR32xG24, the main bootloader resides in main flash:

- Main bootloader @ 0x08000000
- Application @ 0x08006000

###### Design Decisions

The decision of what bootloader type to deploy depends on many factors. Note that the platform type and available flash memory may limit bootloader choices.

Some questions related to this are:

- Where does the device get the new update image? Is this over-the-air via the networking protocol? Using a separate interface connected to the Internet?
- Will the device have an external memory chip to store a new update image? If not, is there enough internal flash memory to store both a current and a newly downloaded copy of the largest expected application image?
- If the device receives the new image over-the-air, will it be multiple hops away from the server holding the download image?
- What kind of image security is needed?
- What communications driver will be used (in the single protocol case)?
- Does the use case require more than one protocol?

The configurable design of the Gecko Bootloader platform means that developers can create bootloaders to fit almost any design choice. See [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-series3-and-higher/).

##### Gecko Bootloader User's Guide for Series 3 and Higher

###### Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher

This guide describes the high-level implementation of the Silicon Labs Gecko Bootloader for Series 3 microcontrollers, SoCs (System on Chips), and NCPs (Network Co-Processors), and provides information on different aspects of configuring the Gecko Bootloader.

The Silicon Labs Gecko Bootloader is a common bootloader for all the newer MCUs and wireless MCUs from Silicon Labs. This guide is specific to Series 3 devices and above. The Gecko Bootloader can be configured to perform a variety of functions, from device initialization to firmware upgrades. Key features of the bootloader are:

- Usable across Silicon Labs Gecko microcontroller and wireless microcontroller families
- In-field upgradeable
- Configurable
- Enhanced security features, including:
- **Secure Boot**: When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot, using asymmetric cryptography. This ensures that the application was created and signed by a trusted party.
- **Signed upgrade image file**: The Gecko Bootloader supports enforcing cryptographic signature verification of the upgrade image file. This allows the bootloader and application to verify that the application or bootloader upgrade comes from a trusted source before starting the upgrade process, ensuring that the image file was created and signed by a trusted party.
- **Encrypted upgrade image**: The image file can also be encrypted to prevent eavesdroppers from acquiring the plaintext firmware image.

For Series 3 devices and above, Gecko Bootloader uses a proprietary format for its upgrade images, called GBL V4 (Gecko Bootloader file). These files have the file extension “.gbl”. See the _Gecko Bootloader File Format_ page for more details. Series 3 and above devices do not support GBL versions lesser than v4.

On Series 3 devices, the Gecko bootloader consist of the main stage bootloader. The main bootloader is upgradable through the Secure Engine.

The Secure Engine provides functionality to install an image to code region 0 in the external flash.

To perform a bootloader upgrade, the running bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The bootloader then writes the upgrade image to the upgrade location in external flash and requests that the Secure Engine installs it. On some devices, the Secure Engine is also capable of verifying the authenticity of the main bootloader update image against a root of trust. The Secure Engine itself is upgradable using the same mechanism. See the _Gecko Bootloader Operation - Secure Engine Upgrade_ page for more details.

The bootloader consists of a common core, drivers, and a set of components that give the bootloader specific capabilities. The common bootloader core is provided as a full-source delivery. The common bootloader core contains functionality to parse GBL v4 files and flash their contents to the device.

The Gecko Bootloader can be configured to perform firmware upgrades in standalone mode (also called a standalone bootloader) or in application mode (also called an application bootloader), depending on the component configuration. Components can be installed in and configured through the Simplicity Studio IDE.

A standalone bootloader uses a communications channel to get a firmware upgrade image. NCP (network co-processor) devices always use standalone bootloaders. Standalone bootloaders perform firmware image upgrades in a single-stage process that allows the application image to be placed into flash memory, overwriting the existing application image, without the participation of the application itself. In general, the only time that the application interacts with a standalone bootloader is when it requests to reboot into the bootloader. Once the bootloader is running, it receives packets containing the firmware upgrade image by a physical connection such as UART or SPI. To function as a standalone bootloader with a physical connection, a component providing a communication interface such as UART or SPI must be configured.

An application bootloader relies on the application to acquire the firmware upgrade image. The application bootloader performs a firmware image upgrade by writing the firmware upgrade image to a region of flash memory referred to as the download space. The application transfers the firmware upgrade image to the download space in any way that is convenient (UART, over-the-air, Ethernet, USB, and so on). The download space is data flash or a section of the device’s flash. The Gecko Bootloader can partition the download space into multiple storage slots and store multiple firmware upgrade images simultaneously. To function as an application bootloader, a component providing a bootloader storage implementation must be configured.

Silicon Labs provides example bootloaders that come with a preconfigured set of installed components for configuration in either standalone or application mode. See the _Configuring the Gecko Bootloader_ page. The following sections provide an overview of the Gecko Bootloader common core, drivers, and components. For details, including details on error codes and conditions, see the Gecko Bootloader API Reference, shipped with the SDK in the platform/bootloader/documentation folder.

###### Core (heading level 7)

The bootloader core contains the bootloader’s main functions. It also contains functionality to write to the external flash, an image parser to parse and act upon the contents of GBL v4 upgrade files, and functionality to boot the application in main flash.

A version of the GBL v4 image parser without support for encrypted upgrade images is also available. This version can be used in flash space constrained bootloader applications where encryption of the upgrade image is not required.

###### Shared Memory (heading level 8)

To exchange information between the bootloader and application, a section of SRAM is used. The contents of SRAM are preserved through a software reset, making SRAM suitable as a communication channel between bootloader and application.

The shared memory has a size of 4 bytes, and is located at the first address of SRAM, 0x20000000. It is used to store a single word containing the reason for a reset. The structure of the reset cause word is defined in the Reset Information part of the Application Interface, in the file **btl_reset_info.h**, as 16 bits containing the reason, and 16 bits of signature indicating if the word is valid or not. If the signature reads 0xF00F, the reset reason is valid.

All 16-bit reset reasons used by Silicon Labs have the most significant bit set to zero. If custom reset reasons are desired, it is recommended to set the most significant bit to avoid conflicting definitions.

###### Drivers (heading level 7)

Different applications for firmware upgrade require different hardware drivers for use by the other components of the bootloader.

Driver modules include:

- Delay: Simple delay routines for use with components that require small delays or timeouts.
- SPI Slave: Flexible SPI Slave driver implementation for use in communication components implementing SPI protocols. This driver supports both blocking and non-blocking operation, with DMA (Direct Memory Access) backing the background transfers to support non-blocking operation.
- UART: Flexible serial UART driver implementation for use in communication components implementing UART protocols. This driver supports both blocking and non-blocking operations, with DMA backing the background transfers to support non-blocking operation. Additionally, support for hardware flow control (RTS/CTS) is included.

###### Components (heading level 7)

All parts of the bootloader that are either optional or that may be exchanged for different configurations are implemented as components. Each component may have a configuration header file, and one or more implementations. Components include:

- Communication
- UART: XMODEM
- UART: BGAPI
- Compression
- Debug
- GPIO Activation
- Security
- Storage

###### Communication (heading level 8)

Communication components provide an interface for implementing communication with a host device, such as a computer or a micro-controller. Several components implement the communication interface, using different transports and protocols.

- BGAPI UART DFU: By enabling the BGAPI communication component, the bootloader communication interface implements the UART DFU protocol using BGAPI commands.
- UART XMODEM: By enabling the UART XMODEM communication component, the bootloader communication interface implements the XMODEM-CRC protocol over UART. This component makes the bootloader compatible with the legacy serial-uart-bootloader that was previously released with the EmberZNet wireless stack. See _AN760: Using the Ember Standalone Bootloader_ for more information about legacy Ember standalone bootloaders.

###### Compression (heading level 8)

Compression components provide capability for the bootloader GBL file parser to handle compressed GBL v4 upgrade images. Each compression component provides support for one (de)compression algorithm. At the time of writing, decompression of data compressed with the LZ4 and LZMA algorithms is supported, through the _GBL Compression (LZ4)_ and _GBL Compression (LZMA)_ components.

###### Debug (heading level 8)

This component provides the bootloader with support for debugging output. If the component is configured to enable debug prints, short debug messages will be printed over Serial Wire Output (SWO), which can be accessed in multiple ways, including using Simplicity Commander, and by connecting to port 4900 of the Wireless Starter Kit TCP/IP interface.

To turn on debug prints, enable the Debug component and select **Debug prints**. Select **Debug asserts** to enable assertions in the source code.

###### GPIO Activation (heading level 8)

This component provides functionality to enter firmware upgrade mode automatically after reset if a GPIO pin is active during boot. The GPIO pin location and polarity are configurable.

- GPIO: By enabling the GPIO activation component, the firmware upgrade mode can be activated by push buttons.

###### Security (heading level 8)

Security components provide implementations of cryptographic operations as well as functionality to compute checksums and to read cryptographic keys from manufacturing tokens.

Modules include:

- AES: AES decryption functionality
- CRC16: CRC16 functionality
- CRC32: CRC32 functionality
- ECDSA: ECDSA signature verification functionality
- SHA-256: SHA-256 digest functionality

###### Storage (heading level 8)

These components provide the bootloader with multiple storage options for SoCs. All storage implementations must provide an API to access image files to be upgraded. This API is based on the concept of dividing the download space into storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Some storage implementations also support a raw storage API to access the underlying storage medium. This can be used by applications to store other data in parts of the storage medium that are not used for storing firmware upgrade images. Implementations include:

- **External Flash**: The external flash storage implementation uses the external flash of the device for upgrade image storage. Note that this storage area is only a download space and is separate from the portion of external flash used to hold the active application code.

###### Gecko Bootloader File Format v4

The Gecko Bootloader supports GBL File format v4 for Series 3 device. This format has significant differences as compared to version 3, The file formats described in this section are generated by [Simplicity Commander](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) commands.

###### File Structures (heading level 7)

The GBL v4 file format is composed of nested TLV (Type-Length-Value) elements. The format of the TLV is as follows:

|Field|Length (Bytes)|Description|
|---|---|---|
|Type|4|Type indicates the content of the Value field|
|Length|4|Length of the Value field in bytes|
|Value|N|Length size field containing either more TLVs or data|

There are two types of TLVs, data and container. Data TLVs value field contains data whose format is specified in the type field and the container TLVs value filed contains more TLVs, which in turn again may contain data or container TLVs.

###### TLV Descriptions (heading level 7)

This section describes each of the TLVs.

###### GBLV4 (heading level 8)

This mandatory TLV is used to identify the GBLv4 file when parsing and tell the length of the file.

|Type|Length|Value|
|---|---|---|
|0x84A617EB|Variable|Contains all the TLVs for the file|

###### MANIFEST (heading level 8)

MANIFEST TLV is present inside the GBLV4 TLV. It has a collection, TLVs, that describes the metadata of the GBLv4 file that is used during the update process.

|Type|Length|Value|
|---|---|---|
|0xAA01012A|Variable|Contains metadata TLVs for applying the file.|

###### MANIFEST_INFO (heading level 8)

The MANIFEST_INFO TVL contains the `ManifestInfo_t` structure that describes the version dependency and the features of the GBL file.

|Type|Length|Value|
|---|---|---|
|0x2B03032B|Variable|manifest_info structure|

The `ManifestInfo_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|version|Minimum version of the GLBv4 parser required, used for future extensions.|
|uint32_t|features|Features requested from the parser (encryption, compression etc.)|

###### BUNDLE_VERSION (heading level 8)

This is the child TVL of MANIFEST TLV, required to identify the bundle/file and is used for versioning and rejection of downgrades.

|Type|Length|Value|
|---|---|---|
|0x2B04042B|Fixed|bundle_version structure|

The `BundleVersion_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|Uint8_t|productId|128 bit unique product ID|
|uint32_t|bundleVersion|Reject if smaller than this exists|
|Uint32_t|minVersion|The minimum previous version to which this update file can be applied|

###### CONTENT_HASH (heading level 8)

An optional TLV that provides integrity checking on the remainder of the file. This TLV is applicable to batch updates only.

|Type|Length|Value|
|---|---|---|
|0x0x2B05052BUL|Fixed|content_hash structure|

The `content_hash` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|hashType|The hash function used to validate (1=SHA, etc.)|
|uint8_t|sha[]|The hash of all contents following the manifest|

###### MANIFEST_CERTIFICATE (heading level 8)

|Type|Length|Value|
|---|---|---|
|0x2B01012B|Fixed|ApplicationCertificate_t|

The `ApplicationCertificate_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint8_t|structVersion|Vesion of the certificate structure|
|uint8_t|flags|Reserved flags|
|uint8_t|key|Public key used to verify GBL file|
|uint32_t|version|Version number of this certificate|
|uint8_t|signature|The signature of the certificate itself (not the GBL file)|

###### MANIFEST_SIGNATURE (heading level 8)

|Type|Length|Value|
|---|---|---|
|0x2B02022BUL|Variable|Manifest signature structure|

The `Manifest_signature` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|Signature function|The function used for signing|
|uint8_t[]|Signature|The signature for authentication|

###### UPDATE_PROCESS (heading level 8)

This is a collection of TLVs that describes the update process. Parsing this TLV does not happen until the MANIFEST_TLV is authenticated. Each TLV contained in this is parsed and processed one at a time in the order they are listed.

|Type|Length|Value|
|---|---|---|
|0xAB06062BUL|Variable|TLVs describing the steps to update the system|

###### UPDATE_SE (heading level 8)

This is an optional TLV that is used to update the SE.

|Type|Length|Value|
|---|---|---|
|0x2C02022CUL|Fixed|UpdateSe_t structure|

The `UpdateSe_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint32_t|version|Version number of the SE update image.|
|uint32_t|tlvPosition|The absolute position of the SE update image Blob TLV|

###### UPDATE_MEMORY_SECTION (heading level 8)

The memory section’s content is present in the file and needs to be updated.

|Type|Length|Value|
|---|---|---|
|0x2C03032CUL|Fixed|UpdateMemorySection_t structure|

The `UpdateMemorySection_t` structure is as follows:

|Data Type|Field|Purpose|
|---|---|---|
|uint8_t|targetMemory|Which memory this definition is for (0=main memory, 0x1-0x7f = reserved, 0x80-0xff=defined by the user)|
|uint8_t|plainImageSize|Represents the size of the plain image in 3 bytes|
|uint32_t|targetAddr|The target memory address for the update|
|uint32_t|type|Bitfield representing the type of application|
|uint32_t|version|Version number for this application (customer-defined)|
|uint32_t|capabilities|Bitfield representing the capabilities of this application|
|uint32_t|memorySectionPos|The absolute position of the MEMORY_SECTION_TLV in the file|
|HashVaule_t|memSecHash|A hash value for verifying the integrity of the memory section|

###### MANIFEST_FINISH (heading level 8)

TLV to indicate the end of an update.

|Type|Length|Value|
|---|---|---|
|0x2C04042CUL|Fixed|Empty|

###### MEMORY_SECTION (heading level 8)

This TLV contains TLVs for a memory section update.

|Type|Length|Value|
|---|---|---|
|0xBA01013AUL|Variable|TLVs for the region|

###### MEMORY_SECTION_INFO (heading level 8)

This TLV contains information about how the blob data is read and where the data is to be written to. This is a common wrapper for all data as it allows the data to be compressed, verified and processed in a unified manner.

The data can be divided into blocks, with each block having its own hash. This can then be compared with the hashes in the memory section info to authenticate the block. This is useful during streaming updates to avoid writing unauthenticated data to flash.

|Type|Length|Value|
|---|---|---|
|0x3B01013BUL|Fixed|MemSectionPartialInfo_t|

The `MemSectionPartialInfo_t` structure is as follows:

<table>
    <thead>
        <tr>
            <th>Data Type</th>
            <th>Field</th>
            <th>Purpose</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>uint8_t</td>
            <td>compressionScheme</td>
            <td>
                <p>0 = No compression</p>
                <p>1 = LZ4 compression</p>
                <p>2 = LMZA compression</p>
            </td>
        </tr>
        <tr>
            <td>uint8_t</td>
            <td>encryptionScheme</td>
            <td>
                <p>0 = No encryption</p>
                <p>1 = AES CCM</p>
            </td>
        </tr>
        <tr>
            <td>uint8_t</td>
            <td>secureBootScheme</td>
            <td>Reserved for future use.</td>
        </tr>
        <tr>
            <td>uint8_t</td>
            <td>reserved</td>
            <td></td>
        </tr>
        <tr>
            <td>uint16_t</td>
            <td>signBlockSize</td>
            <td>Block size if DFU authentication is done for each block.</td>
        </tr>
        <tr>
            <td>uint16_t</td>
            <td>numBlocks</td>
            <td>Number of blocks inside the BLOB.</td>
        </tr>
        <tr>
            <td>uint8_t[]</td>
            <td>nonce</td>
            <td>Nonce for encryption</td>
        </tr>
        <tr>
            <td>uint8_t[]</td>
            <td>finalImageHash</td>
            <td>Reserved for future use.</td>
        </tr>
        <tr>
            <td>uint8_t[]</td>
            <td>secureBootSign</td>
            <td>Reserved for future use.</td>
        </tr>
    </tbody>
</table>

###### BLOB (heading level 8)

This TLV contains variable length binary data.

|Type|Length|Value|
|---|---|---|
|0x3B02023BUL|Variable|Binary Data|

The figure below shows the structure of a GBL v4 file.

![Structure of GBL V4 file](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image1.png)

###### Gecko Bootloader Operation - Application Upgrade

This section summarizes Gecko Bootloader operation for updating application firmware, first if the Gecko Bootloader is configured in standalone mode and then if it is configured in application mode. The _Gecko Bootloader Operation - Bootloader Upgrade_ provides the same information for updating the bootloader firmware.

###### Standalone Bootloader Operation (heading level 7)

Standalone bootloader operation is illustrated in the following figure:

![Standalone Bootloader Operation](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image2.png)

1. The device reboots into the bootloader.
2. A GBL file containing an application image is transmitted from the host to the device. If image encryption is enabled in the  bootloader and the image is encrypted, decryption is performed during the process of receiving and parsing the GBL file.
3. The bootloader applies the application upgrade from the GBL upgrade file on-the-fly. If image authentication is enabled in the bootloader and the GBL file contains a signature, the authenticity of the image is verified before completing the process.
4. The device boots into the application. Application upgrade is complete.

###### Rebooting Into the Bootloader (heading level 8)

The Gecko Bootloader supports multiple mechanisms for triggering the bootloader. If the **GPIO activation** component is installed, the host device can keep this pin low/high (depending on configuration) through reset to make the device enter the bootloader. The bootloader can also be entered through software. The `bootloader_rebootAndInstall` API first signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it will enter firmware upgrade mode instead of booting the existing application.

###### Downloading and Applying a GBL Upgrade File (heading level 8)

When the bootloader enters firmware upgrade mode, it enters a receive loop waiting for data from the host device. The specifics of the receive loop depend on the protocol. Received packets are passed to the image parser, a state machine that parses the data and returns a callback containing any data that should be acted upon. The bootloader core implements this callback and flashes the data to external flash at the specified address. If GBL file authentication or encryption is enabled, the image parser will enforce this, and abort the image upgrade if the authentication fails The bootloader prevents a newly uploaded image from being bootable by holding back parts of the application vector table until the GBL file hash and GBL signature (if required) have been verified.

###### Booting Into the Application (heading level 8)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid and also if the lock bit is set. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

###### Error Handling (heading level 8)

If the application upgrade is interrupted at any time, the device will be without a working application. The bootloader then resets the device, and re-enters firmware upgrade mode. The host device can easily restart the application upgrade process, to try loading the upgrade image again.

###### Application Bootloader Operation (heading level 7)

The following figure illustrates the application bootloader operation both for a single image/single storage slot, and multiple images/ multiple storage slots.

![Application Bootloader Operation: Single Storage Slot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image3.png)

![Application Bootloader Operation: Multiple Storage Slots](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image4.png)

1. A GBL file is downloaded onto the storage medium of the device, as described below, and the presence of an upgrade image is indicated.
2. The device reboots into the bootloader, and the bootloader enters firmware upgrade mode.
3. The device applies the application upgrade.
4. The device boots into the application. Application upgrade is complete.

###### Downloading and Storing a GBL Upgrade Image File (heading level 8)

To prepare for receiving an upgrade image, the application finds an available storage slot or erases an existing one using `bootloader_eraseStorageSlot`. If the bootloader only supports a single storage slot, a value of 0 should be used for the slot ID.

The application then receives a GBL file using an applicable protocol, such as Ethernet, USB, Zigbee, OpenThread or Bluetooth, and stores it in the slot by calling `bootloader_writeStorage`.

When the download is complete, the application can optionally verify the integrity of the GBL file by calling `bootloader_verifyImage`. This is also done by the bootloader before applying the image but can be done from the application to avoid rebooting into the bootloader if the received image was corrupt.

If multiple storage slots are supported, the application should write a bootload list by calling `bootloader_setImageToBootload`. The list is written to the two bootload info pages as shown in the figure above. The bootload list is a prioritized list of slots indicating the order the bootloader should use when attempting to perform a firmware upgrade. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader treats the entire download space as a single storage slot.

###### Rebooting and Applying a GBL Upgrade File (heading level 8)

The bootloader can be entered through software. The `bootloader_rebootAndInstall` API signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it enters firmware upgrade mode instead of booting the existing application.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the image stored in each. Once it finds a valid GBL upgrade file, firmware upgrade is attempted from this GBL file. If the upgrade fails, the bootloader moves to the next image in the list. If no images pass verification, the bootloader reboots back into the existing application with a message in the shared memory location in SRAM indicating that no good upgrade images were found.

###### Booting Into the Application (heading level 8)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid as well as if the lock bit is set. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

###### Gecko Bootloader Operation - Bootloader Upgrade

Bootloader upgrade functionality is provided by the Secure Engine on Series 3 devices. The Secure Engine itself is also upgradable. For more details, see the _Gecko Bootloader Operation - Secure Engine Upgrade_ page.

Requirements for upgrading the main bootloader vary depending on the bootloader configuration:

- Application bootloader with storage: Upgrading the main bootloader requires a single GBL file containing both bootloader and application upgrade images.
- Standalone bootloader with communication interface: Upgrading the bootloader requires a GBL file with only the bootloader upgrade image.

Security of the bootloader upgrade process is provided by signing the GBL file. See _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ on the _Gecko Bootloader Security Features_ page.

###### Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders) (heading level 7)

The process is illustrated in the following figure:

![Standalone Bootloader: Bootloader Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image5.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a bootloader upgrade image is transmitted from the host to the device.
3. The contents of the GBL Bootloader tag are written to the data region in flash
4. The device reboots into the Secure Engine.
5. The Secure Engine replaces the main bootloader with the new version found in the bootloader upgrade GBL.
6. The device boots into the new main bootloader. Bootloader upgrade is complete.

A bootloader upgrade is started in the same way as an application upgrade.

###### Downloading and Applying a Bootloader GBL Upgrade File (heading level 8)

When the bootloader has entered the receive loop, a GBL upgrade file containing a bootloader upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns bootloader upgrade data in a callback. The bootloader core implements this callback and flashes the data to the flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file hash and GBL signature (if required) have been verified.

When a complete bootloader upgrade image is received, the bootloader signals the Secure Engine that it should enter firmware upgrade mode. Secure Engine communication is used to signal that bootloader upgrade is ready to be performed.

The authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See _Setting a Version Number_ on the _Configuring the Gecko Bootloader_ page for more information about versioning bootloader images.

###### Upgrading Bootloaders without Secure Boot to Bootloaders with Secure Boot (heading level 8)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature, using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. Key locations are defined in the bootloader project file btl_security_tokens.c.
4. Create a GBL file using the Gecko Bootloader image. The GBL file needs to be signed/unsigned depending on the current configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
5. Upload the GBL file. For more details on the upgrade process, see the _Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)_ section.

###### Enabling Secure Boot RTSL on Series 3 Devices (heading level 8)

Secure Boot RTSL (Root of Trust and Secure Loader) can be enabled using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in the VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more information on installing public keys, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See the _Signing an Application Image for Secure Boot_ section on the _Gecko Bootloader Security Features_ page for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2.
6. Create a GBL file using the Gecko Bootloader image from step 4.
7. Create a GBL file using the application from step 5. The GBL file need to be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1.
8. Upload the GBL file containing the Gecko Bootloader image.
9. Upload the GBL file containing the application.

###### Bootloader Upgrade on Application Bootloaders with Storage (heading level 7)

The process is illustrated in the following figure.

![Application Bootloader: Bootloader Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image6.png)

1. A single GBL file containing a bootloader upgrade image is downloaded onto the storage medium of the device.
2. The device reboots into the main bootloader.
3. The main bootloader verifies the integrity of the upgrade image and then resets the device with reset reason BOOTLOADER_RESET_REASON_UPGRADE to apply the upgrade.
4. The device reboots into the Secure Engine.
5. The Secure Engine replaces the main bootloader with the new version.
6. The device boots into the new main bootloader.

A bootloader upgrade is started in the same way as an Application Upgrade. A GBL file containing a bootloader is written to storage by the application, and the bootloader is entered.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the GBL file stored within. Verification returns information about whether the GBL file contains a bootloader, or both a bootloader and an application. The image parser parses the file. If the GBL file contains a bootloader, the bootloader upgrade data is returned in a callback. The bootloader core implements this callback and flashes the data to internal flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file hash  and GBL signature (if required) have been verified.

Secure Engine communication interface is used to signal the Secure Engine that a bootloader upgrade is ready to be performed.

On Series 3 devices, the authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See the _Setting a Version Number_ section on the _Configuring the Gecko Bootloader_ page for more information about versioning bootloader images.

The new main bootloader is entered, and the images in the list of storage slots marked for bootload are verified. When the image parser parses the slot containing the GBL file with the bootloader + application upgrade, the version number of the bootloader upgrade is equal to the running main bootloader version, so another bootloader upgrade will not be performed. Instead, the application upgrade data are returned in a callback. Bootloading of the new application proceeds as described in the _Application Bootloader Operation_ section on the _Gecko Bootloader Operation Application Upgrade_ page.

###### Storage Space Size Configuration (heading level 8)

The storage space size must be configured to have enough space to store the upgrade images.

###### Upgrading Bootloaders without Secure Boot to Bootloaders with Secure Boot (heading level 8)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature. The procedure is as follows:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. This key can be written by application code running on the device. The Gecko Bootloader prepared from step 1 can be modified to look for the decryption and signature keys in a different location. Key locations are defined in the bootloader project file `btl_security_tokens.c`.
4. Prepare a signed application image using the private key generated in step 2. See the _Signing an Application Image for Secure Boot_ section on the _Gecko Bootloader Security Features_ page for more information on signing an application.
5. Create a GBL file using the Gecko Bootloader image and the signed application image. The GBL file needs to be signed/unsigned depending on the configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
6. Upload the GBL file. For more details on the upgrade process, see the _Bootloader Upgrade on Application Bootloaders with Storage_ section.

###### Enabling Secure Boot RTSL on Series 3 Devices (heading level 8)

Secure Boot RTSL can be enabled by using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See the _Generating Keys_ section on the _Gecko Bootloader Security Features_ page for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See the _Signing an Application Image for Secure Boot_ section on the _Gecko Bootloader Security Features_ page for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2. For more details on how to turn on secure boot on the Secure Engine.
6. Create a GBL file using the Gecko Bootloader image from step 4 and the application from step 5. The GBL file must be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1. For more details on creating a GBL file, see the _Creating a Signed and Encrypted GBL Upgrade Image File from an Application_ section on the _Gecko Bootloader Security Features_ page.
7. Upload the GBL file containing the Gecko Bootloader image and the application.

###### Gecko Bootloader Operation - Secure Engine Upgrade

The Secure Engine is upgradable and for both application and standalone type of bootloader a GBL file containing the Secure Engine Upgrade image has to be flashed or sent to the bootloader.

A bootloader upgrade can also be included in the same GBL file in application mode, or as a second GBL file in standalone mode. The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the _Memory Space for Bootloading_ section in [Bootloader Fundamentals](https://docs.silabs.com/bootloader/latest/bootloader-fundamentals/).

Signed and encrypted Secure Engine upgrade images are provided by Silicon Labs through Simplicity Studio. Upgrade images with the same or lower version number than the running Secure Engine will be ignored.

To download Secure Engine firmware images, connect a Series 3 device and select a preferred SDK. The Secure Firmware **Update to x.x.x** link appears in the Launcher Perspective, as shown in the following figure.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image7.jpg)

Click **Update to x.x.x** next to Secure FW: x.x.x. A warning dialog box appears. Click **Yes** to continue.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image8.jpg)

The Launcher Perspective is then updated so that the current Secure Firmware version and link version are the same.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image9.jpg)

The Secure Engine firmware images can be found in the _util/se_release/public_ directory under the Gecko SDK. Simplicity Studio displays the SE firmware version available in the Gecko SDK selected.

###### Secure Engine Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders) (heading level 7)

The process is illustrated in the following figure.

![Standalone Bootloader: Secure Engine Bootloader Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image10.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a Secure Engine upgrade image is transmitted from the host to the device.
3. The device reboots into the Secure Engine.
4. The Secure Engine is replaced by the new version found in the pre-configured upgrade location.
5. The device boots into the bootloader.

###### Downloading and Applying a Secure Engine GBL Upgrade File (heading level 8)

When the bootloader has entered the receive loop, a GBL upgrade file containing a Secure Engine upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns Secure Engine upgrade data in a callback. The bootloader core implements this callback and flashes the data to flash at the pre-configured storage data region.

When a complete Secure Engine upgrade image is received, the bootloader signals the Secure Engine that it should enter firmware upgrade mode. This is done by the Secure Engine communication interface that is used to signal that bootloader upgrade is ready to be performed.

###### Secure Engine Upgrade on Application Bootloaders with Storage (heading level 7)

The process is illustrated in the following figure.

![Application Bootloader: Secure Engine Upgrade](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image11.png)

1. A single GBL file containing a Secure Engine upgrade image is downloaded onto the storage medium of the device.
2. The device reboots into the bootloader.
3. The upgrade image will be fetched directly from the GBL file in storage instead of first copying the image to the pre-configured upgrade location.
4. The device reboots into the Secure Engine.
5. The Secure Engine is replaced by the new version found in the pre-configured upgrade location (or directly from storage, ref. 3b).
6. The device boots into the main bootloader.
7. The bootloader applies the application image from the GBL upgrade file.
8. The device boots into the application. Secure Engine upgrade is complete.

###### Getting Started with the Gecko Bootloader

This section describes how to build a Gecko Bootloader from one of the provided examples. These instructions assume that you have installed Simplicity Studio 5, the SiSDK and associated utilities as described in the SDK’s quick start guide, and that you are familiar with generating, compiling, and flashing an example application in the relevant version.

1. Create a project based on the Gecko Bootloader example of your choice. The project opens with a tab describing the example.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image12.png)
2. Click the project (*.slcp) tab to move to the Project Configurator interface.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image13.png)
3. The Software Components tab shows the list of available components that can be installed in the project.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image14.png)
4. The **Storage Slot Setup** component allows you to configure storage slots to be used if a storage component is also installed. The default configuration matches the target part and bootloader type. This component supports a maximum of three storage slots.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image15.png)
5. Click the **Build** (hammer) icon.
6. After the build is complete, the bootloader binaries are available in the **artifact** folder as depicted in the image below.  
   ![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image16.png)

The image containing only a bootloader must be used to create a GBL file for bootloader upgrade.

###### Configuring the Gecko Bootloader

###### Configuring Storage (heading level 7)

Gecko Bootloaders configured as application bootloaders must include an API to store and access image files. This API is based on the concept of storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Slots are configured in the **Bootloader Storage Slot Setup** component.

When multiple storage slots are configured, a bootload list is used to indicate the order in which the bootloader should access slots to find upgrade images. If multiple storage slots are supported, the application should write the bootload list by calling bootloader_setImageToBootload before rebooting into the bootloader to initiate a firmware upgrade process. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader uses this slot implicitly. A maximum of three slots may be configured in the **Bootloader Storage Slot Setup** component.

###### Storage Configuration (heading level 8)

When configuring a Gecko Bootloader to obtain images fromflash, modify the following.

The **base address of the storage area** should be configured in the **Common Storage** component. This is the address at which the bootloader will place the prioritized list of storage slots to attempt to bootload from, if more than one storage slot is configured. In the default configuration, only a single storage slot is configured, so this value is set to 0, and isn’t used. If more than one storage slot is configured, this value needs to be configured too.

The **location and size of the storage slots** can be configured using the **Bootloader Storage Slot Setup** Component (supports a maximum of three configurable storage slots). The addresses input here are absolute addresses (they are not offsets from the base address). If more than a single slot is configured, enough space must be reserved between the base address as configured in the **Common Storage** component and the first storage slot configured in the **Bootloader Storage Slot Setup** component. Enough space to fit two copies of the bootload list must be reserved. These two copies need to reside on different flash pages, to provide redundancy in case of power loss during writing. Two full flash pages therefore need to be reserved. The following figure illustrates how the storage area can be partitioned.

![Internal Storage Area Configurations](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image17.png)

> **Note**: The storage area partitioning in the example for two storage slots above does not take any NVM system into account. If using an NVM3 , take care to place and size the storage area in such a way that bootloader storage does not overlap with NVM3.

###### Compressed Upgrade Images (heading level 7)

The Gecko Bootloader optionally supports compressed GBL files. In a compressed GBL file, only the application upgrade data and bootloader upgrade data is compressed, any metadata (if present) stays uncompressed.  Signature and encryption operations on a compressed GBL work identically to on an uncompressed GBL.

To be able to use compressed upgrade images, a decompressor for the relevant compression algorithm must be added to the Gecko bootloader. The following table shows which compression algorithms are supported by the Gecko Bootloader, and which Bootloader component should be added to enable the feature. The table also shows how much space the decompressor takes up in the bootloader, and how big of a size reduction to expect for the compressed application upgrade image. Be aware of the bootloader size requirement. The bootloader space might be too small to fit the decompressors, depending on the device and enabled components.

|Compression Algorithm|Component|Bootloader Size Requirement|Application Upgrade Size Reduction (typical)|
|---|---|---|---|
|LZ4|GBL Compression (LZ4)|< 1 kB|~ 10%|
|LZMA|Bootloader Compression (LZMA)|~5 kB flash, 18 kB RAM|~ 30%|

It is important to note that the compressed GBL file stays compressed while being transferred to the device, and while it is stored in the upgrade area. It is decompressed by the bootloader when the upgrade is applied. This means that the running application in main flash will be identical to one that was installed using an uncompressed (normal) GBL file.

Compressed GBL files can only be decompressed by the bootloader when running standalone, not through the Application Interface. This means that upgrade image verification performed by the application prior to reboot will not attempt to decompress the application upgrade, it will only verify the signature of the compressed payload. After rebooting into the bootloader, it will decompress the image as part of the upgrade process.

###### LZMA Compression Settings (heading level 8)

LZMA decompression is only supported for images compressed with certain compression settings. Simplicity Commander automatically uses these settings during gbl4 creation.

- Probability model counters: lp + lc <= 2. Simplicity Commander uses lp=1, lc=1.
- Dictionary size no greater than 8 kB. Simplicity Commander uses 8 kB.

Together, these settings cause the decompressor to require 18 kB of RAM for decompression – 10 kB for the counters and 8 kB for the dictionary.

The Gecko bootloader only supports decompressing payloads that contain the end mark as the last 8 bytes of the compressed stream.

###### Bootloader Example Configurations (heading level 7)

The following sections describe the key configuration options for the example bootloader applications.

> **Note**: Security features are disabled for all example configurations. In development, Silicon Labs strongly recommends enabling security features to prevent unauthorized parties from uploading untrusted program code. See the _Using Application Image Security Features_ section on the _Gecko Bootloader Security Features_ page to learn how to configure the security features of the Gecko Bootloader.

###### UART XMODEM Bootloader (heading level 8)

Standalone bootloader for Series 3 devices running the EmberZNet PRO and Silicon Labs Connect protocol stacks, using XMODEM-CRC over UART.

In this configuration, the **UART XMODEM** communication component, **XMODEM Parser** component, and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The **GPIO activation** component is also installed by default, allowing bootloader entry into firmware upgrade mode by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### BGAPI UART DFU Bootloader (heading level 8)

Standalone bootloader for the Bluetooth protocol stack, using the BGAPI protocol for UART DFU. This bootloader should be used for all NCP-mode Bluetooth applications.

In this configuration, the **BGAPI UART DFU** communication component and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The GPIO activation component is also installed by default, allowing bootloader entry by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### Storage Bootloader (heading level 8)

Application bootloader for all wireless protocol stacks, using flash to store upgrade images received over the air by the application.

Multiple examples are provided, including configurations for 2 MB, 3 MB, 4 MB & 8 MB flash memory devices . **The storage layout should be modified before running the bootloader on any other devices**. In this configuration, the flash and common storage components are installed. The base address of the storage area is configured in the **Common Storage** component. The location and size of the storage slots can be configured using the **Bootloader Storage Slot Setup** component (provides up to three configurable storage slots). Default example applications are provided with configurations for both single storage slot and multiple storage slots.

The default storage slot configurations provided by the Gecko Bootloader **must** be configured to match the use-case-specific application configurations, as shown below.

|Sample Applications|Storage Offset|Storage Size|
|---|---|---|
|Storage Bootloader (Single OTA Image of size 792kB)|0x010E0000|0x000C6000 (811,008 bytes)|
|Storage Bootloader (Single OTA Image of size 1180kB)|0x0128F000|0x00127000 (1,210,368 bytes)|
|Storage Bootloader (Single OTA Image of size 1540kB)|0x01379000|0x00181000 (1,577,984 bytes)|

###### Image Acquisition Application Example Configuration (heading level 7)

These examples illustrate applications that acquire and store a GBL upload image for an application bootloader. For the running bootloader to accept an application upgrade, the new application version must be higher than the existing version.

###### Setting a Version Number (heading level 7)

To distinguish between different builds of the Gecko Bootloader, it is useful to set a version number. To perform a bootloader upgrade, not only must the running bootloader pass its integrity checks (see the _Downloading and Applying a Bootloader GBL Upgrade File_ section on the _Gecko Bootloader Operation Bootloader Upgrade_ page), but the bootloader upgrade image must also have a higher version number than the running bootloader image. A version number can be set using Simplicity Studio by configuring the **Bootloader Version Main Customer** option of the **Bootloader Core** component. This macro will be picked up by the config file **btl_config.h**, where it is combined with the version number of the Gecko Bootloader files provided by Silicon Labs.

###### Hardware Configuration (heading level 7)

The Gecko Bootloader uses the Pin Tool for configuration of pinout and other hardware-related settings. When Pin Tool configuration is available for a bootloader component, the relevant settings are shown in the Component Editor for that component.

![Example of USART Configuration for UART Driver](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image18.png)

The standalone Pin Tool User Interface can also be used to configure settings for Gecko Bootloader if desired.

While the Pin Tool provides configuration for many different peripherals, the Gecko Bootloader uses only the following Pin Tool modules:

- SERIAL is used by the UART Driver component to configure baud rate, flow control mode and pinout.
- VCOM is used by the UART Driver component to enable the serial interface if necessary (only on Silicon Labs Wireless Starter Kits).
- BTL_BUTTON is used by the GPIO Activation component.
- CMU HFXO frequency setting is used by the delay driver to calibrate timing if the core is running from the HFXO.

Other settings, like CMU oscillator configuration or DCDC configuration, are not taken into consideration by the default bootloader code. If using these configuration settings is desired, the required code must be added in btl_main.c.

> **Note**: While the delay driver uses the HFXO frequency setting from Pin Tool, the HFXO enable setting is not used to initialize the HFXO on startup. This setting is only used when calling the bootloader through the Application Interface, and the application has switched to the HFXO prior to calling the Bootloader Application Interface API.

###### Simplicity Commander and the Gecko Bootloader

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple CLI (Command Line Interface) that is also scriptable. You can use Simplicity Commander to perform these essential tasks:

- Generating key files for signing and encryption
- Signing application images for Secure Boot
- Creating GBL images (encrypted or unencrypted, signed, or unsigned)
- Parsing GBL images

Simplicity Commander is used throughout the examples in the following sections. For more information on executing commands to complete these tasks, see the [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

> **Note**: Simplicity Commander also offers a GUI (Graphical User Interface) that can be used in the lab for typical tasks such as flashing device images. The functions described in this User Guide are performed from the CLI.

###### Creating GBL V4 Files Using Simplicity Commander (heading level 7)

To create an unsigned GBL V4 file from an application **myapp.s37**, execute `commander gbl4 create myapp.gbl -–config configfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
updates:
  - data: myapp.s37
    block_size: 0
```

To create an unsigned GBL V4 file from a bootloader upgrade **mybootloader.s37**, execute `commander gbl4 create mybootloader.gbl –-config confligfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
updates:
  - data: mybootloader.s37
    block_size: 0
```

This file can be used with the standalone bootloader configurations of the Gecko Bootloader.

To create an unsigned GBL file from a Secure Engine, upgrade **mySecureElement.seuv2**, and execute `commander gbl4 create mySecureElement.gbl –config configfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
se_upgrade:
  se_file: mysecureElement.seuv2
```

The Secure Engine images, .seuv2, are provided by Silicon Labs and can be found through Simplicity Studio. See the _Gecko Bootloader Operation - Secure Engine Upgrade_ section on the _Gecko Bootloader Operation Secure Engine Upgrade_ page.

The command can also be used to create a single upgrade image, suitable for use with application bootloader configurations of the Gecko Bootloader: `commander gbl4 create myupgrade.gbl –config configfile.yaml`.

Example of a config file is as follows:

```c
manifest:
  product_id: “00000000000000000000000000000000”
updates:
  - data: myapp.s37
  - data:mybootloader.s37

se_upgrade:
  se_file: mysecureElement.seuv2
```

###### Gecko Bootloader Security Features

###### About Bootloader Image Security (heading level 7)

Secure Boot and Secure Firmware Upgrade, discussed in the following sections, enables Gecko Bootloader to provide authenticity and integrity checks on the Application image, which provides a sufficient level of security for many applications. However, in systems without a hardware root of trust, no process checks the authenticity or integrity of the Gecko Bootloader itself. Its security is provided solely by the device hardware and the robustness of the software running on the device.

The native behavior of Firmware Upgrade will prevent accidental version rollback of Gecko Bootloader under normal usage conditions.

###### About Application Image Security (heading level 7)

The Gecko Bootloader can enforce security on two levels:

- Secure Boot refers to the verification of the authenticity of the application image in main flash on every boot of the device.
- Secure Firmware Upgrade refers to the verification of the authenticity of an upgrade image before performing a bootload, and optionally enforcing that upgrade images are encrypted.

###### Secure Boot Procedure (heading level 8)

When Secure Boot is enabled, the cryptographic signature of the application image in flash is verified on every boot before the application is allowed to run. Secure Boot is not enabled by default in the example configurations provided by Silicon Labs, but enabling it is highly recommended to ensure the validity and integrity of firmware images.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA (elliptical curve digital signature algorithm) of the SHA-256 digest of the application firmware image, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

1. On boot, the bootloader checks the application image for information about whether it is signed.
2. The type of signature and signature location is determined.
3. If the type of signature does not match the requirements of the bootloader, the bootloader enters device firmware upgrade mode and prevents the application from running.
4. According to the chosen signature algorithm, the signature of the contents of flash from the beginning of the application to the location of the signature is compared to the signature at the signature location.
5. If the signatures do not match, the bootloader enters device firmware upgrade mode and prevents the application from running.

**Secure Boot using ECDSA-P256-SHA256**

For an image to be signed for Secure Boot, the application needs to contain a copy of the **ApplicationProperties_t** struct. This struct contains information about which signature algorithm is used, and where to find the signature.

On every boot, the bootloader calculates the SHA-256 digest of the application image, from the beginning of the application to the start of the signature. The signature of the SHA-256 digest is then verified using ECDSA-P256.

If the signature is valid, the application is allowed to boot. Else, the bootloader is entered, and an application upgrade is attempted if one is available.

Simplicity Commander can be used to generate a key pair and write the public key to the device. See the [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more information.

**Secure Boot with Application Rollback Protection**

On every boot, the application version in the **ApplicationData_t** struct is stored at the end of the bootloader area in flash, which is used to prevent applications from being downgraded. The application version can remain the same for upgrades.

If application rollback prevention component is installed in the bootloader project, then before applying the upgrade image, the bootloader will check the application version in the application properties structure that resides inside the signed/encrypted GBL file and will only apply the OTA image to application area if the application version in ApplicationData structure is equal or higher than the highest application version last seen.

The application rollback prevention feature can be enabled in the **Bootloader Core** component by selecting the **Enable application rollback protection** option. The **Minimum application version allowed** option can be used to configure the minimum application version that should be allowed to boot.

The application versions are stored in the SE OTP area.

**Secure Boot Using a Certificate**

On Series 3 devices, a certificate-based secure boot operation is supported. The Certificate contains:

- Struct version: The version of the certificate structure.
- Public key: ECDSA-P256 public key, X and Y coordinates concatenated, used to validate the image.
- Certificate version: The version of the running certificate.
- Signature: ECDSA-P256 signature, used for the authentication of the public key and the certificate version.

The definition of the certificate struct can be found in `api/application_properties.h`.

To utilize certificate-based secure boot, configure Secure Engine to authenticate the bootloader image by configuring the certificate-based secure boot option in the Secure Engine OTP. Configure the Gecko Bootloader to enable certificate-based secure boot in the **Bootloader Core** component by selecting the **Enable certificate support** option. The Gecko Bootloader certificate must be signed by the private key pair of the public key stored in the Secure Engine OTP. For more information on the key storage, see the _Key Storage_ section.

The certificate-based secure boot procedure is illustrated in the following figure.

![Certificate-Based Secure Boot Procedure](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image19.jpg)

Once the certificate-based secure boot option on Secure Engine is turned on, Secure Engine verifies the Gecko Bootloader certificate. The public key stored in the certificate is used to validate the signature of the Gecko Bootloader. Secure Engine will not accept bootloader images without a certificate.

If only the secure boot option is enabled (not certificate-based) on Secure Engine, and Secure Engine identifies a certificate, the certificate will be used to validate the bootloader image. If the certificate version from the bootloader image is higher than 0 and it gets verified once, Secure Engine will never again accept direct signed bootloader images without a certificate.

The Gecko Bootloader will authenticate the direct signed application using the public key stored in the Gecko Bootloader certificate. If the application contains a certificate, Gecko Bootloader will authenticate it. The procedure is illustrated in the following figure.

![Advanced Certificate-Based Secure Boot Procedure](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image20.jpg)

After authentication of the application certificate, Gecko Bootloader verifies the signature of the application using the public key from the application certificate. In addition, Gecko Bootloader compares the Gecko Bootloader certificate version against the application certificate version. All application images with certificate version lower than the certificate version of the Gecko Bootloader will be rejected. Gecko Bootloader can be configured to only allow applications with certificates to boot by configuring the **Bootloader Core** component by selecting the **Reject direct signed images** option.

The **ApplicationProperties_t** struct contains the certificate struct **ApplicationCertificate_t**. The certificate struct can be injected to images that contain an **ApplicationProperties_t** with **ApplicationCertificate_t**. To inject a certificate to an image, issue the following command from Simplicity Commander:

```C
commander convert <image file> --secureboot --keyfile <signing key> --certificate <certificate>
--outfile <signed image file with certificate>
```

###### Secure Firmware Upgrade (heading level 8)

The Gecko Bootloader supports a secure firmware upgrade process. This is achieved by using symmetric encryption to encrypt the upgrade image, and asymmetric cryptography to sign the upgrade image. Symmetric encryption provides confidentiality, and asymmetric cryptography provides integrity and authenticity. Note that encryption alone is not enough to provide authenticity.

**Encryption Algorithms**

The Gecko Bootloader supports the AES-CTR-128 encryption algorithm. The GBL upgrade file is encrypted using 128-bit AES in Counter mode with a random nonce as the initial counter value.

To make use of the OTA decryption key stored in the Secure Engine OTP, the **Use symmetric key stored in Secure Engine storage** option in the **Bootloader Core** component must be selected. Simplicity Commander can be used to generate an OTA decryption key and write the key to the device. For more information on storing the OTA decryption key on Series 3 devices, see [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

The Secure Engine OTP key support depends on the SE Manager component, which is enabled by default.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA signature of the SHA-256 digest of the GBL upgrade file, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

Before starting a firmware upgrade process, the application can verify an image in storage by calling into the bootloader verification functions. For bootloaders with Communication Interface, the host device should verify the image before sending it to the NCP or RCP.

During firmware upgrade, the GBL file is parsed, and if encrypted, decrypted on-the-fly. A GBL Signature Tag in the GBL file indicates to the bootloader that the file is signed, and the signature is verified. If signature verification fails, the firmware upgrade process is aborted.

On Series 3 devices, Gecko Bootloader will authenticate the GBL signature tag using the public key stored in the bootloader certificate if the **Enable certificate support** option is selected in the **Bootloader Core** component. A GBL Certificate tag in the GBL file indicates to the bootloader that the GBL certificate tag needs to be authenticated using the public key stored in the bootloader certificate. The certificate version in the GBL certificate tag is compared with the bootloader certificate and only a version equal or higher than the bootloader certificate is accepted. Once the GBL certificate tag is authenticated, the GBL file's signature is verified using the authenticated public key from the GBL certificate tag.

###### Using Application Image Security Features (heading level 7)

This example assumes that a bootloader called **bootloader-uart-xmodem** has been built in Simplicity Studio.The relevant version can be flashed to the device using the Flash Programmer in Simplicity Studio or using Simplicity Commander.

This example provides two ways of signing the upgrade images. The first option uses Simplicity Commander to generate key material and sign data. This is suitable for development. The second option uses an external signer, such as a dedicated Hardware Security Module (HSM) to protect private key material and perform signing operations. Silicon Labs recommends using an HSM to safeguard private keys.

###### Generating Keys (heading level 8)

To use the security features of the Gecko Bootloader, encryption and signing keys need to be generated. These keys must then be written to the device. The encryption key is used with the GBL file for secure firmware upgrade. The signing keys are used both with the GBL file for secure firmware upgrade and to sign the application image for Secure Boot.

**Generating a Signing Key Using Simplicity Commander**

```C
commander util genkey --type ecc-p256 --privkey signing-key --pubkey signing-key.pub
```

This creates an ECDSA-P256 key pair for signing; `signing-key` contains the private key in PEM format and **must be kept secret from third parties**. This key will later be used to sign images and GBL files. `signing-key.pub` contains the public key in PEM format and can be used to verify GBL files using commander gbl4 info.

**Generating a Signing Key Using a Hardware Security Module**

When using a Hardware Security Module, the private key is kept secret inside the HSM. According to the instructions from your HSM vendor, have it generate an ECDSA-P256 key pair and export the public key in PEM format to the file **signing-key.pub**. Then use Simplicity Commander to convert the key to token format, suitable for writing to the Series 3 device.

```C
commander gbl keyconvert --type ecc-p256 signing-key.pub
```

**Generating an Encryption Key**

```C
commander util genkey --type aes-ccm --outfile encryption-key
```

This creates an AES-128 key for encryption in the file **encryption-key**.

**Writing Keys to the Device**

> **Note**: Refer to the sections, _Writing the AES Decryption Key_ and _Writing the Public Key to the Device_ in the [Simplicity Commander User Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### Signing an Application Image for Secure Boot (heading level 8)

If the bootloader enforces Secure Boot, the application needs to be signed to pass verification. On every boot, a SHA-256 digest of the application is calculated. The signature is verified using ECDSA-P256, with the same public key as for the GBL file signing. Signature verification failure prevents the application from booting.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see the _Application Properties_ section on the _Application Interface_ page.

**Using Simplicity Commander**

Signing the application can be done with the command:

```C
commander convert myapp.s37 --secureboot --keyfile signing-key --outfile myapp-signed.s37
```

**Using a Hardware Security Module**

The application can be prepared for signing by issuing the command:

```C
commander convert myapp.s37 --secureboot --extsign --outfile myapp-for-signing.s37
```

Using an HSM, sign the output file **myapp-for-signing.s37**, and supply the resulting DER-formatted signature file **signature.der** back to Simplicity Commander:

```C
commander convert myapp-for-signing.s37 --secureboot --signature signature.der --verify signing-key.pub

--outfile myapp-signed.s37
```

###### Creating a Signed and Encrypted GBL Upgrade Image File from an Application (heading level 8)

To create a GBL file from an application, use `commander gbl4 create`.

Note that, as of this writing, secure application images can only be constructed through Simplicity Commander, not through the configuration options available through Simplicity Studio.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see the _Application Properties_ section on the _Application Interface_ page.

**Using Simplicity Commander to Sign**

For an application called **myapp.s37**, use:

```C
commander gbl4 create myapp.gbl -–config configfile.yaml

```

Example of a config file is as follows:

```C
manifest:
 product_id: "[16 B ID] (default from app or 00000000000000000000000000000000)"
 bundle_version: "[version] (default 0x00000000)"
 min_version: "[version] (default 0x00000000)"
 hash_function: "[none | sha256] (default sha256)"
 certificate: "[path to file] (optional)"
 signing_key: "[path to file] (optional)"
se_upgrade:
 se_file: "[path to file] (optional)"
updates:
 - data: <path to file>
  app_type: "[uint32] (default from app or 0x00000000)"
  app_capabilities: "[uint32] (default from app or 0x00000000)"
  version: "[uint32] (default from app or 0x00000000)"
  compression_scheme: "[none | lz4 | lzma] (default none)"
  encryption_scheme: "[none | aes-ctr-128] (default none)"
  block_size: "[size in bytes] (default 0/disabled)"
```

This single command performs three actions:

- Creates a GBL file
- Encrypts the GBL file
- Signs the GBL file

If Secure Boot is also desired, the application must be signed using `commander convert --secureboot` prior to creating the GBL.

###### System Security Considerations (heading level 7)

The Gecko bootloader security features can be used to create a secure device, but do not create a secure system by themselves. This section goes over considerations that need to be taken when designing a secure system where the Gecko Bootloader is a component.

###### Key Storage (heading level 8)

On Series 3 devices, the decryption key and the sign key used by the Gecko Bootloader in the Secure Engine OTP. The decryption key can be provisioned in the Secure Engine OTP using Simplicity Commander or using the Secure Engine Mailbox interface. Once a key value has been programmed into the Secure Engine OTP, it cannot be changed.

###### Application Interface

The bootloader has an application interface exposed through a function table in the bootloader. The application interface provides APIs to use bootloader functions for storing and retrieving upgrade images and verifying their integrity. APIs to reboot into the bootloader are also provided. For details see the Gecko Bootloader API Reference, at [https://docs.silabs.com/gecko-platform/5.1.2/platform-bootloading-overview/folder](https://docs.silabs.com/gecko-platform/5.1.2/platform-bootloading-overview/folder).

If you are not using a protocol stack from Silicon Labs, the **api/btl_interface.h** header provides the bootloader application interface API. If you are using a protocol stack from Silicon Labs, the recommended bootloader interface API for the specific protocol stack should be used instead. The following files provide the implementation of the bootloader interface:

**api/btl_interface.c** (common interface)

**api/btl_interface_storage.c** (interface to storage functionality)

The application interface consists of functions that can be included in the customer application, and that communicate with the bootloader through the **MainBootloaderTable_t**. This table contains function pointers into the bootloader. The 10th word of the bootloader contains a pointer to this structure, allowing any application to easily locate it. Using the wrapper functions provided in the Bootloader Interface API is preferred over accessing the bootloader table directly. Modules include:

- **Application Storage Interface**: Application interface for interfacing with bootloader storage. The Storage Interface is only available on bootloaders that support the storage interface.
- **Common Application Interface**: Generic application interface available on all versions of the bootloader, independently of which components are present.

###### Application Properties (heading level 7)

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. The Simplicity Commander extracts the metadata contained in this structure from the application and places it in the UPDATE_MEMORY_SECTION tag in the GBL upgrade file. If the structure is not present in the application, Simplicity Commander will raise an error. The **ApplicationProperties_t** struct is added to the application on installing the **bootloader_interface** component to the application. The **bootloader_interface** component installs **bootloader_app_properties** component which adds an instance of **ApplicationProperties_t** named **sl_app_properties** to the project. The component adds a source file named **app_properties.c** and a configuration file named **app_properties_config.h**. This configuration file allows users to configure the application version via Simplicity Studio’s Component Editor. To open the Component Editor, locate the **App Properties** component under **Platform > Bootloader** as shown below.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image21.png)

Click **Configure** to open the Component Editor.

![screenshot](/bootloader-user-guide-series3-and-higher/0.2/images/sld737-image22.png)

The application type is automatically populated based on the wireless stack used in building the project. The value of the application type is automatically set during the project generation step and can be found in **autogen/sl_application_type.h** file.

The contents of the **GBL Application Tag** can be extracted from a GBL file by a running application using the Application Storage interface. Note that the **GBL Application Tag** will only be added if the GBL file contains an application image, not if the GBL file only contains a bootloader upgrade or metadata.

The structure in the application is also used to declare whether the application image is signed, and what type of signature is used. This information is added by Simplicity Commander when signing the image using `commander convert (--secureboot, --extsign or -- signature)`. For the bootloader to locate the **ApplicationProperties_t** struct, if not already done by the linker, Simplicity Commander modifies word 13 of the application to insert a pointer to the **ApplicationProperties_t** struct when signing the application image for Secure Boot.

###### Error Codes (heading level 7)

Most Gecko bootloader APIs return error codes. The following table lists the groups of error codes that may be returned. The full list of error codes within each group can be found in _api/btl_errorcode.h_ in the platform/bootloader directory of the SDK, as well as in the API Reference.

|ID|Description|
|---|---|
|0x0|OK|
|0x01xx|Initialization error|
|0x02xx|Image verification error|
|0x04xx|Storage error|
|0x05xx|Bootload error|
|0x06xx|Security error|
|0x07xx|Communication error|
|0x09xx|XMODEM parser error|
|0x10xx|GBL file parser error|
|0x11xx|SPI slave driver error|
|0x12xx|UART driver error|
|0x13xx|Compression error|
|0x14xx|RTOS error|

##### Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher

###### Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher

> **Note: This section replaces _UG489: Silicon Labs Gecko Bootloader User’s Guide for GSDK 4.0 and Higher_. Further updates to this user guide will be provided here**.

This document describes the high-level implementation of the Silicon Labs Gecko Bootloader for EFM32 and EFR32 Series 1 and Series 2 microcontrollers, SoCs (System on Chips) and NCPs (Network Co-Processors), and provides information on different aspects of configuring the Gecko Bootloader. If you are not familiar with the basic principles of performing a firmware upgrade or want more information about upgrade image files, refer to [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/). For more information on using the Gecko Bootloader with different wireless stacks, see the following:

- [Using the Gecko Bootloader with EmberZNet](https://docs.silabs.com/zigbee/latest/using-gecko-bootloader-with-zigbee/)
- [Bootloading and OTA with Silicon Labs Connect v3.x](https://docs.silabs.com/connect-stack/latest/bootloading-and-ota-with-connect-v3x)
- [Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/)

For more information on Series 2 device security, see:

- [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)
- [Series 2 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/)
- [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/)

For more information on security using Series 2 devices with Secure Vault, see:

- [Anti-Tamper Protection Configuration and Use](https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/)
- [Authenticating Silicon Labs Devices using Device Certificates](https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/)
- [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/)

###### Overview

The Silicon Labs Gecko Bootloader is a common bootloader for all the newer MCUs and wireless MCUs from Silicon Labs. The Gecko Bootloader can be configured to perform a variety of functions, from device initialization to firmware upgrades. Key features of the bootloader are:

- Useable across Silicon Labs Gecko microcontroller and wireless microcontroller families
- In-field upgradeable
- Configurable
- Enhanced security features, including:  
  - **Secure Boot**: When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot, using asymmetric cryptography. This ensures that the application was created and signed by a trusted party.  
  - **Signed upgrade image file**: The Gecko Bootloader supports enforcing cryptographic signature verification of the upgrade image file. This allows the bootloader and application to verify that the application or bootloader upgrade comes from a trusted source before starting the upgrade process, ensuring that the image file was created and signed by a trusted party.  
  - **Encrypted upgrade image file**: The image file can also be encrypted to prevent eavesdroppers from acquiring the plaintext firmware image.

The Gecko Bootloader uses a proprietary format for its upgrade images, called GBL (Gecko Bootloader file). These files have the file extension “.gbl”. See section [Gecko Bootloader File Format](02-gecko-bootloader-file-format#gecko-bootloader-file-format) for more details.

On Series 1 devices, the Gecko Bootloader has a two-stage design, first stage and main stage, where a minimal first stage bootloader is used to upgrade the main bootloader. The first stage bootloader only contains functionality to read from and write to fixed addresses in internal flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to a fixed location in internal flash and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader firmware upgrade image, by computing a CRC32 checksum before copying the upgrade image to the main bootloader location.

On Series 2 devices, the Gecko bootloader consists only of the main stage bootloader. The main bootloader is upgradable through the Secure Engine. The Secure Engine may be hardware-based, or virtual (software). If hardware-based, the implementation may be either with or without Secure Vault. Throughout this document, the following conventions will be used.

- HSE - Hardware Secure Engine, either with or without Secure Vault if not specified
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE, in general)

The Secure Engine provides functionality to install an image to address 0x0 in internal flash, by copying from a configurable location in internal flash. This makes it possible to have a 2-stage design, where the main bootloader is not present. However, the presence of a main bootloader is assumed throughout this document.

To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to the upgrade location in flash and requests that the Secure Engine installs it. On some devices, the Secure Engine is also capable of verifying the authenticity of the main bootloader update image against a root of trust. The Secure Engine itself is upgradable using the same mechanism. See [Gecko Bootloader Operation - Secure Engine Upgrade](05-gecko-bootloader-operation-secure-engine-upgrade#gecko-bootloader-operation-secure-engine-upgrade) for more details.

The main bootloader consists of a common core, drivers, and a set of components that give the bootloader specific capabilities. The common bootloader core is now provided as a full-source delivery, as opposed to previously being a combination of compiled libraries and source code while the components continue to be delivered as source code. The common bootloader core contains functionality to parse GBL files and flash their contents to the device.

The Gecko Bootloader can be configured to perform firmware upgrades in standalone mode (also called a standalone bootloader) or in application mode (also called an application bootloader), depending on the component configuration. Components can be installed in and configured through the Simplicity Studio IDE.

A standalone bootloader uses a communications channel to get a firmware upgrade image. NCP (network co-processor) devices always use standalone bootloaders. Standalone bootloaders perform firmware image upgrades in a single-stage process that allows the application image to be placed into flash memory, overwriting the existing application image, without the participation of the application itself. In general, the only time that the application interacts with a standalone bootloader is when it requests to reboot into the bootloader. Once the bootloader is running, it receives packets containing the firmware upgrade image over-the-air using Bluetooth or by a physical connection such as UART or SPI. To function as a standalone bootloader with a physical connection, a component providing a communication interface such as UART or SPI must be configured.

An application bootloader relies on the application to acquire the firmware upgrade image. The application bootloader performs a firmware image upgrade by writing the firmware upgrade image to a region of flash memory referred to as the download space. The application transfers the firmware upgrade image to the download space in any way that is convenient (UART, over-the-air, Ethernet, USB, and so on). The download space is either an external memory device such as an EEPROM or dataflash or a section of the device’s internal flash. The Gecko Bootloader can partition the download space into multiple storage slots and store multiple firmware upgrade images simultaneously. To function as an application bootloader, a component providing a bootloader storage implementation has to be configured.

Silicon Labs provides example bootloaders that come with a preconfigured set of installed components for configuration in either standalone or application mode. See section [Configuring the Gecko Bootloader](07-configuring-the-gecko-bootloader#configuring-the-gecko-bootloader). The Silicon Labs Gecko SDK Suite also includes precompiled bootloader images for several different EFR32 devices. As of this writing, the images shown in the following table are provided.

> **Note**: The bootloader security features are not enabled in these precompiled images.

Table Prebuilt Bootloader Images

<table>
    <thead>
        <tr>
            <th>Use</th>
            <th>Wireless Stack</th>
            <th>Image Name</th>
            <th>Mode</th>
            <th>Interface</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SoC</p>
            </td>
            <td>
                <p>EmberZNet PRO</p>
            </td>
            <td>
                <p>SPI Flash Storage Bootloader</p>
            </td>
            <td>
                <p>Application</p>
            </td>
            <td>
                <p>SPI Serial Flash</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SoC</p>
            </td>
            <td>
                <p>Bluetooth</p>
            </td>
            <td>
                <p>Bluetooth In-Place OTA DFU Bootloader</p>
            </td>
            <td>
                <p>Application</p>
            </td>
            <td>
                <p>OTA/internal flash</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>NCP</p>
            </td>
            <td>
                <p>EmberZNet PRO</p>
            </td>
            <td>
                <p>UART XMODEM Bootloader</p>
            </td>
            <td>
                <p>Standalone</p>
            </td>
            <td>
                <p>UART (EZSP)</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>NCP</p>
            </td>
            <td>
                <p>Bluetooth</p>
            </td>
            <td>
                <p>BGAPI UART DFU Bootloader</p>
            </td>
            <td>
                <p>Standalone</p>
            </td>
            <td>
                <p>UART (BGAPI)</p>
            </td>
        </tr>
    </tbody>
</table>

Note that on devices with a dedicated bootloader area (EFR32xG12 and later Series 1 devices), if the device is configured to boot to the bootloader area (that is, if bit 1 of the Config Lock Word 0 CLW0[1] is set), an image always must be present in the bootloader area. The device is factory-programmed with a dummy bootloader that simply jumps directly to the application in main flash. This means that when flashing a bootloader to a device with a dedicated bootloader area, this dummy bootloader is replaced. If later during development using the bootloader is no longer desired, CLW0[1] must be cleared or the dummy bootloader needs to be re-flashed. Platform-specific prebuilt dummy bootloader images are located in _./platform/bootloader/util/bin/_. Note that since the dummy bootloader only consists of a few instructions and doesn't pad out the remainder of the bootloader area, only the first flash page (where the first-stage bootloader resides) is overwritten, so the main stage bootloader would likely remain intact after programming the dummy bootloader. If desired, the rest of the flash pages in the bootloader area can then be erased separately.

On devices that do not have a dedicated bootloader area (EFR32xG1 and EFR32 Series 2), a dummy bootloader is not needed.

The following sections provide an overview of the Gecko Bootloader common core, drivers, and components. For details, including details on error codes and conditions, see the Gecko Bootloader API Reference, shipped with the SDK in the platform/bootloader/documentation folder.

The bootloader area can be fully erased using the `commander device pageerase --region @bootloader` command with Simplicity Commander. In this state, the device will not boot until CLW0[1] is cleared or the dummy bootloader is flashed. For more information on how to use Simplicity Commander with Gecko bootloader, see section [Simplicity Commander and the Gecko Bootloader](08-simplicity-commander-and-the-gecko-bootloader#simplicity-commander-and-the-gecko-bootloader).

###### Core (heading level 7)

The bootloader core contains the bootloader’s main functions. It also contains functionality to write to the internal flash, an image parser to parse and act upon the contents of GBL upgrade files, and functionality to boot the application in main flash.

The image parser can also optionally support the legacy Ember Bootloader (EBL) file format, but none of the security features offered by the Gecko Bootloader are supported if support for legacy EBL files is enabled.

A version of the GBL image parser without support for encrypted upgrade images is also available. This version can be used in flash space constrained bootloader applications where encryption of the upgrade image is not required.

###### Shared Memory (heading level 8)

To exchange information between the bootloader and application, a section of SRAM is used. The contents of SRAM are preserved through a software reset, making the SRAM suitable as a communication channel between bootloader and application.

The shared memory has a size of 4 bytes, and is located at the first address of SRAM, 0x20000000. It is used to store a single word containing the reason for a reset. The structure of the reset cause word is defined in the Reset Information part of the Application Interface, in the file **btl_reset_info.h**, as 16 bits containing the reason, and 16 bits of signature indicating if the word is valid or not. If the signature reads 0xF00F, the reset reason is valid.

All 16-bit reset reasons used by Silicon Labs have the most significant bit set to zero. If custom reset reasons are desired, it is recommended to set the most significant bit to avoid conflicting definitions.

In addition to the reset causes defined in the Reset Information documentation, the bootloader will enter firmware upgrade mode if the shared memory contains the value 0x00000001. This value is supported for compatibility with certain legacy Bluetooth applications.

###### Drivers (heading level 7)

Different applications of firmware upgrade require different hardware drivers for use by the other components of the bootloader.

Driver modules include:

- Delay: Simple delay routines for use with components that require small delays or timeouts.
- SPI: Simple, blocking SPI master implementation for communication with external devices such as SPI flashes.
- SPI Slave: Flexible SPI Slave driver implementation for use in communication components implementing SPI protocols. This driver supports both blocking and non-blocking operation, with DMA (Direct Memory Access) backing the background transfers to support non-blocking operation.
- UART: Flexible serial UART driver implementation for use in communication components implementing UART protocols. This driver supports both blocking and non-blocking operation, with DMA backing the background transfers to support non-blocking operation. Additionally, support for hardware flow control (RTS/CTS) is included.

###### Components (heading level 7)

All parts of the bootloader that are either optional or that may be exchanged for different configurations are implemented as components. Each component may have a configuration header file, and one or more implementations. Components include:

- Communication  
  - UART: XMODEM  
  - UART: BGAPI  
  - SPI: EZSP  
  - Bluetooth: AppLoader
- Compression
- Debug
- GPIO Activation
- Security
- Storage  
  - Internal flash  
  - External SPI flash
- SMP Switch (Series 2)  
  - Two-Page Switch Record

###### Communication (heading level 8)

The Communication components provide an interface for implementing communication with a host device, such as a computer or a micro-controller. Several components implement the communication interface, using different transports and protocols.

- BGAPI UART DFU: By enabling the BGAPI communication component, the bootloader communication interface implements the UART DFU protocol using BGAPI commands. See _AN1053: Bluetooth® Device Firmware Update over UART for EFR32xG1 and BGM11x Series Products_ for more information about this legacy bootloader.
- Bluetooth:AppLoader: By enabling the Bluetooth AppLoader communication component, the bootloader communication interface implements over-the-air device firmware upgrade functionality using Bluetooth. See [Using the Gecko Bootloader with the Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/) for more information.
- EZSP-SPI: By enabling the EZSP-SPI communication component, the bootloader communication interface implements the EZSP protocol over SPI. This component makes the bootloader compatible with the legacy ezsp-spi-bootloader that was previously released with the EmberZNet wireless stack. See _AN760: Using the Ember Standalone Bootloader_ for more information about legacy Ember standalone bootloaders.
- UART XMODEM: By enabling the UART XMODEM communication component, the bootloader communication interface implements the XMODEM-CRC protocol over UART. This component makes the bootloader compatible with the legacy serial-uart-bootloader that was previously released with the EmberZNet wireless stack. See _AN760: Using the Ember Standalone Bootloader_ for more information about legacy Ember standalone bootloaders.

###### Compression (heading level 8)

The Compression components provide capability for the bootloader GBL file parser to handle compressed GBL upgrade images. Each compression component provides support for one (de)compression algorithm. At the time of writing, decompression of data compressed with the LZ4 and LZMA algorithms is supported, through the _GBL Compression (LZ4)_ and _GBL Compression (LZMA)_ components.

###### Debug (heading level 8)

This component provides the bootloader with support for debugging output. If the component is configured to enable debug prints, short debug messages will be printed over Serial Wire Output (SWO), which can be accessed in multiple ways, including using Simplicity Commander, and by connecting to port 4900 of the Wireless Starter Kit TCP/IP interface.

To turn on debug prints, enable the Debug component and select **Debug prints**. Select **Debug asserts** to enable assertions in the source code.

On Series 1 devices, also select the GPIO peripheral in the Pin Tool.

###### GPIO Activation (heading level 8)

This component provides functionality to enter firmware upgrade mode automatically after reset if a GPIO pin is active during boot. The GPIO pin location and polarity are configurable.

- GPIO: By enabling the GPIO activation component, the firmware upgrade mode can be activated by the push buttons.
- EZSP GPIO: The EZSP communication protocol over SPI can be used together with this component. By enabling the EZSP GPIO component, the firmware upgrade mode can be entered by activating the _nWake_ pin.

###### Security (heading level 8)

Security components provide implementations of cryptographic operations as well as functionality to compute checksums and to read cryptographic keys from manufacturing tokens.

Modules include:

- AES: AES decryption functionality
- CRC16: CRC16 functionality
- CRC32: CRC32 functionality
- ECDSA: ECDSA signature verification functionality
- SHA-256: SHA-256 digest functionality

###### Storage (heading level 8)

These components provide the bootloader with multiple storage options for SoCs. All storage implementations have to provide an API to access image files to be upgraded. This API is based on the concept of dividing the download space into storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Some storage implementations also support a raw storage API to access the underlying storage medium. This can be used by applications to store other data in parts of the storage medium that are not used for storing firmware upgrade images. Implementations include:

- **Internal Flash**: The internal flash storage implementation uses the internal flash of the device for upgrade image storage. Note that this storage area is only a download space and is separate from the portion of internal flash used to hold the active application code.
- **SPI Flash**: Two components are available for SPI Flash storage implementation.  
  1. **SPI Flash Storage**: The SPI flash storage implementation supports a variety of SPI flash parts. The subset of devices supported can be configured in this component in Gecko Bootloader. (The default configuration if no devices are selected is to include drivers for all supported parts.) Including support for multiple devices requires more flash space in the bootloader. The SPI flash storage implementation does not support any write protection functionality. Supported SPI flash parts are shown in Table 1.2.  
  2. **SPI Flash Storage SFDP**: The SPI Flash storage SFDP implementation supports all the SPI flash parts that support SFDP (Serial Flash Description Parameter) Standard from JEDEC. The SPI Flash type is detected automatically by querying the SFDP Parameter table present within the flash memory. All the properties of the SPI Flash are accessed from this parameter table. This component is not configurable since the flash is automatically detected. Any flash that supports the SFDP standard can be used with the Gecko Bootloader. However, performance delays might occur when compared to using the **SPI Flash Storage** component.

> **Note**: Low power devices are recommended for battery-operated applications. Use of the other listed devices will decrease battery life due to higher quiescent current, but this can be mitigated with external shutdown FET circuitry, if desired.

Table Supported Serial Dataflash/EEPROM External Memory Parts

<table>
    <thead>
        <tr>
            <th>Manufacturer Part Number</th>
            <th>Size (kB)</th>
            <th>Quiescent Current (µA Typical)*</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Macronix MX25R8035F (low power)</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>0.007</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25R6435SF (low power)</p>
            </td>
            <td>
                <p>8192</p>
            </td>
            <td>
                <p>0.007</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25R3235F (low power)</p>
            </td>
            <td>
                <p>4096</p>
            </td>
            <td>
                <p>0.007</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Spansion S25FL208K</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>15</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Winbond W25X20BVSNIG (W25X20CVSNJG for high-temperature support)</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Winbond W25Q80BVSNIG (W25Q80BVSNJG for high-temperature support)</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L2006EM1I-12G (MX25L2006EM1R-12G for high-temperature support)</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L4006E</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L8006EM1I-12G (MX25L8006EM1R-12G for high-temperature support)</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25L1606E</p>
            </td>
            <td>
                <p>2048</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Macronix MX25U1635E (2V)</p>
            </td>
            <td>
                <p>2048</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Atmel/Adesto AT25DF041A</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>15</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Atmel/Adesto AT25DF081A</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Atmel/Adesto AT25SF041</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>2</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P20</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P40</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P80</p>
            </td>
            <td>
                <p>1024</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Micron (Numonyx) M25P16</p>
            </td>
            <td>
                <p>2048</p>
            </td>
            <td>
                <p>1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ025B</p>
            </td>
            <td>
                <p>32</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ512B</p>
            </td>
            <td>
                <p>64</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ010B</p>
            </td>
            <td>
                <p>126</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ020B</p>
            </td>
            <td>
                <p>256</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ISSI IS25LQ040B</p>
            </td>
            <td>
                <p>512</p>
            </td>
            <td>
                <p>8</p>
            </td>
        </tr>
    </tbody>
</table>

* Quiescent current values are as of December 2017; check the latest part specifications for any changes.

###### Compatibility (heading level 7)

1. Silicon Labs recommends building the Gecko Bootloader and the application using the same GSDK. This implies that, if the Gecko Bootloader has been built using GSDK v4.0, it is recommended that the application also be built using GSDK v4.0.
2. Backward compatibility is supported wherein the Gecko Bootloader is built using a previous SDK version and the application is built using a newer SDK version.
3. In general, Silicon Labs does not recommend building the Gecko Bootloader using a newer SDK version with the application built using an older SDK version.

The below table attempts to explain the above-mentioned guidelines:

<table>
    <thead>
        <tr>
            <th>
                <p>SDK version X &lt; SDK version Y</p>
            </th>
            <th>
                <p>Application built using SDK version X</p>
            </th>
            <th>
                <p>Application built using SDK version Y</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Gecko Bootloader built using SDK version X</p>
            </td>
            <td>
                <p>Recommended</p>
            </td>
            <td>
                <p>Compatible</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Gecko Bootloader built using SDK version Y</p>
            </td>
            <td>
                <p>Not recommended</p>
            </td>
            <td>
                <p>Recommended</p>
            </td>
        </tr>
    </tbody>
</table>

###### SMP Switch (heading level 7)

The Switch Multi-Protocol (SMP) Switch component provides the bootloader with **dual-application boot selection** on a single device. The bootloader stores a small **switch record** in two dedicated flash erase pages and uses it to select which of two application images (App 1 or App 2) to boot. No NVM3 is required for this selection.

The component is currently available on **Series 2 devices** (EFR32ZG28).

When enabled, the bootloader:

- Reads a `btl_smp_switch_record_t` from each of two configured flash pages and validates magic, app id, version, and CRC32.
- Boots the application identified by the **newest valid** record (higher 16-bit sequence number wins; ties resolve to page 2).
- Uses `BTL_SMP_DEFAULT_APP_ID` when both records are invalid (e.g., first boot).
- Falls back to the **alternate application slot** if image verification of the SMP-selected app fails — for example when the SMP-selected app does not pass Secure Boot verification.

The application can request that the **next reset** runs the other application by calling `btl_smp_switch_request_next_boot_app()`. The application discovers the switch page bases at runtime via the bootloader storage vtable (`getSmpSwitchPageBases`); it does not include the bootloader's `btl_smp_cfg.h`.

The bootloader advertises this capability through the `BOOTLOADER_CAPABILITY_SMP_SWITCH` bit in `BootloaderInformation_t.capabilities`.

Implementations include:

- **SMP Switch (Series 2)** — adds the `bootloader_smp_switch` component, defines `BTL_SMP_SUPPORT`, and configures page and application base addresses through `btl_smp_cfg.h` (see [Configuring the Gecko Bootloader](https://docs.silabs.com/shared-content/latest/bootloader-user-guide-gsdk-4/07-configuring-the-gecko-bootloader). For the application-side API and switch-record format, see [Application Interface](https://docs.silabs.com/shared-content/latest/bootloader-user-guide-gsdk-4/12-application-interface) and the dedicated SMP chapter.

###### Gecko Bootloader File Format

The GBL file format is used by the Gecko Bootloader. File formats described in this section are generated by Simplicity Commander commands. For more information, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### File Structures (heading level 7)

The GBL file format is composed of several tags that indicate a format of the subsequent data and the length of the entire tag. The format of a tag is as follows:

<table>
    <thead>
        <tr>
            <th>
                <p>Tag ID</p>
            </th>
            <th>
                <p>Tag Length</p>
            </th>
            <th>
                <p>Tag Payload</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>4 bytes</p>
            </td>
            <td>
                <p>4 bytes</p>
            </td>
            <td>
                <p>Variable (according to tag length)</p>
            </td>
        </tr>
    </tbody>
</table>

###### Plaintext Tag Description (heading level 7)

<table>
    <thead>
        <tr>
            <th>
                <p>Tag Name</p>
            </th>
            <th>
                <p>ID</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>GBL Header Tag</p>
            </td>
            <td>
                <p>0x03A617EB</p>
            </td>
            <td>
                <p>This must be the first tag in the file. The header tag contains the version number of the GBL file specification, and flags indicating the type of GBL file - whether it is signed or encrypted.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Version Dependency Tag</p>
            </td>
            <td>
                <p>0x76A617EB</p>
            </td>
            <td>
                <p>This optional tag contains encoded version dependencies that the software currently running on the device must satisfy before an upgrade can be attempted. Only available on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Application Info Tag</p>
            </td>
            <td>
                <p>0xF40A0AF4</p>
            </td>
            <td>
                <p>This tag contains information about the application update image that is contained in this GBL file</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL SE Upgrade Tag</p>
            </td>
            <td>
                <p>0x5EA617EB</p>
            </td>
            <td>
                <p>This tag contains a complete encrypted Secure Element update image. Only applicable on Series 2 devices.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Bootloader Tag</p>
            </td>
            <td>
                <p>0xF50909F5</p>
            </td>
            <td>
                <p>This tag contains a complete bootloader update image.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Program Data Tag</p>
            </td>
            <td>
                <p>0xFE0101FE / 0xFD0303FD</p>
            </td>
            <td>
                <p>This tag contains information about what application data to program at a specific address into the main flash memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Delta Tag</p>
            </td>
            <td>
                <p>0xF80A0AF8UL</p>
            </td>
            <td>
                <p>This tag contains the information about the delta patch that should be used to create the new app.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Program LZ4 Compressed Data Tag</p>
            </td>
            <td>
                <p>0xFD0505FD</p>
            </td>
            <td>
                <p>This tag contains LZ4 compressed information about what application data to program at a specific address into the main flash memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Delta LZ4 Compressed Data Tag</p>
            </td>
            <td>
                <p>0xF80B0BF8UL</p>
            </td>
            <td>
                <p>This tag contains LZ4 compressed information about the delta patch that should be used to create the new app.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Program LZMA Compressed Data Tag</p>
            </td>
            <td>
                <p>0xFD0707FD</p>
            </td>
            <td>
                <p>This tag contains LZMA compressed information about what application data to program at a specific address into the main flash memory.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Delta LZMA Compressed Data Tag</p>
            </td>
            <td>
                <p>0xF80C0CF8UL</p>
            </td>
            <td>
                <p>This tag contains LZMA compressed information about the delta patch that should be used to create the new app.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Metadata Tag</p>
            </td>
            <td>
                <p>0xF60808F6</p>
            </td>
            <td>
                <p>This tag contains metadata that the bootloader does not parse but can be returned to the application through a callback.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Certificate Tag</p>
            </td>
            <td>
                <p>0xF30B0BF3</p>
            </td>
            <td>
                <p>This tag contains a certificate that will be used to verify the authenticity of the GBL file.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Signature Tag</p>
            </td>
            <td>
                <p>0xF70A0AF7</p>
            </td>
            <td>
                <p>This tag contains the ECDSA-P256 signature of all preceding data in the file.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL End Tag</p>
            </td>
            <td>
                <p>0xFC0404FC</p>
            </td>
            <td>
                <p>This tag indicates the end of the GBL file. It contains a 32-bit CRC for the entire file as an integrity check. The CRC is a non-cryptographic check. This must be the last tag.</p>
            </td>
        </tr>
    </tbody>
</table>

The allowed sequence of GBL tags in a GBL file is shown in the following figure.

![GBL Tag Sequence](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image1.png)

###### Encrypted Tag Descriptions (heading level 7)

The encrypted GBL file format is like the unencrypted version. It introduces several new tags.

<table>
    <thead>
        <tr>
            <th>
                <p>Tag Name</p>
            </th>
            <th>
                <p>ID</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>GBL Header Tag</p>
            </td>
            <td>
                <p>0x03A617EB</p>
            </td>
            <td>
                <p>The GBL header is the same as for a plaintext GBL file, but the flag indicating that the GBL file is encrypted must be set.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Encryption Init Header</p>
            </td>
            <td>
                <p>0xFA0606FA</p>
            </td>
            <td>
                <p>This contains information about the image encryption such as the Nonce and the amount of encrypted data.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>GBL Encrypted Program Data</p>
            </td>
            <td>
                <p>0xF90707F9</p>
            </td>
            <td>
                <p>This contains an encrypted payload containing a plaintext GBL tag, one of Application Info, Bootloader, Metadata or Program Data. The data is encrypted using AES-CTR-128.</p>
            </td>
        </tr>
    </tbody>
</table>

The allowed sequence of GBL tags in an encrypted GBL file is shown in the following figure.

![Encrypted GBL Tag Sequence](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image2.png)

###### GBL Tag Data Structures and Definitions (heading level 7)

**GBL Tag Header**

```C
typedef struct {

uint32_t  tagId;  // Tag ID representing the type of tag (GBL Header Tag, GBL Bootloader Tag, etc.).

uint32_t  length; // Length of the subsequent tag data in bytes.

} GblTagHeader_t;
```

**GBL Header Tag**

```C
typedef struct {

GblTagHeader_t header;  // Tag header.

uint32_t       version; // Version of the GBL file format specification. E.g. 0x03000000.

uint32_t       type;    // Flags indicating whether the GBL file is encrypted and/or signed.

// See definitions below.

} GblHeader_t;
```

```C
// GBL types

#define GBL_TYPE_NONE                 0x00000000UL

#define GBL_TYPE_ENCRYPTION_AESCCM    0x00000001UL

#define GBL_TYPE_SIGNATURE_ECDSA      0x00000100UL
```

**GBL Version Dependency Tag**

```C
typedef struct {

uint8_t  imageType;  // Type of image (application, bootloader, SE)

uint8_t  statement;  // Encoded dependency statement (ex. appVersion > (0).1.2.3)

uint16_t reserved;   // Reserved

uint32_t version;    // The version number used in the statement (ex. (0).1.2.3)

} VersionDependency_t;

// Image types

#define GBL_VERSION_DEPENDENCY_TYPE_APPLICATION             0x01U

#define GBL_VERSION_DEPENDENCY_TYPE_BOOTLOADER              0x02U

#define GBL_VERSION_DEPENDENCY_TYPE_SE                      0x03U

// Operator encoding

#define GBL_VERSION_DEPENDENCY_OPERATOR_MASK                0x0FU

#define GBL_VERSION_DEPENDENCY_OPERATOR_SHIFT               0x00U

#define GBL_VERSION_DEPENDENCY_OPERATOR_TYPE_MASK           0x0EU

#define GBL_VERSION_DEPENDENCY_OPERATOR_NEGATOR_BIT_MASK    0x01U

#define GBL_VERSION_DEPENDENCY_OPERATOR_LT                  0x00U

#define GBL_VERSION_DEPENDENCY_OPERATOR_LEQ                 0x02U

#define GBL_VERSION_DEPENDENCY_OPERATOR_EQ                  0x04U

#define GBL_VERSION_DEPENDENCY_OPERATOR_GEQ                 0x06U

#define GBL_VERSION_DEPENDENCY_OPERATOR_GT                  0x08U

// Connective encoding

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_MASK              0xF0U

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_SHIFT             0x04U

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_TYPE_MASK         0x0EU

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_NEGATOR_BIT_MASK  0x01U

#define GBL_VERSION_DEPENDENCY_CONNECTIVE_AND               0x00U

// SE version mask for ignoring the compatibility byte when comparing versions

#define GBL_VERSION_DEPENDENCY_SE_VERSION_MASK              0x00FFFFFFUL
```

**GBL Application Info Tag**

```C
typedef struct {

GblTagHeader_t    header;  // Tag header.

ApplicationData_t appInfo; // Application information structure. See definition below.

} GblApplication_t;
```

```C
typedef struct ApplicationData {

uint32_t type;           // Bitfield representing the type of application.

// See definitions below for possible values.

uint32_t version;        // Version number for this application (customer-defined).

uint32_t capabilities;   // Bitfield representing the capabilities of this application.

uint8_t  productId[16];  // Unique ID (UUID or GUID) for the product this application is built for.

} ApplicationData_t;
```

```C
// Application types

#define APPLICATION_TYPE_ZIGBEE          (1UL << 0UL)

#define APPLICATION_TYPE_THREAD          (1UL << 1UL)

#define APPLICATION_TYPE_FLEX            (1UL << 2UL)

#define APPLICATION_TYPE_BLUETOOTH       (1UL << 3UL)

#define APPLICATION_TYPE_MCU             (1UL << 4UL)

#define APPLICATION_TYPE_BLUETOOTH_APP   (1UL << 5UL)

#define APPLICATION_TYPE_BOOTLOADER      (1UL << 6UL)

#define APPLICATION_TYPE_ZWAVE           (1UL << 7UL)
```

**GBL SE Upgrade Tag**

```C
typedef struct {

GblTagHeader_t header;   // Tag header.

uint32_t       blobSize; // Size of the SE upgrade data blob.

uint32_t       version;  // Version of the SE image.

uint8_t        data[];   // Array of data containing the SE upgrade blob.

} GblSeUpgrade_t;
```

**GBL Bootloader Tag**

```C
typedef struct {

GblTagHeader_t header;            // Tag header.

uint32_t       bootloaderVersion; // Version number of the bootloader.

uint32_t       address;           // Base address of the bootloader image.

uint8_t        data[];            // Array of data containing the bootloader upgrade image.

} GblBootloader_t;
```

**GBL Program Data Tag**

```C
typedef struct {

GblTagHeader_t header;            // Tag header.

uint32_t       flashStartAddress; // Address at which to start flashing data.

uint8_t        data[];            // Array of data to be flashed

// (compressed data in the LZ4 and LZMA variants of the tag).

} GblProg_t;
```

**GBL Metadata Tag**

```C
typedef struct {

GblTagHeader_t header;     // Tag header.

uint8_t        metadata[]; // Array containing the metadata.

} GblMetadata_t;
```

**GBL Certificate Tag**

```C
typedef struct {

GblTagHeader_t           header;      // Tag header.

ApplicationCertificate_t certificate; // Certificate used to verify the GBL file. See definition below.

} GblCertificateEcdsaP256_t;

typedef struct ApplicationCertificate {

uint8_t  structVersion;     // Version of the certificate structure.

uint8_t  flags[3];          // Reserved flags.

uint8_t  key[64];           // Public key used to verify the GBL file.

uint32_t version;           // Version number of this certificate.

uint8_t  signature[64];     // The signature of the certificate itself (not the GBL file).

} ApplicationCertificate_t;
```

**GBL Signature Tag**

```C
typedef struct {

GblTagHeader_t header; // Tag header.

uint8_t        r[32];  // The r value of the ECDSA signature.

uint8_t        s[32];  // The s value of the ECDSA signature.

} GblSignatureEcdsaP256_t;
```

**GBL End Tag**

```C
typedef struct {

GblTagHeader_t header; // Tag header.

uint32_t       gblCrc; // CRC32 checksum of the entire GBL file.

} GblEnd_t;
```

**GBL Encryption Init Header Tag**

```C
typedef struct {

GblTagHeader_t header;    // Tag header.

uint32_t       msgLen;    // Length of the ciphertext in bytes.

uint8_t        nonce[12]; // Random AES-CTR nonce.

} GblEncryptionInitAesCcm_t;
```

**GBL Encrypted Data Tag**

```C
typedef struct {

GblTagHeader_t header;             // Tag header.

uint8_t        encryptedGblData[]; // Array containing the ciphertext (encrypted GBL data).

// Note that the corresponding plaintext must contain one or

// more complete GBL tags. Put differently: A single plaintext GBL

// tag cannot be split across multiple encrypted tags.

} GblEncryptionData_t;
```

###### Gecko Bootloader Operation - Application Upgrade

This section summarizes Gecko Bootloader operation for updating application firmware, first if the Gecko Bootloader is configured in standalone mode and then if it is configured in application mode. Section [Gecko Bootloader Operation - Bootloader Upgrade](04-gecko-bootloader-operation-bootloader-upgrade#gecko-bootloader-operation-bootloader-upgrade) provides the same information for updating the bootloader firmware.

The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the section "Memory Space for Bootloading" in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

###### Standalone Bootloader Operation (heading level 7)

Standalone bootloader operation is illustrated in the following figure:

![Standalone Bootloader Operation](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image3.png)

1. The device reboots into the bootloader.
2. A GBL file containing an application image is transmitted from the host to the device. If image encryption is enabled in the main stage bootloader and the image is encrypted, decryption is performed during the process of receiving and parsing the GBL file.
3. The bootloader applies the application upgrade from the GBL upgrade file on-the-fly. If image authentication is enabled in the main stage bootloader and the GBL file contains a signature, the authenticity of the image is verified before completing the process.
4. The device boots into the application. Application upgrade is complete.

###### Rebooting Into the Bootloader (heading level 8)

The Gecko Bootloader supports multiple mechanisms for triggering the bootloader. If the **GPIO activation** component is installed, the host device can keep this pin low/high (depending on configuration) through reset to make the device enter the bootloader. The bootloader can also be entered through software. The `bootloader_rebootAndInstall` API first signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it will enter firmware upgrade mode instead of booting the existing application.

###### Downloading and Applying a GBL Upgrade File (heading level 8)

When the bootloader enters firmware upgrade mode, it enters a receive loop waiting for data from the host device. The specifics of the receive loop depend on the protocol. Received packets are passed to the image parser, a state machine that parses the data and returns a callback containing any data that should be acted upon. The bootloader core implements this callback and flashes the data to internal flash at the address specified. If GBL file authentication or encryption is enabled, the image parser will enforce this, and abort the image upgrade if the authentication fails.

The bootloader prevents a newly uploaded image from being bootable by holding back parts of the application vector table until the GBL file CRC and GBL signature (if required) have been verified.

###### Booting Into the Application (heading level 8)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If a valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

###### Error Handling (heading level 8)

If the application upgrade is interrupted at any time, the device will be without a working application. The bootloader then resets the device, and re-enters firmware upgrade mode. The host device can easily restart the application upgrade process, to try loading the upgrade image again.

###### Application Bootloader Operation (heading level 7)

The following figure illustrates the application bootloader operation both for a single image/single storage slot, and multiple images/ multiple storage slots.

![Application Bootloader Operation: Single Storage Slot](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image4.png)

![Application Bootloader Operation: Multiple Storage Slots](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image5.png)

1. A GBL file is downloaded onto the storage medium of the device (internal flash or external dataflash), as described below, and the presence of an upgrade image is indicated.
2. The device reboots into the bootloader, and the bootloader enters firmware upgrade mode.
3. The bootloader applies the application upgrade from the GBL upgrade file.
4. The device boots into the application. Application upgrade is complete.

###### Downloading and Storing a GBL Upgrade Image File (heading level 8)

To prepare for receiving an upgrade image, the application finds an available storage slot, or erases an existing one using `bootloader_eraseStorageSlot`. If the bootloader only supports a single storage slot, a value of 0 should be used for the slot ID.

The application then receives a GBL file using an applicable protocol, such as Ethernet, USB, Zigbee, OpenThread, or Bluetooth, and stores it in the slot by calling `bootloader_writeStorage`.

When download is complete, the application can optionally verify the integrity of the GBL file by calling `bootloader_verifyImage`. This is also done by the bootloader before applying the image but can be done from the application in order to avoid rebooting into the bootloader if the received image was corrupt.

If multiple storage slots are supported, the application should write a bootload list by calling `bootloader_setImageToBootload`. The list is written to the two bootload info pages as shown in Figure The bootload list is a prioritized list of slots indicating the order the bootloader should use when attempting to perform a firmware upgrade. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader treats the entire download space as a single storage slot.

###### Rebooting and Applying a GBL Upgrade File (heading level 8)

The bootloader can be entered through software. The `bootloader_rebootAndInstall` API signals to the bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performs a software reset. If the bootloader finds the correct command in shared memory upon boot, it enters firmware upgrade mode instead of booting the existing application.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the image stored in each. Once it finds a valid GBL upgrade file, firmware upgrade is attempted from this GBL file. If the upgrade fails, the bootloader moves to the next image in the list. If no images pass verification, the bootloader reboots back into the existing application with a message in the shared memory location in SRAM indicating that no good upgrade images were found.

###### Booting Into the Application (heading level 8)

When an application upgrade is completed, the bootloader triggers a reboot with a message in shared memory at the bottom of SRAM signaling that an application upgrade has been successfully completed. The application can use this reset information to learn that an application upgrade was just performed.

Before jumping to the main application, the bootloader verifies that the application is ready to run. This includes verifying if the Program counter and Stack Pointer are valid. If secure boot is enabled, the bootloader expects a signed application and attempts to validate the signature of the application. In scenarios where secure boot is not enabled, the bootloader attempts to validate if the Application properties pointer points to valid app properties structure in the flash. If valid app properties struct is found, the bootloader proceeds based on the signature type indicated by the application properties struct or else the bootloader assumes that the Application properties pointer points to the Reset Handler of the application (an app without application properties) and proceeds to boot into the application. In case the verification of the application fails at any stage, the bootloader enters the bootload mode instead of booting into the application.

###### Gecko Bootloader Operation - Bootloader Upgrade

Bootloader upgrade functionality is provided by the first stage bootloader on Series 1 devices, or the Secure Engine on Series 2 devices. The Secure Engine itself is also upgradable. For more details, see section [Gecko Bootloader Operation - Secure Engine Upgrade](05-gecko-bootloader-operation-secure-engine-upgrade#gecko-bootloader-operation-secure-engine-upgrade). On Series 1 devices, the first stage bootloader is not upgradable.

Requirements for upgrading the main bootloader vary depending on the bootloader configuration:

- Application bootloader with storage: Upgrading the main bootloader requires a single GBL file containing both bootloader and application upgrade images.
- Standalone bootloader with communication interface: Upgrading the bootloader requires two GBL files, one with only the bootloader upgrade image, and one with only the application upgrade image.

Security of the bootloader upgrade process is provided by signing the GBL file. See section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).

The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the “Memory Space for Bootloading” section in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/). For convenience, the figures do not distinguish between SE and VSE.

###### Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders) (heading level 7)

The process is illustrated in the following figure:

![Standalone Bootloader: Bootloader Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image6.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a bootloader upgrade image is transmitted from the host to the device.
3. The contents of the GBL Bootloader tag are written to the bootloader upgrade location in internal flash, overwriting the existing application.
4. The device reboots into the first stage bootloader / Secure Engine.
5. The first stage bootloader / Secure Engine replaces the main bootloader with the new version found in the bootloader upgrade location.
6. The device boots into the new main bootloader.
7. A GBL file containing only an application image is transmitted from the host to the device.
8. The bootloader applies the application image from the GBL upgrade file on-the-fly.
9. The device boots into the application. Bootloader upgrade is complete.

A bootloader upgrade is started in the same way as an application upgrade.

###### Downloading and Applying a Bootloader GBL Upgrade File (heading level 8)

When the bootloader has entered the receive loop, a GBL upgrade file containing a bootloader upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns bootloader upgrade data in a callback. The bootloader core implements this callback and flashes the data to internal flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file CRC and GBL signature (if required) have been verified.

When a complete bootloader upgrade image is received, the main bootloader signals the first stage bootloader / Secure Engine that it should enter firmware upgrade mode. On Series 1 devices, this is done by writing a command to the shared memory location at the bottom of SRAM, and then performing a software reset. On Series 2 devices, Secure Engine communication is used to signal that bootloader upgrade is ready to be performed.

On Series 1 devices, the first stage bootloader verifies the CRC on the current main bootloader and verifies the CRC of the bootloader upgrade present in the bootloader upgrade location in internal flash.

- If the CRC in the upgrade image location and the CRC in the current main bootloader are both valid, then the upgrade image will be copied over the main bootloader if the version number of the upgrade is higher than the current main bootloader version.
- If the CRC in the upgrade image location is valid and the CRC in the current main bootloader location is not valid, the upgrade image will be copied over the main bootloader regardless of the version. This is because the version of the main bootloader cannot be relied upon if the main bootloader image is corrupt.
- If the CRC in the upgrade location is not valid, the upgrade will not be applied.

On Series 2 devices, the authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See section [Setting a Version Number](07-configuring-the-gecko-bootloader#setting-a-version-number) for more information about versioning bootloader images.

###### Upgrading Bootloaders Without Secure Boot to Bootloaders with Secure Boot (heading level 8)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature, using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. This key can be written by application code running on the device as long as the Lock Bits page is configured to allow flash writes. If the Lock Bits page is locked, it can only be erased by the debugger. Therefore, signing/decryption keys residing in the Lock Bits page cannot be erased from firmware. This means that, for devices in the field, those areas in flash cannot be replaced with new ones. However, the Gecko Bootloader prepared from step 1 can be modified to look for the decryption and signature keys in a different location. Key locations are defined in the bootloader project file `btl_security_tokens.c`.
4. Create a GBL file using the Gecko Bootloader image. The GBL file needs to be signed/unsigned depending on the current configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
5. Upload the GBL file. For more details on the upgrade process, see section [Bootloader Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders)](#bootloader-upgrade-on-bootloaders-with-communication-interface-standalone-bootloaders).

###### Enabling Secure Boot RTSL on Series 2 Devices (heading level 8)

Secure Boot RTSL (Root of Trust and Secure Loader) can be enabled using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot in Simplicity Studio by going to the **Bootloader Core** component and selecting the **Enable secure boot** option.  
   - For EFR32xG21, in the **Bootloader Core** component, disable the **Allow use of public key from manufacturing token storage** option. This means that the Gecko Bootloader will never make use of the public key stored in the last page of the main flash  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in the VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more information on installing public keys, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See section [Signing an Application Image for Secure Boot](09-gecko-bootloader-security-features#signing-an-application-image-for-secure-boot) for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2. For more details on how to turn on secure boot on the Secure Engine, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).
6. Create a GBL file using the Gecko Bootloader image from step 4.
7. Create a GBL file using the application from step 5. The GBL file need to be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1.
8. Upload the GBL file containing the Gecko Bootloader image.
9. Upload the GBL file containing the application.

###### Downloading and Applying an Application GBL Upgrade File (heading level 8)

Once the bootloader upgrade is completed, the existing application is rendered invalid, since the bootloader upgrade location overlaps with the application. A GBL upgrade file containing an application upgrade is transmitted to the bootloader. The application upgrade process follows that in section [Standalone Bootloader Operation](03-gecko-bootloader-operation-application-upgrade#standalone-bootloader-operation).

###### Bootloader Upgrade on Application Bootloaders with Storage (heading level 7)

The process is illustrated in the following figure.

![Application Bootloader: Bootloader Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image7.png)

1. A single GBL file containing both a bootloader upgrade image and an application image is downloaded onto the storage medium of the device (internal flash or external SPI flash).
2. The device reboots into the main bootloader.
3. The main bootloader parses its upgrade image into internal flash at the bootloader upgrade location. Depending on the application size as well as how the “scratch space” is configured for the bootloader on Series 2 devices, the existing application may be overwritten.
4. The main bootloader verifies the integrity of the upgrade image and then resets the device with reset reason BOOTLOADER_RESET_REASON_UPGRADE to apply the upgrade.
5. The device reboots into the first stage bootloader / Secure Engine.
6. The first stage bootloader / Secure Engine replaces the main bootloader with the new version.
7. The device boots into the new main bootloader.
8. The bootloader applies the application image from the GBL upgrade file.
9. The device boots into the application. Bootloader upgrade is complete.

A bootloader upgrade is started in the same way as an Application Upgrade. A single GBL file containing both a bootloader and an application upgrade is written to storage by the application, and the bootloader is entered.

The bootloader iterates over the list of storage slots marked for bootload and attempts to verify the GBL file stored within. Verification returns information about whether the GBL file contains an application, or both a bootloader and an application. The image parser parses the file. If the GBL file contains a bootloader, the bootloader upgrade data is returned in a callback. The bootloader core implements this callback and flashes the data to internal flash at the bootloader upgrade location.

The bootloader prevents a newly uploaded bootloader upgrade image from being interpreted as valid by holding back parts of the bootloader upgrade vector table until the GBL file CRC and GBL signature (if required) have been verified.

On Series 1 devices, the main bootloader signals the first stage bootloader that it should enter firmware upgrade mode by writing a command to the shared memory location at the bottom of SRAM, and then performing a software reset. On Series 2 devices, Secure Engine communication interface is used to signal the Secure Engine that a bootloader upgrade is ready to be performed.

On Series 1 devices, the first stage bootloader verifies the CRC of the bootloader upgrade present in the bootloader upgrade location in internal flash and copies the bootloader upgrade over the main bootloader if the version number of the upgrade is higher than the version number of the existing main bootloader. On Series 2 devices, the authenticity of the main bootloader optionally can be verified before applying the bootloader upgrade. See section [Setting a Version Number](07-configuring-the-gecko-bootloader#setting-a-version-number) for more information about versioning bootloader images.

The new main bootloader is entered, and the images in the list of storage slots marked for bootload are verified. When the image parser parses the slot containing the GBL file with the bootloader + application upgrade, the version number of the bootloader upgrade is equal to the running main bootloader version, so another bootloader upgrade will not be performed. Instead, the application upgrade data are returned in a callback. Bootloading of the new application proceeds as described in section [Application Bootloader Operation](03-gecko-bootloader-operation-application-upgrade#application-bootloader-operation).

###### Storage Space Size Configuration (heading level 8)

The storage space size must be configured to have enough space to store the upgrade images. Depending on the configuration, the bootloader size can vary. For size requirements of the bootloader, see section [Size Requirements for Different Bootloader Configurations for Series 1 Devices](07-configuring-the-gecko-bootloader#size-requirements-for-different-bootloader-configurations-for-series-1-devices).

###### Upgrading Bootloaders without Secure Boot to Bootloaders with Secure Boot (heading level 8)

A bootloader without the secure boot feature can be upgraded to a bootloader with the secure boot feature. The procedure is as follows:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the bootloader needs to be higher than the bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Write the public key generated from the previous step to the device. The public key is stored as a manufacturing token in the device by default. This key can be written by application code running on the device as long as the Lock Bits page is configured to allow flash writes. If the Lock Bits page is locked, it can only be erased by the debugger. Therefore, signing/decryption keys residing in the Lock Bits page cannot be erased from firmware. This means that, for devices in the field, those areas in flash cannot be replaced with new ones. However, the Gecko Bootloader prepared from step 1 can be modified to look for the decryption and signature keys in a different location. Key locations are defined in the bootloader project file `btl_security_tokens.c`.
4. Prepare a signed application image using the private key generated in step 2. See section [Signing an Application Image for Secure Boot](09-gecko-bootloader-security-features#signing-an-application-image-for-secure-boot) for more information on signing an application.
5. Create a GBL file using the Gecko Bootloader image and the signed application image. The GBL file needs to be signed/unsigned depending on the configuration of the Gecko Bootloader running on the device. For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
6. Upload the GBL file. For more details on the upgrade process, see section [Bootloader Upgrade on Application Bootloaders with Storage](#bootloader-upgrade-on-application-bootloaders-with-storage).

###### Enabling Secure Boot RTSL on Series 2 Devices (heading level 8)

Secure Boot RTSL can be enabled by using the following procedure:

1. Prepare a Gecko Bootloader image with secure boot enabled. The version of the Gecko Bootloader needs to be higher than the Gecko Bootloader on the device.  
   - Turn on secure boot from the **Bootloader Core** component in Simplicity Studio by selecting the **Enable secure boot** option.  
   - For EFR32xG21, in the **Bootloader Core** component, disable the **Allow use of public key from manufacturing token storage** option. This means that the Gecko Bootloader will never make use of the public key stored in the last page of the main flash.  
   - (Optional) In the **Bootloader Core** component, select the **Require signed firmware upgrade files** option. This means that the Gecko Bootloader will only accept signed GBL files.
2. Generate a public/private Signing Key pair. See section [Generating Keys](09-gecko-bootloader-security-features#generating-keys) for more information on creating a Signing Key pair.
3. Prepare an application that installs the public key generated from step 2 to the Secure Engine One-time Programmable memory. Installing a key in VSE requires a reset routine. Make sure that the application does not end up in the reset loop. Create an unsigned GBL file from this application and upload it. For more information on installing public keys, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/). For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
4. Sign the Gecko Bootloader image generated from step 1 using the private key generated in step 2. See section [Signing an Application Image for Secure Boot](09-gecko-bootloader-security-features#signing-an-application-image-for-secure-boot) for more information on signing binaries.
5. Make a custom application that turns on secure boot on the Secure Engine and sign this application binary with the private key generated from step 2. For more details on how to turn on secure boot on the Secure Engine, see [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).
6. Create a GBL file using the Gecko Bootloader image from step 4 and the application from step 5. The GBL file must be signed if the **Bootloader Core** component option **Require signed firmware upgrade files** was selected in step 1. For more details on creating a GBL file, see section [Creating a Signed and Encrypted GBL Upgrade Image File from an Application](09-gecko-bootloader-security-features#creating-a-signed-and-encrypted-gbl-upgrade-image-file-from-an-application).
7. Upload the GBL file containing the Gecko Bootloader image and the application.

###### Gecko Bootloader Operation - Secure Engine Upgrade

The Secure Engine is upgradable and requirements for upgrading the Secure Engine vary depending on the bootloader configuration:

- **Application bootloader with storage**: Upgrading the Secure Engine requires a single GBL file containing both Secure Engine and application upgrade images.
- **Standalone bootloader with communication interface**: Upgrading the Secure Engine requires two GBL files, one with only the Secure Engine upgrade image, and one with only the application upgrade image and optionally a third image containing only the Main bootloader upgrade.

A bootloader upgrade can also be included in the same GBL file in application mode, or as a third GBL file in standalone mode. The figures that illustrate Gecko Bootloader operation in this section do not provide information about the bootloader memory layouts for different devices. For more details refer to the section “Memory Space for Bootloading” in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

Signed and encrypted Secure Engine upgrade images are provided by Silicon Labs through Simplicity Studio. Upgrade images with the same or lower version number than the running Secure Engine will be ignored.

To download Secure Engine firmware images, connect a Series 2 device and select a preferred SDK. The Secure Firmware **Update to x.x.x** link appears in the Launcher Perspective, as shown in the following figure.

![Launcher Perspective](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image8.jpg)

Click **Update to x.x.x** next to Secure FW: x.x.x. A warning dialog box appears. Click **[Yes]** to continue.

![Warning dialog box when click Update to x.x.x](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image9.jpg)

The Launcher Perspective is then updated so that the current Secure Firmware version and link version are the same.

![Launcher Perspective after clicking Update to x.x.x](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image10.jpg)

The Secure Engine firmware images can be found in the _util/se_release/public_ directory under the Gecko SDK. Simplicity Studio displays the SE firmware version available in the Gecko SDK selected.

###### Secure Engine Upgrade on Bootloaders with Communication Interface (Standalone Bootloaders) (heading level 7)

The process is illustrated in the following figure.

![Standalone Bootloader: Secure Engine Bootloader Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image11.png)

1. The device reboots into the bootloader.
2. A GBL file containing only a Secure Engine upgrade image is transmitted from the host to the device.
3. The contents of the GBL Secure Engine tag are written to the pre-configured upgrade location in internal flash, overwriting the existing application.
4. The device reboots into the Secure Engine.
5. The Secure Engine is replaced by the new version found in the pre-configured upgrade location.
6. The device boots into the main bootloader.
7. A GBL file containing only an application image is transmitted from the host to the device.
8. The bootloader applies the application image from the GBL upgrade on the fly.
9. The device boots into the application. Secure Engine upgrade is complete.

###### Downloading and Applying a Secure Engine GBL Upgrade File (heading level 8)

When the bootloader has entered the receive loop, a GBL upgrade file containing a Secure Engine upgrade is transmitted to the bootloader. When a packet is received, it is passed to the image parser. The image parser parses the data and returns Secure Engine upgrade data in a callback. The bootloader core implements this callback and flashes the data to internal flash at the pre-configured bootloader upgrade location.

When a complete Secure Engine upgrade image is received, the main bootloader signals the Secure Engine that it should enter firmware upgrade mode. This is done by the Secure Engine communication interface that is used to signal that bootloader upgrade is ready to be performed.

###### Downloading and Applying an Application GBL Upgrade File (heading level 8)

Once the Secure Engine upgrade is completed, the existing application is rendered invalid if the Secure Engine upgrade location overlaps with the application. A GBL upgrade file containing an application upgrade is transmitted to the bootloader. The application upgrade process follows that. For more information, see section [Standalone Bootloader Operation](03-gecko-bootloader-operation-application-upgrade#standalone-bootloader-operation).

###### Secure Engine Upgrade on Application Bootloaders with Storage (heading level 7)

The process is illustrated in the following figure.

![Application Bootloader: Secure Engine Upgrade](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image12.png)

1. A single GBL file containing both a Secure Engine upgrade image and an application image is downloaded onto the storage medium of the device (internal flash or external SPI flash).
2. The device reboots into the bootloader.
3. a) The main bootloader copies its upgrade image into internal flash at the pre-configured upgrade location.  
   b) Alternatively, if the no-staging Secure Engine upgrade option has been enabled, the upgrade image will be fetched directly from the GBL file in storage instead of first copying the image to the pre-configured upgrade location.
4. The device reboots into the Secure Engine.
5. The Secure Engine is replaced by the new version found in the pre-configured upgrade location (or directly from storage, ref. 3b).
6. The device boots into the main bootloader.
7. The bootloader applies the application image from the GBL upgrade file.
8. The device boots into the application. Secure Engine upgrade is complete.

###### Storage Space Size Configuration (heading level 8)

The storage space size must be configured to have enough space to store the upgrade images. The following table shows the reserved SE upgrade image sizes.

<table>
    <thead>
        <tr>
            <th>
                <p>Device Family</p>
            </th>
            <th>
                <p>Reserved Flash for SE Upgrade Image</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>EFR32xG21</p>
            </td>
            <td>
                <p>48 kB</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EFR32xG22</p>
            </td>
            <td>
                <p>24 kB</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EFR32xG23</p>
            </td>
            <td>
                <p>96 kB</p>
            </td>
        </tr>
    </tbody>
</table>

Depending on the configuration, the bootloader size can vary. For size requirements of the bootloader, see section [Size Requirements for Different Bootloader Configurations for Series 1 Devices](07-configuring-the-gecko-bootloader#size-requirements-for-different-bootloader-configurations-for-series-1-devices). The bootloader size for EFR32xG21 devices can be up to 16 kB and for EFR32xG22, EFR32xG23, and EFR32xG24 devices the bootloader size can be up to 24 kB. For more details, see [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).

###### Getting Started with the Gecko Bootloader

This section describes how to build a Gecko Bootloader from one of the provided examples. Simplicity Studio 5, used with Gecko SDK Suite (GSDK) v3.x and higher, differs from Simplicity Studio 4, used with GSDK v2.x, in how sample applications are selected and how projects are created. Refer to the documentation provided with your SDK for details. These instructions assume that you have installed Simplicity Studio 5, the GSDK and associated utilities as described in the SDK’s quick start guide, and that you are familiar with generating, compiling, and flashing an example application in the relevant version.

- [Bluetooth Getting Started Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-getting-started-overview/)
- [Proprietary Flex SDK v3.x Quick-Start Guide](https://docs.silabs.com/connect-stack/latest/proprietary-flex-sdk-v3x-quick-start-guide/)
- [Silicon Labs OpenThread SDK Quick-Start Guide](https://docs.silabs.com/openthread/latest/openthread-quick-start-guide/)
- [Zigbee EmberZNet Quick-Start Guide for SDK 7.0 and Higher](https://docs.silabs.com/zigbee/latest/zigbee-7x-quick-start-guide/)

1. Create a project based on the Gecko Bootloader example of your choice. The project opens with a tab describing the example.  
   ![Project based on the Gecko Bootloader example](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image13.png)
2. Click the project (*.slcp) tab to move to the Project Configurator interface.  
   ![Project Configurator interface](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image14.png)
3. The Software Components tab shows the list of available components that can be installed in the project.  
   ![Software Components tab](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image15.png)
4. The **Storage Slot Setup** component allows you to configure storage slots to be used if a storage component is also installed. The default configuration matches the target part and bootloader type. This component supports a maximum of three storage slots.  
   ![Storage Slot Setup](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image16.png)
5. Click the **Build** (hammer) icon.
6. After the build is complete, the bootloader binaries are available in the **artifact** folder as depicted in the image below.  
   ![Bootloader binaries files in the artifact folder](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image17.png)

On Series 1 devices, three bootloader images are generated into the build directory: a main bootloader, a main bootloader with CRC32 checksum, and a combined first stage and main bootloader with CRC32 checksum. The main bootloader image is called **<projectname>.s37**, the main bootloader with CRC32 checksum is called **<projectname>-crc.s37**, while the combined first stage image + main bootloader image with a CRC32 checksum is called **<projectname>-combined.s37**. The first time a device is programmed, whether during development or manufacturing, the combined image needs to be programmed. For subsequent programming, when a first stage bootloader is already present on the device, it is okay to download an image containing just the main bootloader. In this case, the main bootloader with CRC32 should be used.

The requirement is that any main bootloader image that is programmed via serial wire must contain the CRC32 in the image. Files downloaded via serial wire are “s37” files. Most often, the **<projectname>-combined.s37** file is the one downloaded during production programming. However, it is possible to download only the main bootloader over serial wire, in which case **<projectname>-crc.s37** should be used.

Any main bootloader that is upgraded with the OTA or host method should already contain CRC32 because bootloader-initiated upgrades use GBL files (not “s37” files) and Simplicity Commander adds the CRC32 when it constructs the GBL file. The input files to Simplicity Commander can (and should) use the non-CRC “s37” file.

On Series 2 devices, the combined image is not present, since the first stage bootloader does not exist. The image containing only a main bootloader is the image that must be used to create a GBL file for bootloader upgrade.

###### Configuring the Gecko Bootloader

###### Configuring Storage (heading level 7)

Gecko Bootloaders configured as application bootloaders must include an API to store and access image files. This API is based on the concept of storage slots, where each slot has a predefined size and location in memory and can be used to store a single upgrade image. Slots are configured in the **Bootloader Storage Slot Setup** component.

When multiple storage slots are configured, a bootload list is used to indicate the order in which the bootloader should access slots to find upgrade images. If multiple storage slots are supported, the application should write the bootload list by calling bootloader_setImageToBootload before rebooting into the bootloader to initiate a firmware upgrade process. The bootloader attempts to verify the images in these storage slots in sequence and applies the first image to pass verification. If only a single storage slot is supported, the bootloader uses this slot implicitly. A maximum of three slots may be configured in the **Bootloader Storage Slot Setup** component.

###### SPI Flash Storage Configuration (heading level 8)

When configuring a Gecko Bootloader to obtain images from SPI flash, modify the following.

The **base address of the storage area** should be configured in the **Common Storage** component. This is the address at which the bootloader places the bootload list, if more than one storage slot is configured. In the default configuration, this address is set to 0. If only a single storage slot is configured, the bootload list is not used, so configuring it may be omitted.

The **location and size of the storage slots** can be configured using the **Bootloader Storage Slot Setup** component (supports a maximum of three configurable storage slots). The addresses input here are absolute addresses (they are not offsets from the base address). If more than a single slot is configured, space must be reserved between the base address as configured in the **Common Storage** component and the first storage slot configured in the **Bootloader Storage Slot Setup** component. Enough space to fit two copies of the bootload list must be reserved. These two copies need to reside on different flash pages, to provide redundancy in case of power loss during writing. Two full flash pages therefore need to be reserved. In the default example application, a SPI flash part with 4 kB flash sectors is used. This means that 8 kB must be reserved before the first storage slot. The following figure illustrates how the storage area can be partitioned, where the numbers in the top row represent the starting addresses.

![SPI Flash Storage Area Configuration](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image18.png)

###### Internal Storage Configuration (heading level 8)

When configuring a Gecko Bootloader to obtain images from internal flash, modify the following.

The **base address of the storage area** should be configured in the **Common Storage** component. This is the address at which the bootloader will place the prioritized list of storage slots to attempt to bootload from, if more than one storage slot is configured. In the default configuration, only a single storage slot is configured, so this value is set to 0, and isn’t used. If more than one storage slot is configured, this value needs to be configured too.

The **location and size of the storage slots** can be configured using the **Bootloader Storage Slot Setup** Component (supports a maximum of three configurable storage slots). The addresses input here are absolute addresses (they are not offsets from the base address). If more than a single slot is configured, enough space must be reserved between the base address as configured in the **Common Storage** component and the first storage slot configured in the **Bootloader Storage Slot Setup** component. Enough space to fit two copies of the bootload list must be reserved. These two copies need to reside on different flash pages, to provide redundancy in case of power loss during writing. Two full flash pages therefore need to be reserved. The following figure illustrates how the storage area can be partitioned.

![Internal Storage Area Configurations](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image19.png)

> **Note**: The storage area partitioning in the example for two storage slots above does not take any NVM system into account. If using an NVM system like SimEE or PS Store, take care to place and size the storage area in such a way that bootloader storage does not overlap with NVM.

###### Compressed Upgrade Images (heading level 7)

The Gecko Bootloader optionally supports compressed GBL files. In a compressed GBL file, only the application upgrade data is compressed, any metadata and bootloader upgrade data (if present) stay uncompressed. This means that a compressed GBL file is identical to a normal (uncompressed) GBL file, except that the GBL Programming Tag containing the application upgrade image (as described in [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/)) has been replaced by a GBL LZ4 Compressed Programming Tag or GBL LZMA Compressed Programming Tag. Signature and encryption operations on a compressed GBL work identically to on an uncompressed GBL.

To be able to use compressed upgrade images, a decompressor for the relevant compression algorithm must be added to the Gecko bootloader. The following table shows which compression algorithms are supported by the Gecko Bootloader, and which Bootloader component should be added to enable the feature. The table also shows how much space the decompressor takes up in the bootloader, and how big of a size reduction to expect for the compressed application upgrade image. Be aware of the bootloader size requirement. The bootloader space might be too small to fit the decompressors, depending on the device and enabled components.

<table>
    <thead>
        <tr>
            <th>
                <p>Compression Algorithm</p>
            </th>
            <th>
                <p>Component</p>
            </th>
            <th>
                <p>Bootloader Size Requirement</p>
            </th>
            <th>
                <p>Application Upgrade Size Reduction (typical)</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>LZ4</p>
            </td>
            <td>
                <p>GBL Compression (LZ4)</p>
            </td>
            <td>
                <p>&lt; 1 kB</p>
            </td>
            <td>
                <p>~ 10%</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>LZMA</p>
            </td>
            <td>
                <p>Bootloader Compression (LZMA)</p>
            </td>
            <td>
                <p>~5 kB flash, 18 kB RAM</p>
            </td>
            <td>
                <p>~ 30%</p>
            </td>
        </tr>
    </tbody>
</table>

It is important to note that the compressed GBL file stays compressed while being transferred to the device, and while it is stored in the upgrade area. It is decompressed by the bootloader when the upgrade is applied. This means that the running application in main flash will be identical to one that was installed using an uncompressed (normal) GBL file.

Compressed GBL files can only be decompressed by the bootloader when running standalone, not through the Application Interface. This means that upgrade image verification performed by the application prior to reboot will not attempt to decompress the application upgrade, it will only verify the signature of the compressed payload. After rebooting into the bootloader, it will decompress the image as part of the upgrade process.

> **Note**: The above means that Bluetooth in-place application upgrades cannot be compressed, as they are processed by the Bluetooth Supervisor or AppLoader using functionality in the bootloader through the Application Interface. Supervisor/stack and AppLoader updates can be compressed, but the user application cannot.

###### LZMA Compression Settings (heading level 8)

LZMA decompression is only supported for images compressed with certain compression settings. Simplicity Commander automatically uses these settings when using the `commander gbl create --compress lzma` command.

- Probability model counters: lp + lc <= 2. Simplicity Commander uses lp=1, lc=1.
- Dictionary size no greater than 8 kB. Simplicity Commander uses 8 kB.

Together, these settings cause the decompressor to require 18 kB of RAM for decompression – 10 kB for the counters and 8 kB for the dictionary.

The GBL LZMA Compressed Programming Tag contains a full LZMA file, containing the LZMA header, raw stream, and end mark. The Gecko bootloader only supports decompressing payloads that contain the end mark as the last 8 bytes of the compressed stream.

###### Bootloader Example Configurations (heading level 7)

The following sections describe the key configuration options for the example bootloader applications.

> **Note**: Security features are disabled for all example configurations. In development, Silicon Labs strongly recommends enabling security features to prevent unauthorized parties from uploading untrusted program code. See section [Using Application Image Security Features](09-gecko-bootloader-security-features#using-application-image-security-features) to learn how to configure the security features of the Gecko Bootloader.

###### UART XMODEM Bootloader (heading level 8)

Standalone bootloader for EFM32 and EFR32 devices running the EmberZNet PRO and Silicon Labs Connect protocol stacks, using XMODEM-CRC over UART.

In this configuration, the **UART XMODEM** communication component, **XMODEM Parser** component, and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The **GPIO activation** component is also installed by default, allowing bootloader entry into firmware upgrade mode by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### BGAPI UART DFU Bootloader (heading level 8)

Standalone bootloader for the Bluetooth protocol stack, using the BGAPI protocol for UART DFU. This bootloader should be used for all NCP-mode Bluetooth applications.

In this configuration, the **BGAPI UART DFU** communication component and **Bootloader UART Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for UART need to be configured in the **Bootloader UART Driver** component. Here, Hardware Flow Control can be enabled or disabled, and the baud rate and pinout can be configured.

The GPIO activation component is also installed by default, allowing bootloader entry by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### EZSP SPI Bootloader (heading level 8)

Standalone bootloader for EmberZNet PRO and Silicon Labs Connect protocol stacks using EZSP for SPI.

In this configuration, the **EZSP-SPI** communication component, **XMODEM Parser** component, and **Bootloader SPI Peripheral Driver** component are installed. For the example application to run on a custom board, the GPIO ports and pins used for SPI and EZSP signaling need to be configured in the **Bootloader SPI Peripheral Driver** and **EZSP-SPI** components, respectively.

The **EZSP GPIO activation** component is also installed by default, allowing bootloader entry into firmware upgrade mode by activating a GPIO through reset. The GPIO pin used can be configured here. This component can be uninstalled if this functionality is not desired.

###### Bluetooth AppLoader OTA DFU Bootloader (heading level 8)

Standalone bootloader for the Bluetooth protocol stack, using Bluetooth for Over-The-Air DFU.

In this configuration, the **Bluetooth AppLoader** communication component is installed.

###### SPI Flash Storage Bootloader (heading level 8)

Application bootloader for all wireless protocol stacks, using an external SPI flash to store upgrade images received over the air by the application.

In this configuration, the **SPI Flash Storage** and **Common Storage** components, as well as the **Bootloader SPI Controller Driver** component, are installed. For the example application to run on a custom board, the GPIO ports and pins used for SPI communication with the external flash need to be configured in the **Bootloader SPI Controller Driver** component, and the type of SPI flash needs to be configured in the **SPI Flash Storage** component. The base address of the storage area can be configured in the **Common Storage** component. The location and size of the storage slots themselves can be configured using the **Bootloader Storage Slot Setup** component (supports up to three configurable storage slots).

The SPI Flash storage bootloader provides customizable callback functions, which can be found in _bootloader-callback-stubs.c_. The callback functions _storage_customInit_ and _storage_customShutdown_, for example, can be used for custom hardware setups. Those callback functions can be interfaced from the applications using the bootloader interface functions such as _bootloader_init_ and _bootloader_deinit_ from _api/btl_interface.h_.

Currently, Silicon Labs supports the following SPI Flash storage bootloaders:

1. SPI Flash storage bootloader (multiple images)
2. SPI Flash storage bootloader (single image)
3. SPI Flash storage bootloader (single image with slot size of 1MB). **Note: This bootloader should only be used for systems with an external SPI Flash size >= 1 MB**.

###### SPI Flash Storage Bootloader SFDP (heading level 8)

Application bootloader for all wireless protocol stacks, using an external SPI flash to store upgrade images received over the air by the application.

In this configuration, the **SPI Flash Storage SFDP** and **Common Storage** components, as well as the **Bootloader SPI Controller Driver** component, are installed. For the example application to run on a custom board, the GPIO ports and pins used for SPI communication with the external flash need to be configured in the **Bootloader SPI Controller Driver** component. The type of SPI flash is detected at runtime. The base address of the storage area can be configured in the **Common Storage** component. The location and size of the storage slots themselves can be configured using the **Bootloader Storage Slot Setup** component (supports up to three configurable storage slots).

The SPI Flash storage bootloader SFDP provides customizable callback functions, which can be found in _bootloader-callback-stubs.c_. The callback functions _storage_customInit_ and _storage_customShutdown_, for example, can be used for custom hardware setups. Those callback functions can be interfaced from the applications using the bootloader interface functions such as _bootloader_init_ and _bootloader_deinit_ from _api/btl_interface.h_.

###### Internal Storage Bootloader (heading level 8)

Application bootloader for all wireless protocol stacks, using internal flash to store upgrade images received over the air by the application.

Multiple examples are provided, including configurations for 512 kB flash memory devices like EFR32xG13, 1024 kB flash memory devices like EFR32xG12, and 2048 kB flash memory devices like EFM32GG11. **The storage layout should be modified before running the bootloader on any other devices**. In this configuration, the internal flash and common storage components are installed. The base address of the storage area is configured in the **Common Storage** component. The location and size of the storage slots can be configured using the **Bootloader Storage Slot Setup** component (provides up to three configurable storage slots). Default example applications are provided with configurations for both single storage slot and multiple storage slots.

The default storage slot configurations provided by the Gecko Bootloader **must** be configured to match the use-case-specific application configurations.

**Table**: Internal Storage Bootloader Default Storage Configurations

<table>
    <thead>
        <tr>
            <th>
                <p>Sample Applications</p>
            </th>
            <th>
                <p>Storage Offset</p>
            </th>
            <th>
                <p>Storage Size</p>
            </th>
            <th>
                <p>Additional Notes</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 256 kB device)</p>
            </td>
            <td>
                <p>0x21800 (137216)</p>
            </td>
            <td>
                <p>88064</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8021800 (134354944)</p>
            </td>
            <td>
                <p>88064</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 352 kB device)</p>
            </td>
            <td>
                <p>0x28000 (163840)</p>
            </td>
            <td>
                <p>147456</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8028000 (134381568)</p>
            </td>
            <td>
                <p>147456</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 512 kB device)</p>
            </td>
            <td>
                <p>0x44000 (278528)</p>
            </td>
            <td>
                <p>196608</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8044000 (134496256)</p>
            </td>
            <td>
                <p>196608</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 1 MB device)</p>
            </td>
            <td>
                <p>0x84000 (540672)</p>
            </td>
            <td>
                <p>458752</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8084000 (134758400)</p>
            </td>
            <td>
                <p>458752</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 2 MB device)</p>
            </td>
            <td>
                <p>0x10000 (1048576)</p>
            </td>
            <td>
                <p>1011712</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x8100000 (135266304)</p>
            </td>
            <td>
                <p>1011712</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (multiple images on 1 MB device)</p>
            </td>
            <td>
                <p>0x5A000 (368640)</p>
            </td>
            <td>
                <p>337920</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0xAC800 (706560)</p>
            </td>
            <td>
                <p>337920</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 1536kB device)</p>
            </td>
            <td>
                <p>0xC0000 (786432)</p>
            </td>
            <td>
                <p>737280</p>
            </td>
            <td>
                <p>This configuration is available for devices where flash base address is 0x00</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>0x80C0000 (135004160)</p>
            </td>
            <td>
                <p>737280</p>
            </td>
            <td>
                <p>This configuration is only available for devices where the flash base address is 0x08000000</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal Storage Bootloader (single image on 1920kB device)</p>
            </td>
            <td>
                <p>0x80E8000 (135168000)</p>
            </td>
            <td>
                <p>966656</p>
            </td>
            <td>
                <p>This example application is available for device families with flash size of 1920kB or higher (for example xG25 device family)</p>
            </td>
        </tr>
    </tbody>
</table>

###### Image Acquisition Application Example Configuration (heading level 7)

These examples illustrate applications that acquire and store a GBL upload image for an application bootloader. For the running bootloader to accept an application upgrade, the new application version must be higher than the existing version. The version number can be set in Appbuilder by defining the macro “APP_PROPERTIES_VERSION” in the **Additional Macros** field on the **Other** tab.

###### Setting a Version Number (heading level 7)

To distinguish between different builds of the Gecko Bootloader, it is useful to set a version number. To perform a bootloader upgrade, not only must the running bootloader pass its integrity checks (see section [Downloading and Applying a Bootloader GBL Upgrade File](04-gecko-bootloader-operation-bootloader-upgrade#downloading-and-applying-a-bootloader-gbl-upgrade-file)), but the bootloader upgrade image must also have a higher version number than the running bootloader image. A version number can be set using Simplicity Studio by configuring the **Bootloader Version Main Customer** option of the **Bootloader Core** component. This macro will be picked up by the config file **btl_config.h**, where it is combined with the version number of the Gecko Bootloader files provided by Silicon Labs.

###### Placing Bootloader in Main Flash (heading level 7)

For device families xG13 and xG14, the entire main stage bootloader might not fit into the bootloader flash if the user installs some extra components. In such scenarios, the main stage bootloader can be placed in the main flash by installing the Bootloader in Main Flash core component. This component internally provides a MACRO named MAIN_BOOTLOADER_IN_MAIN_FLASH which is used to set the appropriate address required to place the main bootloader in main flash. The MACRO is used to generate the linker file from the common linker template with the appropriate addresses to place the main stage bootloader in the main flash.

###### Hardware Configuration (heading level 7)

The Gecko Bootloader uses the Pin Tool for configuration of pinout and other hardware-related settings. When Pin Tool configuration is available for a bootloader component, the relevant settings are shown in the Component Editor for that component.

![Example of USART Configuration for UART Driver](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image20.png)

The standalone Pin Tool User Interface can also be used to configure settings for Gecko Bootloader if desired.

While the Pin Tool provides configuration for many different peripherals, the Gecko Bootloader uses only the following Pin Tool modules:

- SERIAL is used by the UART Driver component to configure baud rate, flow control mode and pinout.
- VCOM is used by the UART Driver component to enable the serial interface if necessary (only on Silicon Labs Wireless Starter Kits).
- EXTFLASH is used by the SPI Driver to configure frequency and pinout.
- SPINCP is used by the SPI Slave Driver to configure pinout.
- BTL_BUTTON is used by the GPIO Activation component.
- CMU HFXO frequency setting is used by the delay driver to calibrate timing if the core is running from the HFXO.

Other settings, like CMU oscillator configuration or DCDC configuration, are not taken into consideration by the default bootloader code. If using these configuration settings is desired, the required code must be added in btl_main.c.

> **Note**: While the delay driver uses the HFXO frequency setting from Pin Tool, the HFXO enable setting is not used to initialize the HFXO on startup. This setting is only used when calling the bootloader through the Application Interface (see section [Gecko Bootloader and TrustZone](10-gecko-bootloader-and-trustzone#gecko-bootloader-and-trustzone)), and the application has switched to the HFXO prior to calling the Bootloader Application Interface API.

###### Size Requirements for Different Bootloader Configurations for Series 1 Devices (heading level 7)

Enabling different configuration options for the Gecko Bootloader changes the size of the resulting image. The following table shows a list of example bootloader configurations and the resulting approximate size of the main bootloader. Note that any size above 14 kB will be too large to fit in the bootloader area of flash of EFR32xG13, and that any size above 16 kB will be too large to fit in the bootloader area of flash on EFR32xG14 and EFM32TG11. This table was last updated for Gecko SDK Suite 4.0 (Gecko Bootloader 2.0), and no guarantees are made that a configuration of a specific size with one SDK version will maintain that size in future releases.

**Table**: Bootloader Size Requirements

<table>
    <thead>
        <tr>
            <th>
                <p>Base Configuration</p>
            </th>
            <th>
                <p>Enabled Options</p>
            </th>
            <th>
                <p>Size (kB)</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>XMODEM UART</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.7</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>17.9</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal storage, single slot</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>11.5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>11.5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>12.4</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>16.6</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Internal storage, multiple slots</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>17.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SPI flash, single slot</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.6</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.6</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.5</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>17.7</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SPI flash, multiple slots</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>14</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>18</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SPI flash using SFDP, single slot</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>12.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>18</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>BGAPI UART</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>11.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>11.8</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>12.7</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>16.9</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EZSP SPI</p>
            </td>
            <td>
                <p>Default configuration</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade</p>
            </td>
            <td>
                <p>13.1</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZ4 compression</p>
            </td>
            <td>
                <p>13.9</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>'</p>
            </td>
            <td>
                <p>Secure boot, signed and encrypted upgrade, LZMA compression</p>
            </td>
            <td>
                <p>18.1</p>
            </td>
        </tr>
    </tbody>
</table>

###### EM4 GPIO Retention for OTA Upgrades (heading level 7)

The EM4 GPIO Retention feature allows Series 2 devices to retain GPIO pin states during Over-The-Air (OTA) firmware upgrades by entering EM4 sleep mode instead of performing a full system reset. This is particularly useful for applications that must preserve GPIO states, such as LED indicators, relay outputs, or control signals throughout the upgrade process.

Normally, an OTA upgrade triggers a system reset that clears all GPIO configurations and output states. EM4 GPIO Retention avoids this by saving the GPIO configuration in Backup RAM (BURAM), which remains powered through EM4 sleep and wake cycles. When the device wakes, the GPIO configuration and output levels are automatically restored, ensuring uninterrupted operation during the upgrade.

When an OTA upgrade with GPIO retention is initiated, the bootloader performs the following sequence:

- Saves GPIO configurations to **BURAM**, which retains data during EM4 sleep.
- Configures **EM4 GPIO retention mode** to `SWUNLATCH`.
- Sets up the **Backup Real-Time Counter (BURTC)** for the wake event.
- Enters **EM4 sleep mode** instead of issuing a system reset.
- On wakeup, validates BURAM contents and restores GPIO states.
- Continues with the OTA process according to the reset reason stored in BURAM.

To protect against repeated boot failures, the bootloader uses a reset counter stored in BURAM. The counter increments whenever the device cannot find or validate a valid application image. After three failed wakeups, the system halts in a controlled infinite loop, requiring user intervention (e.g., a manual reset or power cycle) to recover.

The reason for boot failure is stored in BURAM using one of the following codes:

- `BADAPP`: Invalid application
- `BADIMAGE`: Invalid or missing upgrade image
- `FATAL`: Other unrecoverable error

###### Enabling and Usage of EM4 GPIO Retention (heading level 8)

To use the EM4 GPIO Retention during OTA upgrades, complete the following two steps:

###### Step-1: Install the EM4 GPIO Retention Compoenent (heading level 9)

Install the following component in the application via Simplicity Studio Configurator.

Component: **BTL_EM4_GPIO_RETENTION**

Path: **Platform → Bootloader → EM4 GPIO Retention**

This component enables the EM4 GPIO retention capability in the bootloader, to manage save and restore the GPIO states during OTA updates.

###### Step-2: Call the API from Application (heading level 9)

After the OTA image has been received and stored, `bootloader_rebootAndInstallWithGpioRetention()` API must be called in the application.

This API saves the current GPIO configurations to BURAM and instructs the bootloader to perform OTA upgrade using EM4 sleep instead of a system reset. GPIO settings are defined with the `gpio_em4_retention_t` structure, which specifies the port, pin number, and output state. A maximum of 16 GPIO pins can be retained as mentioned in `MAX_EM4_RETAINED_PINS`.

For detailed API usage, parameter descriptions, and return values, refer to the README file located at `<Simplicity SDK>/platform/bootloader/em4-gpio-retention/`

###### Limitations and Considerations (heading level 8)

**Upgrade Type Support**

- GPIO retention is supported only for **application-level upgrades**.
- Upgrades involving the Secure Engine (SE) or the Bootloader are not supported because they involve multiple reset cycles that clear GPIO states.

**GPIO Configuration Limits**

- Maximum of **16 GPIO pins** can be retained.
- Supported ports: **A, B, C, and D** (ports 0–3).
- Pins are restored as **push-pull outputs**.
- Only **output states** are retained; input states are not preserved.

**Power Requirements**

- BURAM retains data only while the device remains powered.
- If power is lost during EM4, BURAM contents and GPIO states will be cleared.
- Continuous power must be maintained throughout the OTA process to ensure successful restoration of GPIO states.

###### Configuring the SMP Two-Page Switch (heading level 7)

The SMP Switch component (bootloader_smp_switch) lets a single bootloader boot one of two application images: App 1 or App 2. The active application image is selected using a small switch record stored in two dedicated flash pages.
To enable SMP support, install the Bootloader SMP Switch component in the bootloader project. This component defines BTL_SMP_SUPPORT and exposes the BOOTLOADER_CAPABILITY_SMP_SWITCH capability bit at runtime.

> SMP support is currently available on **EFR32 Series 2** devices (EFR32ZG28).

###### Configuration symbols (`btl_smp_cfg.h`) (heading level 8)

|Symbol|Description|
|---|---|
|`BTL_SMP_PAGE_1_BASE`|Switch record page 1 base address. Must be the start of a flash erase page (`FLASH_PAGE_SIZE`-aligned, see `em_device.h`).|
|`BTL_SMP_PAGE_2_BASE`|Switch record page 2 base address. Must differ from page 1 and not overlap. Typical layout: `BTL_SMP_PAGE_1_BASE + FLASH_PAGE_SIZE`.|
|`BTL_SMP_APP_1_BASE`|Application 1 base address. Defaults to `BTL_APPLICATION_BASE`; not normally overridden.|
|`BTL_SMP_APP_2_BASE`|Application 2 base address (start of the App 2 vector table in flash).|
|`BTL_SMP_DEFAULT_APP_ID`|Application booted when both switch records are invalid (1 = App 1, 2 = App 2).|

The two switch pages and both application images must fit within the device memory map without overlapping other regions, such as the bootloader, NVM3, OTA storage, or manufacturing tokens.
On many EFR32 Series 2 devices, FLASH_PAGE_SIZE is 8192 bytes (8 KiB). However, always verify the value for the device in use.

Application-side Configuration

Application projects do **not** include `btl_smp_cfg.h`. They obtain switch page bases at runtime by calling `get_smp_page_bases_from_storage()`, which uses the bootloader storage vtable callback `getSmpSwitchPageBases`. Application 1 and Application 2 are built as two separate images linked at `BTL_SMP_APP_1_BASE` and `BTL_SMP_APP_2_BASE` respectively.

Example Flash Memory Map (EFR32ZG28, 1 MB Internal Flash)

The following layout illustrates a working SMP configuration:

|Address|Region|
|---|---|
|`0x08000000`|Bootloader|
|`0x08006000`|App 1 (`BTL_APPLICATION_BASE` / `BTL_SMP_APP_1_BASE`)|
|`0x08016000`|App 2 (`BTL_SMP_APP_2_BASE`)|
|`0x08074000`|SMP switch page 1 (`BTL_SMP_PAGE_1_BASE`, 8 KiB)|
|`0x08076000`|SMP switch page 2 (`BTL_SMP_PAGE_2_BASE`, 8 KiB)|
|`0x08084000`|Bootloader storage slot|

Adjust the addresses to match your part's flash size, application sizes, storage requirements, and any reserved regions. Both switch pages must be erase-page-aligned and disjoint from every other region.

![Bootloader_smp screenshot](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image27.png)

Interactions with Other Features:

Secure Boot: When SMP is enabled, an image verification failure in the SMP-selected application automatically triggers a fallback to the alternate slot by using btl_smp_switch_get_alternate_app_base(). For more information, see Gecko Bootloader Security Features.
Storage: The bootloader storage backend must implement BootloaderStorageFunctions_t.getSmpSwitchPageBases. Storage backends that do not implement this callback do not support SMP.
TrustZone: This revision does not expose the SMP switch across the TrustZone boundary.

For information about the Flash API used by applications, see [Application Interface](https://docs.silabs.com/shared-content/latest/bootloader-user-guide-gsdk-4/12-application-interface)

###### Simplicity Commander and the Gecko Bootloader

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple CLI (Command Line Interface that is also scriptable. You can use Simplicity Commander to perform these essential tasks:

- Generating key files for signing and encryption
- Signing application images for Secure Boot
- Creating GBL images (encrypted or unencrypted, signed, or unsigned)
- Parsing GBL images

Simplicity Commander is used throughout the examples in the following sections. For more information on executing the commands to complete these tasks, see [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

> **Note**: Simplicity Commander also offers a GUI (Graphical User Interface) that can be used in the lab for typical tasks such as flashing device images. The functions described in this User Guide are performed from the CLI.

###### Creating GBL Files Using Simplicity Commander (heading level 7)

To create an unsigned GBL file from an application **myapp.s37**, execute `commander gbl create myapp.gbl --app myapp.s37`.

To create an unsigned GBL file from a main bootloader upgrade **mybootloader.s37**, execute `commander gbl create mybootloader.gbl --bootloader mybootloader.s37`. This file can be used with the standalone bootloader configurations of the Gecko Bootloader.

To create an unsigned GBL file from a Secure Engine, upgrade **mySecureElement.seu**, and execute `commander gbl create mySecureElement.gbl --seupgrade mySecureElement.seu`. The Secure Engine images, .seu, are provided by Silicon Labs and  can be found through Simplicity Studio. See section [Gecko Bootloader Operation - Secure Engine Upgrade](05-gecko-bootloader-operation-secure-engine-upgrade#gecko-bootloader-operation-secure-engine-upgrade).

These commands can also be combined to create a single upgrade image, suitable for use with application bootloader configurations of the Gecko Bootloader: `commander gbl create myupgrade.gbl --app myapp.s37 --bootloader mybootloader.s37 --seupgrade mySecureElement.seu`.

###### Gecko Bootloader Security Features

###### About Bootloader Image Security (heading level 7)

Secure Boot and Secure Firmware Upgrade, discussed in the following sections, enable Gecko Bootloader to provide authenticity and integrity checks on the Application image, which provides a sufficient level of security for many applications. However, in systems without a hardware root of trust, no process checks the authenticity or integrity of the Gecko Bootloader itself. Its security is provided solely by the device hardware and the robustness of the software running on the device.

The native behavior of Firmware Upgrade will prevent accidental version rollback of Gecko Bootloader under normal usage conditions. However, without a hardware root of trust, intentional downgrade attacks may be feasible. If a higher level of security assurance is required by the application, using a Series 2 device with hardware root of trust and anti-rollback protection is recommended. For more information, refer to [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/).

###### About Application Image Security (heading level 7)

The Gecko Bootloader can enforce security on two levels:

- Secure Boot refers to the verification of the authenticity of the application image in main flash on every boot of the device.
- Secure Firmware Upgrade refers to the verification of the authenticity of an upgrade image before performing a bootload, and optionally enforcing that upgrade images are encrypted.

###### Secure Boot Procedure (heading level 8)

When Secure Boot is enabled, the cryptographic signature of the application image in flash is verified on every boot before the application is allowed to run. Secure Boot is not enabled by default in the example configurations provided by Silicon Labs, but enabling it is highly recommended to ensure the validity and integrity of firmware images.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA (elliptical curve digital signature algorithm) of the SHA-256 digest of the application firmware image, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

1. On boot, the bootloader checks the application image for information about whether it is signed.
2. The type of signature and signature location is determined.
3. If the type of signature does not match the requirements of the bootloader, the bootloader enters device firmware upgrade mode and prevents the application from running.
4. According to the chosen signature algorithm, the signature of the contents of flash from the beginning of the application to the location of the signature is compared to the signature at the signature location.
5. If the signatures do not match, the bootloader enters device firmware upgrade mode and prevents the application from running.

**Secure Boot using ECDSA-P256-SHA256**

For an image to be signed for Secure Boot, the application needs to contain a copy of the **ApplicationProperties_t** struct. This struct contains information about which signature algorithm is used, and where to find the signature.

On every boot, the bootloader calculates the SHA-256 digest of the application image, from the beginning of the application to the start of the signature. The signature of the SHA-256 digest is then verified using ECDSA-P256.

If the signature is valid, the application is allowed to boot. Else, the bootloader is entered, and an application upgrade is attempted if one is available.

The public key used for signature verification is stored as a manufacturing token on Series 1 and EFR32xG22 devices. OnEFR32xG21 devices, the public key can either be stored as a manufacturing token or stored in the Secure Engine One-time Programmable memory (OTP). Simplicity Commander can be used to generate a key pair and write the public key to the device. See [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more information.

**Secure Boot with Application Rollback Protection**

On every boot, the application version in the **ApplicationData_t** struct is stored at the end of the bootloader area in flash, which is used to prevent applications from being downgraded. The application version can remain the same for upgrades. The bootloader will only allow applications to increment its version 6 times by default. The bootloader can be upgraded after that to reset the stored application versions and to allow application upgrades again. The allowed number of upgrades can be increased by modifying linkerfiles to reserve an extra 4 bytes for each version and by increasing SL_GBL_APPLICATION_VERSION_STORAGE_CAPACITY from _btl_bootload.c_. **For Series 2 devices, this option is not applicable on devices with Secure Engine configured to perform full page lock**. If the bootloader area in flash is locked by Secure Engine, the bootloader will not be able to store the application versions in flash, and it would continue without performing that function.

When the application upgrade version check option is enabled in the **Bootloader Core** component, the bootloader checks where App properties points into flash. If app properties struct is present, then it will check compatibility of the application properties struct and check if the upgrade version is greater than the installed app; otherwise, it will check if product ID is correct before applying the upgrade image.

If app properties struct is absent at the app properties location, it is assumed that the previous upgrade was interrupted, and allows the upgrade to continue.

If application rollback prevention component is installed in the bootloader project, then before applying the upgrade image, the bootloader will check the application version in the application properties structure that resides inside the signed/encrypted GBL file and will only apply the OTA image to application area if the application version in ApplicationData structure is equal or higher than the highest application version last seen.

The application rollback prevention feature can be enabled in the **Bootloader Core** component by selecting the **Enable application rollback protection** option. The **Minimum application version allowed** option can be used to configure the minimum application version that should be allowed to boot.

The application versions are stored in the bootloader area in flash. To properly protect the stored application versions, it is recommended to lock the bootloader flash by selecting the **Prevent bootloader write/erase** option in the **Bootloader Core** component.

**Secure Boot Using a Certificate**

On Series 2 devices, a certificate-based secure boot operation is supported. The Certificate contains:

- Struct version: The version of the certificate structure.
- Public key: ECDSA-P256 public key, X and Y coordinates concatenated, used to validate the image.
- Certificate version: The version of the running certificate.
- Signature: ECDSA-P256 signature, used for the authentication of the public key and the certificate version.

The definition of the certificate struct can be found in api/application_properties.h.

To utilize certificate-based secure boot, configure Secure Engine to authenticate the bootloader image by configuring the certificate-based secure boot option in the Secure Engine OTP. Configure the Gecko Bootloader to enable certificate-based secure boot in the **Bootloader Core** component by selecting the **Enable certificate support** option. The Gecko Bootloader certificate must be signed by the private key pair of the public key stored in the Secure Engine OTP. For more information on the key storage, see section [Key Storage](#key-storage).

The certificate-based secure boot procedure is illustrated in the following figure.

![Certificate-Based Secure Boot Procedure](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image21.jpg)

Once the certificate-based secure boot option on Secure Engine is turned on, Secure Engine verifies the Gecko Bootloader certificate. The public key stored in the certificate is used to validate the signature of the Gecko Bootloader. Secure Engine will not accept bootloader images without a certificate.

If only the secure boot option is enabled (not certificate-based) on Secure Engine, and Secure Engine identifies a certificate, the certificate will be used to validate the bootloader image. If the certificate version from the bootloader image is higher than 0 and it gets verified once, Secure Engine will never again accept direct signed bootloader images without a certificate.

The Gecko Bootloader will authenticate the direct signed application using the public key stored in the Gecko Bootloader certificate. If the application contains a certificate, Gecko Bootloader will authenticate it. The procedure is illustrated in the following figure.

![Advanced Certificate-Based Secure Boot Procedure](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image22.jpg)

After authentication of the application certificate, Gecko Bootloader verifies the signature of the application using the public key from the application certificate. In addition, Gecko Bootloader compares the Gecko Bootloader certificate version against the application certificate version. All application images with a certificate version lower than the certificate version of the Gecko Bootloader will be rejected. Gecko Bootloader can be configured to only allow applications with certificate to boot by configuring the **Bootloader Core** component by selecting the **Reject direct signed images** option.

The **ApplicationProperties_t** struct contains the certificate struct **ApplicationCertificate_t**. The certificate struct can be injected to images that contain an **ApplicationProperties_t** with **ApplicationCertificate_t**. To inject a certificate to an image, issue the following command from Simplicity Commander:

`commander convert <image file> --secureboot --keyfile <signing key> --certificate <certificate>--outfile <signed image file with certificate>`

###### Secure Firmware Upgrade (heading level 8)

The Gecko Bootloader supports a secure firmware upgrade process. This is achieved by using symmetric encryption to encrypt the upgrade image, and asymmetric cryptography to sign the upgrade image. Symmetric encryption provides confidentiality and asymmetric cryptography provides integrity and authenticity. Note that encryption alone is not enough to provide authenticity.

**Encryption Algorithms**

The Gecko Bootloader supports the AES-CTR-128 encryption algorithm. The GBL upgrade file is encrypted using 128-bit AES in Counter mode with a random nonce as the initial counter value. Through configuration, the GBL file’s decryption duration can be improved by increasing the counter's block size. The block size is configurable with options 1, 2, 4, or 8 blocks. The configuration is available as part of the AES CTR Stream Block Config component.

The AES-128 key used for decryption, more commonly called the OTA decryption key, is stored as a manufacturing token on Series 1 and EFR32xG22 devices. On EFR32xG21 devices, the OTA decryption key can either be stored as a manufacturing token or stored in the Secure Engine OTP. To make use of the OTA decryption key stored in the Secure Engine OTP, the **Use symmetric key stored in Secure Engine storage** option in the **Bootloader Core** component must be selected. Simplicity Commander can be used to generate an OTA decryption key and write the key to the device. See [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more information. For more information on storing the OTA decryption key on Series 2 devices, see [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/).

The Secure Engine OTP key support depends on the SE Manager component, which is enabled by default.

**Signature Algorithms**

The Gecko Bootloader supports the ECDSA-P256-SHA256 cryptographic signature algorithm. This is the ECDSA signature of the SHA-256 digest of the GBL upgrade file, using the NIST P-256 (secp256r1) curve.

**Summary of Operation**

Before starting a firmware upgrade process, the application can verify an image in storage by calling into the bootloader verification functions. For bootloaders with Communication Interface, the host device should verify the image before sending it to the NCP or RCP.

During firmware upgrade, the GBL file is parsed, and if encrypted, decrypted on-the-fly. A GBL Signature Tag in the GBL file indicates to the bootloader that the file is signed, and the signature is verified. If signature verification fails, the firmware upgrade process is aborted.

On Series 2 devices, Gecko Bootloader will authenticate the GBL signature tag using the public key stored in the bootloader certificate if the **Enable certificate support** option is selected in the **Bootloader Core** component. A GBL Certificate tag in the GBL file indicates to the bootloader that the GBL certificate tag needs to be authenticated using the public key stored in the bootloader certificate. The certificate version in the GBL certificate tag is compared with the bootloader certificate and only a version equal or higher than the bootloader certificate is accepted. Once the GBL certificate tag is authenticated, the GBL file's signature is verified using the authenticated public key from the GBL certificate tag. On EFRxG21 devices, the GBL certificate tag can also be signed by the private key pair of the public key stored in the Secure Engine OTP.

###### Using Application Image Security Features (heading level 7)

This example assumes that a bootloader called **bootloader-uart-xmodem** has been built in Simplicity Studio. For a Series 1 device, three files of interest have been generated in the output directory:

- **bootloader-uart-xmodem.s37** – This file contains the main bootloader. Can be used for bootloader upgrade.
- **bootloader-uart-xmodem-crc.s37** - This file contains the main bootloader with CRC32 checksum.
- **bootloader-uart-xmodem-combined.s37** – This file contains the first stage and main bootloader with a CRC32 checksum in a single image. Can be used for manufacturing and initial deployment of the bootloader.

The relevant version can be flashed to the EFR32 using the Flash Programmer in Simplicity Studio or using Simplicity Commander. For Series 2 devices, only the main bootloader binary is generated.

This example provides two ways of signing the upgrade images. The first option uses Simplicity Commander to generate key material and sign data. This is suitable for development. The second option uses an external signer, such as a dedicated Hardware Security Module (HSM) to protect private key material and perform signing operations. Silicon Labs recommends using an HSM to safeguard private keys.

###### Generating Keys (heading level 8)

To use the security features of the Gecko Bootloader, encryption and signing keys need to be generated. These keys must then be written to the EFR32 device. The encryption key is used with the GBL file for secure firmware upgrade. The signing keys are used both with the GBL file for secure firmware upgrade and to sign the application image for Secure Boot.

**Generating a Signing Key Using Simplicity Commander**

`commander util genkey --type ecc-p256 --privkey signing-key --pubkey signing-key.pub --tokenfile signing-key-tokens.txt`

This creates an ECDSA-P256 key pair for signing; **signing-key** contains the private key in PEM format and **must be kept secret from third parties**. This key will later be used to sign images and GBL files. **signing-key.pub** contains the public key in PEM format and can be used to verify GBL files using commander gbl parse. **signing-key-tokens.txt** contains the public key in token format, suitable for writing to the EFR32 device.

**Generating a Signing Key Using a Hardware Security Module**

When using a Hardware Security Module, the private key is kept secret inside the HSM. According to the instructions from your HSM vendor, have it generate an ECDSA-P256 key pair and export the public key in PEM format to the file **signing-key.pub**. Then use Simplicity Commander to convert the key to token format, suitable for writing to the EFR32 device.

`commander gbl keyconvert --type ecc-p256 signing-key.pub --outfile signing-key-tokens.txt`

**Generating an Encryption Key**

`commander util genkey --type aes-ccm --outfile encryption-key`

This creates an AES-128 key for encryption in the file **encryption-key**. The file has token format, making it suitable to write to the EFR32 device using `commander flash --tokenfile`.

**Writing Keys to the Device**

To write the two token files containing the encryption key and public key as manufacturing tokens to the device, issue the following command:

`commander flash --tokengroup znet --tokenfile encryption-key --tokenfile signing-key-tokens.txt`

###### Signing an Application Image for Secure Boot (heading level 8)

If the bootloader enforces Secure Boot, the application needs to be signed to pass verification. On every boot, a SHA-256 digest of the application is calculated. The signature is verified using ECDSA-P256, with the same public key as for the GBL file signing. Signature verification failure prevents the application from booting.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see section [Application Properties](12-application-interface#application-properties).

**Using Simplicity Commander**

Signing the application can be done with the command:

`commander convert myapp.s37 --secureboot --keyfile signing-key --outfile myapp-signed.s37`

**Using a Hardware Security Module**

The application can be prepared for signing by issuing the command:

`commander convert myapp.s37 --secureboot --extsign --outfile myapp-for-signing.s37`

###### Creating a Signed and Encrypted GBL Upgrade Image File from an Application (heading level 8)

To create a GBL file from an application, use `commander gbl create`.

Note that, as of this writing, secure application images can only be constructed through Simplicity Commander, not through the configuration options available through Simplicity Studio.

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. If **ApplicationProperties_t** is missing, the application image cannot be signed. For more details on adding **ApplicationProperties_t**, see section [Application Properties](12-application-interface#application-properties).

**Using Simplicity Commander to Sign**

For an application called **myapp.s37**, use:

`commander gbl create myapp.gbl --app myapp.s37 --sign signing-key --encrypt  encryption-key`

This single command performs three actions:

- Creates a GBL file
- Encrypts the GBL file
- Signs the GBL file

If Secure Boot is also desired, the application must be signed using `commander convert --secureboot` prior to creating the GBL.

**Using a Hardware Security Module to Sign**

For an application called **myapp-signed.s37**, which has previously been signed for Secure Boot, use:

`commander gbl create myapp-for-signing.gbl --app myapp-signed.s37 --extsign --encrypt  encryption-key`

This command performs the following actions:

- Creates a partial GBL file
- Encrypts the partial GBL file
- Prepares the partial GBL file for signing by an external signer

Using an HSM, sign the output file **myapp-for-signing.gbl.extsign**, and supply the resulting DER-formatted signature file **signature.der** back to Simplicity Commander:

`commander gbl sign myapp-for-signing.gbl.extsign --signature signature.der --verify signing-key.pub --outfile myapp.gbl`

The GBL file is not valid until the signature has been applied using gbl sign.

###### System Security Considerations (heading level 7)

The Gecko bootloader security features can be used to create a secure device, but do not create a secure system by themselves. This section goes over considerations that need to be taken when designing a secure system where the Gecko Bootloader is a component.

###### Key Storage (heading level 8)

On Series 1 devices, the decryption and public sign keys used by the Gecko bootloader are stored in the Lockbits page in flash. To prevent a rogue application from being able to change or wipe the keys, the Lockbits page should be write protected after the keys have been written in manufacturing.

On Series 2 devices, the decryption key and the sign key used by the Gecko Bootloader can either be stored in the topmost page of the main flash or in the Secure Engine OTP. The decryption key can be provisioned in the Secure Engine OTP using Simplicity Commander or using the Secure Engine Mailbox interface. The keys are not accessible from the user applications on EFR32xG22 devices, which means that the keys used by Gecko Bootloader need to be stored in the topmost page of the main flash. Once a key value has been programmed into the Secure Engine OTP, it cannot be changed. For more details, refer to [Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/) and [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

The default behavior of the Gecko Bootloader is to use the sign key stored in the Secure Engine OTP to perform the signature verification. If the sign key is not provisioned, the Gecko Bootloader will try to use the public sign key stored in the topmost page of the main flash. This fallback mechanism can be disabled by disabling the “Allow use of public key from manufacturing token storage” component option from the **Bootloader Core** component in Simplicity Studio.

###### Write-Protecting the Bootloader (heading level 8)

By default, the region in flash used by the Gecko bootloader is readable and writeable. The region needs to stay readable for the Application Interface to be able to interact with the bootloader. Immediately after reset, the region also needs to be writable to be able to perform bootloader upgrades.

###### Series 1 (heading level 9)

It is possible to write-protect the bootloader region on EFR32xG12 and newer. This is done by setting the write-once MSC_BOOTLOADERCTRL_BLWDIS bit on every bootup on Series 1 devices. The pages are write-protected until the next reboot. This is done by the Gecko bootloader main stage if the “Prevent bootloader write/erase” component option is enabled in the **Bootloader Core** component in Simplicity Studio.

On EFR32xG1, where the bootloader resides in main flash rather than the information block, the BLWDIS option does not exist. On EFR32xG1, the first flash page containing the first stage bootloader can be write-protected with a Page Lock word, using commander `device protect --write --range 0x0:+0x800`. If bootloader upgrades are to be supported, the pages containing the main bootloader need to stay writeable.

> **Note**: Setting MSC_BOOTLOADERCTRL_BLWDIS will also prevent debuggers from flashing a new bootloader. This means that debug tools that do not completely halt and reset the target device before re-flashing might fail to flash the new bootloader, as the flash is write-protected. If you are unsure whether your debug tools will handle this gracefully, Silicon Labs recommends keeping this setting disabled during development, and enabling it before going into production. If your debug tools halt and reset the target device before flashing, this is not an issue, and Silicon Labs recommends enabling this setting early in the development cycle.

###### Series 2 (heading level 9)

On Series 2 devices, the write-once MSC_PAGELOCKx register is used to write-protect the pages used by the bootloader if the “Prevent bootloader write/erase” component option is enabled in the **Bootloader Core** component in Simplicity Studio. The pages are write-protected until the next reboot.

###### Write-Protecting the Application (heading level 8)

On Series 2 devices, it is also possible to write-protect the application. When the component option “Prevent write/erase of verified application” is enabled, the bootloader will write-protect the pages used by the application after successfully verifying the application signature, before allowing the application to start. This option is only available when Secure Boot of the application is enabled. The MSC_PAGELOCKx register is used to protect the pages, and the write protection lasts until the next reboot.

###### Debug Access (heading level 8)

###### Series 1 (heading level 9)

To prevent debugger access to the Series 1 devices, the Debug Lock word needs to be written. Device recovery after enabling the Debug Lock is possible but will erase the main flash and the Lockbits page. This will erase the main application and the key material stored in the Lockbits page. The Userdata page and bootloader area will survive Debug Unlock, so secrets should not be stored in these locations. To debug lock the device, issue `commander device lock --debug enable`. The AAP Lock can be used to permanently lock the debug port. This also prevents Debug Unlock. To AAP lock the device, please see the reference manual for your device for the address location of the AAP lock word, and use `commander flash --patch` to write the appropriate value to this address.

###### Series 2 (heading level 9)

On Series 2 devices, debugger access can be prevented through Secure Engine. Debugger access can be re-enabled after enabling the Debug Lock by issuing device erase. To debug-unlock the device, issue commander device lock --debug disable from Simplicity Commander. This also erases the main flash, which results in the top page of main flash that stores the encryption and signing keys being erased. To permanently lock the debug port, the device erase disable command can first be issued through Secure Engine. Thereafter, the debug lock command can be issued to the Secure Engine. For more details, refer to [Series 2 and Series 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/).

###### Disabling Debug Access from Software (heading level 9)

The software APIs `DBG_DisableDebugAccess(dbgLockModeAllowErase)` and `DBG_DisableDebugAccess (dbgLockModePermanent)` from the EMLIB DBG module can be used from the application to lock the debug interface.

###### Gecko Bootloader and TrustZone

With GSDK v4.2.2, Gecko Bootloader comes with TrustZone support to build TrustZone aware solutions. This section outlines the major points that should be considered when using a TrustZone aware bootloader.

###### Gecko Bootloader Operation (heading level 7)

A TrustZone aware application can have the following configurations:

- Secure app only
- Non-secure app only
- Secure and Non-secure pair

With TrustZone enabled, the application bootloaders are entirely configured as Secure applications whereas the communication bootloaders are split into Secure and Non-secure application pairs. The communication interfaces are typically in the Non-secure part of the application and the GBL parser, and other functionalities are in the Secure part of the application. TrustZone aware applications are generated and built using pre-defined workspace applications. Refer to [Series 2 TrustZone](https://docs.silabs.com/mcu-bootloader/latest/series2-trustzone/) and [Software Project Generation and Configuration with SLC-CLI](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-tools-slc-cli/) for more details regarding TrustZone workspaces and the SLC CLI tool.

For the communication bootloaders to function properly, a combined bootloader binary image (containing both the Secure and Non-secure binary images) needs to be programmed onto the device. A combined bootloader binary can be obtained by either using the post-build steps defined for the workspace or using the Commander tool. Refer to [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/) for more details on how to use the Commander tool to combine multiple binaries into a single binary. Application bootloaders need to be built with the **Bootloader TrustZone Secure** component when building a TrustZone aware solution. The **Bootloader TrustZone Secure** component is required to set up the necessary configuration for the application to function correctly within a TrustZone aware solution.

To create a bootloader upgrade file, the combined bootloader binary (Secure and Non-secure) should be used. Refer to [Series 2 TrustZone](https://docs.silabs.com/mcu-bootloader/latest/series2-trustzone/) for more details on upgrading an existing application to TrustZone. Special care must be taken while building the TrustZone aware communication bootloaders for the xG21 family as the bootloader size increases from 16kB (non TrustZone aware solution) to 24kB (TrustZone aware solution). Similarly, the Bootloader – SoC Bluetooth Apploader OTA DFU application’s size increases from 72kB to 80kB with TrustZone enabled.

###### Gecko Bootloader Configuration (heading level 7)

The following table provides three of the configuration options available as part of the Bootloader Interface with TrustZone enabled.

<table>
    <thead>
        <tr>
            <th>
                <p>Configuration Option</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>BOOTLOADER_DISABLE_OLD_BOOTLOADER_MITIGATION</p>
            </td>
            <td>
                <p>Disables multi-tiered fallback logic. The fault handling logic as well as the USART auto-detection logic will be disabled. Default value is set to 0.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>BOOTLOADER_DISABLE_NVM3_FAULT_HANDLING</p>
            </td>
            <td>
                <p>Disables peripheral access fault handling. The fault handling triggered by an erroneous access of peripherals will be disabled. This should be disabled if all the peripherals that are in use by the bootloader have been properly configured by the Manually override security state of peripherals option. Default value is set to 0.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>BOOTLOADER_MANUAL_OVERRIDE_SECURITY_STATE</p>
            </td>
            <td>
                <p>Manually override the security state of peripherals in use by the bootloader. This option can be used to manually set a peripheral's access state before calling into the bootloader. Default value is set to 0.</p>
            </td>
        </tr>
    </tbody>
</table>

###### Gecko Bootloader and Delta DFU Upgrades

With GSDK v2024.6.1, Gecko Bootloader support comes with support for delta DFU upgrades. This section provides an introduction to Delta DFU upgrades and describes the major points that should be considered while using the Delta DFU component.

###### Introduction to Delta DFU (heading level 7)

The main function of the image delta DFU is to calculate the difference between the current firmware stored on the device and the new firmware to be updated. This difference is used to create a patch file that can be applied to the current firmware, resulting in the new firmware. The patch file is created using the Simplicity Commander tool, transferred to the device with any wireless protocol as a GBL, and applied on top of the current firmware by the Gecko Bootloader. The patch file creation and application are both implemented in a library that is shared between these tools.

The following diagram illustrates the complete process.

![Delta DFU process: patch creation, transfer, and firmware update](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image23.png)

###### Gecko Bootloader Operation (heading level 7)

The Delta DFU upgrades can be enabled by including the Delta DFU component in the Gecko Bootloader. Simplicity Commander supports the creation of a Delta DFU GBL file.

With Delta DFU enabled, the application bootloaders are equipped to accept Delta DFU GBL files. These GBL files contain a patch file that is extracted into the slot. The Gecko Bootloader creates the new firmware using this patch file and the currently running firmware within the slot. The slot size should have enough number of pages to hold the GBL file, patch file, and the new firmware binary in the slot. Each file starts on a new page.

The Delta DFU upgrades are triggered in the same way as in an application bootloader. Once the bootloader finds a GBL that contains Delta Patch, it extracts the patch file and then re-constructs the new firmware file within the slot. If the new firmware is created correctly, then the bootloader copies this new firmware to the application area, completing the upgrade.

To create the GBL file, Commander needs two input files, one of the firmware that is current and one that is the upgrade. For Delta DFU upgrades to work, it is essential that the firmware on the device and the firmware used to create the GBL are the same. Also, the version dependency tag is included in Delta DFU and should be correctly set by the user.

Delta DFU operation is illustrated in the following figure:

![Delta DFU flow: patch extraction, firmware reconstruction, and upgrad](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image24.png)

###### Delta Patch Extraction (Flash vs. RAM) (heading level 7)

In Delta DFU, the Silicon Labs Gecko Bootloader must extract the patch file inside the GBL before it can reconstruct the new firmware image. The bootloader supports two extraction modes:

- Flash-based extraction (default).
- RAM-based extraction (optional).

###### Flash-Based Extraction (Default) (heading level 8)

By default, the bootloader stores the extracted delta patch in the upgrade slot in flash. The storage slot must therefore be large enough to hold all three of the following, each written to flash and aligned to page boundaries:

- The GBL file.
- The extracted delta patch.
- The reconstructed firmware image.

This approach adds no RAM requirements, but it increases the total flash space the upgrade process needs.

###### RAM-Based Extraction (heading level 8)

On devices with sufficient RAM, you can configure the bootloader to extract the delta patch into RAM by enabling the `BTL_DELTA_DFU_EXTRACT_TO_RAM` configuration option. In this mode:

- The GBL file remains in the upgrade slot.
- The bootloader extracts and decompresses the delta patch into RAM.
- The bootloader reconstructs the firmware image and writes it to flash.

Because the extracted patch is no longer stored in flash, the storage slot only needs to accommodate the GBL file and the reconstructed image. This reduces flash (NVM) usage and allows larger firmware images to be updated in the same slot.

###### RAM Buffer Sizing (heading level 9)

When RAM-based extraction is enabled, the bootloader allocates a RAM buffer large enough to hold the entire extracted patch. The bootloader determines the buffer size as follows:

- **Uncompressed delta tags and LZMA-compressed patches:** The buffer matches the uncompressed patch size, which the bootloader reads directly.
- **LZ4-compressed patches:** The compressed data does not expose the uncompressed size, so the bootloader assumes a compression ratio of at least 20% and allocates approximately 1.25× the compressed size.

If RAM is insufficient, the bootloader rejects the update before reconstruction begins. Partial or streaming extraction is not supported — the entire patch must be fully present in RAM.

###### Behavior During Power Loss (heading level 9)

Because RAM is volatile, any reset or power interruption during extraction forces the bootloader to repeat the extraction step on resume. The GBL file itself stays intact in flash, so the bootloader can reprocess it when the upgrade continues.

Flash-based extraction avoids this rework: the extracted patch persists in non-volatile memory, so a reset doesn't cost the extraction work already done.

###### When to Use Each Mode (heading level 8)

|Choose this mode|When|
|---|---|
|RAM-based|The device has ample RAM, and you need to reduce flash usage or fit a larger upgrade.|
|Flash-based (default)|RAM is constrained, or your application can't afford to redo extraction after a reset.|

For more details on how to set up and configure Delta DFU in the Bootloader as well as creating the Patch File, see [OTA Delta DFU](https://docs.silabs.com/mcu-bootloader/latest/using-gecko-bootloader-with-bluetooth-apps/05-ota-delta-dfu).

###### Application Interface

The bootloader has an application interface exposed through a function table in the bootloader. The application interface provides APIs to use bootloader functions for storing and retrieving upgrade images and verifying their integrity. APIs to reboot into the bootloader are also provided. For details see the Gecko Bootloader API Reference, shipped with the SDK in the platform/bootloader/documentation folder.

If you are not using a protocol stack from Silicon Labs, the **api/btl_interface.h** header provides the bootloader application interface API. If you are using a protocol stack from Silicon Labs, the recommended bootloader interface API for the specific protocol stack should be used instead. The following files provide the implementation of the bootloader interface:

**api/btl_interface.c** (common interface)

**api/btl_interface_storage.c** (interface to storage functionality)

The application interface consists of functions that can be included into the customer application, and that communicate with the bootloader through the **MainBootloaderTable_t**. This table contains function pointers into the bootloader. The 10th word of the bootloader contains a pointer to this structure, allowing any application to easily locate it. Using the wrapper functions provided in the Bootloader Interface API is preferred over accessing the bootloader table directly. Modules include:

- **Application Parser Interface**: Application interface for interfacing with the bootloader image parser.
- **Application Storage Interface**: Application interface for interfacing with the bootloader storage. The Storage Interface is only available on bootloaders that support the storage interface.
- **Common Application Interface**: Generic application interface available on all versions of the bootloader, independently of which components are present.

###### Application Properties (heading level 7)

Application images should contain an **ApplicationProperties_t** struct declaring the application version, capabilities, and other metadata. Simplicity Commander extracts the metadata contained in this structure from the application and places it in the GBL upgrade file **GBL Application Tag**. If the structure is not present in the application, Simplicity Commander will raise an error. The **ApplicationProperties_t** struct is added to the application on installing the **bootloader_interface** component to the application. The **bootloader_interface** component installs **bootloader_app_properties** component which adds an instance of **ApplicationProperties_t** named **sl_app_properties** to the project. The component adds a source file named **app_properties.c** and a configuration file named **app_properties_config.h**. This configuration file allows users to configure the application version via Simplicity Studio’s Component Editor. To open the Component Editor, locate the **App Properties** component under **Platform > Bootloader** as shown below.

![App Properties component location under Platform > Bootloader menu](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image25.png)

Click **Configure** to open the Component Editor.

![Component Editor interface](/bootloader-user-guide-gsdk-4/0.2/images/sld718-image26.png)

The application type is automatically populated based on the wireless stack used in building the project. The value of the application type is automatically set during the project generation step and can be found in **autogen/sl_application_type.h** file.

The contents of the **GBL Application Tag** can be extracted from a GBL file by a running application using the Application Storage interface. Note that the **GBL Application Tag** will only be added if the GBL file contains an application image, not if the GBL file only contains a bootloader upgrade or metadata.

The structure in the application is also used to declare whether the application image is signed, and what type of signature is used. This information is added by Simplicity Commander when signing the image using `commander convert (--secureboot, --extsign or -- signature)`. For the bootloader to locate the **ApplicationProperties_t** struct, if not already done by the linker, Simplicity Commander modifies word 13 of the application to insert a pointer to the **ApplicationProperties_t** struct when signing the application image for Secure Boot.

###### Error Codes (heading level 7)

Most Gecko bootloader APIs return error codes. The following table lists the groups of error codes that may be returned. The full list of error codes within each group can be found in _api/btl_errorcode.h_ in the platform/bootloader directory of the SDK, as well as in the API Reference.

<table>
    <thead>
        <tr>
            <th>
                <p>ID</p>
            </th>
            <th>
                <p>Description</p>
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>0x0</p>
            </td>
            <td>
                <p>OK</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x01xx</p>
            </td>
            <td>
                <p>Initialization error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x02xx</p>
            </td>
            <td>
                <p>Image verification error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x04xx</p>
            </td>
            <td>
                <p>Storage error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x05xx</p>
            </td>
            <td>
                <p>Bootload error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x06xx</p>
            </td>
            <td>
                <p>Security error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x07xx</p>
            </td>
            <td>
                <p>Communication error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x09xx</p>
            </td>
            <td>
                <p>XMODEM parser error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x10xx</p>
            </td>
            <td>
                <p>GBL file parser error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x11xx</p>
            </td>
            <td>
                <p>SPI slave driver error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x12xx</p>
            </td>
            <td>
                <p>UART driver error</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>0x13xx</p>
            </td>
            <td>
                <p>Compression error</p>
            </td>
        </tr>
    </tbody>
</table>

###### SMP Switch Application Interface (heading level 7)

When the bootloader is built with the **Bootloader SMP Switch** component (`bootloader_smp_switch`), it advertises the capability and exposes a storage callback so an application can locate the switch pages and update the switch record at runtime. The application links against the **Bootloader Application Interface Series 2** (`bootloader_interface_s2`), which provides the SMP Flash API header `core/smp_switch/btl_smp_switch_flash_api.h`.

> SMP support is currently available on **EFR32 Series 2** devices (EFR32ZG28).

Capability Bit

The bootloader sets the following bit in `BootloaderInformation_t.capabilities` (returned by `bootloader_getInfo()`):

|Capability bit|Meaning|
|---|---|
|`BOOTLOADER_CAPABILITY_SMP_SWITCH`|The bootloader supports the SMP two-page switch (built with `BTL_SMP_SUPPORT`). The storage vtable callback `getSmpSwitchPageBases` is non-NULL.|

Applications must check this bit before calling any SMP Flash API; the helpers in `btl_smp_switch_flash_api.h` perform this check internally.

Storage vtable Callback

The SMP component adds one function pointer to `BootloaderStorageFunctions_t`:

```c
void (*getSmpSwitchPageBases)(uint32_t *page1Base, uint32_t *page2Base);
```

#### Non-Volatile Memory Use

##### Non-Volatile Memory Use

This section offers an introduction to non-volatile data storage and describes how to use NVM3 data storage.

- [**Non-Volatile Data Storage Fundamentals**](/wisun/2.12.0/non-volatile-data-storage-fundamentals): Introduces non-volatile data storage using flash and the three different storage implementations offered for Silicon Labs microcontrollers and SoCs: Simulated EEPROM, PS Store, and NVM3.
- [**Using NVM3 Data Storage**](/wisun/2.12.0/using-third-generation-nonvolatile-memory): Explains how NVM3 can be used as non-volatile data storage in various protocol implementations.

##### Non-Volatile Data Storage Fundamentals

###### Non-Volatile Data Storage Fundamentals

> **Note: This section replaces _UG103.07: Non-Volatile Data Storage Fundamentals_. Further updates to this user guide will be provided here**.

This guide provides a general introduction to non-volatile data storage using flash, with a focus on the three different dynamic data storage implementations offered for Silicon Labs microcontrollers and radio SoCs (Systems on Chip). It offers a comparison of the three implementations and provides recommendations on when to use each. Additional detail on using the various data storage implementations may be found in the following documents:

- [Using Tokens for Non-Volatile Data Storage](https://docs.silabs.com/gecko-platform/latest/using-tokens-for-non-volatile-storage/index.html)
- _AN703: Using Simulated EEPROM Version 1 and Version 2 for the EFR32 SoC Series 1 Platform_
- [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](https://docs.silabs.com/gecko-platform/latest/using-third-generation-nonvolatile-memory/)

Silicon Labs’ _Fundamentals_ series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs Bluetooth, and associated development tools. These guides can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

###### Introduction

Non-volatile memory (NVM) is memory that persists even when the device is power-cycled. On Silicon Labs microcontrollers and radio SoCs, the NVM is implemented as flash memory. In many applications the flash is not only used to store the application code but also to store data objects that are written and read frequently by the application. As flash memory can only be erased a limited number of times, several methods exist to efficiently read and write non-volatile data without wearing out the flash.

Some data is considered manufacturing data that is written only once at manufacturing time. This document is concerned with dynamic data that changes frequently over the life of the product.

This document provides an introduction to the main design options for dynamic data storage in microcontrollers and radio SoCs, along with guidelines on what factors affect flash lifetime. In addition it introduces the main flash data storage implementations offered by Silicon Labs:

- NVM3
- Simulated EEPROM version 1 (SimEEv1) and version 2 (SimEEv2)
- Persistent Store (PS Store)

###### Implementations of Non-Volatile Data Storage

This chapter introduces some of the challenges and design options when implementing non-volatile data storage in flash memory. It describes at a high level how non-volatile data storage is implemented in flash memory in PS Store, SimEEv1/v2, and NVM3.

###### Basic Implementations (heading level 7)

One of the characteristics of flash memory is that it is writable in smaller pieces, usually 32-bit words, while it can only be erased in larger chunks, usually pages of several kilobytes. When using flash as data storage, the most straightforward implementation option would be to store each data object in its own flash page, as shown in the following figure. This way each object can be erased and re-written without influencing the other data objects. Usually the data objects are much smaller than the page size, and this solution is not an effective way of using the available flash space.

![One Object Per Page](/non-volatile-data-storage-fundamentals/0.1/images/one-object-per-page.png)

To avoid wasting flash space we can store several data objects in one flash page, as shown in the following figure. This solution then introduces a challenge when we want to write a new value to one of the data objects. In that case the page must be erased before all objects are written back to the page again, including the object we changed. As flash memory can only endure a limited amount of flash erases before the flash cells are worn out, this solution results in a very limited device lifetime.

![Multiple Objects in One Flash Page](/non-volatile-data-storage-fundamentals/0.1/images/multiple-objects-in-one-flash-page.png)

To avoid erasing the flash page for every object write, we can instead write new versions of each object to new empty locations in the flash page. This is a simple form of wear-levelling that reduces the number of page erases. However, this requires that we store some identification information along with the object data that tells us what object the data belongs to, so we know how to find the latest version of the data object. This is illustrated in the following figure, where a key is added to each version of the object data to identify what object the data belongs to. When accessing an object we then need to search through the flash page for the most recent version of the object. In this case the newest version is the one with the highest address, as we start writing from the lowest address of the page.

![Object Versions With Keys](/non-volatile-data-storage-fundamentals/0.1/images/object-versions-with-keys.png)

###### Handling Resets and Power Failures (heading level 7)

As we fill up the flash page with new versions of the data objects, eventually no room is left to write new object data. At this point we need to erase the page and start over by writing only the latest versions of each object to the flash page. In many applications, however, power failures or resets can happen at any time, and we should not risk losing data if this occurs. If a reset occurs after the flash page is being erased, but before the data objects are written back, then we will lose this data. To handle this case we introduce a second page, to which we copy the latest version of the data objects, before erasing the original page, as shown in the following figure Then we can start filling the second page with data. When the second page is full we move the latest data back to the first page and so on. This mechanism, where the storage is alternated between two flash pages, is how PS Store operates.

![Latest Data Copied to New Page Before Erase](/non-volatile-data-storage-fundamentals/0.1/images/latest-data-copied-to-new-page-before-erase.png)

###### Introducing Virtual Pages (heading level 7)

In some applications we write to data objects frequently, and the flash pages therefore also need to be erased frequently. As the data objects in the implementation so far are only spread across two flash pages, each page will frequently get erased and the flash lifetime will be limited. To increase the lifetime we can use more flash pages to store the data objects. In this example, instead of two physical pages, we operate with two virtual pages (A and B) that each consist of several physical flash pages. The virtual pages are erased and written to as if they were one larger flash page. The difference is simply that each virtual page is bigger and we can write more data before we need to erase the virtual page, hence the lifetime is extended. In addition to increasing flash lifetime, using several flash pages per virtual page allows you to store more or larger objects. SimEEv1 uses this design, with each virtual page consisting of two flash pages, A and B, as shown in the following figure.

![Virtual Pages](/non-volatile-data-storage-fundamentals/0.1/images/virtual-pages.png)

In some applications the time it takes to write a non-volatile data object must be minimized so as to not interfere with the timing of other critical operations. If an object write is triggered when a virtual page is full, the latest version of all objects must first be copied to the new virtual page before writing the new object version in question to the new page. All objects must be copied over immediately to allow the first page to be quickly erased so we can move data there in case of a failure. Copying all objects at once increases the worst-case object write time.

To reduce the write times, a third virtual page can be introduced that is always kept erased. Instead of copying over the latest version of every object when the first page is full, we can instead copy over only some of the objects. The rest of the objects are copied over as a part of subsequent write operations. This way we spread the copy process to the new page over more write operations, hence each write operation takes less time to complete. With this approach we have live object data spread out across two virtual pages and the third page is always kept erased, so we have somewhere to move the data to in case of a failure. SimEEv2 uses this implementation with 3 virtual pages where each virtual page consists of 6 flash pages.

###### Basic Storage (heading level 7)

Basic storage is defined as the size of all the latest version of all objects, including any overhead stored with them. Except for NVM3, every time a flash page or virtual page is erased we must first move the basic storage over to a new page. The basic storage size is important, as it determines how much flash space is left over in a page to store any new versions of the object data. If the basic storage takes up almost the entire page, we can only write a few new object versions before we need to move to a new page and erase the old one. This leads to frequent page erases and a short flash lifetime.

NVM3 only copies unique objects that are stored in the page that will be erased. If newer versions of the object exist in other pages, the object will not be copied.

###### FIFO Model (heading level 7)

The flash data storage implementations can be modelled as a First-In First-Out (FIFO) buffer (see the following figure), where we write new versions to the input of the FIFO. As the FIFO fills up, we need to free up space by erasing one or more pages at the end of the FIFO. Before we erase a page, we need to copy any object versions for which no newer version of the same object exists in the rest of the flash pages. Other object data can be discarded, because newer versions exist. To maximize flash lifetime we want to copy as few object versions as possible, so that most of the writes to the flash memory are new versions of the objects. If the FIFO is implemented over a large flash space, it is more likely that the new version of the object has been written and that object versions at the end of the FIFO can be discarded. In this case the flash page can be erased with few or no object versions copied.

![FIFO Buffer](/non-volatile-data-storage-fundamentals/0.1/images/fifo-buffer.png)

A drawback of using a few virtual pages is that the available memory for the FIFO is limited to only the virtual pages that can hold live data. For implementations using two virtual pages, like SimEEv1, this means only half the storage space is used for the FIFO, while for SimEEv2 two thirds of the storage space is used for the FIFO.

To allow a higher portion of the storage space to be used for the FIFO, we can instead implement the FIFO as a circular buffer over the entire flash storage space allocated, as shown in the following figure. In this implementation we always need to keep enough erased pages in front of the leading edge of the buffer to write the largest-sized object in case of a failure. When the FIFO fills up to reach the critical number of erased flash pages, we copy over any object versions that have not been superseded and erase the page at the back of the FIFO. This means that, instead of keeping a full virtual page erased, we only need to keep enough space erased to fit the largest-sized object. We can use the rest of the space for the FIFO. NVM3 is implemented as a circular buffer implemented over the entire storage space, thus increasing flash lifetime compared to implementations using smaller virtual pages.

![Circular Buffer](/non-volatile-data-storage-fundamentals/0.1/images/circular-buffer.png)

###### Counter Objects (heading level 7)

For some types of data, the storage format can be optimized for the flash medium. EFR32 Series 0 and 1 can write each word two times, allowing for half word updates.  Series 2 devices allow just one write per word.

For example, counter values are usually incremented by 1 or some other low value every time they are written. Normally this means that we would have to write the entire counter value in addition to identification bytes every time the counter is incremented. We can optimize this by only storing a start value in addition to the identification value the first time a counter is written. Then we reserve a number of the words following the initial value for writing increments. The flash words in Silicon Labs devices EFR32 Series 0 and 1 can write words twice between each erase by keeping a 1 in the bits that are not to be changed.

As an example, assume we are writing two 16 bit values, 0xAAAA and 0x5555. To safely write them in the same flash word this method can be used:

- Write 0xFFFFAAAA (word in flash becomes 0xFFFFAAAA)
- Write 0x5555FFFF (word in flash becomes 0x5555AAAA)

Note that there is a maximum of two writes to the same word between each erase due to a physical limitation of the flash.

To find the current counter value, we start with the initial value and add the increment values in the halfwords following the initial value. This means that we only need to write one halfword for each increment, instead of the whole counter value and identification value. NVM3 and SimEEv1/v2 support counter objects.

###### Indexed Objects (heading level 7)

When storing data such as arrays in flash, we often only update one index at a time. If we store the whole array as one regular object, we must write the whole array to flash even if just one index is updated. Instead of storing the entire array in one object, we can divide each data array over multiple objects and only update the objects holding the changed array indexes. While it is possible to split arrays into multiple objects manually for all the Silicon Labs storage implementations, SimEEv1/v2 allow all of the indexes to share one object key. The index entry into the array to be looked up is then provided as a separate parameter.

NVM3 does not support reading and writing parts of an object. If the application wants to access indexes individually, each index must be accessed using a unique key.

###### Dynamic Data Storage Implementations

This chapter introduces some of the dynamic data storage implementations offered by Silicon Labs, including SimEEv1 and SimEEv2, PS Store, and NVM3.

###### SimEEv1/v2 (heading level 7)

SimEEv1/v2 can be used with EmberZNet PRO and Silicon Labs Connect (installed with the Flex SDK). SimEEv1 uses two virtual pages with a fixed total size of 8 kB, while SimEEv2 uses three virtual pages with a fixed total size of 36 kB.

One characteristic of SimEEv1/v2 is that all objects are defined with size and type at compile time, hence a new object cannot be created or deleted at runtime.

Silicon Labs provides a plugin for upgrading SimEEv1 data to SimEEv2.

Information about the SimEEv1/v2 implementations is found in _AN703: Using Simulated EEPROM Version 1 and Version 2 for the EFR32 Series 1 SoC Platform_.

###### PS Store (heading level 7)

PS Store can be used with Bluetooth devices on all platforms except for EFR32 Series 2. PS Store API commands are used to manage user data in PS keys in the flash memory of the Bluetooth device. User data stored within the flash memory is persistent across reset and power cycling of the device. The persistent store size is 2048 bytes and uses two flash pages for storage. As Bluetooth bondings are also stored in this area, the space available for user data also depends on the number of bondings the device has at the time. The size of a Bluetooth bonding is around 150 bytes. With its simple implementation and few storage flash pages, PS Store is the smallest of Silicon Labs' non-volatile storage options. PS Store allows objects to be created and deleted at runtime.

Information about the PS Store APIs may be found in the _Bluetooth API Software Reference Manual_.

###### NVM3 (heading level 7)

The third generation Non-Volatile Memory (NVM3) data storage driver is an alternative to SimEEv1/v2 and PS Store. The NVM3 driver provides a means to write and read data objects (key/value pairs) stored in flash. Wear-leveling is applied to reduce erase and write cycles and maximize flash lifetime. The driver is resilient to power loss and reset events, ensuring that objects retrieved from the driver are always in a valid state. Because NVM3 can be used with several protocols, such as Bluetooth and EmberZNet PRO, it allows a single data storage instance to be shared in Dynamic Multiprotocol (DMP) applications.

Some of the main features of NVM3 are as follows:

- Key/value pair data storage in flash
- Runtime creation and deletion of objects
- Persistence across power loss and reset events
- Wear-leveling to maximize flash lifetime
- Object sizes from 0 to 4096 bytes
- Configurable flash storage size (minimum 3 flash pages)
- Cache with configurable size for fast object access
- Data and counter object types
- Compatibility layers with token and PS Store APIs provided
- Single shared storage instance in multiprotocol applications
- Repack API to allow application to run clean-up page erases during periods with low CPU load

Detailed information on NVM3 is documented in the EMDRV->NVM3 section of the [Gecko HAL & Driver API Reference Guide](http://devtools.silabs.com/dl/documentation/doxygen/). Users who are accessing NVM3 through its native API should refer to this API reference guide for information. Users who are developing dynamic multiprotocol applications should refer to [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](https://docs.silabs.com/gecko-platform/latest/using-third-generation-nonvolatile-memory/).

###### Comparing Non-Volatile Data Storage Implementations

The following table presents an overview of the main features of the various Silicon Labs Non-Volatile Data Storage implementations.

|Feature|NVM3|SimEEv1|SimEEv2|PS Store|
|---|---|---|---|---|
|Compatible devices|EFM32, EFR32|EFR32 Series 1|EFR32 Series 1|EFR32 Series 1|
|Compatible radio protocols|EmberZNet, Connect, Z-Wave, OpenThread, Bluetooth|EmberZNet, Connect|EmberZNet, Connect|Bluetooth|
|Flash used for storage|3 or more flash pages|8 KB|36 KB|4 KB|
|Virtual pages|NA|2|3|NA|
|Max basic storage (Sum of all object data with overhead)|Variable (see [Using Third Generation Non-Volatile Memory (NVM3) Data Storage](https://docs.silabs.com/gecko-platform/latest/using-third-generation-nonvolatile-memory/) for details)|2 KB|8 KB|2 KB|
|Max number of objects|Limited by basic storage|254|254|Limited by basic storage|
|Max object size (bytes)|Configurable 208-4096|254|254|56|
|Object creation/deletion|Runtime|Compile time|Compile time|Runtime|
|Compiled flash size excluding data storage|9.1 KB|3.5 KB|5.4 KB|1.6 KB|
|Counter object support|Yes|Yes|Yes|No|
|Indexed object support|Partial (note 1)|Yes|Yes|No|
|Overhead per object (bytes)|4 (size <= 128 bytes); 8 (size > 128 bytes)|2|6|10|
|Counter object size including overhead (bytes)|212|60|56|NA|
|Counter increments before rewrite|100 (EFR32 Series 1); 50 (EFR32 Series 2)|25|25|NA|

Note 1: When using NVM3, indexed objects are implemented by storing each index in a separate NVM3 object.

###### Flash Lifetime (heading level 7)

All Silicon Labs Flash Data Storage implementations use some form of wear-levelling to prolong flash lifetime. The effectiveness of the wear-levelling depends on the implementation, the type of data stored, and how often it is updated. The main factors that affect wear-levelling and thereby flash lifetime are:

- Size of flash used for data storage: More flash area gives longer flash lifetime. For NVM3, the number of flash pages used for data storage can be configured, while the rest of the implementations use fixed storage sizes.
- Stored overhead per object: When writing data to the object storage, some overhead bytes are added to identify the data. Implementation with less overhead means the data objects take up less space in flash, and gives longer flash lifetime.
- Alignment to minimum object size: Objects are stored in multiples of the smallest object size. If the data size does not align with this size, padding bytes are added, which adds to the stored data and reduces flash lifetime. For instance, when storing 16-bit objects, NVM3 and PS Store add two extra bytes of padding in addition to the overhead bytes. SimEEv1/v2 are able to store 16-bit data objects without padding.
- Remaining storage after basic storage: For implementations using virtual pages, when switching to a new virtual page one instance of each object is written to the page. The rest of the virtual page can then be used to store new writes of the objects. If a lot of space is used to store one instance of each object, little space is left in the virtual page to use for wear-levelling the subsequent object writes. The flash lifetime will therefore be reduced when the total amount of object data is large relative to the virtual page size. Even for NVM3, where virtual pages are not used, the flash lifetime is limited by the available space of the total NVM3 storage.

To help monitor the actual flash wear, NVM3 and SimEEv1/v2 include function calls for reporting the number of page erases of the data storage flash pages. These erase counters can be read during accelerated lifetime testing of a product to verify if the flash wears at an acceptable rate.

##### Using Third Generation Non-Volatile Memory (NVM3) Data Storage

###### Using Third Generation Non-Volatile Memory (NVM3) Data Storage

> **Note: This section replaces _AN1135: Using Third Generation Non-Volatile Memory (NVM3) Data Storage_. Further updates to this application note will be provided here**.

The NVM3 driver provides a means to write and read data objects (key/value pairs) stored in flash. Wear-leveling is applied to reduce erase and write cycles and maximize flash lifetime. The driver is resilient to power loss and reset events, ensuring that objects retrieved from the driver are always in a valid state. A single NVM3 instance can be shared among several wireless stacks and application code, making it well-suited for multiprotocol applications. This application note explains how NVM3 can be used as non-volatile data storage in Zigbee (EmberZNet), Open Thread, Z-Wave, Bluetooth, Connect, and WiseConnect applications.

Version 3.x of the Gecko SDK Suite, used with Simplicity Studio 5, introduced a new component-based project architecture that replaced AppBuilder. Eventually all wireless protocols will move to the component-based architecture. This document addresses both this new approach to NVM3 configuration as well as the AppBuilder configuration still in use.

###### Key Points (heading level 7)

- Key/value pair data object storage in flash
- Wear-leveling to maximize flash lifetime
- Resilient to power and reset events
- Shared by Zigbee, Connect, OpenThread, Z-Wave, and Bluetooth stacks
- Compatible with PS Store and Token APIs through wrappers
- Data upgradable from Simulated EEPROM version 2 to NVM3

###### Overview

The third generation Non-Volatile Memory (NVM3) data storage driver is for storing persistent data in flash.

NVM3 is designed to work on all Silicon Labs wireless stacks running on EFR32, Series-3, and Si91x devices, as well as MCU applications running on EFM32.

Some of the main features of NVM3 are:

- Key/value pair data storage in flash
- Runtime object creation and deletion
- Persistence across power loss and reset events
- Wear-leveling to maximize flash lifetime
- Object sizes configurable up to 4096 bytes
- Configurable flash storage size (minimum 3 flash pages)
- Cache with configurable size for fast object access
- Data and counter object types
- Compatibility layers included for several Silicon Labs persistent storage APIs
- Single shared storage instance in multiprotocol applications
- Repack API to allow application to run clean-up page erases during periods with low CPU load

NVM3 is described in detail in the NVM3 Documentation on [https://docs.silabs.com/](https://docs.silabs.com/). The rest of this document assumes you are familiar with that content.

While the NVM3 API can be used directly, NVM3 is also used as the underlying storage mechanism for several other persistent storage APIs provided by Silicon Labs:

- Token API used in Zigbee EmberZNet and Connect applications
- Persistent Storage API used in Silicon Labs Bluetooth applications

###### NVM3 Default Instance

Several NVM3 instances can be created on a device and live independently of each other, but to save memory it is usually desirable to use only one NVM3 instance as each instance adds some overhead. For applications based on Silicon Labs wireless stacks, a common default instance is used. This allows Dynamic Multiprotocol (DMP) applications that combine several wireless stacks to share the same NVM3 instance.

The number of flash pages used for the NVM3 default instance is configurable, but this setting must match if an application includes several stacks that all use the default instance.

> **IMPORTANT**: When creating an application that includes an NVM3 instance for a device that already contains an NVM3 instance in flash, the number of flash pages configured for the NVM3 instance must match the number of flash pages for the NVM3 instance already found on the device. Therefore it is not possible to change the size of an NVM3 instance once it has been installed on a device, without first erasing the flash pages holding the NVM3 instance and the NVM3 objects stored there.

NVM3 has a cache to speed up access to NVM3 objects. The cache size must be set to a value greater than or equal to the number of objects found in NVM3. This includes the number of NVM3 objects created through the native NVM3 API and any objects created through higher level APIs such as the Token API. The cache must also be large enough to hold any deleted NVM3 objects. The `nvm3_countObjects()` and `nvm3_countDeletedObjects()` functions can be used to find the number of live and deleted objects in NVM3 at any given point. Silicon Labs recommends checking these functions after initialization of all NVM3 objects, both through the native NVM3 API and higher level APIs such as the token API, to figure out the correct size of the NVM3 default cache size.

###### NVM3 Default Instance Key Space (heading level 7)

NVM3 uses a 20-bit key to identify each object. To avoid using the same key for more than one object, the NVM3 key space for the default NVM3 instance has been divided into several domains as outlined in the following table. For example, NVM3 objects defined in the Zigbee EmberZNet stack should use NVM3 keys in the range 0x10000 to 0x1FFFF, while user application tokens should use keys below 0x10000. Note that any user defined NVM3 objects should be placed below 0x10000.

|**Domain**|**NVM3 Key**|
|---|---|
|User|0x00000 - 0x0FFFF|
|Zigbee EmberZNet stack|0x10000 - 0x1FFFF|
|OpenThread stack|0x20000 - 0x2FFFF|
|Connect stack|0x30000 - 0x3FFFF|
|Bluetooth stack|0x40000 - 0x4FFFF|
|Z-Wave stack|0x50000 - 0x5FFFF|
|Bluetooth mesh stack|0x60000 - 0x6FFFF|
|Reserved|0x70000 - 0x7FFFF|
|Apple HomeKit|0x80000 - 0x80FFF|
|Zigbee Cluster Library (ZCL)|0x81000 - 0x81FFF|
|dotdot|0x82000 - 0x82FFF|
|Platform CLI SM|0x83000 - 0x830FF|
|Platform Crypto|0x83100 - 0x870FF|
|Bootloader|0x87100 - 0x871FF|
|Matter|0x87200 - 0x87FFF|
|AWS Late Provision|0x88000 - 0x88FFF|
|KNX IoT|0x89000 - 0x897FF|
|Antenna Calibration (Platform)|0x89800 - 0x8987F|
|Antenna Calibration (RAIL)|0x89880 - 0x898FF|
|Trackers|0x89900 - 0x899FF|
|Aliro|0x89A00 - 0x89FFF|
|Reserved|0x8A000 - 0x8DBFF|
|Platform|0x8DC00 - 0x8FFFF|
|Wi-SUN|0x90000 - 0x9FFFF|
|Sidewalk|0xA0000 - 0xAFFFF|
|Wi-Fi|0xB0000 - 0xBFFFF|
|Reserved|0xC0000 - 0xFFFFF|

###### NVM3 in the Simplicity Studio 5 Project Configurator

The Simplicity Studio 5 Project Configurator, used with Silicon Labs Bluetooth v3.x, Connect v3.x, EmberZNet Zigbee v7.x, and OpenThread SDK applications, includes an NVM3 Core component. A separate component is also provided for the NVM3 default instance, which will initialize this instance.

![screenshot](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image1.png)

For Si91x devices, the NVM3 default instance can be configured under NVM3 for Si91x.

![screenshot](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image4.png)

The **NVM3 Default Instance** component provides the following configurations:

- **Cache Size**: Number of objects to cache. To reduce access times, this number should be equal to or higher than the number of live and deleted objects stored in NVM3 at any time.
- **Max Object Size**: Size of largest allowed NVM3 object in bytes. Must be between 208 and 4096 bytes.
- **User Repack Headroom**: Headroom determining how many bytes below the forced repack limit the user repack limit is placed. The default value is 0, which means that the forced and the user repack limits are the same.
- **Default Instance Size**: Size of the NVM3 storage region in flash. This must be set to match an integer number of flash pages, 3 pages at minimum.

If the **NVM3 Default Instance** component is included in a project, the default instance will be initialized automatically during `sl\_system\_init()` if the **System Init** component is included in the project.

###### Using NVM3 with Silicon Labs Connect

This chapter applies to Connect in the Proprietary Flex SDK v3.x used with the Project Configurator in Simplicity Studio 5. Connect in Proprietary Flex SDK v2.x uses AppBuilder in Simplicity Studio 4. AppBuilder use is described in [Using NVM3 in AppBuilder-Based Applications](08-using-nvm3-in-appbuilder-based-applications).

For Silicon Labs Connect v3.x applications, a **Token Manager** component is available under Platform > Driver in the Simplicity Studio Project Configurator Software Component view. While the token manager provides the [Token API](10-nvm3-api-options), an additional component must be selected for the token storage backend, either **Token Manager using Sim EEPROM 1**, **Token Manager using Sim EEPROM 2**, or **Token Manager using NVM3.** If NVM3 is chosen as the storage backend, **NVM3** and the **NVM3 Default Instance** components are included in the project.

###### Using NVM3 with Silicon Labs OpenThread Applications

This section applies to the Silicon Labs OpenThread SDK v1.x used with the Simplicity Project Configurator in Simplicity Studio 5. All OpenThread sample applications in the GSDK by default are configured to use NVM3 to store data in non-volatile memory. When doing so, these applications:

- Use the common default NVM3 instance.
- Include the NVM3 Core and the NVM3 Default Instance components in the project.
- Use the native NVM3 API to access the NVM3 object

The NVM3 key space used by the OpenThread stack is 0x20000 to 0x2FFFF.

###### Using NVM3 with Zigbee EmberZNet v7.x and Higher

This chapter applies to the Silicon Labs Zigbee EmberZNet SDK v7.x and higher used with the Simplicity Project Configurator in Simplicity Studio 5. Zigbee EmberZNet 6.x and lower use AppBuilder. AppBuilder use is described in [Using NVM3 in AppBuilder-Based Applications](08-using-nvm3-in-appbuilder-based-applications).

All Zigbee sample applications in the GSDK by default are configured to use NVM3 to store data in non-volatile memory. When doing so, these applications:

- Use the common default NVM3 instance
- Include the NVM3 Core and the NVM3 Default Instance components in the project
- Use the native NVM3 API to access the NVM3 object

If you have non-volatile data stored in the older SimEE format and need to preserve the data when migrating your Zigbee application to EmberZNet v7.x or higher, then the Token Manager component is available to help manage the data storage. For more information, see the Token Manager component's description.

The NVM3 key space used by the Zigbee stack is 0x10000 to 0x1FFFF.

###### Using NVM3 with Silicon Labs Bluetooth Applications

Traditionally the Bluetooth stack uses its own proprietary solution to store data in non-volatile memory, called **Persistent Store (PS Store)**. PS Store stores both data handled by the stack (such as temporary Bluetooth address, bonding keys, and so on) and user data (such as the device state) that has to be preserved on resetting the device. To learn more about PS Store, read the related section of the [Bluetooth API Reference Guide](https://docs.silabs.com/bluetooth/latest/bluetooth-stack-api/).

Some of the sample applications in the Bluetooth SDK are still configured to use PS Store, while others are already configured to use NVM3. This means that:

- On Series 1 devices sample apps are configured to use PS Store, except Bluetooth Mesh NCP sample projects, where NVM3 is used by default.
- On Series 2 devices all sample apps are configured to use NVM3.

While Series 2 devices support NVM3 only, on Series 1 devices both PS Store and NVM3 can be used. This section describes how to configure NVM3 in the Bluetooth SDK, and how to switch between PS Store and NVM3 if needed.

###### Configuring NVM3 in the Bluetooth SDK (heading level 7)

**With Simplicity Studio 5 and Bluetooth SDK v3.x**

NVM3 can be configured with the Project Configurator as described in [NVM3 in the Simplicity Studio 5 Project Configurator](03-nvm3-in-the-simplicity-studio-5-project-configurator).

**With Simplicity Studio 4 and Bluetooth SDK v2.x**

The Project Configurator is not available to configure NVM3 parameters. Therefore, the parameters have to be defined manually. To overwrite the default parameters:

1. Open the project settings.
2. Find the defined symbols:  
   - If you use GCC as your compiler, go to C/C++ Build>Settings>GNU ARM C Compiler>Symbols>Defined Symbols  
   - If you use IAR as your compiler, go to C/C++ Build>Settings>IAR C/C++ compiler for ARM>Preprocessor>Defined Symbols
3. Add any of the following defines to overwrite the default parameters:  
   - NVM3_DEFAULT_NVM_SIZE  
   - NVM3_DEFAULT_CACHE_SIZE  
   - NVM3_DEFAULT_MAX_OBJECT_SIZE  
   - NVM3_DEFAULT_REPACK_HEADROOM

You can find the description of each parameter in [NVM3 in the Simplicity Studio 5 Project Configurator](03-nvm3-in-the-simplicity-studio-5-project-configurator). Be careful when providing the size of NVM3, as it must be a multiple of the flash page size. Note: On Series 1 devices the flash page size is typically 2 kB, while on Series 2 devices the flash page size is typically 8 kB. Check the Wireless Gecko Reference Manual for your device. The NVM size must be at least 3 flash pages.

###### Switching from PS Store to NVM3 (heading level 7)

Beginning with Bluetooth SDK v2.13.0, both PS Store and NVM3 are supported as non-volatile memory solutions on Series 1 devices. Most sample applications are configured to use PS Store by default, but for some applications (where larger non-volatile memory is needed) NVM3 may be a better solution.

> **Note**: PS Store and NVM3 are not compatible with each other, therefore upgrading an already existing application from PS Store to NVM3 will result in losing all data stored on the device. If you have an application running in the field, it may be wiser to stay with PS Store. If you still want to upgrade, see [Using the Gecko Bootloader with the Silicon Labs Bluetooth Application](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/) for details.

> **Note**: PS Store uses only 2 flash pages (=4 kB on an EFR32BG1/12/13 device). Therefore, changing to NVM3 will affect the available space in flash. You must be particularly careful when you upgrade the firmware not to overwrite the NVM3 area with the application.

**With Simplicity Studio 5 and Bluetooth SDK v3.x**

To change your project configuration from PS Store to NVM3, simply install the **NVM3 Default Instance** component in the Project Configurator as discussed in [NVM3 in the Simplicity Studio 5 Project Configurator](03-nvm3-in-the-simplicity-studio-5-project-configurator). This will automatically uninstall the (otherwise hidden) PS Store component.

**With Simplicity Studio 4 and Bluetooth SDK v2.x**

To change your project configuration from PS Store to NVM3, use the following procedure.

1. Copy the following folder with all of its content:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\platform\emdrv\nvm3` under the `/platform/emdrv` folder of your project.
2. Remove the following files from the project:  
   - `/platform/emdrv/nvm3/src/nvm3_hal_extflash.c`  
   - `/platform/emdrv/nvm3/src/nvm3_default_extflash.c` (NVM3 use with external flash is deprecated)
3. If you use Apploader in your project, also copy the NVM3 version of Apploader from:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\lib\<device>\<compiler>\binapploader_nvm3.o`  
   into the `/protocol/bluetooth/lib/<device>/<compiler>` folder of your project.
4. **If you use GCC as a compiler:**  
   1. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Compiler > Includes`.  
   2. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` to the include directory.  
   3. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Linker > Miscellaneous`.  
   4. Remove `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/libpsstore.a}`.  
   5. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a}`.  
   **If you use IAR as a compiler:**  
   1. Go to `Project > Properties > C/C++ Build > Settings > IAR C/C++ Compiler for ARM > Preprocessor`.  
   2. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` to the include directory.  
   3. Go to `Project > Properties > C/C++ Build > Settings > IAR Linker for ARM > Library`.  
   4. Remove `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/\<device\>/\<compiler\>/libpsstore.a}`.  
   5. Add `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_iar.a}`.
5. If you use Apploader, also modify:  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/\<device\>/\<compiler\>/binapploader.o}`  
   to  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/\<device\>/\<compiler\>/binapploader_nvm3.o}`
6. Configure NVM3 as described in [Configuring NVM3 in the Bluetooth SDK](#configuring-nvm3-in-the-bluetooth-sdk).

###### Switching from NVM3 to PS Store (heading level 7)

It may happen that, for a reason such as backward compatibility, you have to change the configuration from NVM3 to PS Store.

**With Simplicity Studio 5 and Bluetooth SDK v3.x**

To change your project configuration from NVM3 to PS Store, simply uninstall the NVM3 Default Instance component. This will automatically install the (otherwise hidden) PS Store component. Note, that this can only be done on series 1 devices, as series 2 devices do not support PS Store. **Also, it is not possible with Bluetooth Mesh Stack in use**.

**With Simplicity Studio 4 and Bluetooth SDK v2.x**

To change your project configuration from NVM3 to PS Store, use the following procedure:

1. Remove the /platform/emdrv/nvm3 folder from your project.
2. Copy the PS Store library from:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\lib\<device>\<compiler>\libpsstore.a`  
   into the `/protocol/bluetooth/lib/<device>/<compiler>` folder of your project.
3. If you use Apploader in your project, also copy the PS Store version of Apploader from:  
   `C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\<version>\protocol\bluetooth\lib\<device>\<compiler>\binapploader.o`  
   into the `/protocol/bluetooth/lib/<device>/<compiler>` folder of your project.  
   > **Note**: PS Store is not supported on Series 2 devices (EFR32xG2x), therefore there is only an NVM3 version of the Apploader for these devices.
4. **If you use GCC as your compiler**  
   1. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Compiler > Includes`.  
   2. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` from the include directory.  
   3. Go to `Project > Properties > C/C++ Build > Settings > GNU ARM C Linker > Miscellaneous`.  
   4. Add `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/libpsstore.a}`.  
   5. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a}`.  
   **If you use IAR as your compiler**  
   1. Go to `Project > Properties > C/C++ Build > Settings > IAR C/C++ Compiler for ARM > Preprocessor`.  
   2. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/inc}` from the include directories.  
   3. Go to `Project > Properties > C/C++ Build > Settings > IAR Linker for ARM > Library`.  
   4. Add `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/libpsstore.a}`.  
   5. Remove `${workspace_loc:/${ProjName}/platform/emdrv/nvm3/lib/libnvm3_CM4_iar.a}`.
5. If you use Apploader, also change:  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/binapploader_nvm3.o}`  
   to  
   `${workspace_loc:/${ProjName}/protocol/bluetooth/lib/<device>/<compiler>/binapploader.o}`.

###### Using NVM3 in AppBuilder-Based Applications

This section explains how NVM3 can be used for non-volatile storage in AppBuilder-based applications like EmberZNet 6.10.x and lower, EmberZNet-based DMP applications in GSDK 3.2 and lower, and Connect applications in Gecko SDK Suite 2.7 and lower.

###### NVM Library Plugin (heading level 7)

To use NVM3 with an AppBuilder-based example application, the NVM3 Library plugin should be included in the project. All PS Store and SimEE plugins should be deselected.

![NVM3 Library Plugin in AppBuilder](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image2.png)

The **NVM3 Library** plugin offers four plugin options:

- **Flash Pages**: Number of flash pages to use for NVM3 data storage. Must be 3 or higher. Default is 18 (36KB) for EFR32 Series-1 devices and 4 (32KB) for EFR32 Series-2 devices
- **Cache Size**: Number of objects to cache. To reduce access times, this number should be equal to or higher than the number of objects, including tokens and deleted objects, stored in NVM3 at any time.
- **Max Object Size**: Size of largest allowed NVM3 object in bytes. Must be between 208 and 4096 bytes. Note that the token API can only be used to access objects of 254 bytes or smaller. When accessing larger objects, the native NVM3 API must be used.
- **User Repack Headroom**: Headroom determining how many bytes below the forced repack limit the user repack limit is placed. The default value is 0, which means that the forced and the user repack limits are the same.

When the NVM3 Library plugin is used the **Simulated EEPROM version 2 to NVM3 Upgrade Library** or **Simulated EEPROM version 2 to NVM3 Upgrade Stub Library** must be included, as described in [SimEEv2 to NVM3 Upgrade Plugin](#simeev2-to-nvm3-upgrade-plugin).

###### SimEEv2 to NVM3 Upgrade Plugin (heading level 7)

An AppBuilder plugin (**Simulated EEPROM version 2 to NVM3 Upgrade Library**) is provided for EmberZNet applications that upgrade tokens stored in SimEEv2 to NVM3. For tokens to be successfully upgraded to NVM3, CREATOR_* and NVM3KEY_* defines must be added for all tokens as described in [Token API](10-nvm3-api-options). The upgrade plugin will replace the SimEEv2 storage in-place with an NVM3 storage instance. The plugin does this by compacting the SimEEv2 storage down to 12 kB, and then creates an NVM3 instance in the remaining 24 kB of the original 36 kB SimEEv2 storage space. After the token data has been copied over from SimEEv2 to NVM3, the SimEEv2 storage is erased and the NVM3 instance is resized to use the entire 36 kB storage space. Apart from the code space needed for the upgrade library code, the upgrade does not require any additional flash space to the 36 kB storage area. The upgrade plugin requires that the existing SimEEv2 storage space and new NVM3 storage space are located at the same address and have the same size.

The **Simulated EEPROM version 2 to NVM3 Upgrade Library** plugin should be included to enable the upgrade as shown in the figure below. If no SimEEv2 token data is found, the upgrade plugin will look for NVM3 data, and if neither is found it will create a new NVM3 instance with tokens set to their default values. For applications that do not need to upgrade any SimEEv2 tokens, the **Simulated EEPROM version 2 to NVM3 Upgrade Stub** plugin should be included instead.

![SimEEv2 to NVM3 Upgrade Library and Stub Plugins in AppBuilder](/using-third-generation-nonvolatile-memory/0.2/images/sld770-image3.png)

###### Using NVM3 with Z-Wave Applications

For details on using NVM3 with Z-Wave applications, see [https://www.silabs.com/documents/public/user-guides/INS14259.pdf](https://www.silabs.com/documents/public/user-guides/INS14259.pdf), section 7.4.

###### NVM3 API Options

This chapter describes the three different APIs available to access NVM3 objects.

- Token API
- Persistent Store API
- Native NVM3 API

###### Token API (heading level 7)

The token API is used to access data stored in SimEEv1 and SimEEv2 with the EmberZNet and Connect stacks, as well as multiprotocol applications. Information on how to define and access tokens can be found in [Using Tokens for Non-Volatile Data Storage](https://docs.silabs.com/gecko-platform/latest/using-tokens-for-non-volatile-storage/), and users should read this document before using the token API. When selecting the NVM3 Library plugin instead of one the SimEE plugins, the NVM3 default instance is used to store the token data instead of SimEE. The same token API can still be used to access tokens stored in NVM3, but the token definition needs some modifications to work with NVM3, as described below.

When defining a token to be used with SimEE, a creator code must be defined as an identifier for the token. Similarly, when defining a token to be used with NVM3, an NVM3 key must be defined for the token. A token definition that is compatible with both NVM3 and SimEE would include both an NVM3 key and a creator code and look like this:

```sh
#define CREATOR_name 16bit_value
#define NVM3KEY_name 20bit_value
#ifdef DEFINETYPES
  typedef data_type type #endif
#ifdef DEFINETOKENS
DEFINE_*_TOKEN(name, type, ... ,defaults) #endif
```

Select a 20-bit NVM3 key for the token, according to the domains in [NVM Default Instance Key Space](02-nvm3-default-instance#nvm3-default-instance-key-space). Each token must have a unique NVM3 key, except for indexed tokens, where more NVM3 keys must be reserved as outlined in [Special Considerations for Indexed Tokens](#special-considerations-for-indexed-tokens).

###### Deleting Tokens (heading level 8)

As tokens are created at compile time, they cannot be created or deleted at run time. NVM3 objects are, however, created and deleted at run time, and the token initialization function creates NVM3 objects for each defined token if they do not already exist. The token initialization generally does not delete NVM3 objects found that do not have a corresponding token associated with them. Therefore, if a token is no longer included in an application, the application should manually delete the associated NVM3 object by using the NVM3 Native API described in [Native NVM3 API](#native-nvm3-api). For indexed tokens, however, the token initialization checks if indexed tokens have more or less indexes than the number of NVM3 objects found in the indexed token's NVK3KEY range. If there are fewer indexes, the token initialization deletes the extra NVM3 objects. If the number of indexes has been increased, new NVM3 objects will be created to hold these indexes.

When NVM3 objects are deleted, the actual object data remains in NVM3 but is marked as deleted. The deleted object data remains in NVM3 and consumes cache space until NVM3 repacks have erased the page(s) holding all versions of these objects.

###### Special Considerations for Indexed Tokens (heading level 8)

NVM3 does not have native support for indexed tokens. Therefore an extra requirement is imposed on the NVM3 key selection for indexed tokens. With NVM3, indexed tokens are implemented by storing each index in a separate object, starting with index 0 stored at the defined NVM3KEY_name key value and the last index (127) stored with key NVM3KEY_name + 127. Because of this implementation, 128 NVM3 keys must be reserved for each indexed token. The user still only defines one NVM3KEY_name key value, but no other tokens should be defined with key values in the 127 values following this defined key. Even if the token is defined with fewer than 128 indices, all 128 indices should be reserved as the token might be expanded with more indices later on.

The example below shows two indexed tokens defined in the user key domain:

```sh
// This key is used for an indexed token and the subsequent 0x7F keys are also reserved #define
NVM3KEY_MY_INDEXED_TOKEN_A 0x00000
// This key is used for an indexed token and the subsequent 0x7F keys are also reserved #define
NVM3KEY_MY_INDEXED_TOKEN_B 0x00080
```

The table below provides indexed token NVM3 key selections in the example.

|**NVM3KEY**|**NVM3 Objects Contents**|
|---|---|
|0x00000|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 0|
|0x00001|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 1|
|0x00002|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 2|
|…| |
|0x0007F|Reserved for TOKEN_MY_INDEXED_TOKEN_A index 127|
|0x00080|Reserved for TOKEN_MY_INDEXED_TOKEN_B index 0|
|0x00081|Reserved for TOKEN_MY_INDEXED_TOKEN_B index 1|
|…| |
|0x000FF|Reserved for TOKEN_MY_INDEXED_TOKEN_B index 127|

###### Bluetooth NVM API (heading level 7)

The Bluetooth NVM API that was originally designed for PS Store can be used in the same way when using NVM3 as when using PS Store. The Bluetooth stack will automatically translate its NVM API calls to PS Store API calls or to NVM3 API calls in the background, depending on what components the project uses. The same applies for Zigbee + Bluetooth DMP projects, where NVM3 is applied as the storage mechanism, but the Bluetooth NVM API can still be used. The Bluetooth API is documented in the Bluetooth API Reference Manual. In Bluetooth SDK v2.x it can be found under the _Flash_ class (commands starting with `gecko_cmd_flash_`), while in Bluetooth SDK v3.x it can be found under the _NVM_ class (commands starting with `sl_bt_nvm`).

16-bit keys are used with the Bluetooth NVM API, which are then mapped to a 20-bit NVM3 key when NVM3 is used as storage mechanism. The four most significant bits are set to 0x4 to place these objects in the Bluetooth domain of the NVM3 default instance key space. As the Bluetooth NVM API is fixed to use only the Bluetooth domain, any objects to be placed in other domains, for example the User domain, must be created and accessed using the native NVM3 API.

If you want to use the Bluetooth NVM API and the native NVM3 API in the same app, then:

1. Call `gecko_init(pconfig)` to initialize the Bluetooth stack and open its own NVM3 instance. This is done in all Bluetooth sample apps.
2. Open NVM3 by calling the `nvm3_open()` function with the default (!) parameters to open your NVM3 instance:  
   `nvm3_open(nvm3_defaultHandle, nvm3_defaultInit);`

User data can now be saved to:

- PS key range 0x4000 - 0x407F. All other PS keys (0x0000-0xFFFF) are reserved for the stack (for example for storing bonding data).
- NVM3 key range 0x00000-0x0FFFF (NVM3 user data area), and 0x44000-0x4407F (PS Store user data area).

For example, the following API calls will have the same effect (writing to the same area):

- `nvm3_writeData(nvm3_defaultHandle,0x44000,(void\*)data,len);`
- `gecko_cmd_flash_ps_save(0x4000,len,data); //in Bluetooth SDK v2.x`
- `sl_bt_nvm_save(0x4000,len,data); //in Bluetooth SDK v3.x`

Similarly, you can read the same data with the following API calls:

- `nvm3_readData(nvm3_defaultHandle,0x44000,(void\*)read_buffer,maxlen);`
- `gecko_cmd_flash_ps_load(0x4000); //in Bluetooth SDK v2.x`
- `sl_bt_nvm_load(0x4000,maxlen,&read_len,(uint8_t\*)read_buffer); //in Bluetooth SDK v3.x`

###### Native NVM3 API (heading level 7)

For code accessing NVM3 objects that does not need to be compatible with the token or PS Store APIs, using the native NVM3 API to access NVM3 data is recommended to reduce code size and allow using the full feature set of NVM3. Any PS Store object or token can also be accessed through the native NVM3 API using the same NVM3 key. Complete documentation of this API is found online in the Drivers section of the [Gecko Platform Developer Documentation](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3). If you are using an earlier version of the GSDK, search that page's version history for the corresponding release.

###### Simplicity Commander and NVM3

Simplicity Commander is a single, all-purpose tool to be used in a production environment. It is invoked using a simple CLI (Command Line Interface) that is also scriptable. Simplicity Commander supports reading out the NVM3 data area from a device and parsing the NVM3 data to extract stored values. This can be useful in a debugging scenario where you may need to find out the stored state of an application that has been running for some time.

More information on how to use the Simplicity Commander with NVM3 can be found in [Simplicity Commander Reference Guide](https://docs.silabs.com/simplicity-commander/latest/simplicity-commander-start/).

###### Securing NVM3 Data on External Flash Devices

Series-3 devices do not have on-die NVM. Since off-chip memory such as external flash is vulnerable to persistent attacks, data objects are securely stored and retrieved from the external flash using AES-GCM authenticated encryption. On Series-3 devices, the NVM3 AES-128 symmetric key is used to encrypt the data, ensuring it cannot be read in plain text from the external flash. The NVM3 AES-128 symmetric key is a device-generated, non-exportable key stored in the Secure Engine MTP. The NVM3 symmetric key is invalidated or erased during a device erase. Any attempt to load previously recorded NVM3 data (encrypted with the older key) into flash will result in invalid reads and must be avoided. In the case of a device erase, it is essential to reinitialize the NVM3 instance and add the objects again. For details about DFA and DPA countermeasures and the AES engines being used, refer to [Secure Key Storage](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/).

###### Impact of External Flash and Security on Repack Timings (heading level 7)

For Series-3 devices using external flash, repack operations may take longer due to the increased latency of accessing external flash over the bus. Additionally, with security features such as authenticated encryption (AES-GCM) enabled, the repack timings may be further impacted due to the cryptographic overhead. It is recommended to schedule repack operations during periods of low CPU and bus activity to minimize the impact on application performance.

###### Best Practices and Optimizations for NVM3

###### Right Sizing the NVM3 Storage Region in Flash (heading level 7)

To minimize repacks and reduce flash wear, it is important to configure the NVM3 region size appropriately. The size of the NVM3 region should be based on:

- The number of objects stored in NVM3.
- The size of each object, including metadata overhead.
- The frequency of object updates and deletions.
- The flash page size of the device.

With the addition of security on Series 3 devices, storing a data object incurs a size overhead of 8 bytes. Ensure that the NVM3 region has sufficient space to accommodate active objects, deleted objects, and spare pages for repack operations. A larger NVM3 region reduces the frequency of repacks, thereby extending the flash lifetime. The "Maximum allowed basic storage" section at [Storage Capacity](https://docs.silabs.com/gecko-platform/latest/platform-driver/nvm3#storage-capacity) can help with configuring the appropriate number of flash pages and right-sizing the NVM3 storage in flash.

###### Right Sizing the Cache (heading level 7)

The NVM3 cache size should be configured to match the number of live and deleted objects in the NVM3 region. This ensures faster access to objects and reduces the overhead of searching for objects in flash. Users can query the cache size and memory information using the `nvm3_getMemInfo()` API. This API provides details about the current memory state, including available memory, cache status, and additional cache requirements. Properly sizing the cache improves performance and reduces object lookup latency.

###### Low Memory Notification Callback (heading level 7)

Users can use the `nvm3_registerCallback()` API to register a callback function, which is triggered when the NVM3 instance detects low memory conditions or a cache overflow. The callback allows the application to handle conditions such as freeing up memory by triggering repack. It is recommended that the callback be registered before calling any NVM3 APIs. Additionally, users can deregister the callback using the `nvm3_deregisterCallback()` API.

###### NVM3 Optimizations (heading level 7)

Enabling NVM3 optimization improves the NVM3 initialization and object lookup time. NVM3 optimization can be enabled or disabled from Simplicity Studio UC for Series-2 and Series-3 devices. The optimization support has implications on code size. With optimization support enabled, the code size increases by approximately 1248 bytes. NVM3 optimization is enabled by default for Series-3 devices and disabled for Series-2 devices.

By following these best practices and leveraging the available APIs and optimizations, users can maximize the efficiency and reliability of the NVM3 storage system while maintaining high performance for their applications.

###### Repack Management in NVM3

###### What is a Repack Operation? (heading level 7)

A **repack** operation in NVM3 reclaims memory in non-volatile memory (NVM) by copying valid objects to new pages and erasing old pages with obsolete or deleted data. This operation is essential for maintaining available storage and ensuring the NVM3 instance can continue to store new or updated objects.

###### Why is Repack Needed? (heading level 8)

As the NVM3 fills up with new and updated objects, old versions and deleted objects accumulate, consuming memory. When there is insufficient free memory to store additional objects, a repack operation is required to release this memory by removing outdated data.

###### When is Repack Triggered? (heading level 7)

Repack can be triggered in two ways:

- **Forced repack**  
  NVM3 automatically initiates a repack during a write operation if free memory falls below a critical threshold (forced threshold). This threshold represents the minimum limit and cannot be modified by the user. Forced repacks are performed internally using the `repackUntilGood` API. When a forced repack occurs, write operations may take longer, potentially impacting application timing.
- **User repack**  
  Applications can manually trigger a repack by calling `nvm3_repack()`. The function will execute the repack only if the available free memory drops below the user threshold. This threshold is configurable through the `repackHeadroom` parameter and is evaluated by `nvm3_repackNeeded()`. The function `nvm3_repackNeeded()` can be used to check whether a repack is required, and `nvm3_repack()` will proceed only if this function returns `true`. For time-sensitive applications, it is recommended to trigger a user repack during periods of low activity.

###### The Role of Repack Headroom (heading level 7)

The **repack headroom** parameter (`repackHeadroom` in `nvm3_Init_t`) specifies the gap between the user-defined repack threshold and the forced repack threshold. This allows applications to reserve additional memory before a forced repack occurs, giving more control over when repacks happen.

- **Default Value**  
  By default, `repackHeadroom` is configured to 0, making the user threshold equal to the forced threshold plus the maximum configured object size.
- **Increasing Headroom**  
  Configuring a higher `repackHeadroom` value means user or manually triggered repacks will occur earlier, reserving more memory and reducing the risk of forced repacks during critical operations. However, this can increase the frequency of user repacks and thus flash wear.

###### Best Practices for Repack Configuration (heading level 7)

- **Call `nvm3_repack()` proactively**  
  Before writing large objects or performing a batch of writes, check `nvm3_repackNeeded()` and call `nvm3_repack()` if needed. This avoids forced repacks during time-critical operations.
- **Tune `repackHeadroom`**  
  Configure `repackHeadroom` according to the application's tolerance for repack latency (the amount of delay it can accept when a repack occurs during a write) and the available NVM3 memory. A smaller value allows more objects to be stored before a repack is needed but increases the risk of a forced repack during a write, adding latency. A larger value causes repacks to occur earlier, which lowers the risk of a forced repack but results in more frequent user repacks.  
  Repack headroom can be configured using `NVM3_DEFAULT_REPACK_HEADROOM` macro or through the Studio UI to reserve a specific amount of memory in advance, helping to avoid forced repacks during time-critical operations.  
  For example, if the application writes 512 bytes of data (including object overhead) during bootup, which is a time-sensitive operation, configure the repack headroom to 512 bytes to ensure that a forced repack does not occur during boot. Proactively check for repack before the next bootup.  
  ```c  
  // Example: Configure repack headroom to 512 bytes to ensure sufficient memory for a critical write  
  #define NVM3_DEFAULT_REPACK_HEADROOM  512  
    
  // Proactively check and perform a repack if needed  
  if (nvm3_repackNeeded(nvm3_defaultHandle)) {  
    nvm3_repack(nvm3_defaultHandle);  
  }  
  ```
- **Monitor Available Memory:**  
  Use `nvm3_getMemInfo()` to monitor available memory and repack proactively if memory is running low.  
  ```c  
  // Example: Monitor available memory and trigger a repack  
  nvm3_MemInfo_t memInfo;  
  nvm3_getMemInfo(nvm3_defaultHandle, &memInfo);  
    
  if (memInfo.nvm3Available < 512) {  // Threshold: 512 bytes  
    nvm3_repack(nvm3_defaultHandle);  
  }  
  ```  
  For more information, see the [NVM3 Memory Info](https://docs.silabs.com/gecko-platform/latest/platform-driver/nvm3-mem-info-t).

###### Avoid Large Max Object Size Unless Needed (heading level 7)

The `maxObjectSize` parameter has a significant impact on both the minimum required NVM3 size and the amount of usable storage before a repack is triggered. Basic storage is defined as the total size of all objects, including any overhead stored with the data. The maximum amount of data that can be stored in NVM3 depends on the number of flash pages allocated for storage and the configured maximum object size.

The maximum allowed basic storage for an NVM3 instance can be estimated using the following formula:

```c
allowed_basic_storage =
  total_nvm_size
  - ((total_nvm_size / page_size) * page_header_size)             // per-page bookkeeping
  - 2 * (page_size - page_header_size)                            // repack window
  - (max_object_size + obj_header_size_large)
  - ((page_size == 4096 && max_object_size > 4064) ? 212 : 0);    // extra buffer for 4KB pages
```

where:

- `total_nvm_size` is the total NVM3 region size in bytes
- `page_size` is the flash page size in bytes
- `page_header_size` is the page header size in bytes (20 bytes)
- `max_object_size` is the configured maximum object size in bytes
- `object_header_size_large` is the large object header size in bytes (8 bytes)

This is a theoretical limit. If the basic storage is at this limit, no memory is left for wear-levelling, and page erases will be forced for every object written. Therefore, the NVM3 instance should be configured with enough flash pages so that the maximum allowed basic storage is well above the actual basic storage required by the application.

For detailed tables showing the relationship between flash page count, page size, and max object size, see the [Storage Capacity](https://docs.silabs.com/gecko-platform/latest/platform-driver/nvm3#storage-capacity) section in the NVM3 API documentation.

> **Best Practice**: Configure `maxObjectSize` to the smallest value that still accommodates the largest object. Avoid configuring it unnecessarily high, as this reduces usable memory and increases the frequency of repacks, which can accelerate flash wear.
> 
> **Tip**: If an application only occasionally needs to store a few large objects (e.g., 4096 bytes), these objects can be broken into smaller chunks (such as four 1024-byte objects). Each chunk is written separately and later read back and reassembled into the original object when needed. This approach keeps `maxObjectSize` small, maximizing usable memory and minimizing repack frequency and flash wear for the majority of the data.

###### Impact of Max Object Size on Repack and Usable Storage (heading level 7)

The maximum object size (`maxObjectSize`) directly affects the repack thresholds and the amount of usable storage before a repack is needed. A larger `maxObjectSize`:

- Increases the minimum NVM3 size required for operation.
- Reduces the amount of storage available for user data before a repack is triggered.
- May result in more frequent repacks, especially if the stored objects are much smaller than the configured maximum.

#### Security

##### Security

Silicon Labs offers a range of security features depending on the part you are using and your application and production needs. As well as the security features available, this section describes Wi-SUN-specific security design considerations.

- [**IoT Security Fundamentals**](/wisun/2.12.0/iot-endpoint-security-fundamentals): Introduces the security concepts that must be considered when implementing an Internet of Things (IoT) system. Using the ioXt Alliance's eight security principles as a structure, it clearly delineates the solutions Silicon Labs provides to support endpoint security and what you must do outside of the Silicon Labs framework.
- [**Wi-SUN FAN Security Concepts and Design Considerations**](/wisun/2.12.0/wisun-security-concepts-design-considerations): Discusses security in terms of authentication, the Wi-SUN Router, and the Wi-SUN Border Router.
- [**Integrating Crypto Functionality with PSA Crypto vs. Mbed TLS**](/wisun/2.12.0/mbedtls-psa-crypto-porting-guide): Describes how to integrate crypto functionality into applications using PSA Crypto compared to Mbed TLS.

##### Wi-SUN FAN Security Concepts and Design Considerations

Wi-SUN FAN security mechanisms are built on widely-used industry standards.
Access control is based on IEEE 802.1X and IEEE 802.11i concepts, providing
mutual authentication and establishment of a security association between the
joining node and the Wi-SUN Border Router. Frame security uses AES-CCM* from
IEEE 802.15.4, providing both data confidentiality and data authenticity.

This page discusses security in terms of:

- [Authentication](#authentication)
- [Wi-SUN Router](#wi-sun-router)
- [Wi-SUN Border Router](#wi-sun-border-router)
- [Create your Own Wi-SUN Certificates](#create-your-own-demo-wi-sun-certificates)

###### Authentication

Wi-SUN authentication is done using the Extensible Authentication Protocol - Transport Layer Security (EAP-TLS) protocol over Extensible Authentication Protocol over LAN (EAPOL). The authentication results in a Pairwise Master Key (PMK), a unique key shared between the border router and the device.

The PMK is used in the 4-way-handshake procedure with the border router. During the authentication, the border router delivers up to four Group Transient Keys (GTKs) to the devices. GTKs are shared between all connected devices in the network. The flow is described in the diagram below.

![Wi-SUN Authentication](/wisun-security-concepts-design-considerations/0.1/images/wisun-authentication.png)

In the Wi-SUN FAN context, authentication is considered to be an “expensive”
operation. This is reflected in the default lifetime of various authentication
keys. Silicon Labs' Wi-SUN FAN stack stores the
authentication keys and the TX frame counter in non-volatile storage in order to make reconnection faster
after a reboot or a loss of connection.

|Key|Default Lifetime|Refresh Procedure|
|---|---|---|
|Pairwise Master Key (PMK)|4 months|EAP-TLS|
|Pairwise Transient Key (PTK)|2 months|4-way-handshake|
|Group Transient Key (GTK)|1 month|4-way-handshake or 2-way-handshake|

###### Wi-SUN Router

Each Wi-SUN device has a unique X.509 certificate (NIST EC P-256) signed by a Certification Authority (CA). A Wi-SUN device must store at least two certificates:

- The device certificate: Used to authenticate the device to an authentication server. The authentication server may run on the border router or on the backhaul network.
- The CA root certificate: Used by the device to verify the authentication server.

###### Device Certificate (heading level 7)

Each Wi-SUN node has a secure identity based on a unique per-device X.509
certificate and its corresponding private key, using the Secure Device
Identifier (DevID) concept from IEEE 802.1AR. Wi-SUN device certificates must
adhere to the requirements in the table below.

###### X.509 w/ v3 Extensions (heading level 8)

|Fields and Extensions|Value|
|---|---|
|version|v3|
|serialNumber|an unique serial number|
|signature|ecdsa-with-SHA256|
|issuer|copied from issuer's subject field|
|notBefore|issuing time and date in UTC (GeneralizedTime)|
|notAfter|99991232235959Z (GeneralizedTime)|
|subjectPublicKeyInfo|id-ecPublicKey, namedCurve secp256r1|
|signatureAlgorithm|ecdsa-with-SHA256|
|keyUsage|digitalSignature, keyAgreement|
|extendedKeyUsage|clientAuth, id-kp-wisun-fan-device|
|authorityIdentifier|only the keyIdentifier field|
|subjectAltName|id-on-hardwareModuleName|

###### id-kp-wisun-fan-device (heading level 8)

In addition to clientAuth, all Wi-SUN device certificates must contain the
id-kp-wisun-fan-device object identifier.

```bash
id-kp-wisun-fan-device OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) Wi-SUN (45605) FieldAreaNetwork(1) }
```

###### id-on-hardwareModuleName (heading level 8)

All Wi-SUN device certificates must contain one and only one alternative name
of type OtherName of type id-on-hardwareModuleName. The sequence is specified
in RFC4108.

```bash
HardwareModuleName ::= SEQUENCE { hwType OBJECT IDENTIFIER, hwSerialNum OCTET STRING }
```

`hwType` is an object identifier that, at a minimum, identifies the manufacturer's
enterprise number (IANA) but may optionally be subtyped to contain
manufacturer-specific information, such as the device model.

`hwSerialNum` is the serial number of the hardware module.  No particular
structure is imposed on the serial number.  However, the combination of the
hwType and hwSerialNum uniquely identifies the hardware module.

###### Device Private Key (heading level 7)

In addition to a plaintext key in the buffer, the stack also accepts a PSA key
reference to the device private key. When using the key reference, the PSA key
attributes must be set according to the following table.

|Attribute|Value|
|---|---|
|psa_set_key_usage_flags|PSA_KEY_USAGE_SIGN_HASH|
|psa_set_key_type|PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)|
|psa_set_key_algorithm|PSA_ALG_ECDSA(PSA_ALG_SHA_256)|

###### Credential Cache (heading level 7)

The device maintains a credential cache for the previously connected PAN.
If the same PAN is joined again, the device will use the stored credentials
to bypass the authentication phase.

**NOTE**: The credential cache can be cleared before the join attempt by using
the API function `sl_wisun_clear_credential_cache()` but it should be used with
care. Clearing the cache on the joining node may prevent it from re-joining
the same PAN. This is due to AES-CCM* replay protection security mechanism.

###### Wi-SUN Border Router

In the authentication process, the Wi-SUN border router has the
Authenticator role. Depending of the architecture, the authentication server can
be hosted on the border router or on another device connected over IP. In the
latter case, the authentication server must run
[RADIUS](https://en.wikipedia.org/wiki/RADIUS) (Remote Authentication Dial-In
User Service). The border router/authenticator acts as a RADIUS client while
the external device acts as a RADIUS server.

###### Create your Own Demo Wi-SUN Certificates

As a prerequisite, install [OpenSSL](https://www.openssl.org/) on your machine.

###### How to View a Certificate (heading level 7)

```bash
openssl x509 -in <certificate pem> -text
```

###### How to Create the Wi-SUN Demo Certificates (heading level 7)

First, retrieve the `openssl-wisun.conf` file in this [Community post](https://community.silabs.com/s/relatedlist/ka08Y000000wupqQAA/AttachedContentDocuments).

1. Create the certificate database, used to track created certificates.

```bash
touch certdb.txt
```

1. Generate a Certificate Signing Request (CSR) for the root CA.

```bash
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout wisun_root_ca_key.pem -out wisun_root_ca_req.pem -config openssl-wisun.conf
```

1. Self-sign the root CA.

```bash
openssl ca -selfsign -rand_serial -keyfile wisun_root_ca_key.pem -in wisun_root_ca_req.pem -out wisun_root_ca_cert.pem -notext -extensions v3_root_ca -config openssl-wisun.conf -subj "/CN=Wi-SUN Demo Root CA"
```

1. Generate a CSR for the intermediate 1 CA.

```bash
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout wisun_intermediate1_ca_key.pem -out wisun_intermediate1_ca_req.pem -config openssl-wisun.conf
```

1. Sign the intermediate 1 CA with the root CA.

```bash
openssl ca -rand_serial -cert wisun_root_ca_cert.pem -keyfile wisun_root_ca_key.pem -in wisun_intermediate1_ca_req.pem -out wisun_intermediate1_ca_cert.pem -notext -extensions v3_ca1 -config openssl-wisun.conf -subj "/CN=Wi-SUN Demo Intermediate 1 CA"
```

1. Generate a CSR for the intermediate 2 CA.

```bash
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout wisun_intermediate2_ca_key.pem -out wisun_intermediate2_ca_req.pem -config openssl-wisun.conf
```

1. Sign the intermediate 2 CA with the intermediate 1 CA.

```bash
openssl ca -rand_serial -cert wisun_intermediate1_ca_cert.pem -keyfile wisun_intermediate1_ca_key.pem -in wisun_intermediate2_ca_req.pem -out wisun_intermediate2_ca_cert.pem -notext -extensions v3_ca2 -config openssl-wisun.conf -subj "/CN=Wi-SUN Demo Intermediate 2 CA"
```

1. Generate a CSR for the border router.

```bash
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout wisun_br_key.pem -out wisun_br_req.pem -config openssl-wisun.conf
```

1. Sign the border router certificate with the desired CA.

```bash
openssl ca -rand_serial -cert wisun_root_ca_cert.pem -keyfile wisun_root_ca_key.pem -in wisun_br_req.pem -out wisun_br_cert.pem -notext -extensions v3_br -config openssl-wisun.conf -subj "/CN=Wi-SUN Demo Border Router"
```

1. Generate a CSR for the device.

```bash
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout wisun_device_key.pem -out wisun_device_req.pem -config openssl-wisun.conf
```

1. Sign the device certificate with the desired CA.

```bash
openssl ca -rand_serial -cert wisun_root_ca_cert.pem -keyfile wisun_root_ca_key.pem -in wisun_device_req.pem -out wisun_device_cert.pem -notext -extensions v3_device -config openssl-wisun.conf -subj "/CN=Wi-SUN Demo Device"
```

Note that the "openssl-wisun.conf" file contains the Silicon Labs enterprise number. You should replace it with your own
(cf. [https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers](https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers)).

##### IoT Endpoint Security Fundamentals

###### IoT Endpoint Security Fundamentals

> **Note: This section replaces _UG103.05: IoT Endpoint Security Fundamentals_. Further updates to this user guide will be provided here**.

This guide introduces the security concepts that must be considered when implementing an Internet of Things (IoT) system. The guide clearly delineates the solutions Silicon Labs provides to support endpoint security and what you must do outside of the Silicon Labs framework. Where appropriate, Silicon Labs’ approach to our own security is offered as an example. This document is designed for product developers and managers.

Silicon Labs’ _Fundamentals_ series covers topics that project managers, application designers, and developers should understand before beginning to work on an embedded networking solution using Silicon Labs chips, networking stacks such as EmberZNet PRO or Silicon Labs _Bluetooth®_, and associated development tools. The guides can be used as a starting place for anyone needing an introduction to developing wireless networking applications, or who is new to the Silicon Labs development environment.

###### Key Points (heading level 7)

- Describes what manufacturers must do to have a secure product
- Reviews the tools and solutions Silicon Labs provides to support product security
- Provides references to other general and product-specific information

###### Overview

Securing the IoT is challenging. It is also mission-critical. Threats are continuously evolving, and the demand on product developers to keep up can be burdensome – particularly in low-cost, resource-constrained IoT products. Protecting your product in a connected world is a necessity, as customer data and modern online business models are increasingly targets for costly hacks that jeopardize end-user privacy and corporate brand damage. Silicon Labs is committed to working with the security community, customers, and other experts to bring state-of-the-art technology to help protect your connected portfolio.

###### No Universal Passwords

_The product shall not have a universal password; unique security credentials will be required for operation. Universal passwords allow an attacker to easily gain access to any device. Therefore, products shall either have a unique password or require the user to enter a new password immediately upon first use._

It is your responsibility to ensure that your product enforces the creation of a unique password before activation.

Silicon Labs’ products are designed to be configured by the manufacturer before being delivered to customers, and therefore passwords are outside of our scope. However, Silicon Labs tools are designed to support the various levels of security provided by the protocol in question. Most protocols offer different security levels, with tradeoffs between security level and other features such as ease of network formation. You need to review and decide on the level required by your application. For example:

- The EmberZNet Pro SDK supports a highly secure centralized trust-center-controlled method that replaces a device’s factory-programmed link key with a key that is unique to each device on the network.
- Z-Wave 700 products come with a factory-programmed unique S2 keypair on first power-up, and support SmartStart commissioning through a package QR code containing the public key.
- Bluetooth options range from an unsecured “Just Works” approach to a LE Secure Connections Pairing model. Application designers can implement additional device authentication methods, such as through the companion smartphone app, to help ensure secure pairing even for devices without a user interface.

###### Secured Interfaces

_All product interfaces shall be appropriately secured by the manufacturer._

The interfaces to be secured will vary by product configuration. For example, in an NCP topology the NCP interface must be secured. Debug interfaces should always be locked. Wireless interfaces should be secured by using strong pairing and commissioning methods and by enabling encrypted and authenticated transmissions.

While securing the interfaces is in the end your responsibility, Silicon Labs provides the tools to enable that security.

Series 1, Series 2 and Series 3 devices are designed to support securing debug access. For Series 1 devices, that functionality is provided through writing a Debug Lock word to the device. Unlocking the device erases the main application and the key material stored in the Lockbits page. For Series 2 and 3 devices, securing debug access is done through the device’s Secure Engine. Both allow the developer to lock the debug port itself. See [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or _UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower_ for an overview of securing debug access, and [Series 2 and 3 Secure Debug](https://docs.silabs.com/iot-security/latest/series2-secure-debug/) for details on the Series 2 and 3 implementation. [Testing and Debugging Applications for the Silicon Labs EFR32MG Platforms](https://docs.silabs.com/zigbee/latest/test-debug-apps-efr32mg/) provides an overview of the various application testing stages and the debug access (hardware and software) required in each.

For more information on Wireless interface security in the different protocols, see the following:

- [Zigbee Security](https://docs.silabs.com/zigbee/latest/zigbee-security/)
- [Bluetooth LE Fundamentals](https://docs.silabs.com/bluetooth/latest/bluetooth-le-fundamentals/)
- [UG235.03: Architecture of the Silicon Labs Connect Stack v2.x](https://www.silabs.com/documents/public/user-guides/ug235-03-architecture-of-connect.pdf)
- [Architecture of the Silicon Labs Connect Stack v3.x](https://docs.silabs.com/connect-stack/latest/network-co-processor-applications-connect-v3x/)

###### Proven Cryptography

_Product security shall use strong, proven, updatable cryptography using open, peer-reviewed methods and algorithms._

An important aspect of any IoT device is how secure the device is when it communicates with other devices, gateways, or the cloud. This standard mandates using proven cryptographic methods rather than attempting to implement your own.

Developers commonly secure communications such as TCP/IP connections, Bluetooth, Zigbee, or Z-Wave using the standardized and proven cryptographic methods native to the protocol. However, if a microcontroller sends sensitive information over a simple interface such as a UART to another microcontroller, it is important to realize that data should also be secured to prevent someone from snooping the UART line.

Silicon Labs offers a hardware accelerator module that provides an efficient acceleration of common cryptographic operations and allows these to be used efficiently with low CPU overhead. The cryptographic accelerator module includes hardware accelerators for the Advanced Encryption Standard (AES), optionally ChaCha20/Poly1305, Secure Hash Algorithm SHA-1 and SHA-2 (SHA-224 and SHA-256), and modular multiplication used in ECC (Elliptic Curve Cryptography) and GCM (Galois Counter Mode). The accelerator module can autonomously execute and iterate a sequence of instructions to aid software and speed up complex cryptographic functions like ECC, GCM, and CCM (Counter with CBC-MAC).

In addition to the cryptographic accelerator module, Silicon Labs includes the PSA Crypto and Mbed TLS libraries as part of the Gecko Platform SDK. Mbed TLS is open source software licensed by ARM Limited. It provides an SSL library that makes it easy to use cryptography and SSL/TLS in applications. Mbed TLS supports software implementations of all crypto algorithms that are supported by TLS 1.3 as well as a build API that allows hardware drivers to replace the software implementations when cipher accelerators are supported by the platform. Its modular framework allows for subcomponents like the crypto libraries to be incorporated into a design independently of the SSL/TLS components, saving valuable code space and runtime RAM. Mbed TLS supports SSLv3 up to TLSv1.3 communication by providing the following:

- TCP/IP communication functions: listen, connect, accept, read/write.
- SSL/TLS communication functions: init, handshake, read/write.
- X.509 functions: CRT, CRL and key handling
- Random number generation
- Hashing
- Encryption/decryption

These functions are split up into logical interfaces. They can be used separately to provide any of the above functions or to mix-and-match into an SSL server/client solution that utilizes a X.509 public key infrastructure (PKI). Examples of such implementations are provided with the source code. Components or plugins and APIs provide configuration interfaces accessible through the various SDK installations.

For more information, see the latest MCU and Peripheral Software Documentation for the target part at [https://docs.silabs.com.](https://docs.silabs.com/).

###### Security by Default

_Product security shall be appropriately enabled by default by the manufacturer._

The state in which a product is shipped is up to the manufacturer. This standard mandates that any security features provided with the product be enabled before shipping. Customers should not have to turn security on; rather they should actively have to disable it. For example, Silicon Labs Z-Wave end-nodes and gateway SDKs ship with S2 cryptography and SmartStart network formation enabled by default.

Silicon Labs believes that product security should be considered during product design, and not as an afterthought. Within development environments, all Silicon Labs application security features may be enabled or disabled as appropriate during application development. Security must also be considered during device design and testing. [Bringing Up Custom Devices for the EFR32MG and EFR32FG Families](https://docs.silabs.com/connect-stack/latest/custom-nodes-efr32/) describes the security tokens (keys, certificates, and so on) that can be programmed into a custom device to support various types of security, including that provided by the Gecko Bootloader. See [Signed Software Updates](06-signed-software-updates).

###### Signed Software Updates

_The product shall only support signed software updates. While it is critical that all products be updatable, it is just as critical that these update images be secured. A manufacturer must cryptographically sign update images to prevent tampering during deployment. The product must not use unsigned updates, as they could be fraudulent._

Silicon Labs development tools support building signed upgrade images and securely updating devices in the field, through the Silicon Labs Gecko Bootloader. The Gecko Bootloader can be configured to perform a variety of functions, from device initialization to firmware upgrades. Key features of the bootloader are:

- Usable across Silicon Labs Gecko microcontroller and wireless microcontroller families
- In-field upgradeable
- Configurable
- Enhanced security features, including:
- Secure Boot: When Secure Boot is enabled, the bootloader enforces cryptographic signature verification of the application image on every boot, using asymmetric cryptography. This ensures that the application was created and signed by a trusted party.
- Signed upgrade image file: The Gecko Bootloader supports enforcing cryptographic signature verification of the upgrade image file. This allows the bootloader and application to verify that the application or bootloader upgrade comes from a trusted source before starting the upgrade process, ensuring that the image file was created and signed by a trusted party.
- Encrypted upgrade image file: The image file can also be encrypted to prevent eavesdroppers from acquiring the plaintext firmware image.

On Series 1 devices, the Gecko Bootloader has a two-stage design, first stage and main stage, where a minimal first stage bootloader is used to upgrade the main bootloader. The first stage bootloader only contains functionality to read from and write to fixed addresses in internal flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to a fixed location in internal flash and issues a reboot into the first stage bootloader. The first stage bootloader verifies the integrity of the main bootloader firmware upgrade image, by computing a CRC32 checksum before copying the upgrade image to the main bootloader location.

On Series 2 and Series 3 devices, the Gecko Bootloader consists only of the first stage bootloader. The main bootloader is upgradable through the hardware peripheral Secure Engine. The Secure Engine provides functionality to install an image to the base address of flash, by copying from a configurable location in flash. To perform a main bootloader upgrade, the running main bootloader verifies the integrity and authenticity of the bootloader upgrade image file. The running main bootloader then writes the upgrade image to the upgrade location in flash and requests that the Secure Engine install it. The Secure Engine is also capable of verifying the authenticity of the main bootloader update image against a root of trust. The Secure Engine itself is upgradable using the same mechanism.

In summary, Series 2 and Series 3 devices support a hardware root of trust and a Secure Boot process that verifies the authenticity and integrity of Gecko Bootloader, whereas in Series 1 devices, the authenticity and integrity of Gecko Bootloader are assumed trusted and are not explicitly checked.

The Gecko Bootloader can enforce application image security on two levels:

- Secure Boot refers to the verification of the authenticity of the application image in main flash on every boot of the device. When Secure Boot is enabled, the cryptographic signature of the application image in flash is verified on every boot, before the application is allowed to run. Secure Boot is not enabled by default in the example configurations provided by Silicon Labs, but enabling it is highly recommended to ensure the validity and integrity of firmware images.
- Secure Firmware Upgrade refers to the verification of the authenticity of an upgrade image before applying the upgrade and optionally enforcing that upgrade images are encrypted. The Secure Firmware Upgrade process uses symmetric encryption to encrypt the upgrade image, and asymmetric cryptography to sign the upgrade image in order to ensure its integrity and authenticity.

For more information on Silicon Labs’ support for software update security, refer to the following:

- Bootloaders in general: [Bootloader Fundamentals](https://docs.silabs.com/mcu-bootloader/latest/bootloader-fundamentals/).
- The Gecko Bootloader in general: [Silicon Labs Gecko Bootloader User's Guide for GSDK 4.0 and Higher (series 1 and 2 devices)](https://docs.silabs.com/mcu-bootloader/latest/bootloader-user-guide-gsdk-4/) or _UG266: Silicon Labs Gecko Bootloader User’s Guide for GSDK 3.2 and Lower_

Using the Gecko Bootloader with specific protocols:

[Using the Gecko Bootloader with EmberZNet](https://docs.silabs.com/zigbee/latest/using-gecko-bootloader-with-zigbee/)

[Using the Gecko Bootloader with Silicon Labs Connect](https://docs.silabs.com/connect-stack/latest/using-gecko-bootloader-with-connect/)

[Using the Gecko Bootloader with Silicon Labs Bluetooth Applications](https://docs.silabs.com/bluetooth/latest/using-gecko-bootloader-with-bluetooth-apps/)

[Series 2 and Series 3 Secure Boot with RTSL](https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/)

###### Automatically Applied Updates

_The manufacturer will act quickly to apply timely security updates. Whenever a security vulnerability is detected, the manufacturer will automatically apply a patch to the product. No user intervention will be required._

It is the manufacturer’s responsibility to develop and implement automatic security updates. The design and methodology of such systems, for example through a Cloud-connected infrastructure or by direct intervention by a service representative, is up to you.

Silicon Labs will notify you of any security-related updates, as described in [Vulnerability Reporting Program](08-vulnerability-reporting-program) Your responsibility is to evaluate the level of risk that vulnerability poses for your particular product and to integrate the update into your platform as appropriate so that your end users are protected. Updated components might include the protocol libraries, Secure Engine firmware inside the Series 2 and Series 3 families, or an SDK module such as the Gecko Bootloader that enforces secure OTA updates and secure boot functionality.

Silicon Labs recommends the following:

- Subscribe to security updates through our [Salesforce portal](https://community.silabs.com/s/support-home). To review or change your subscriptions, log in to the portal, click **HOME** to go to the portal home page, and then click the **Manage Notifications** tile. Make sure that **Software/Security Advisory Notices & Product Change Notices (PCNs)** is checked, and that you are subscribed at minimum for your platform and protocol. Click **Save** to save any changes.  
  ![screenshot](/iot-endpoint-security-fundamentals/0.3/images/sld875-image15.png)
- Do not turn off Simplicity Studio’s update notification. Within Simplicity Studio you can download updates and easily access product release notes.

###### Vulnerability Reporting Program

_The manufacturer shall implement a vulnerability reporting program, which will be addressed in a timely manner. All companies that offer Internet-connected devices and services shall provide a public point of contact as part of a vulnerability disclosure policy in order that security researchers and others are able to report issues. Disclosed vulnerabilities should be acted on in a timely manner._

Manufacturers are responsible for implementing their own program. For any individual vulnerability, you will need to weigh the value of transparency with your customers against the risk of malicious use of the information to exploit a vulnerability before it can be addressed. Silicon Labs makes similar decisions about how broadly to report security vulnerabilities discovered in our products.

Silicon Labs customers and security researchers can report security vulnerabilities in Silicon Labs hardware and software products on the Silicon Labs website: [https://www.silabs.com/security/product-security](https://www.silabs.com/security/product-security).

Silicon Labs’ Security Vulnerability Disclosure Policy may be found here: [https://www.silabs.com/security/security-vulnerability-disclosure-policy](https://www.silabs.com/security/security-vulnerability-disclosure-policy).

Silicon Labs has a Product Security Incident Response Team (PSIRT) that is dedicated to the case management of reported security vulnerabilities. The PSIRT works with other Silicon Labs groups including Applications, Developers, Sales, and Marketing to assess reported vulnerabilities, perform technical analysis and determine an appropriate response. The key processes for addressing vulnerabilities include:

- **Triage**: Determines what is needed to reproduce the vulnerability.
- **Technical Analysis and Disposition**: Confirms the validity of the security vulnerability, its scope, and its impact, and provides a resolution or disposition decision. Silicon Labs scores incidents according to CVSS 4.0 (Common Vulnerability Scoring System): low, medium, high, critical.
- **Output**: Communicates with our customers. The level and method of disclosure beyond the reporting entity depends on the severity and scope of the vulnerability.

Silicon Labs’ provides broad vulnerability reporting to customers subscribed through our Salesforce portal (see [Automatically Applied Updates](07-automatically-applied-updates) for information on how to subscribe). A subscribed customer will see Security Advisory notifications something like the following:

![screenshot](/iot-endpoint-security-fundamentals/0.3/images/sld875-image16.jpg)

###### Security Expiration Date

_The manufacturer shall be transparent about the period of time that security updates will be provided. Like a manufacturer’s product warranty, there shall be transparency around the support period of security updates._

Manufacturers should provide details about product support at various stages and publish security expiration dates. Z-Wave’s Protocol Lifecycle provides an example.

![diagram](/iot-endpoint-security-fundamentals/0.3/images/sld875-image17.jpg)

The Lifecycle details in what phases updates will be applied, and to what product branch. For details on the various phases and how the lifecycle is implemented for specific Z-Wave products, see:

[https://www.silabs.com/products/development-tools/software/z-wave/embedded-sdk/life-cycle](https://www.silabs.com/products/development-tools/software/z-wave/embedded-sdk/life-cycle)

###### Next Steps

The Silicon Labs Security web page ([https://www.silabs.com/security)](https://www.silabs.com/security)) contains links to a variety of general security-related resources. You may wish to bookmark the page, as it will be continually updated with new content, new tools, and new flows.

If you are already in development, we strongly recommend that you implement the standards described here as you develop, test, and release your product to customers.

If you are in the early stages of your product design and have not already selected a device or development environment, we recommend that you include security considerations in your decision. Silicon Labs provides information about the security features of our devices and development environments. [Series 2 and Series 3 Device Security Features](11-series-2-and-series-3-device-security-features) highlights the features and their documentation references. In addition, protocol-specific security information is available in the following documents.

- [Zigbee Security](https://docs.silabs.com/zigbee/latest/zigbee-security/) (contents were previously in this document under the title Application Security Fundamentals)
- [Bluetooth® Low Energy Application Security Design Considerations in SDK v3.x and Higher](https://docs.silabs.com/bluetooth/latest/bluetooth-application-security-design-considerations/)
- [Using Silicon Labs Secure Vault Features with OpenThread](https://docs.silabs.com/openthread/latest/using-secure-vault-openthread/)
- [Bluetooth® LE Fundamentals](https://docs.silabs.com/bluetooth/latest/bluetooth-le-fundamentals/) and relevant Knowledge Base Articles (KBAs)
- [Architecture of the Silicon Labs Connect Stack v3.x](https://docs.silabs.com/connect-stack/latest/architecture-of-connect-v3x/)

###### Series 2 and Series 3 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys, and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

On Series 3 devices, the security features are implemented by the Secure Engine and HOSTCRYPTO (if available). The Secure Engine may is hardware-based.

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Security Level (1)**|**SE Support**|**MCU**|**Wireless SoC (2)**|
|---|---|---|---|
|Secure Vault Base (SVB)|N/A|EFM32JG1, EFM32PG1, EFM32JG12, EFM32PG12, EFM32GG11, EFM32GG12, EFM32TG11|EFR32xG1, EFR32xG12, EFR32xG13, EFR32xG14|
|Secure Vault Mid (SVM)|VSE (VSE-SVM)|EFM32PG22C|EFR32xG22C, EFR32xG27C (3)|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|-|EFR32xG21A, EFR32xG21A (Rev C), EFR32MR21A (Rev C), EFR32xG23A, EFR32xG24A, EFR32xG25A, EFR32xG28A|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|EFM32PG23B, EFMPG26B, EFM32PG28B|EFR32xG21B, EFR32Xg21B (Rev C) EFR32xG23B, EFR32xG24B, EFR32xG25B, EFR32xG26B, EFR32xG28B, EFR32xG29B, SixG301|

> Note:
> 
> 1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security.](https://www.silabs.com/security).
> 2. The x is a letter B, F, M, or Z.
> 3. Unlike other VSE-SVM parts, the EFR32xG27C device has a built-in PUF.

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

Silicon Labs strongly recommends installing the latest SE FW image on Series 2 and Series 3 devices and updating to the latest GSDK or SiSDK to mitigate security vulnerabilities. The latest SE FW image can be found in this Windows folder for GSDK v4.x:

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public`

Or

`C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\simplicity_sdk\util\se_release\public`

Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for guidance on the SE firmware upgrade procedure. The latest SE firmware shipped with Series 2 and Series 3 devices and modules (if available) at the time of this writing are listed in the following table:

|**Series 2 MCU and Wireless SoC VSE - SVM**|**Shipped SE Firmware Version**|
|---|---|
|EFM32PG22C|1.2.12|
|EFR32xG22C|1.2.12|
|EFR32xG22C (Rev D)|1.2.14|
|EFR32xG27C|2.2.1|

|**Series 2 Wireless SoC HSE - SVM**|**Shipped SE Firmware Version**|
|---|---|
|EFR32xG21A|1.2.13|
|EFR32MR21A (Rev C)|1.2.16|
|EFR32xG21A (Rev C)|1.2.16|
|EFR32xG23A|2.1.7|
|EFR32xG24A|2.1.7|
|EFR32xG25A|2.2.1|
|EFR32xG28A|2.2.2|

|**Series 2 MCU and Wireless SoC HSE - SVH**|**Shipped SE Firmware Version**|
|---|---|
|EFR32xG21B|1.2.13|
|EFR32xG21B (Rev C)|1.2.16|
|EFM32PG23B|2.1.7|
|EFR32xG23B|2.1.7|
|EFR32xG24B|2.1.7|
|EFR32xG25B|2.2.1|
|EFM32PG28B|2.2.2|
|EFR32xG28B|2.2.2|

|**Series 3 MCU and Wireless SoC HSE - SVH**|**Shipped SE Firmware Version**|
|---|---|
|SixG301|3.3.2|

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th>Document</th>
            <th>Summary</th>
            <th>Applicability</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-trustzone/">Series 2 TrustZone</a></p>
            </td>
            <td>
                <p>Describes the basics of TrustZone, secure and privileged programming model, and shows how to upgrade existing application to TrustZone.</p>
            </td>
            <td>
                <p>Series 2 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1504: Series 3 Security Overview</p>
            </td>
            <td>
                <p>High level overview of the security features included in Series 3 devices</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AN1509: Series 3 AXiP</p>
            </td>
            <td>
                <p>How to encrypt and authenticate memory contents</p>
            </td>
            <td>
                <p>Series 3</p>
            </td>
        </tr>
    </tbody>
</table>

|**Document**|**Summary**|**Applicability**|
|---|---|---|
|[Programming Series 2 Devices Using the Debug Challenge Interface (DCI) and Serial Wire Debug (SWD)](https://docs.silabs.com/iot-security/latest/efr32-dci-swd-programming/)|How to provision and configure Series 2 devices through the DCI and how to program their internal flash memory through the SWD|Series 2|
|[Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS](https://docs.silabs.com/iot-security/latest/mbedtls-psa-crypto-porting-guide/)|How to integrate crypto functionality into applications using Silicon Labs implementation of PSA Crypto compared to Mbed TLS|Series 1, Series 2 and Series 3|

##### Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS

###### Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS

> **Note: This section replaces _AN1311: Integrating Crypto Functionality Using PSA Crypto Compared to Mbed TLS_. Further updates to this application note will be provided here**.

This application note describes how to integrate crypto functionality into applications using PSA Crypto compared to Mbed TLS. It includes a guide to migrating existing Mbed TLS implementations to PSA Crypto.

This document focuses on the Silicon Labs PSA Crypto implementations that support the RNG, symmetric and asymmetric keys, message digests, MAC, unauthenticated ciphers, AEAD, KDF, DSA, and ECDH.

This document assumes familiarity with the crypto algorithms discussed.

###### Key Points (heading level 7)

- Overview of Mbed TLS and PSA Crypto
- Key management in PSA Crypto
- Migration guide
- PSA Crypto platform examples

###### Series 2 Device Security Features

Protecting IoT devices against security threats is central to a quality product. Silicon Labs offers several security options to help developers build secure devices, secure application software, and secure paths of communication to manage those devices. Silicon Labs’ security offerings were significantly enhanced by the introduction of the Series 2 products that included a Secure Engine. The Secure Engine is a tamper-resistant component used to securely store sensitive data and keys and to execute cryptographic functions and secure services.

On Series 1 devices, the security features are implemented by the TRNG (if available) and CRYPTO peripherals.

On Series 2 devices, the security features are implemented by the Secure Engine and CRYPTOACC (if available). The Secure Engine may be hardware-based, or virtual (software-based). Throughout this document, the following abbreviations are used:

- HSE - Hardware Secure Engine
- VSE - Virtual Secure Engine
- SE - Secure Engine (either HSE or VSE)

Additional security features are provided by Secure Vault. Three levels of Secure Vault feature support are available, depending on the part and SE implementation, as reflected in the following table:

|**Level (1)**|**SE Support**|**Part (2)**|
|---|---|---|
|Secure Vault High (SVH)|HSE only (HSE-SVH)|Refer to _IoT Endpoint Security Fundamentals_ for details on supporting devices.|
|Secure Vault Mid (SVM)|HSE (HSE-SVM)|"|
|"|VSE (VSE-SVM)|"|
|Secure Vault Base (SVB)|N/A|"|

> **Notes**:
> 
> 1. The features of different Secure Vault levels can be found in [https://www.silabs.com/security](https://www.silabs.com/security).
> 2. [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/).

Secure Vault Mid consists of two core security functions:

- **Secure Boot**: Process where the initial boot phase is executed from an immutable memory (such as ROM) and where code is authenticated before being authorized for execution.
- **Secure Debug access control**: The ability to lock access to the debug ports for operational security, and to securely unlock them when access is required by an authorized entity.

Secure Vault High offers additional security options:

- **Secure Key Storage**: Protects cryptographic keys by “wrapping” or encrypting the keys using a root key known only to the HSE-SVH.
- **Anti-Tamper protection**: A configurable module to protect the device against tamper attacks.
- **Device authentication**: Functionality that uses a secure device identity certificate along with digital signatures to verify the source or target of device communications.

A Secure Engine Manager and other tools allow users to configure and control their devices both in-house during testing and manufacturing, and after the device is in the field.

###### User Assistance (heading level 7)

In support of these products Silicon Labs offers whitepapers, webinars, and documentation. The following table summarizes the key security documents:

<table>
    <thead>
        <tr>
            <th><strong>Document</strong></th>
            <th><strong>Summary</strong></th>
            <th><strong>Applicability</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/series2-secure-debug/">Series 2 and Series 3 Secure Debug</a></p>
            </td>
            <td>
                <p>How to lock and unlock Series 2 and Series 3 debug access, including background information about the SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/mcu-bootloader/latest/series2-secure-boot-with-rtsl/">Series 2 and Series 3 Secure Boot with RTSL</a></p>
            </td>
            <td>
                <p>Describes the secure boot process on Series 2 and Series 3 devices using SE</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-vault-tamper/">Anti-Tamper Protection Configuration and Use</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure the anti-tamper module</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/authenticating-devices-using-device-certificates/">Authenticating Silicon Labs Devices using Device Certificates</a></p>
            </td>
            <td>
                <p>How to authenticate a device using secure device certificates and signatures, at any time during the life of the product</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/">Secure Key Storage</a></p>
            </td>
            <td>
                <p>How to securely "wrap" keys so they can be stored in non-volatile storage.</p>
            </td>
            <td>
                <p>Secure Vault High, and Series 3 devices</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><a href="https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/">Production Programming of Series 2 and Series 3 Devices</a></p>
            </td>
            <td>
                <p>How to program, provision, and configure security information using SE during device production</p>
            </td>
            <td>
                <p>Secure Vault Mid, High, and Series 3 devices</p>
            </td>
        </tr>
    </tbody>
</table>

###### Key Reference (heading level 7)

Public/Private keypairs along with other keys are used throughout Silicon Labs security implementations. Because terminology can sometimes be confusing, the following table lists the key names, their applicability, and the documentation where they are used.

|**Key Name**|**Customer Programmed**|**Purpose**|
|---|---|---|
|Public Sign key (Sign Key Public)|Yes|Secure Boot binary authentication and/or OTA upgrade payload authentication|
|Public Command key (Command Key Public)|Yes|Secure Debug Unlock or Disable Tamper command authentication|
|OTA Decryption key (GBL Decryption key) aka AES-128 Key|Yes|Decrypting GBL payloads used for firmware upgrades|
|Attestation key aka Private Device Key|No|Device authentication for secure identity|

###### SE Firmware (heading level 7)

Silicon Labs strongly recommends installing the latest SE firmware on Series 2 devices to support the required security features. Refer to [Production Programming of Series 2 and Series 3 Devices](https://docs.silabs.com/iot-security/latest/prod-programming-series2-and-series3/) for the procedure to upgrade the SE firmware and [IoT Endpoint Security Fundamentals](https://docs.silabs.com/iot-security/latest/iot-endpoint-security-fundamentals/) for the latest SE Firmware shipped with Series 2 devices and modules.

###### Device Capability

The following table lists the hardware related to cryptography hardware acceleration features on Series 1 and Series 2 devices (MCU and Wireless SoC).

|**Feature**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|
|---|---|---|---|
|TRNG|TRNG peripheral (1)|CRYPTOACC peripheral|HSE|
|Crypto Engine (2)|CRYPTO peripheral|CRYPTOACC peripheral|HSE|
|Advanced Crypto (3)|—|—|HSE-SVH|
|Secure Key Storage (4)|—|—|HSE-SVH|

> **Notes**:
> 
> 1. See [Table Entropy Source on Series 1 and Series 2 Devices](06-migration-guide#initialization-and-random-number-generation-rng) for details of TRNG (True Random Number Generator) on Series 1 devices.
> 2. Crypto engine supports up to 256-bit ciphers and elliptic curves.
> 3. Advanced crypto supports up to 512-bit ciphers and 521-bit elliptic curves.
> 4. See [Table PSA Crypto Key Lifetime Support on Series 1 and Series 2 Devices](04-key-management-in-psa-crypto#key-lifetimes) for details of Secure Key Storage support on HSE-SVH devices.

###### Overview

###### Mbed TLS (heading level 7)

Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation, and the SSL/TLS and DTLS protocols.

ARM developed Mbed TLS, which was formerly known as PolarSSL. Mbed TLS has been handed over to [Trusted Firmware](https://www.trustedfirmware.org/projects/mbed-tls/) under open governance since March 2020.

For the time being, Trusted Firmware Mbed TLS is the project containing a reference implementation of the PSA Crypto API and the TLS portion of Mbed TLS. The following table lists different Mbed TLS versions supported in Simplicity Studio and Gecko SDK (GSDK) suites.

|**Mbed TLS**|**Gecko SDK Suite**|**PSA Crypto**|**Location in Windows**|
|---|---|---|---|
|v3.2.1|v4.3.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\mbedtls|
|v3.2.1|v4.2.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\mbedtls|
|v3.1.0|v4.1.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\mbedtls|
|v3.0.0|v4.0.x (Simplicity Studio 5)|Y|C:\Users\<PC USER NAME>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\mbedtls|
|v2.26.0|v3.2.x (Simplicity Studio 5)|Y|C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.2\util\third_party\crypto\mbedtls|
|v2.24.0|v3.1.x (Simplicity Studio 5)|Y|C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.1\util\third_party\crypto\mbedtls|
|v2.16.6|v3.0.x (Simplicity Studio 5)|—|C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\v3.0\util\third_party\mbedtls|
|v2.7.12|v2.7.8 (Simplicity Studio 4)|—|C:\SiliconLabs\SimplicityStudio\v4\developer\sdks\gecko_sdk_suite\v2.7\util\third_party\mbedtls|

###### PSA Crypto (heading level 7)

**Platform Security Architecture (PSA)**

The [Platform Security Architecture](https://developer.arm.com/architectures/security-architectures/platform-security-architecture) (PSA) is made up of four key stages:

- Threat modeling
- Predefined architectural choices
- Standardized implementation
- Certification

The PSA Crypto API is one of the standardized implementation features and is discussed in the following sections.

**PSA Root of Trust (PSA-RoT)**

For an IoT product to achieve its security goals, it must meet the requirements of one of the pillars known as Root of Trust. The following figure shows the four PSA-Certified key elements that make up the Root of Trust.

![Key Requirements of PSA-RoT](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image8.png)

The PSA Root of Trust (PSA-RoT) is a source of confidentiality (for example, crypto keys) and integrity. The PSA-RoT defines what it takes for a hardware or software system to be trusted.

The [Trusted Firmware-M](https://www.trustedfirmware.org/projects/tf-m/) (TF-M) offers an open-source firmware reference implementation and APIs. These resources provide developers with a trusted codebase that complies with PSA specifications and APIs that create a consistent interface to underlying Root of Trust hardware.

**PSA Functional APIs**

[PSA Certified](https://www.psacertified.org/) defines a set of PSA Functional APIs (which are implemented as part of TF-M) to access the Root of Trust features. The PSA Functional APIs provide a standardized set of vetted APIs to ensure portability and promote adherence to best practices.

- PSA Crypto APIs
- PSA Attestation APIs
- PSA Secure Storage (Internal Trusted Storage and Protected Storage) APIs

Since the Trusted boot (aka Secure boot) shown in [Figure Key Requirements of PSA-RoT](#psa-crypto) is used when booting up the device and is not used after the system is up and running, there is no need for a Trusted boot API.

The three APIs provide software developers with access to security functions to ensure interoperability across different hardware implementations of the Root of Trust. It means another hardware platform can reuse the applications in the following figure, because these APIs are standardized across various security hardware.

![PSA Functional APIs](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image9.png)

[PSA Functional API Certification](https://www.psacertified.org/getting-certified/functional-api-certification/) is part of [PSA Certified](https://www.psacertified.org/), and demonstrates that software is compatible with the PSA Functional API specification. PSA Functional API Certified does not imply that a device has a security capability or is robust. Only PSA Certified Levels 1–3 can achieve this.

This application note only focuses on the PSA Crypto API.

**PSA Crypto API**

The PSA Crypto API is a low-level cryptographic API optimized for MCU and Wireless SoC. It provides APIs related to [Random Number Generation](06-migration-guide#initialization-and-random-number-generation-rng) (RNG), cryptographic algorithm usage, and [key handling](06-migration-guide#key-handling) (symmetric and asymmetric).

The PSA Crypto API provides developers with an easy-to-use and easy-to-learn interface to crypto primitives. It is designed for usability and flexibility and is based on the idea of a key store. The store can isolate the keys from the rest of the applications, which means keys remain opaque in [storage](04-key-management-in-psa-crypto#key-lifetimes) and only accessible for usage through crypto primitives.

###### Key Management in PSA Crypto

Key attributes are managed in a `psa_key_attributes_t` object. These are used when a key is created, after which the key attributes are impossible to change.

The actual key material is not considered an attribute of a key. Key attributes do not contain information that is generally considered highly confidential. The individual attributes ([Key Types](#key-types), [Key Lifetimes](#key-lifetimes), [Key Identifiers](#key-identifiers), and [Key Policies](#key-policies)) are described in the following sections.

The `crypto_values.h` in the Windows folder below includes the defines for macros of key attributes.

For GSDK v3.1.x and v3.2.x: `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION\>\util\third_party\crypto\mbedtls\include\psa`

For GSDK v4.0.0 and higher: `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\mbedtls\include\psa`

###### Key Types (heading level 7)

This attribute consists of information about the key: the type, and the size used by this type. The key type and size are encoded in

`psa_key_type_t` and `psa_key_bits_t` objects. The following table describes the type and size in symmetric and asymmetric keys.

<table>
    <thead>
        <tr>
            <th><strong>Category</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Size in Bits</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td rowspan="4">Symmetric Keys</td>
            <td>HMAC key<br>• <code>PSA_KEY_TYPE_HMAC</code></td>
            <td>Non-zero multiple of 8</td>
        </tr>
        <tr>
            <td>Key derivation<br>• <code>PSA_KEY_TYPE_DERIVE</code></td>
            <td>Non-zero multiple of 8</td>
        </tr>
        <tr>
            <td>Cipher/AEAD/MAC key<br>• <code>PSA_KEY_TYPE_AES</code></td>
            <td>
                <ul>
                    <li>128 (16-byte)</li>
                    <li>192 (24-byte)</li>
                    <li>256 (32-byte)</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>ChaCha20/ChaCha20-Poly1305 AEAD key<br>• <code>PSA_KEY_TYPE_CHACHA20</code></td>
            <td>256 (32-byte)</td>
        </tr>
        <tr>
            <td rowspan="4">Elliptic Curve Cryptography (ECC) Keys</td>
            <td>SEC random curves over prime fields<br>• <code>PSA_ECC_FAMILY_SECP_R1</code></td>
            <td>
                <ul>
                    <li>secp192r1 : 192</li>
                    <li>secp224r1 : 224</li>
                    <li>secp256r1 : 256</li>
                    <li>secp384r1 : 384</li>
                    <li>secp521r1 : 521</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>SEC Koblitz curve over prime fields<br>• <code>PSA_ECC_FAMILY_SECP_K1</code></td>
            <td>secp256k1 : 256</td>
        </tr>
        <tr>
            <td>Montgomery curves<br>• <code>PSA_ECC_FAMILY_MONTGOMERY</code></td>
            <td>
                <ul>
                    <li>Curve25519 : 255</li>
                    <li>Curve448 : 448</li>
                </ul>
            </td>
        </tr>
        <tr>
            <td>Twisted Edwards curve<br>• <code>PSA_ECC_FAMILY_TWISTED_EDWARDS</code></td>
            <td>Edwards25519 : 255</td>
        </tr>
    </tbody>
</table>

###### Key Lifetimes (heading level 7)

The lifetime is encoded in the `psa_key_lifetime_t` object (`[31:0]`). This object consists of a persistence level (`psa_key_persistence_t`) and a location indicator (`psa_key_location_t`). The persistent level indicates whether the key is volatile, persistent, or read-only. The location indicator indicates where the key is stored and where operations on the key are performed.

|**Type**|**Persistence Level [7:0]**|**Location Indicator [31:8]**|**Storage**|
|---|---|---|---|
|Volatile Plain Key|PSA_KEY_PERSISTENCE_VOLATILE|Local (0x0)|RAM|
|Persistent Plain Key|PSA_KEY_PERSISTENCE_DEFAULT|Local (0x0)|Flash (2)|
|Volatile Wrapped Key|PSA_KEY_PERSISTENCE_VOLATILE|Secure (0x1) (1)|RAM|
|Persistent Wrapped Key|PSA_KEY_PERSISTENCE_DEFAULT|Secure (0x1) (1)|Flash (2)|
|Public Sign Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|Public Command Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|AES-128 Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|Private Device Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|SE OTP|
|PUF-derived Hardware Unique Key|PSA_KEY_PERSISTENCE_READ_ONLY|Secure (0x1)|PUF Module|

> **Notes**:
> 
> 1. If the key cannot be stored persistently inside the SE, it must be stored in a [wrapped form](https://docs.silabs.com/iot-security/latest/efr32-secure-key-storage/) in RAM or flash such that only the SE can access the key material in plaintext.
> 2. Persistent storage in flash memory is implemented by the [NVM3 driver](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3).

|**Type**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|
|---|---|---|---|
|Volatile Plain Key|Y|Y|Y|
|Persistent Plain Key|Y|Y|Y|
|Volatile Wrapped Key|—|—|HSE-SVH|
|Persistent Wrapped Key|—|—|HSE-SVH|
|Public Sign Key|—|— (1)|Y (2)|
|Public Command Key|—|— (1)|Y (2)|
|AES-128 Key|—|—|Y (3)|
|Private Device Key|—|—|HSE-SVH (2)|
|PUF-derived Hardware Unique Key|—|Y (4)|—|

> **Notes**:
> 
> 1. The PSA Crypto cannot access the Public Sign Key and Public Command Key in the VSE-SVM OTP.
> 2. These keys can only be used for ECDSA (SECP256R1) precomputed hash operations.
> 3. This key can only be used for AES cipher operations. The `SL_SE_BUILTIN_KEY_AES128_ALG` in `sli_se_opaque_types.h` or `sl_psa_values.h` in the Windows folder below defines the default AES cipher algorithm (AES CTR) for this key.
> 
> For GSDK v3.1.x and v3.2.x (`sli_se_opaque_types.h`): `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION>\util\third_party\crypto\sl_component\sl_psa_driver\inc`
> 
> For GSDK v4.0.x (`sli_se_opaque_types.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\sl_component\sl_psa_driver\inc`
> 
> For GSDK v4.1.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\sl_component\sl_psa_driver\inc\public`
> 
> For GSDK v4.2.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_psa_driver\inc\public`
> 
> For GSDK v4.3.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_mbedtls_support\inc`
> 
> 1. The PUF-derived Hardware Unique Key is only available on VSE-SVM devices with a built-in PUF module (e.g., EFR32xG27C). This key can only be used by the [CRYPTOACC](02-device-capability#device-capability) peripheral for [Message Authentication Codes (MAC)](06-migration-guide#message-authentication-codes-mac) and [Key Derivation](06-migration-guide#key-derivation).
> 
> The `SL_CRYPTOACC_BUILTIN_KEY_PUF_ALG` in `sl_psa_values.h` in the Windows folder below defines the default algorithm (PBKDF2 CMAC) for this key.
> 
> For GSDK v4.3.x and higher: `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_compon ent\sl_mbedtls_support\inc`

###### Key Identifiers (heading level 7)

A key identifier can be a permanent name for a persistent key, or a transient reference to a volatile key. Key identifiers are encoded in a

`psa_key_id_t` object. The identifier and [lifetime](#key-lifetimes) of a key indicate the location of the key in storage.

The `sli_se_opaque_types.h` or `sl_psa_values.h` in the Windows folder below includes the defines for SE key identifier macros.

For GSDK v3.1.x and v3.2.x (`sli_se_opaque_types.h`): `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\\<GSDK VERSION\>\util\third_party\crypto\sl_component\sl_psa_driver\inc`

For GSDK v4.0.x (`sli_se_opaque_types.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\ crypto\sl_component\sl_psa_driver\inc`

For GSDK v4.1.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\third_party\crypto\sl_component\sl_psa_driver\inc\public`

For GSDK v4.2.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_psa_driver\inc\public`

For GSDK v4.3.x (`sl_psa_values.h`): `C:\Users\\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\platform\security\sl_component\sl_mbedtls_support\inc`

|**Type**|**Key Identifier (Key ID)**|**SE Key Identifier**|
|---|---|---|
|Volatile Plain Key|0 (Assigned by the PSA Crypto)|—|
|Persistent Plain Key|PSA_KEY_ID_USER_MIN to PSA_KEY_ID_USER_MAX|—|
|Volatile Wrapped Key|0 (Assigned by the PSA Crypto)|—|
|Persistent Wrapped Key|PSA_KEY_ID_USER_MIN to PSA_KEY_ID_USER_MAX|—|
|Public Sign Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_SECUREBOOT_ID|
|Public Command Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_SECUREDEBUG_ID|
|AES-128 Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_AES128_ID|
|Private Device Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID|
|PUF-derived Hardware Unique Key|PSA_KEY_ID_VENDOR_MIN to PSA_KEY_ID_VENDOR_MAX|SL_CRYPTOACC_BUILTIN_KEY_PUF_ID (GSDK ≥ v4.3.0)|

If users are about to use the PSA Crypto for persistent key storage in their application, adhere to the identifier (Key ID) allocation below. The value 0 is reserved as an invalid key identifier.

![image-10](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image10.png)

###### Key Policies (heading level 7)

This attribute consists of usage flags and a specification of the permitted algorithm. The `psa_key_usage_t` encodes the usage flags in a bit-mask. The following table describes three kinds of usage flag in the PSA Crypto.

<table>
    <thead>
        <tr>
            <th><strong>Flag</strong></th>
            <th><strong>Bit-mask</strong></th>
            <th><strong>Description</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Extractable</td>
            <td>PSA_KEY_USAGE_EXPORT</td>
            <td>Permission to export the key.</td>
        </tr>
        <tr>
            <td>Copyable</td>
            <td>PSA_KEY_USAGE_COPY</td>
            <td>Permission to copy the key.</td>
        </tr>
        <tr>
            <td>Other usage</td>
            <td>PSA_KEY_USAGE_ENCRYPT</td>
            <td>Permission for a symmetric encryption operation, for an AEAD encryption-and-authentication operation, or for an asymmetric encryption operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_DECRYPT</td>
            <td>Permission for a symmetric decryption operation, for an AEAD decryption-and-verification operation, or for an asymmetric decryption operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_SIGN_MESSAGE</td>
            <td>Permission for a MAC calculation operation or for an asymmetric message signature operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_VERIFY_MESSAGE</td>
            <td>Permission for a MAC verification operation or for an asymmetric message signature verification operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_SIGN_HASH</td>
            <td>Permission to sign a message hash as part of an asymmetric signature operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_VERIFY_HASH</td>
            <td>Permission to verify a message hash as part of an asymmetric signature verification operation.</td>
        </tr>
        <tr>
            <td>#</td>
            <td>PSA_KEY_USAGE_DERIVE</td>
            <td>Permission to derive other keys from this key.</td>
        </tr>
    </tbody>
</table>

> **Note**: Users can always export a public key or the public part of a key pair regardless of the value of the `PSA_KEY_USAGE_EXPORT` ﬂag.

The `psa_algorithm_t` encodes the permitted algorithm with the key. The [Symmetric Cryptographic Operation](06-migration-guide#symmetric-cryptographic-operation) and [Asymmetric Cryptographic Operation](06-migration-guide#asymmetric-cryptographic-operation) describe which algorithms can apply to the corresponding cryptographic operations.

The application must supply the algorithm to use for the operation. This algorithm is checked against the permitted algorithm policy of the key.

###### Summary (heading level 7)

The `psa_key_attributes_t` object specifies the attributes for the new key during the creation process. The attributes are immutable once the key has been created.

The key identifier and lifetime in the attributes determine the location of the key in storage. The application must set the key type and size, key algorithm policy, and the appropriate key usage flags in the attributes for the key to be used in any cryptographic operations.

The key material can be copied into a new key, which can have a different lifetime or a more restrictive usage policy.

If the key creation succeeds, the PSA Crypto will return an identifier for the newly created key. The PSA Crypto can destroy a key from volatile memory and non-volatile storage [NVM3 object](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3). The destroying process makes the key identifier invalid, and the key identifier must not be used again by the application until it is allocated to a newly created key.

If not necessary, the extractable usage flag (`PSA_KEY_USAGE_EXPORT`) should not be set to allow the key to export in binary format.

###### Key Attributes API

The following table lists the PSA Crypto API for the [key attributes](04-key-management-in-psa-crypto#key-management-in-psa-crypto).

<table>
    <thead>
        <tr>
            <th><strong>API</strong></th>
            <th><strong>Description</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p><code>psa_key_attributes_init(…)</code></p>
            </td>
            <td>
                <p>Initialize the key attributes (<code>psa_key_attributes_t</code>) before calling any function.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_attributes(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key attributes (<code>psa_key_attributes_t</code>) of a key if successful.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_reset_key_attributes(…)</code></p>
            </td>
            <td>
                <p>Reset the key attributes (<code>psa_key_attributes_t</code>) to an initialized state.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_type(…)</code></p>
            </td>
            <td>
                <p>Declare the key type (<code>psa_key_type_t</code>) of a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_type(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key type (<code>psa_key_type_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_bits(…)</code></p>
            </td>
            <td>
                <p>Declare the key size (<code>psa_key_bits_t</code>) of a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_bits(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key size (<code>size_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_usage_flags(…)</code></p>
            </td>
            <td>
                <p>Declare the usage flags (<code>psa_key_usage_t</code>) for a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_usage_flags(…)</code></p>
            </td>
            <td>
                <p>Retrieve the usage flags (<code>psa_key_usage_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_algorithm(…)</code></p>
            </td>
            <td>
                <p>Declare the permitted algorithm policy (<code>psa_algorithm_t</code>) for a key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_algorithm(…)</code></p>
            </td>
            <td>
                <p>Retrieve the algorithm policy (<code>psa_algorithm_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_id(…)</code></p>
            </td>
            <td>
                <p>Declare a key as persistent and set its key identifier (<code>psa_key_id_t</code>).</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_id(…)</code></p>
            </td>
            <td>
                <p>Retrieve the key identifier (<code>psa_key_id_t</code>) from key attributes.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_set_key_lifetime(…)</code></p>
            </td>
            <td>
                <p>Set the location (<code>psa_key_lifetime_t</code>) of a persistent key.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>psa_get_key_lifetime(…)</code></p>
            </td>
            <td>
                <p>Retrieve the lifetime (<code>psa_key_lifetime_t</code>) from key attributes.</p>
            </td>
        </tr>
    </tbody>
</table>

The following sections describe how to use the key attributes API to set up the [storage](04-key-management-in-psa-crypto) for a key. Refer to the quick reference examples in [Symmetric Key](06-migration-guide#symmetric-key) and [Asymmetric Key](06-migration-guide#asymmetric-key) for more details.

**Volatile Plain Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>= 0</td>
            <td><code>PSA_KEY_PERSISTENCE_VOLATILE</code></td>
            <td>Local (0x0)</td>
            <td>
                It is the default setting after calling <code>psa_key_attributes_init()</code>.
                No need to call <code>psa_set_key_id()</code> and <code>psa_set_key_lifetime()</code>.
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
```

**Persistent Plain Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>&gt; 0</td>
            <td><code>PSA_KEY_PERSISTENCE_DEFAULT</code></td>
            <td>Local (0x0)</td>
            <td>
                A non-zero key ID in <code>psa_set_key_id()</code> will change the persistence level from <code>PSA_KEY_PERSISTENCE_VOLATILE</code> to <code>PSA_KEY_PERSISTENCE_DEFAULT</code>.
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
psa_set_key_id(&key_attr, 0x02);
```

**Volatile Wrapped Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>= 0</p>
            </td>
            <td>
                <p><code>PSA_KEY_PERSISTENCE_VOLATILE</code></p>
            </td>
            <td>
                <p>Secure (0x1)</p>
            </td>
            <td>
                <p>Use the <code>psa_set_key_lifetime()</code> to change the location indicator from Local to Secure (0x01).</p>
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, 0x01));
```

**Persistent Wrapped Key**

<table>
    <thead>
        <tr>
            <th><strong>Key ID</strong></th>
            <th><strong>Persistence Level</strong></th>
            <th><strong>Location Indicator</strong></th>
            <th><strong>API Flow</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>&gt; 0</p>
            </td>
            <td>
                <p><code>PSA_KEY_PERSISTENCE_DEFAULT</code></p>
            </td>
            <td>
                <p>Local (0x0)</p>
            </td>
            <td>
                <p>A non-zero key ID in <code>psa_set_key_id()</code> will change the persistence level from <code>PSA_KEY_PERSISTENCE_VOLATILE</code> to <code>PSA_KEY_PERSISTENCE_DEFAULT</code>.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>&gt; 0</p>
            </td>
            <td>
                <p><code>PSA_KEY_PERSISTENCE_DEFAULT</code></p>
            </td>
            <td>
                <p>Secure (0x1)</p>
            </td>
            <td>
                <p>Use the <code>psa_set_key_lifetime()</code> to change the location indicator from Local to Secure (0x01).</p>
            </td>
        </tr>
    </tbody>
</table>

**Example**:

```sh
psa_key_attributes_t key_attr;
key_attr = psa_key_attributes_init();
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attr, 256);
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
psa_set_key_id(&key_attr, 0x02);
psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));
```

> **Note**:
> 
> - The `PSA_KEY_PERSISTENCE_DEFAULT` is equal to `PSA_KEY_LIFETIME_PERSISTENT`.
> - Refer to [Key Identifiers](04-key-management-in-psa-crypto#key-identifiers) for details about the Key ID.

###### Migration Guide

###### System Requirements and Document (heading level 7)

1. Simplicity Studio 5
2. GSDK v3.1.1 (Mbed TLS v2.24.0) or later
3. The latest SE Firmware image and release note can be found in the Windows folder below.  
   - For GSDK v3.1.x and v3.2.x: `C:\SiliconLabs\SimplicityStudio\v5\developer\sdks\gecko_sdk_suite\<GSDK VERSION\>\util\se_release\public`  
   - For GSDK v4.0.0 and higher: `C:\Users\<PC USER NAME\>\SimplicityStudio\SDKs\gecko_sdk\util\se_release\public`
4. PSA Crypto API (aka PSA Cryptography API) document: [ARM](https://arm-software.github.io/psa-api/crypto/)

###### Mbed TLS Versus PSA Crypto API (heading level 7)

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto API</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Key input</p>
            </td>
            <td>
                <p>APIs take key input directly.</p>
            </td>
            <td>
                <p>
                    • APIs do not take key input directly.<br>
                    • Key (identifier) needs to be created or imported before use.<br>
                    • APIs take an identifier if a key is required.
                </p>
            </td>
        </tr>
        <tr>
            <td rowspan="3">
                <p>Symmetric cryptographic operation</p>
            </td>
            <td>
                <p>Individual API (one-shot and streaming) for algorithm-specific functions.</p>
            </td>
            <td>
                <p>
                    • APIs are grouped by algorithm category for one-shot and streaming modes.<br>
                    • The exact algorithm is a parameter (<code>psa_algorithm_t</code>) to the function, not an individual API.
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Except for AEAD (encrypt and decrypt), a one-shot function is not in a pair.</p>
            </td>
            <td>
                <p>Single-part (one-shot) functions are in a pair. For example, compute and verify, or encrypt and decrypt.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Initialization and free a context are required.</p>
            </td>
            <td>
                <p>Initialization and abort an operation are only required in multi-part (streaming) operations.</p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Error code</p>
            </td>
            <td>
                <p>APIs always return an integer.</p>
            </td>
            <td>
                <p>APIs always return <code>psa_status_t</code>.</p>
            </td>
        </tr>
    </tbody>
</table>

###### Migration (heading level 7)

In [Key Handling](#key-handling), [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation), [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) the following items will be considered when migrating from Mbed TLS to PSA Crypto.

1. The algorithms that can be used in a cryptographic operation.
2. The [key attributes](04-key-management-in-psa-crypto#key-management-in-psa-crypto) [type](04-key-management-in-psa-crypto#key-types) and [usage flags](04-key-management-in-psa-crypto#key-policies) for specific [algorithms](04-key-management-in-psa-crypto#key-policies) in the PSA Crypto.
3. Security Software Components.
4. The functions (APIs) for the Mbed TLS and PSA Crypto. For each type of [symmetric cryptographic operation](#symmetric-cryptographic-operation), the functions include:  
   - A pair of single-part (one-shot) functions  
   - A series of functions that implement multi-part (streaming) operations
5. Quick Reference Examples. These examples do not have error checking, but the user should always check the return code ([psa_status_t](https://docs.silabs.com/gecko-platform/latest/service/api/group-error) = `PSA_SUCCESS` or `PSA_ERROR_XXX`) from PSA Crypto to determine whether to use the output parameters in the application.

###### Platform Examples (heading level 7)

Simplicity Studio 5 includes the PSA Crypto platform examples to evaluate the performance on [key handling](#key-handling), [symmetric](#symmetric-cryptographic-operation) and [asymmetric cryptographic operations](#asymmetric-cryptographic-operation), and [X.509 certificate](#x509-certificate).

- Refer to the corresponding `readme` file for details about each PSA Crypto platform example. This file also includes the procedures to create the project and run the example.
- Unless specified in the example, the PSA Crypto platform examples will use the software fallback feature in Mbed TLS if the [cryptography hardware accelerator](02-device-capability#device-capability) of the selected device does not support the corresponding ECC key or algorithm.

The figures in the following sections are based on GSDK v4.1.0. These figures may be different on other versions of the GSDK.

###### Security Software Components (heading level 7)

The `slcp` file for each PSA Crypto platform example defines the software components installed in the project. The following figure shows the installed security software components (under the **Platform → Security** category) in the PSA Crypto ECDH example (`psa_crypto_ecdh.slcp`) on an HSE-SVH device.

![Installed Security Software Components](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image12.png)

The Simplicity IDE uses the installed security software components to automatically generate the configuration files for Mbed TLS (`mbedtls_config_autogen.h`) and PSA Crypto (`psa_crypto_config_autogen.h`) in the `autogen` folder when creating the project.

![Mbed TLS and PSA Crypto Configuration Files](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image13.png)

The user can browse the available security software components (under the **Platform → Security** category) on the target MCU or Wireless SoC if the [**Installed Components**] checkbox is unchecked.

![Available Security Software Components on the Target Device](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image14.png)

The Mbed TLS and PSA Crypto configuration files automatically regenerates when the user installs or uninstalls a security software component in the project.

![Install a Security Software Component](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image15.png)

![Uninstall a Security Software Component](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image16.png)

For a new project (like `empty.slcp`), the required security software components will be automatically added to the project after installing any cryptographic operation in PSA Crypto (like `GCM`) from the user. The `SE Manager` component is only for the HSE devices.

![Security Software Components for PSA Crypt](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image17.png)

If users are about to use the PSA Crypto for persistent key storage (either plain or wrapped) in their application, make sure to add the `PSA Persistent Storage Support (ITS)` component to the project.

![Security Software Component for Persistent Key Storage](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image18.png)

###### PSA Crypto Configuration (heading level 7)

Click **Configuration** in **Installed Components**. Click [**Configure**] to open the Configuration Wizard in Context Menu.

![image19](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image19.png)

Enter the desired values in **PSA User Maximum Open Keys Count** (`SL_PSA_KEY_USER_SLOT_COUNT`) and **PSA Maximum User Persistent Keys Count** (`SL_PSA_ITS_USER_MAX_FILES`) to replace the default values. Click [**X**] to exit.

The default value of **PSA User Maximum Open Keys Count** is equal to 0 if the project installed any Wireless Stack before.

![image20](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image20.png)

The PSA Crypto configuration file (`psa_crypto_config_autogen.h`) in the `autogen` folder [Figure Mbed TLS and PSA Crypto Configuration Files](#security-software-components) includes the definitions for PSA key slot count and maximum PSA ITS files.

```sh
#define MBEDTLS_PSA_KEY_SLOT_COUNT (2 + 1 + SL_PSA_KEY_USER_SLOT_COUNT)
#define SL_PSA_ITS_MAX_FILES (1 + SL_PSA_ITS_USER_MAX_FILES)
```

The first digit in `MBEDTLS_PSA_KEY_SLOT_COUNT` is Wireless Stack (if installed) dependent. The second digit should be 1 for the PSA Crypto.

The first digit in `SL_PSA_ITS_MAX_FILES` is equal to 1 if the project installed the `PSA persistent storage support (ITS)` component [Figure Security Software Component for Persistent Key Storage](#security-software-components) before.

###### Initialization and Random Number Generation (RNG) (heading level 7)

In PSA Crypto, applications must call `psa_crypto_init()` to initialize the library before using any other function. The PSA Crypto initialization includes seeding the pseudo-random generator (CTR-DRBG) with a hardware entropy source during the execution of `psa_crypto_init()`.

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Initialization</p>
            </td>
            <td>
                <p>
                    Initialize CTR-DRBG<br>
                    • <code>void mbedtls_entropy_init(…)</code><br>
                    • <code>void mbedtls_ctr_drbg_init(…)</code><br>
                    • <code>int mbedtls_entropy_add_source(…)</code><br>
                    Seed and set up the CTR-DRBG entropy<br>
                    • <code>int mbedtls_ctr_drbg_seed(…)</code>
                </p>
            </td>
            <td>
                <p>
                    Initialize PSA Crypto<br>
                    • <code>psa_status_t psa_crypto_init(void)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Generate random bytes</p>
            </td>
            <td>
                <p><code>int mbedtls_ctr_drbg_random(…)</code></p>
            </td>
            <td>
                <p><code>psa_status_t psa_generate_random(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Free resources</p>
            </td>
            <td>
                <p>
                    • <code>void mbedtls_ctr_drbg_free(…)</code><br>
                    • <code>void mbedtls_entropy_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>void mbedtls_psa_crypto_free(void)</code></p>
            </td>
        </tr>
    </tbody>
</table>

If a device includes a True Random Number Generator (TRNG) hardware module, the example will use the TRNG as an entropy source to seed the CTR-DRBG. If the device does not incorporate a TRNG, the example will use [RAIL](https://docs.silabs.com/rail/latest/), Non-volatile (NV) seed (requires [NVM3 driver](https://docs.silabs.com/gecko-platform/latest/driver/api/group-nvm3)), or ADC as the entropy source.

|**Device**|**Entropy Source**|
|---|---|
|MCU Series 1 - EFM32JG1, EFM32PG1|NV seed (default) or ADC|
|MCU Series 1 - EFM32JG12, EFM32PG12, EFM32GG11, EFM32GG12, EFM32TG11|TRNG|
|Wireless SoC Series 1 - EFR32xG1, EFR32xG14|RAIL|
|Wireless SoC Series 1 - EFR32xG12, EFR32xG13 (Revision D or later)|TRNG|
|All MCU Series 2 and Wireless SoC Series 2 devices|TRNG|

**Quick Reference Examples**

**PSA Crypto Initialization and Random Number Generation**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  uint8_t rand_buf[32];
  psa_status_t ret;

  // Initialize the PSA Crypto and generate random numbers
  ret = psa_crypto_init();
  ret = psa_generate_random(rand_buf, sizeof(rand_buf));
}
```

###### Key Handling (heading level 7)

The following table describes the main differences in key handling between Mbed TLS and PSA Crypto.

|**Item**|**Mbed TLS**|**PSA Crypto**|
|---|---|---|
|Random Number Generation (RNG)|It requires application code to keep track of RNG.|The core keeps track of RNG.|
|Buffer|It requires dedicated key buffers.|The core manages the key.|
|Key export|The key is exportable.|The usage flag manages this option.|
|Lifetime|It is volatile.|It can be volatile or persistent.|
|Location|Local|Local or Secure|

###### Symmetric Key (heading level 7)

A symmetric key can be used with a block cipher or a stream cipher.

**Algorithms**

Refer to the [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation) section.

**Key Attributes in PSA Crypto**

Refer to the [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation) section.

**Security Software Components**

Refer to the [Symmetric Cryptographic Operation](#symmetric-cryptographic-operation) section.

**Functions**

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Create a random key</p>
            </td>
            <td>
                <p>
                    Generate random numbers to a buffer<br>
                    • <code>int mbedtls_ctr_drbg_random(…)</code><br>
                    Set up a key from a buffer (API is algorithm dependent)<br>
                    • <code>int mbedtls_aes_setkey_enc(…)</code><br>
                    • <code>int mbedtls_aes_setkey_dec(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    • <code>int mbedtls_ccm_setkey(…)</code><br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chacha20_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p>
                    Create a key from randomly generated data<br>
                    • <code>psa_status_t psa_generate_key(…)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Import a key from a buffer</p>
            </td>
            <td>
                <p>
                    API is algorithm dependent<br>
                    • <code>int mbedtls_aes_setkey_enc(…)</code><br>
                    • <code>int mbedtls_aes_setkey_dec(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    • <code>int mbedtls_ccm_setkey(…)</code><br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chacha20_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_import_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Copy a key</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_copy_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Export a key to a buffer</p>
            </td>
            <td>
                <p>The key is always in a buffer.</p>
            </td>
            <td>
                <p><code>psa_status_t psa_export_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Destroy a key</p>
            </td>
            <td>
                <p>Zero the key buffer.</p>
            </td>
            <td>
                <p><code>psa_status_t psa_destroy_key(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The `psa_export_key()` can export a symmetric key in plaintext if the [PSA_KEY_USAGE_EXPORT](04-key-management-in-psa-crypto#key-policies) usage flag is set.

**Quick Reference Examples**

**Symmetric Plain Key Creation and Import**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ecb_key[16] = {0};

  psa_status_t ret;
  psa_key_id_t generate_key_id;
  psa_key_id_t import_key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a AES ECB key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, 128);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);

  // Generate a random volatile plain key for AES ECB
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a volatile plain key for AES ECB
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the volatile plain keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);

  // Generate a random persistent plain key for AES ECB (ID = 0x02)
  psa_set_key_id(&key_attr, 0x02);
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a persistent plain key for AES ECB (ID = 0x03)
  psa_set_key_id(&key_attr, 0x03);
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the persistent plain keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);
}
```

**Symmetric Wrapped Key Creation and Import (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ecb_key[16] = {0};

  psa_status_t ret;
  psa_key_id_t generate_key_id;
  psa_key_id_t import_key_id;
  psa_key_attributes_t key_attr;
  ret = psa_crypto_init();

  // Set up attributes for a AES ECB key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, 128);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
  psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_VOLATILE, 0x01));

  // Generate a random volatile wrapped key for AES ECB
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a volatile wrapped key for AES ECB
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the volatile wrapped keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);

  // Generate a random persistent wrapped key for AES ECB (ID = 0x02)
  psa_set_key_id(&key_attr, 0x02);
  psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));
  ret = psa_generate_key(&key_attr, &generate_key_id);

  // Import a persistent wrapped key for AES ECB (ID = 0x03)
  psa_set_key_id(&key_attr, 0x03);
  psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &import_key_id);

  // Destroy the persistent wrapped keys for AES ECB
  ret = psa_destroy_key(generate_key_id);
  ret = psa_destroy_key(import_key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image21](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image21.png)

The following table describes the implementation status of the PSA Crypto symmetric key platform example.

|**Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|Extractable|Y|Y|Y|—|
|Copyable|Y|Y|Y|The PSA_KEY_USAGE_COPY usage flag does not apply to the wrapped key.|
|Wrapped|—|—|Y|Only on HSE-SVH devices.|
|128-bit|Y|Y|Y|—|
|192-bit|Y|Y|Y|—|
|256-bit|Y|Y|Y|—|

###### Asymmetric Key (heading level 7)

An asymmetric key pair consists of a (secret) private key and a public key (not secret). A public key cryptographic algorithm can be used for key distribution and digital signatures.

**Algorithms**

Refer to the [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) section.

**Key Attributes in PSA Crypto**

Refer to the [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) section.

**Security Software Components**

Refer to the [Asymmetric Cryptographic Operation](#asymmetric-cryptographic-operation) section.

**Functions**

<table>
    <thead>
        <tr>
            <th><strong>Item</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Create a random key</p>
            </td>
            <td>
                <p>
                    ECDH<br>
                    • <code>void mbedtls_ecdh_init(…)</code><br>
                    • <code>int mbedtls_ecp_group_load(…)</code><br>
                    • <code>int mbedtls_ecdh_gen_public(…)</code><br>
                    ECDSA<br>
                    • <code>void mbedtls_ecdsa_init(…)</code><br>
                    • <code>int mbedtls_ecdsa_genkey(…)</code>
                </p>
            </td>
            <td>
                <p>
                    Create a key from randomly generated data<br>
                    • <code>psa_status_t psa_generate_key(…)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Import a private or public key from a buffer</p>
            </td>
            <td>
                <p>
                    • <code>int mbedtls_ecp_point_read_binary(…)</code><br>
                    • <code>int mbedtls_mpi_read_binary(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_import_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Copy a key</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_copy_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Export a private key to a buffer</p>
            </td>
            <td>
                <p>
                    • <code>int mbedtls_ecp_point_write_binary(…)</code><br>
                    • <code>int mbedtls_mpi_write_binary(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_export_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Export a public key to a buffer</p>
            </td>
            <td>
                <p>
                    • <code>int mbedtls_ecp_point_write_binary(…)</code><br>
                    • <code>int mbedtls_mpi_write_binary(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_export_public_key(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Destroy a key</p>
            </td>
            <td>
                <p>
                    ECDH<br>
                    • <code>void mbedtls_ecdh_free(…)</code><br>
                    ECDSA<br>
                    • <code>void mbedtls_ecdsa_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_destroy_key(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - The `psa_import_key()` cannot store a public key in [wrapped](04-key-management-in-psa-crypto) form.
> - The `psa_export_key()` can export a private key in plaintext if the [PSA_KEY_USAGE_EXPORT](04-key-management-in-psa-crypto) usage flag is set.

|**ECC Key**|**Private Key Size (Import and Export)**|**Public Key Size (Import and Export)**|
|---|---|---|
|secp192r1|24-byte|49-byte|
|secp224r1|28-byte|57-byte|
|secp256r1|32-byte|65-byte|
|secp384r1|48-byte|97-byte|
|secp521r1|66-byte|133-byte|
|secp256k1|32-byte|65-byte|
|Curve25519|32-byte|32-byte|
|Curve448|56-byte|56-byte|
|Edwards25519|32-byte|32-byte|

> **Note**:
> 
> - The public key of the `secpxxx` curve is stored in an uncompressed format (prefix `0x04` with the X and Y coordinates).
> - EFR32xG21A/B devices do not support hardware acceleration on the secp224r1 curve.
> - Only the VSE-SVM devices support hardware acceleration on the secp256k1 curve.
> - The secp224r1 and secp256k1 with wrapped keys are not supported yet.

**Quick Reference**

**Examples Asymmetric Key Creation and Import**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  uint8_t public_key[65];         // Uncompressed point format
  size_t pubkey_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Check if there is already a persistent key with the given identifier (ID = 0x02)
  key_attr = psa_key_attributes_init();
  ret = psa_get_key_attributes(0x02, &key_attr);

  if (ret == PSA_ERROR_INVALID_HANDLE) {
    // Key identifier does not exist, set up attributes for a persistent private wrapped key (secp256r1)
    key_attr = psa_key_attributes_init();
    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
    psa_set_key_bits(&key_attr, 256);
    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
    psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);
    psa_set_key_id(&key_attr, 0x02);
    psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_PERSISTENCE_DEFAULT, 0x01));

    // Generate a random persistent private wrapped key (ID = 0x02)
    ret = psa_generate_key(&key_attr, &key_id);

    // Export a public key from a persistent private wrapped key (ID = 0x02)
    ret = psa_export_public_key(0x02, public_key, sizeof(public_key), &pubkey_len);

    // Set up attributes for a public key (secp256r1)
    key_attr = psa_key_attributes_init();
    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
    psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

    // Import a public key
    ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

    // Destroy a persistent private wrapped key (ID = 0x02) and public key
    ret = psa_destroy_key(0x02);
    ret = psa_destroy_key(key_id);
  } else if (ret == PSA_SUCCESS) {
    // Key identifier already exists
    return;
  } else {
      // Unexpected error
    return;
  }
}
```

> **Note**: Remove the code for the `psa_set_key_lifetime()` function to generate a random persistent private plain key on non-HSE-SVH devices.

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image22](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image22.png)

The following table describes the implementation status of the PSA Crypto asymmetric key platform example.

|**ECC Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|Extractable|Y|Y|Y|—|
|Copyable|Y|Y|Y|The PSA_KEY_USAGE_COPY usage flag does not apply to the wrapped key.|
|Wrapped|—|—|Y|Only on HSE-SVH devices.|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Curve25519|Y|Y|Y|Hardware acceleration only on HSE devices.|
|Curve448|—|—|Y|Only on HSE-SVH devices with hardware acceleration.|
|Edwards25519|—|—|Y|Only on HSE devices with hardware acceleration.|

> **Note**:
> 
> - This example does not include secp224r1 and secp256k1.
> - The PSA Crypto does not yet support software fallback on the Curve448 and Edwards25519.
> - The HSE-SVM devices require SE firmware v1.2.11 or higher (EFR32xG21) and v2.1.7 or higher (other HSE devices) to support hardware acceleration on Curve25519 and Edwards25519. This feature also requires GSDK v4.0.1 or higher.

###### Symmetric Cryptographic Operation (heading level 7)

###### Message Digests (heading level 8)

Message digests are designed to protect the integrity of a piece of data or media to detect changes to any part of a message. They are a type of cryptography utilizing hash values that can warn the receiver of any modifications applied to a message transmitted over an insecure channel.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>SHA-1</p>
            </td>
            <td>
                <p><code>MBEDTLS_MD_SHA1</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_SHA_1</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>SHA-2</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_MD_SHA224</code><br>
                    • <code>MBEDTLS_MD_SHA256</code><br>
                    • <code>MBEDTLS_MD_SHA384</code><br>
                    • <code>MBEDTLS_MD_SHA512</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_SHA_224</code><br>
                    • <code>PSA_ALG_SHA_256</code><br>
                    • <code>PSA_ALG_SHA_384</code><br>
                    • <code>PSA_ALG_SHA_512</code>
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_SHA_1|SHA-1|
|PSA_ALG_SHA_224|SHA-224|
|PSA_ALG_SHA_256|SHA-256|
|PSA_ALG_SHA_384|SHA-384|
|PSA_ALG_SHA_512|SHA-512|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_ret(…)</code><br>
                    • <code>int mbedtls_sha256_ret(…)</code><br>
                    • <code>int mbedtls_sha512_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_compute(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_compare(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_md_init(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_sha1_init(…)</code><br>
                    • <code>void mbedtls_sha256_init(…)</code><br>
                    • <code>void mbedtls_sha512_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_hash_operation_t psa_hash_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_setup(…)</code><br>
                    • <code>int mbedtls_md_starts(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_starts_ret(…)</code><br>
                    • <code>int mbedtls_sha256_starts_ret(…)</code><br>
                    • <code>int mbedtls_sha512_starts_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_update(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_update_ret(…)</code><br>
                    • <code>int mbedtls_sha256_update_ret(…)</code><br>
                    • <code>int mbedtls_sha512_update_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_update(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_finish(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_finish_ret(…)</code><br>
                    • <code>int mbedtls_sha256_finish_ret(…)</code><br>
                    • <code>int mbedtls_sha512_finish_ret(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_verify(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_md_free(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_sha1_free(…)</code><br>
                    • <code>void mbedtls_sha256_free(…)</code><br>
                    • <code>void mbedtls_sha512_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_abort(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_md_clone(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_sha1_clone(…)</code><br>
                    • <code>int mbedtls_sha256_clone(…)</code><br>
                    • <code>int mbedtls_sha512_clone(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_hash_clone(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The multi-part operation allows the data to be processed for message digest in fragments instead of all at once.

**Quick Reference Examples**

**SHA-256 (One-shot)**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  char test_msg[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
  uint8_t expect_sha256_hash[] = {
    0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
  };

  uint8_t hash_buf[32];
  size_t hash_len;
  psa_status_t ret;

  ret = psa_crypto_init();

  // Calculate the hash of a message
  ret = psa_hash_compute(PSA_ALG_SHA_256,
                        (uint8_t *)test_msg,
                        sizeof(test_msg) - 1,
                        hash_buf,
                        sizeof(hash_buf),
                        &hash_len);

  // Calculate the hash of a message and compare it with a reference value
  ret = psa_hash_compare(PSA_ALG_SHA_256,
                        (uint8_t *)test_msg,
                        sizeof(test_msg) - 1,
                        expect_sha256_hash,
                        sizeof(expect_sha256_hash));
}
```

**SHA-256 (Streaming)**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  char test_msg[] = {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"};
  uint8_t hash_buf[32];
  size_t hash_len;
  uint32_t hash_total;
  uint32_t stream_block_size = 16;            // Block size for streaming

  psa_status_t ret;
  psa_hash_operation_t hash_op;
  psa_hash_operation_t verify_op;

  ret = psa_crypto_init();

  hash_op = psa_hash_operation_init();
  ret = psa_hash_setup(&hash_op, PSA_ALG_SHA_256);

  // Streaming block
  hash_total = 0;
  while ((sizeof(test_msg) - 1 - hash_total) > stream_block_size) {
  ret = psa_hash_update(&hash_op, (uint8_t *)(test_msg + hash_total), stream_block_size);
  hash_total += stream_block_size;
  }
  ret = psa_hash_update(&hash_op, (uint8_t *)(test_msg + hash_total), sizeof(test_msg) -1 - hash_total);

  // Generate hash and verify
  // Expected hash:
  // 24 8d 6a 61 d2 06 38 b8 e5 c0 26 93 0c 3e 60 39 a3 3c e4 59 64 ff 21 67 f6 ec ed d4 19 db 06 c1
  verify_op = psa_hash_operation_init();
  ret = psa_hash_clone(&hash_op, &verify_op);
  ret = psa_hash_finish(&hash_op, hash_buf, sizeof(hash_buf), &hash_len);
  ret = psa_hash_verify(&verify_op, hash_buf, hash_len);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image23](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image23.png)

The following table describes the implementation status of the PSA Crypto hash platform example.

|**Algorithm**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|SHA-1|Y|Y|Y|—|
|SHA-224|Y|Y|Y|—|
|SHA-256|Y|Y|Y|—|
|SHA-384|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|SHA-512|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|

###### Message Authentication Codes (MAC) (heading level 7)

A Message Authentication Code (MAC), sometimes known as a tag, is a short piece of information used to confirm that the message came from the stated sender (its authenticity) and has not been changed.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HMAC</p>
            </td>
            <td>
                <p><code>• MBEDTLS_MD_SHA1</code><br><code>• MBEDTLS_MD_SHA224</code><br><code>• MBEDTLS_MD_SHA256</code><br><code>• MBEDTLS_MD_SHA384</code><br><code>• MBEDTLS_MD_SHA512</code></p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_1)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_HMAC(PSA_ALG_SHA_512)</code><br>
                    • <code>PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)</code><br>
                    • <code>PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_HMAC(hash_alg))</code><br>
                    • <code>PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CMAC</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_ECB</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_CMAC</code><br>
                    • <code>PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)</code><br>
                    • <code>PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_CMAC)</code><br>
                    • <code>PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)</code>
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>•PSA_ALG_HMAC(PSA_ALG_SHA_1)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_224)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_256)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_384)<br><br>
                •PSA_ALG_HMAC(PSA_ALG_SHA_512)<br><br>
                •PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)<br><br>
                •PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_HMAC(hash_alg))<br><br>
                •PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)
            </td>
            <td>PSA_KEY_TYPE_HMAC</td>
            <td>Multiple of 8</td>
            <td rowspan="2">•PSA_KEY_USAGE_SIGN_MESSAGE<br><br>
                •PSA_KEY_USAGE_VERIFY_MESSAGE
            </td>
        </tr>
        <tr>
            <td>•PSA_ALG_CMAC<br><br>
                •PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)<br><br>
                •PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_CMAC)<br><br>
                •PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)
            </td>
            <td>PSA_KEY_TYPE_AES</td>
            <td>•128 (16-byte)<br><br>
                •192 (24-byte)<br><br>
                •256 (32-byte)
            </td>
        </tr>
    </tbody>
</table>

> **Note**: For GSDK lower than v4.1.0, use usage flag `PSA_KEY_USAGE_SIGN_HASH` and `PSA_KEY_USAGE_VERIFY_HASH` instead of `PSA_KEY_USAGE_SIGN_MESSAGE` and `PSA_KEY_USAGE_VERIFY_MESSAGE`.

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_HMAC(PSA_ALG_SHA_1)|HMAC and SHA-1|
|PSA_ALG_HMAC(PSA_ALG_SHA_224)|HMAC and SHA-224|
|PSA_ALG_HMAC(PSA_ALG_SHA_256)|HMAC and SHA-256|
|PSA_ALG_HMAC(PSA_ALG_SHA_384)|HMAC and SHA-384|
|PSA_ALG_HMAC(PSA_ALG_SHA_512)|HMAC and SHA-512|
|PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)|HMAC and SHA-X|
|PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_HMAC(hash_alg))|HMAC and SHA-X|
|PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)|HMAC and SHA-X|
|PSA_ALG_CMAC|CMAC|
|PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)|CMAC|
|PSA_ALG_FULL_LENGTH_MAC(PSA_ALG_CMAC)|CMAC|
|PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)|CMAC|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_compute(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_verify(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>void mbedtls_md_init(…)</code><br>
                    • <code>int mbedtls_md_setup(…)</code><br>
                    CMAC<br>
                    • <code>void mbedtls_cipher_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_mac_operation_t psa_mac_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac_starts(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_sign_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_verify_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac_update(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac_update(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_update(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>int mbedtls_md_hmac_finish(…)</code><br>
                    CMAC<br>
                    • <code>int mbedtls_cipher_cmac_finish(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_sign_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_verify_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    HMAC<br>
                    • <code>void mbedtls_md_free(…)</code><br>
                    CMAC<br>
                    • <code>void mbedtls_cipher_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_mac_abort(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The multi-part operation allows the data to be processed for MAC in fragments instead of all at once.

**Quick Reference Examples**

**CMAC (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t cmac_key[] = {
    0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
  };
  uint8_t cmac_msg[] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11
  };
  uint8_t mac_buf[16];
  size_t mac_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a CMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC);

  // Import a volatile plain key for CMAC
  ret = psa_import_key(&key_attr, cmac_key, sizeof(cmac_key), &key_id);

  // Calculate the CMAC MAC of a message
  // Expected CMAC MAC: aa f3 d8 f1 de 56 40 c2 32 f5 b1 69 b9 c9 11 e6
  ret = psa_mac_compute(key_id, PSA_ALG_CMAC,
                        cmac_msg, sizeof(cmac_msg),
                        mac_buf, sizeof(mac_buf), &mac_len);

  // Verify the CMAC MAC of a message
  ret = psa_mac_verify(key_id, PSA_ALG_CMAC,
                        cmac_msg, sizeof(cmac_msg),
                        mac_buf, mac_len);

  // Destroy a volatile plain key for CMACss
  ret = psa_destroy_key(key_id);
}
```

> **Note**: There are two ways to change the CMAC MAC length (default 16 bytes).
> 
> 1. Replace all MAC algorithm `PSA_ALG_CMAC` with `PSA_ALG_TRUNCATED_MAC``(PSA_ALG_CMAC, mac_length)` for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_CMAC` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC)` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)` to set the minimum MAC length (≥ 4) in bytes. Replace the MAC algorithm `PSA_ALG_CMAC` in `psa_mac_compute()` and `psa_mac_verify()` with `PSA_ALG_TRUNCATED_MAC``(PSA_ALG_CMAC, mac_length)` to set the desired MAC length (≥ `min_mac_length` and ≤ `PSA_MAC_LENGTH``(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC))` in bytes.

**HMAC SHA-256 (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t hmac_key[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t hmac_msg[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t mac_buf[32];
  size_t mac_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a HMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_HMAC);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));

  // Import a volatile plain key for HMAC
  ret = psa_import_key(&key_attr, hmac_key, sizeof(hmac_key), &key_id);

  // Calculate the HMAC MAC of a message
  // Expected HMAC MAC:
  // fb 5b 26 22 9c 20 b7 ed 86 67 06 a2 fb fa e6 7e 3f 40 4b b6 ab e7 7f f4 50 63 a4 59 a4 29 24 a4
  ret = psa_mac_compute(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256),
                        hmac_msg, sizeof(hmac_msg),
                        mac_buf, sizeof(mac_buf), &mac_len);
  // Verify the HMAC MAC of a message
  ret = psa_mac_verify(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256),
                        hmac_msg, sizeof(hmac_msg),
                        mac_buf, mac_len);

  // Destroy a volatile plain key for HMAC
  ret = psa_destroy_key(key_id);
}
```

> **Notes**: There are two ways to change the HMAC MAC length (default is `hash_alg` dependent).
> 
> 1. Replace all MAC algorithm `PSA_ALG_HMAC(hash_alg)` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg)`, `mac_length`) for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(hash_alg))` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)` to set the minimum MAC length (≥ 4) in bytes.
> 
> Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in `psa_mac_compute()` and `psa_mac_verify()` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)` to set the desired MAC length `(≥ min_mac_length` and `≤ PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 256, PSA_ALG_HMAC(hash_alg)))` in bytes.

**CMAC (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t cmac_key[] = {
    0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4
  };
  uint8_t cmac_msg[] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11
  };
  uint8_t mac_buf[16];
  size_t mac_len;
  uint32_t mac_total;
  uint32_t stream_block_size = 8;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_mac_operation_t mac_op;

  ret = psa_crypto_init();

  // Set up attributes for a CMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC);

  // Import a volatile plain key for CMAC
  ret = psa_import_key(&key_attr, cmac_key, sizeof(cmac_key), &key_id);

  // Stream message and calculate the CMAC MAC
  // Expected CMAC MAC: aa f3 d8 f1 de 56 40 c2 32 f5 b1 69 b9 c9 11 e6
  mac_op = psa_mac_operation_init();
  ret = psa_mac_sign_setup(&mac_op, key_id, PSA_ALG_CMAC);
  mac_total = 0;        // Streaming block
  while ((sizeof(cmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, cmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, cmac_msg + mac_total, sizeof(cmac_msg) - mac_total);
  ret = psa_mac_sign_finish(&mac_op, mac_buf, sizeof(mac_buf), &mac_len);

  // Stream message and verify the CMAC MAC
  mac_op = psa_mac_operation_init();
  ret = psa_mac_verify_setup(&mac_op, key_id, PSA_ALG_CMAC);
  mac_total = 0;        // Streaming block
  while ((sizeof(cmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, cmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, cmac_msg + mac_total, sizeof(cmac_msg) - mac_total);
  ret = psa_mac_verify_finish(&mac_op, mac_buf, mac_len);

  // Destroy a volatile plain key for CMAC
  ret = psa_destroy_key(key_id);
}
```

> **Notes**: There are two ways to change the CMAC MAC length (default 16 bytes).
> 
> 1. Replace all MAC algorithm `PSA_ALG_CMAC` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)` for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_CMAC` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_CMAC)` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_CMAC, min_mac_length)` to set the minimum MAC length (≥ 4) in bytes.
> 
> Replace the MAC algorithm `PSA_ALG_CMAC` in `psa_mac_sign_setup()` and `psa_mac_verify_setup()` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_CMAC, mac_length)` to set the desired MAC length `(≥ min_mac_length and ≤ PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC))` in bytes.

**HMAC SHA-256 (Streaming)**

```c++
#include "psa/crypto.h"
void app_process_action(void)
{
  uint8_t hmac_key[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t hmac_msg[] = {
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
  };
  uint8_t mac_buf[32];
  size_t mac_len;
  uint32_t mac_total;
  uint32_t stream_block_size = 8;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_mac_operation_t mac_op;

  ret = psa_crypto_init();

  // Set up attributes for a HMAC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_HMAC);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));

  // Import a volatile plain key for HMAC
  ret = psa_import_key(&key_attr, hmac_key, sizeof(hmac_key), &key_id);

  // Stream message and calculate the HMAC MAC
  // Expected HMAC MAC:
  // fb 5b 26 22 9c 20 b7 ed 86 67 06 a2 fb fa e6 7e 3f 40 4b b6 ab e7 7f f4 50 63 a4 59 a4 29 24 a4
  mac_op = psa_mac_operation_init();
  ret = psa_mac_sign_setup(&mac_op, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
  mac_total = 0; // Streaming block
  while ((sizeof(hmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, hmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, hmac_msg + mac_total, sizeof(hmac_msg) - mac_total);
  ret = psa_mac_sign_finish(&mac_op, mac_buf, sizeof(mac_buf), &mac_len);

  // Stream message and verify the HMAC MAC
  mac_op = psa_mac_operation_init();
  ret = psa_mac_verify_setup(&mac_op, key_id, PSA_ALG_HMAC(PSA_ALG_SHA_256));
  mac_total = 0; // Streaming block
  while ((sizeof(hmac_msg) - mac_total) > stream_block_size) {
    ret = psa_mac_update(&mac_op, hmac_msg + mac_total, stream_block_size);
    mac_total += stream_block_size;
  }
  ret = psa_mac_update(&mac_op, hmac_msg + mac_total, sizeof(hmac_msg) - mac_total);
  ret = psa_mac_verify_finish(&mac_op, mac_buf, mac_len);

  // Destroy a volatile plain key for HMAC
  ret = psa_destroy_key(key_id);
}
```

> **Notes**: There are two ways to change the HMAC MAC length (default is `hash_alg` dependent).
> 
> 1. Replace all MAC algorithm `PSA_ALG_HMAC(hash_alg)` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)` for the desired size (≥ 4) of the MAC in bytes.
> 2. Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_HMAC(hash_alg))` function with `PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(PSA_ALG_HMAC(hash_alg), min_mac_length)` to set the minimum MAC length (≥ 4) in bytes.
> 
> Replace the MAC algorithm `PSA_ALG_HMAC(hash_alg)` in `psa_mac_sign_setup()` and `psa_mac_verify_setup()` with `PSA_ALG_TRUNCATED_MAC(PSA_ALG_HMAC(hash_alg), mac_length)` to set the desired MAC length `(≥ min_mac_length and ≤ PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 256, PSA_ALG_HMAC(hash_alg)))` in bytes.

**PSA Crypto Platform Example**

Click the View Project Documentation link to open the readme file.

![image24](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image24.png)

The following table describes the implementation status of the PSA Crypto MAC platform example.

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Series 1</strong></th>
            <th><strong>Series 2 - VSE</strong></th>
            <th><strong>Series 2 - HSE</strong></th>
            <th>Remark</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HMAC</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>
                    - Hardware acceleration only on Series 2 devices.<br>
                    - HMAC streaming with wrapped key is not supported yet.
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CMAC</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Y</p>
            </td>
            <td>
                <p>Series 1 devices do not support a 192-bit key.</p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - The MAC platform example uses the default MAC length.
> - The single-part MAC functions are only available on GSDK v4.0.0 and higher.

###### Unauthenticated Ciphers (heading level 8)

The unauthenticated cipher API is for use cases where the data integrity and authenticity are guaranteed by non-cryptographic means.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>AES ECB</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_ECB</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_ECB</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_ECB_NO_PADDING</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CBC</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_CBC</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_CBC</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_CBC</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_CBC_NO_PADDING</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CFB</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_CFB128</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_CFB128</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_CFB128</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_CFB</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CTR</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_CIPHER_AES_128_CTR</code><br>
                    • <code>MBEDTLS_CIPHER_AES_192_CTR</code><br>
                    • <code>MBEDTLS_CIPHER_AES_256_CTR</code>
                </p>
            </td>
            <td>
                <p><code>PSA_ALG_CTR</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CHACHA20</p>
            </td>
            <td>
                <p><code>MBEDTLS_CIPHER_CHACHA20</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_STREAM_CIPHER</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>PSA_ALG_ECB_NO_PADDING</code></td>
            <td rowspan="4"><code>PSA_KEY_TYPE_AES</code></td>
            <td rowspan="4">128 (16-byte)<br>192 (24-byte)<br>256 (32-byte)</td>
            <td rowspan="5"><code>PSA_KEY_USAGE_ENCRYPT</code><br><code>PSA_KEY_USAGE_DECRYPT</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CBC_NO_PADDING</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CFB</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CTR</code></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_STREAM_CIPHER</code></td>
            <td><code>PSA_KEY_TYPE_CHACHA20</code></td>
            <td>256 (32-byte)</td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm and Built-in Key**|**Security Software Components**|
|---|---|
|PSA_ALG_ECB_NO_PADDING|ECB Mode|
|PSA_ALG_CBC_NO_PADDING|CBC Mode|
|PSA_ALG_CFB|CFB Mode|
|PSA_ALG_CTR|CTR Mode|
|PSA_ALG_STREAM_CIPHER|Chacha20 Stream Cipher|

|**Built-in Key**|**Security Software Components**|
|---|---|
|secp256r1 keys in SE OTP|Built-In Keys|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_crypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_aes_crypt_ecb(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cbc(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cfb128(…)</code><br>
                    • <code>int mbedtls_aes_crypt_ctr(…)</code><br>
                    • <code>int mbedtls_chacha20_crypt(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_encrypt(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_crypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_aes_crypt_ecb(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cbc(…)</code><br>
                    • <code>int mbedtls_aes_crypt_cfb128(…)</code><br>
                    • <code>int mbedtls_aes_crypt_ctr(…)</code><br>
                    • <code>int mbedtls_chacha20_crypt(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_decrypt(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - The `psa_cipher_encrypt()` encrypts a message with a random initialization vector (IV). The output of this function is the IV followed by the ciphertext. Use the multi-part operations to manage the IV and ciphertext separately.
> - The input to `psa_cipher_decrypt()` must contain the IV followed by the ciphertext, as output by` psa_cipher_encrypt()`. Use the multi-part operations to decrypt data that is not in the expected input format.

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_init(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_chacha20_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_cipher_operation_t psa_cipher_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_encrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_generate_iv(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_decrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_set_iv(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_update(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_update(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_update(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p><code>int mbedtls_cipher_finish(…)</code></p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_free(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_chacha20_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_cipher_abort(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The following situations require the use of a multi-part operation:
> 
> - Processing messages that cannot be assembled in memory.
> - Using a deterministic initialization vector (IV) for unauthenticated encryption.
> - Providing the IV separately for unauthenticated encryption or decryption.

**Quick Reference Examples**

**AES ECB (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ecb_key[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
  };
  uint8_t plain_msg_buf[] = {
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
  };
  uint8_t cipher_buf[16];
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES ECB key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);

  // Import a volatile plain key for AES ECB
  ret = psa_import_key(&key_attr, aes_ecb_key, sizeof(aes_ecb_key), &key_id);
  
  // AES ECB encryption and decryption
  // Expected ciphertext: 69 c4 e0 d8 6a 7b 04 30 d8 cd b7 80 70 b4 c5 5a
  // Single-part
  ret = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_ECB_NO_PADDING,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_ECB_NO_PADDING);
  ret = psa_cipher_update(&cipher_op, plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_ECB_NO_PADDING);
  ret = psa_cipher_update(&cipher_op, cipher_buf, sizeof(cipher_buf),
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);

  // Destroy a volatile plain key for AES ECB
  ret = psa_destroy_key(key_id);
}
```

**AES CFB (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_cbc_key[] = {
    0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
  };
  uint8_t iv_buf[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
  };
  uint8_t plain_msg_buf[] = {
    0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
  };
  uint8_t cipher_buf[32]; // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES CBC key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CBC_NO_PADDING);

  // Import a volatile plain key for AES CBC
  ret = psa_import_key(&key_attr, aes_cbc_key, sizeof(aes_cbc_key), &key_id);

  // AES CBC encryption and decryption
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(key_id, PSA_ALG_CBC_NO_PADDING,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_CBC_NO_PADDING,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  // Expected ciphertext: 76 49 ab ac 81 19 b2 46 ce e9 8e 9b 12 e9 19 7d
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_CBC_NO_PADDING);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_CBC_NO_PADDING);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);

  // Destroy a volatile plain key for AES CBC
  ret = psa_destroy_key(key_id);
}
```

> **Note**: The multi-part operations provide the IV separately for AES CFB encryption or decryption.

**AES CTR (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t aes_ctr_key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  };
  uint8_t iv_buf[] = {
    0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70
  };
  uint8_t plain_msg_buf[] = {
    0xd8, 0x65, 0xc9, 0xcd, 0xea, 0x33, 0x56, 0xc5, 0x48, 0x8e, 0x7b, 0xa1, 0x5e, 0x84, 0xf4, 0xeb,
    0xa3, 0xb8, 0x25, 0x9c, 0x05, 0x3f, 0x24, 0xce, 0x29, 0x67, 0x22, 0x1c, 0x00, 0x38, 0x84, 0xd7,
    0x9d, 0x4c, 0xa4, 0x87, 0x7f, 0xfa, 0x4b, 0xc6, 0x87, 0xc6, 0x67, 0xe5, 0x49, 0x5b, 0xcf, 0xec,
    0x12, 0xf4, 0x87, 0x17, 0x32, 0xaa, 0xe4, 0x5a, 0x11, 0x06, 0x76, 0x11, 0x3d, 0xf9, 0xe7, 0xda
  };
  uint8_t cipher_buf[80]; // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES CTR key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Import a volatile plain key for AES CTR
  ret = psa_import_key(&key_attr, aes_ctr_key, sizeof(aes_ctr_key), &key_id);

  // AES CTR encryption and decryption
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(key_id, PSA_ALG_CTR,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_CTR,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);
  // Multi-part
  // Expected ciphertext:
  // b6 72 f2 af 6a cc 20 ae ee 1a d8 14 12 8c 31 8b 95 5b be 80 5b 38 92 49 89 76 00 f5 20 74 54 32
  // 7d 6d 0f b4 ac 0a 94 f3 7c a0 9e 45 05 33 98 fe a8 9c 20 0a d3 58 12 6d 9e 89 a4 05 26 5c 96 e7
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);
  // Destroy a volatile plain key for AES CTR
  ret = psa_destroy_key(key_id);
}
```

> **Note**: The multi-part operations provide the IV separately for AES CTR encryption or decryption.

**CHACHA20 (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t chacha20_key[32] = {0};
  uint8_t iv_buf[12] = {0};
  uint8_t plain_msg_buf[64] = {0};
  uint8_t cipher_buf[76];         // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // Set up attributes for a CHACHA20 key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_CHACHA20);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_STREAM_CIPHER);

  // Import a volatile plain key for CHACHA20
  ret = psa_import_key(&key_attr, chacha20_key, sizeof(chacha20_key), &key_id);

  // CHACHA20 encryption and decryption
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(key_id, PSA_ALG_STREAM_CIPHER,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(key_id, PSA_ALG_STREAM_CIPHER,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  // Expected ciphertext:
  // 76 b8 e0 ad a0 f1 3d 90 40 5d 6a e5 53 86 bd 28 bd d2 19 b8 a0 8d ed 1a a8 36 ef cc 8b 77 0d c7
  // da 41 59 7c 51 57 48 8d 77 24 e0 3f b8 d8 4a 37 6a 43 b8 f4 15 18 a1 1c c3 87 b6 69 b2 ee 65 86
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_STREAM_CIPHER);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_STREAM_CIPHER);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);

  // Destroy a volatile plain key for CHACHA20
  ret = psa_destroy_key(key_id);
}
```

> **Note**: The multi-part operations provide the IV separately for CHACHA20 encryption or decryption.

**AES CTR (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
 uint8_t aes_ctr_key[] = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
 };
 uint8_t iv_buf[] = {
   0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70, 0x22, 0x22, 0x1a, 0x70
 };
 uint8_t plain_msg_buf[] = {
  0xd8, 0x65, 0xc9, 0xcd, 0xea, 0x33, 0x56, 0xc5, 0x48, 0x8e, 0x7b, 0xa1, 0x5e, 0x84, 0xf4, 0xeb,
  0xa3, 0xb8, 0x25, 0x9c, 0x05, 0x3f, 0x24, 0xce, 0x29, 0x67, 0x22, 0x1c, 0x00, 0x38, 0x84, 0xd7,
  0x9d, 0x4c, 0xa4, 0x87, 0x7f, 0xfa, 0x4b, 0xc6, 0x87, 0xc6, 0x67, 0xe5, 0x49, 0x5b, 0xcf, 0xec,
  0x12, 0xf4, 0x87, 0x17, 0x32, 0xaa, 0xe4, 0x5a, 0x11, 0x06, 0x76, 0x11, 0x3d, 0xf9, 0xe7, 0xda
 };
 uint8_t cipher_buf[64];
 size_t out_len;
 uint32_t out_total;
 uint32_t stream_block_size = 14;                 // Block size for streaming

 psa_status_t ret;
 psa_key_id_t key_id;
 psa_key_attributes_t key_attr;
 psa_cipher_operation_t cipher_op;

 ret = psa_crypto_init();

 // Set up attributes for a AES CTR key
 key_attr = psa_key_attributes_init();
 psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
 psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

 // Import a volatile plain key for AES CTR
 ret = psa_import_key(&key_attr, aes_ctr_key, sizeof(aes_ctr_key), &key_id);

 // AES CTR stream encryption and decryption
 // Expected ciphertext:
 // b6 72 f2 af 6a cc 20 ae ee 1a d8 14 12 8c 31 8b 95 5b be 80 5b 38 92 49 89 76 00 f5 20 74 54 32
 // 7d 6d 0f b4 ac 0a 94 f3 7c a0 9e 45 05 33 98 fe a8 9c 20 0a d3 58 12 6d 9e 89 a4 05 26 5c 96 e7
 cipher_op = psa_cipher_operation_init();
 ret = psa_cipher_encrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
 ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));

 out_total = 0; // Streaming block
 while ((sizeof(plain_msg_buf) - out_total) > stream_block_size) {
   ret = psa_cipher_update(&cipher_op,
                            plain_msg_buf + out_total, stream_block_size,
                            cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                            &out_len);
  out_total += out_len;
 }
  ret = psa_cipher_update(&cipher_op, // Last block
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
  out_total += out_len;

 ret = psa_cipher_finish(&cipher_op,
                        cipher_buf + out_total,
                        sizeof(cipher_buf) - out_total,
                        &out_len);

 cipher_op = psa_cipher_operation_init();
 ret = psa_cipher_decrypt_setup(&cipher_op, key_id, PSA_ALG_CTR);
 ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));

 out_total = 0; // Streaming block
 while ((sizeof(cipher_buf) - out_total) > stream_block_size) {
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf + out_total, stream_block_size,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
  out_total += out_len;
 }

  ret = psa_cipher_update(&cipher_op, // Last block
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
  out_total += out_len;

  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_total,
                          sizeof(plain_msg_buf) - out_total,
                          &out_len);

 // Destroy a volatile plain key for AES CTR
 ret = psa_destroy_key(key_id);
}
```

**AES CTR with Built-in AES-128 Key (HSE only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t iv_buf[16] = {0};
  uint8_t plain_msg_buf[16] = {0};
  uint8_t cipher_buf[32]; // Random IV + Ciphertext for single-part
  size_t out_len;

  psa_status_t ret;
  psa_cipher_operation_t cipher_op;

  ret = psa_crypto_init();

  // AES CTR encryption and decryption with built-in AES-128 key
  // ret = -140 (PSA_ERROR_DOES_NOT_EXIST) if the AES-128 key has not been provisioned
  // Single-part - Random IV generated during encryption is embedded in the ciphertext buffer
  ret = psa_cipher_encrypt(SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf), &out_len);

  ret = psa_cipher_decrypt(SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR,
                          cipher_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf), &out_len);

  // Multi-part
  // Built-in AES-128 key: 81 a5 e2 1f a1 52 86 f1 df 44 5c 2c c1 20 fa 3f
  // Expected ciphertext: 66 d2 0f 99 65 3e a8 d0 83 05 a6 39 d4 4e 98 a6
  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_encrypt_setup(&cipher_op, SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_buf, sizeof(cipher_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          cipher_buf + out_len,
                          sizeof(cipher_buf) - out_len,
                          &out_len);

  cipher_op = psa_cipher_operation_init();
  ret = psa_cipher_decrypt_setup(&cipher_op, SL_SE_BUILTIN_KEY_AES128_ID, PSA_ALG_CTR);
  ret = psa_cipher_set_iv(&cipher_op, iv_buf, sizeof(iv_buf));
  ret = psa_cipher_update(&cipher_op,
                          cipher_buf, sizeof(plain_msg_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
  ret = psa_cipher_finish(&cipher_op,
                          plain_msg_buf + out_len,
                          sizeof(plain_msg_buf) - out_len,
                          &out_len);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image25](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image25.png)

The following table describes the implementation status of the PSA Crypto cipher platform example.

|**Algorithm/Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|AES ECB|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES CBC|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES CFB|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES CTR|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|CHACHA20|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|AES-128 Key|—|—|Y|—|

> **Note**: The single-part unauthenticated cipher functions are only available on GSDK v4.0.0 and higher.

###### Authenticated Encryption with Associated Data (AEAD) (heading level 8)

The authenticated encryption with associated data (AEAD) is a form of encryption that simultaneously assures the confidentiality and authenticity of data.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>AES GCM</p>
            </td>
            <td>
                <p>
                    • MBEDTLS_CIPHER_AES_128_GCM<br>
                    • MBEDTLS_CIPHER_AES_192_GCM<br>
                    • MBEDTLS_CIPHER_AES_256_GCM
                </p>
            </td>
            <td>
                <p>
                    • PSA_ALG_GCM<br>
                    • PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_length)<br>
                    • PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(PSA_ALG_GCM)<br>
                    • PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, min_tag_length)
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>AES CCM</p>
            </td>
            <td>
                <p>
                    • MBEDTLS_CIPHER_AES_128_CCM<br>
                    • MBEDTLS_CIPHER_AES_192_CCM<br>
                    • MBEDTLS_CIPHER_AES_256_CCM
                </p>
            </td>
            <td>
                <p>
                    • PSA_ALG_CCM<br>
                    • PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length)<br>
                    • PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(PSA_ALG_CCM)<br>
                    • PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, min_tag_length)
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>CHACHA20_POLY1305</p>
            </td>
            <td>
                <p>MBEDTLS_CIPHER_CHACHA20_POLY1305</p>
            </td>
            <td>
                <p>PSA_ALG_CHACHA20_POLY1305</p>
            </td>
        </tr>
    </tbody>
</table>

|**Algorithm**|**Nonce Length (Bytes)**|**Authentication Tag Length (Bytes)**|
|---|---|---|
|AES GCM|1 - 16 (Default 12)|4, 8, 12, 13, 14, 15, and 16 (Default)|
|AES CCM|7 - 13|4, 6, 8, 10, 12, 14, and 16 (Default)|
|CHACHA20_POLY1305|12|16|

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <code>PSA_ALG_GCM</code> or<br>
                <code>PSA_ALG_AEAD_WITH_*(PSA_ALG_GCM…)</code>
            </td>
            <td rowspan="2"><code>PSA_KEY_TYPE_AES</code></td>
            <td>128 (16-byte)<br>192 (24-byte)<br>256 (32-byte)</td>
            <td rowspan="3">
                <code>PSA_KEY_USAGE_ENCRYPT</code><br>
                <code>PSA_KEY_USAGE_DECRYPT</code>
            </td>
        </tr>
        <tr>
            <td>
                <code>PSA_ALG_CCM</code> or<br>
                <code>PSA_ALG_AEAD_WITH_*(PSA_ALG_CCM…)</code>
            </td>
        </tr>
        <tr>
            <td><code>PSA_ALG_CHACHA20_POLY1305</code></td>
            <td><code>PSA_KEY_TYPE_CHACHA20</code></td>
            <td>256 (32-byte)</td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_GCM or PSA_ALG_AEAD_WITH_*(PSA_ALG_GCM…)|GCM (12-byte IV) or GCM with Non-Recommended IV Lengths|
|PSA_ALG_CCM or PSA_ALG_AEAD_WITH_*(PSA_ALG_CCM…)|CCM Mode|
|PSA_ALG_CHACHA20_POLY1305|ChachaPoly|

**Single-Part Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_auth_encrypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_ccm_encrypt_and_tag(…)</code><br>
                    • <code>int mbedtls_gcm_crypt_and_tag(…)</code><br>
                    • <code>int mbedtls_chachapoly_encrypt_and_tag(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_encrypt(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_auth_decrypt(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_ccm_auth_decrypt(…)</code><br>
                    • <code>int mbedtls_gcm_auth_decrypt(…)</code><br>
                    • <code>int mbedtls_chachapoly_auth_decrypt(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_decrypt(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The single-part functions use one buffer for the ciphertext and AEAD authentication tag.

**Multi-Part Operations**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_init(…)</code><br>
                    Algorithm specific<br>
                    • <code>void mbedtls_gcm_init(…)</code><br>
                    • <code>void mbedtls_chachapoly_init(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_aead_operation_t psa_aead_operation_init(void)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_encrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_starts(…)</code><br>
                    • <code>int mbedtls_chachapoly_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_generate_nonce(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_set_lengths(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_setup(…)</code><br>
                    • <code>int mbedtls_cipher_setkey(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_setkey(…)</code><br>
                    • <code>int mbedtls_chachapoly_setkey(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_decrypt_setup(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_set_iv(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_starts(…)</code><br>
                    • <code>int mbedtls_chachapoly_starts(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_set_nonce(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_update_ad(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_starts(…)</code><br>
                    • <code>int mbedtls_chachapoly_update_aad(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_update_ad(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_update(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_update(…)</code><br>
                    • <code>int mbedtls_chachapoly_update(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_update(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>int mbedtls_cipher_finish(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_finish(…)</code><br>
                    • <code>int mbedtls_chachapoly_finish(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_finish(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_verify(…)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>
                    Generic<br>
                    • <code>void mbedtls_cipher_free(…)</code><br>
                    Algorithm specific<br>
                    • <code>int mbedtls_gcm_free(…)</code><br>
                    • <code>int mbedtls_chachapoly_free(…)</code>
                </p>
            </td>
            <td>
                <p><code>psa_status_t psa_aead_abort(…)</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**:
> 
> - For `PSA_ALG_CCM`, calling` psa_aead_set_lengths()` is required.
> - For the other AEAD algorithms, calling `psa_aead_set_lengths()` is not required.
> - The following situations require the use of a multi-part operation:
> - Processing messages that cannot be assembled in memory.
> - Separating the AEAD authentication tag from the ciphertext.

**Quick Reference Examples**

**AES CCM (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0xea, 0x4f, 0x6f, 0x3c, 0x2f, 0xed, 0x2b, 0x9d, 0xd9, 0x70, 0x8c, 0x2e, 0x72, 0x1a, 0xe0, 0x0f
  };
  uint8_t nonce_buf[] = {0xf9, 0x75, 0x80, 0x9d, 0xdb, 0x51, 0x72, 0x38, 0x27, 0x45, 0x63, 0x4f};
  uint8_t ad_buf[] = {0x5c, 0x65, 0xd4, 0xf2, 0x61, 0xd2, 0xc5, 0x4f, 0xfe, 0x6a};
  uint8_t plain_msg_buf[] = {0x8d, 0x6c, 0x08, 0x44, 0x6c, 0xb1, 0x0d, 0x9a, 0x20, 0x75};
  uint8_t cipher_tag_buf[32];       // Ciphertext + Tag
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a AES CCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CCM);

  // Import a volatile plain key for AES CCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES CCM encryption and descryption
  // Expected ciphertext: e2 2f 37 3b eb f6 4a 3e 9b 87
  // Expected tag: 75 2b f9 db 34 dc 4d 43 3f 00 f5 5c 3f 53 0c 89
  ret = psa_aead_encrypt(key_id, PSA_ALG_CCM,
                        nonce_buf, sizeof(nonce_buf),
                        ad_buf, sizeof(ad_buf),
                        plain_msg_buf, sizeof(plain_msg_buf),
                        cipher_tag_buf, sizeof(cipher_tag_buf),
                        &out_len);
  ret = psa_aead_decrypt(key_id, PSA_ALG_CCM,
                        nonce_buf, sizeof(nonce_buf),
                        ad_buf, sizeof(ad_buf),
                        cipher_tag_buf, out_len,
                        plain_msg_buf, sizeof(plain_msg_buf),
                        &out_len);

  // Destroy a volatile plain key for AES CCM
  ret = psa_destroy_key(key_id);
}
```

> **Notes**:
> 
> - There are two ways to change the CCM authentication tag length (default 16 bytes).
>   1. Replace all AEAD algorithm `PSA_ALG_CCM` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length)` for the desired size of the authentication tag in bytes.
>   2. Replace the AEAD algorithm `PSA_ALG_CCM` in the `psa_set_key_algorithm(&key_attr, PSA_ALG_CCM)` function with `PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, min_tag_length)` to set the minimum authentication tag length in bytes. Replace the AEAD algorithm `PSA_ALG_CCM in psa_aead_encrypt()` and `psa_aead_decrypt()` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length)` to set the desired tag length `(≥ min_tag_length and ≤ PSA_AEAD_TAG_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CCM))` in bytes.

**AES GCM (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0xea, 0x4f, 0x6f, 0x3c, 0x2f, 0xed, 0x2b, 0x9d, 0xd9, 0x70, 0x8c, 0x2e, 0x72, 0x1a, 0xe0, 0x0f
  };
  uint8_t nonce_buf[] = {0xf9, 0x75, 0x80, 0x9d, 0xdb, 0x51, 0x72, 0x38, 0x27, 0x45, 0x63, 0x4f};
  uint8_t ad_buf[] = {0x5c, 0x65, 0xd4, 0xf2, 0x61, 0xd2, 0xc5, 0x4f, 0xfe, 0x6a};
  uint8_t plain_msg_buf[] = {0x8d, 0x6c, 0x08, 0x44, 0x6c, 0xb1, 0x0d, 0x9a, 0x20, 0x75};
  uint8_t cipher_tag_buf[32]; // Ciphertext + Tag
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a AES GCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_GCM);

  // Import a volatile plain key for AES GCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES GCM encryption and decryption
  // Expected ciphertext: 0f 51 f7 a8 3c 5b 5a a7 96 b9
  // Expected tag: 70 25 9c dd fe 8f 9a 15 a5 c5 eb 48 5a f5 78 fb
  ret = psa_aead_encrypt(key_id, PSA_ALG_GCM,
                          nonce_buf, sizeof(nonce_buf),
                          ad_buf, sizeof(ad_buf),
                          plain_msg_buf, sizeof(plain_msg_buf),
                          cipher_tag_buf, sizeof(cipher_tag_buf),
                          &out_len);

  ret = psa_aead_decrypt(key_id, PSA_ALG_GCM,
                          nonce_buf, sizeof(nonce_buf),
                          ad_buf, sizeof(ad_buf),
                          cipher_tag_buf, out_len,
                          plain_msg_buf, sizeof(plain_msg_buf),
                          &out_len);
                          
  // Destroy a volatile plain key for AES GCM
  ret = psa_destroy_key(key_id);
}
```

> **Notes**:
> 
> - There are two ways to change the GCM authentication tag length (default 16 bytes).
>   1. Replace all AEAD algorithm `PSA_ALG_GCM` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_length)` for the desired size of the authentication tag in bytes.
>   2. Replace the AEAD algorithm `PSA_ALG_GCM in the psa_set_key_algorithm(&key_attr, PSA_ALG_GCM)` function with `PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_GCM, min_tag_length)` to set the minimum authentication tag length in bytes. Replace the AEAD algorithm `PSA_ALG_GCM in psa_aead_encrypt()` and `psa_aead_decrypt()` with `PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_length)` to set the desired tag length `(≥ min_tag_length and ≤ PSA_AEAD_TAG_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_GCM))` in bytes.

**CHACHA20_POLY1305 (One-shot)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
  };
  uint8_t nonce_buf[] = {0x07, 0x00, 0x00, 0x00, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47};
  uint8_t ad_buf[] = {0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7};
  uint8_t plain_msg_buf[] = {
    0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
    0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
    0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
    0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
    0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
    0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
    0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
    0x74, 0x2e
  };
  uint8_t cipher_tag_buf[130]; // Ciphertext + Tag
  size_t out_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  
  ret = psa_crypto_init();

  // Set up attributes for a CHACHA20_POLY1305 key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_CHACHA20);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CHACHA20_POLY1305);

  // Import a volatile plain key for CHACHA20_POLY1305
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // CHACHA20_POLY1305 encryption
  // Expected ciphertext:
  // d3 1a 8d 34 64 8e 60 db 7b 86 af bc 53 ef 7e c2 a4 ad ed 51 29 6e 08 fe a9 e2 b5 a7 36 ee 62 d6
  // 3d be a4 5e 8c a9 67 12 82 fa fb 69 da 92 72 8b 1a 71 de 0a 9e 06 0b 29 05 d6 a5 b6 7e cd 3b 36
  // 92 dd bd 7f 2d 77 8b 8c 98 03 ae e3 28 09 1b 58 fa b3 24 e4 fa d6 75 94 55 85 80 8b 48 31 d7 bc
  // 3f f4 de f0 8e 4b 7a 9d e5 76 d2 65 86 ce c6 4b 61 16
  // Expected tag: 1a e1 0b 59 4f 09 e2 6a 7e 90 2e cb d0 60 06 91
  ret = psa_aead_encrypt(key_id,
                        PSA_ALG_CHACHA20_POLY1305,
                        nonce_buf,
                        sizeof(nonce_buf),
                        ad_buf,
                        sizeof(ad_buf),
                        plain_msg_buf,
                        sizeof(plain_msg_buf),
                        cipher_tag_buf,
                        sizeof(cipher_tag_buf),
                        &out_len);

  // CHACHA20_POLY1305 decryption
  ret = psa_aead_decrypt(key_id,
                        PSA_ALG_CHACHA20_POLY1305,
                        nonce_buf,
                        sizeof(nonce_buf),
                        ad_buf,
                        sizeof(ad_buf),
                        cipher_tag_buf,
                        out_len,
                        plain_msg_buf,
                        sizeof(plain_msg_buf),
                        &out_len);

  // Destroy a volatile plain key for CHACHA20_POLY1305
  ret = psa_destroy_key(key_id);
}
```

**AES CCM (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0x9c, 0xde, 0xba, 0xee, 0xe8, 0x69, 0x0b, 0x68, 0x75, 0x10, 0x70, 0x69, 0x1f, 0x49, 0x59, 0x36,
    0x68, 0xa6, 0xde, 0x12, 0xd3, 0xa9, 0x48, 0xb3, 0x8d, 0xdb, 0xd3, 0xf7, 0x52, 0x18, 0xb2, 0xd4
  };
  uint8_t nonce_buf[] = {0xaf, 0x1a, 0x97, 0xd4, 0x31, 0x51, 0xf5, 0xea, 0x9c, 0x48, 0xad, 0x36, 0xa3};
  uint8_t ad_buf[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x10, 0x11, 0x12, 0x13
  };
  uint8_t plain_msg_buf[] = {
    0x3c, 0xbb, 0x08, 0xf1, 0x33, 0x27, 0x0e, 0x44, 0x54, 0xbc, 0xaa, 0xa0, 0xf2, 0x0f, 0x6d, 0x63,
    0xc3, 0x8b, 0x65, 0x72, 0xe7, 0x66
  };
  uint8_t cipher_buf[22];
  uint8_t tag_buf[16];
  size_t tag_len;
  size_t out_len;
  uint32_t out_total;
  uint32_t stream_cnt;
  uint32_t stream_block_size = 14;                      // Block size for streaming

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_aead_operation_t aead_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES CCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CCM);

  // Import a volatile plain key for AES CCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES CCM stream encryption and decryption
  // Expected ciphertext:
  // 39 66 93 0a 2a e8 fd d8 f4 0e 70 07 f3 fd e0 bd 6e b4 8a 46 e6 d2
  // Expected tag: 7c 0c 1b a4 bf d2 bd 21 5b 0c d9 21 f0 6a 8f 3b
  aead_op = psa_aead_operation_init();
  ret = psa_aead_encrypt_setup(&aead_op, key_id, PSA_ALG_CCM);
  ret = psa_aead_set_lengths(&aead_op, sizeof(ad_buf), sizeof(plain_msg_buf));
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0;                                             // Streaming block
  out_total = 0;
  while ((sizeof(plain_msg_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          plain_msg_buf + (stream_cnt * stream_block_size), stream_block_size,
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
  }
    ret = psa_aead_update(&aead_op,                         // Last block
                          plain_msg_buf + (stream_cnt * stream_block_size),
                          sizeof(plain_msg_buf) - (stream_cnt * stream_block_size),
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
    out_total += out_len;

    ret = psa_aead_finish(&aead_op,                         // Generate tag
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len,
                          tag_buf, sizeof(tag_buf),
                          &tag_len);
  out_total += out_len;

  aead_op = psa_aead_operation_init();
  ret = psa_aead_decrypt_setup(&aead_op, key_id, PSA_ALG_CCM);
  ret = psa_aead_set_lengths(&aead_op, sizeof(ad_buf), sizeof(plain_msg_buf));
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0;                                           // Streaming block
  out_total = 0;
  while ((sizeof(cipher_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          cipher_buf + (stream_cnt * stream_block_size), stream_block_size,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
  }

    ret = psa_aead_update(&aead_op,                           // Last block
                        cipher_buf + (stream_cnt * stream_block_size),
                        sizeof(cipher_buf) - (stream_cnt * stream_block_size),
                        plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                        &out_len);
    out_total += out_len;
    ret = psa_aead_verify(&aead_op,                           // Verify tag
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len,
                          tag_buf, sizeof(tag_buf));
    out_total += out_len;

    // Destroy a volatile plain key for AES CCM
    ret = psa_destroy_key(key_id);
}
```

**AES GCM (Streaming)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t key_buf[] = {
    0x5f, 0xe0, 0x1c, 0x4b, 0xaf, 0x01, 0xcb, 0xe0, 0x77, 0x96, 0xd5, 0xaa, 0xef, 0x6e, 0xc1, 0xf4,
    0x51, 0x93, 0xa9, 0x8a, 0x22, 0x35, 0x94, 0xae, 0x4f, 0x0e, 0xf4, 0x95, 0x2e, 0x82, 0xe3, 0x30
  };
  uint8_t nonce_buf[] = {0xbd, 0x58, 0x73, 0x21, 0x56, 0x6c, 0x7f, 0x1a, 0x5d, 0xd8, 0x65, 0x2d};
  uint8_t ad_buf[] = {
    0x90, 0x13, 0x61, 0x78, 0x17, 0xdd, 0xa9, 0x47, 0xe1, 0x35, 0xee, 0x6d, 0xd3, 0x65, 0x33, 0x82
  };
  uint8_t plain_msg_buf[] = {
    0x88, 0x1d, 0xc6, 0xc7, 0xa5, 0xd4, 0x50, 0x9f, 0x3c, 0x4b, 0xd2, 0xda, 0xab, 0x08, 0xf1, 0x65,
    0xdd, 0xc2, 0x04, 0x48, 0x9a, 0xa8, 0x13, 0x45, 0x62, 0xa4, 0xea, 0xc3, 0xd0, 0xbc, 0xad, 0x79,
    0x65, 0x84, 0x7b, 0x10, 0x27, 0x33, 0xbb, 0x63, 0xd1, 0xe5, 0xc5, 0x98, 0xec, 0xe0, 0xc3, 0xe5,
    0xda, 0xdd, 0xdd
  };
  uint8_t cipher_buf[51];
  uint8_t tag_buf[16];
  size_t tag_len;
  size_t out_len;
  uint32_t out_total;
  uint32_t stream_cnt;
  uint32_t stream_block_size = 14;                              // Block size for streaming

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;
  psa_aead_operation_t aead_op;

  ret = psa_crypto_init();

  // Set up attributes for a AES GCM key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_GCM);

  // Import a volatile plain key for AES GCM
  ret = psa_import_key(&key_attr, key_buf, sizeof(key_buf), &key_id);

  // AES GCM stream encryption and decryption
  // Expected ciphertext:
  // 16 e3 75 b4 97 3b 33 9d 3f 74 6c 1c 5a 56 8b c7 52 6e 90 9d df f1 e1 9c 95 c9 4a 6c cf f2 10 c9
  // a4 a4 06 79 de 57 60 c3 96 ac 0e 2c eb 12 34 f9 f5 fe 26
  // Expected tag: ab d3 d2 6d 65 a6 27 5f 7a 4f 56 b4 22 ac ab 49
  aead_op = psa_aead_operation_init();
  ret = psa_aead_encrypt_setup(&aead_op, key_id, PSA_ALG_GCM);
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0; // Streaming block
  out_total = 0;
  while ((sizeof(plain_msg_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          plain_msg_buf + (stream_cnt * stream_block_size), stream_block_size,
                          cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
    }

    ret = psa_aead_update(&aead_op,                                     // Last block
                        plain_msg_buf + (stream_cnt * stream_block_size),
                        sizeof(plain_msg_buf) - (stream_cnt * stream_block_size),
                        cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                        &out_len);
    out_total += out_len;

    ret = psa_aead_finish(&aead_op,                                       // Generate tag
                        cipher_buf + out_total, sizeof(cipher_buf) - out_total,
                        &out_len,
                        tag_buf, sizeof(tag_buf),
                        &tag_len);
    out_total += out_len;

  aead_op = psa_aead_operation_init();
  ret = psa_aead_decrypt_setup(&aead_op, key_id, PSA_ALG_GCM);
  ret = psa_aead_set_nonce(&aead_op, nonce_buf, sizeof(nonce_buf));
  ret = psa_aead_update_ad(&aead_op, ad_buf, sizeof(ad_buf));

  stream_cnt = 0;                                                       // Streaming block
  out_total = 0;
  while ((sizeof(cipher_buf) - (stream_cnt * stream_block_size)) > stream_block_size) {
    ret = psa_aead_update(&aead_op,
                          cipher_buf + (stream_cnt * stream_block_size), stream_block_size,
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
                          stream_cnt++;
    out_total += out_len;
  }

    ret = psa_aead_update(&aead_op,                                         // Last block
                          cipher_buf + (stream_cnt * stream_block_size),
                          sizeof(cipher_buf) - (stream_cnt * stream_block_size),
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len);
    out_total += out_len;

    ret = psa_aead_verify(&aead_op,                                         // Verify tag
                          plain_msg_buf + out_total, sizeof(plain_msg_buf) - out_total,
                          &out_len,
                          tag_buf, sizeof(tag_buf));
    out_total += out_len;

    // Destroy a volatile plain key for AES GCM
    ret = psa_destroy_key(key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image26](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image26.png)

The following table describes the implementation status of the PSA Crypto AEAD platform example.

|**Algorithm**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|AES CCM|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|AES GCM|Y|Y|Y|Series 1 devices do not support a 192-bit key.|
|CHACHA20_POLY1305|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|

> **Notes**:
> 
> - The AEAD platform example uses default nonce (12-byte for GCM) and tag length (16-byte for CCM and GCM).
> - The multi-part AEAD operations are only available on GSDK v4.2.0 and higher.
> - The multi-part AEAD operations for CHACHA20_POLY1305 are not yet implemented.
> - The multi-part AEAD operations for a shortened tag length (AES CCM and GCM) are not yet implemented.
> - The multi-part GCM operations do not support non-12-byte nonce (GCM with Non-Recommended IV Lengths).
> - The AEAD platform example for multi-part AEAD operations is pending for fully-featured multi-part AEAD drivers.

###### Key Derivation (heading level 7)

A Key Derivation Function (KDF) derives one or many secret keys from a secret value such as a master key, a password, or a pass-phrase using a pseudo-random function. The typical usage of a key derivation function is to use a secret, such as a password or an ECDH shared secret, and a salt to produce a symmetric key and initialization vector (IV) for use with AES.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>HKDF (SHA-1)</p>
            </td>
            <td>
                <p><code>MBEDTLS_MD_SHA1</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_HKDF(PSA_ALG_SHA_1)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>HKDF (SHA-2)</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_MD_SHA224</code><br>
                    • <code>MBEDTLS_MD_SHA256</code><br>
                    • <code>MBEDTLS_MD_SHA384</code><br>
                    • <code>MBEDTLS_MD_SHA512</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_HKDF(PSA_ALG_SHA_512)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PBKDF2 (SHA-1)</p>
            </td>
            <td>
                <p><code>MBEDTLS_MD_SHA1</code></p>
            </td>
            <td>
                <p><code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PBKDF2 (SHA-2)</p>
            </td>
            <td>
                <p>
                    • <code>MBEDTLS_MD_SHA224</code><br>
                    • <code>MBEDTLS_MD_SHA256</code><br>
                    • <code>MBEDTLS_MD_SHA384</code><br>
                    • <code>MBEDTLS_MD_SHA512</code>
                </p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_512)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>PBKDF2 CMAC</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_PBKDF2_AES_CMAC_PRF_128</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDH + HKDF</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))</code></p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

|**Algorithm**|**Key Type**|**Key Size in Bits**|**Key Usage Flag**|
|---|---|---|---|
|- PSA_ALG_HKDF(PSA_ALG_SHA_1)|PSA_KEY_TYPE_DERIVE|Multiple of 8|PSA_KEY_USAGE_DERIVE|
|- PSA_ALG_HKDF(PSA_ALG_SHA_224)| | | |
|- PSA_ALG_HKDF(PSA_ALG_SHA_256)| | | |
|- PSA_ALG_HKDF(PSA_ALG_SHA_384)| | | |
|- PSA_ALG_HKDF(PSA_ALG_SHA_512)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_224)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_384)| | | |
|- PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_512)| | | |
|PSA_ALG_PBKDF2_AES_CMAC_PRF_128| | | |

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_HKDF(PSA_ALG_SHA_1)|HKDF and SHA-1|
|PSA_ALG_HKDF(PSA_ALG_SHA_224)|HKDF and SHA-224|
|PSA_ALG_HKDF(PSA_ALG_SHA_256)|HKDF and SHA-256|
|PSA_ALG_HKDF(PSA_ALG_SHA_384)|HKDF and SHA-384|
|PSA_ALG_HKDF(PSA_ALG_SHA_512)|HKDF and SHA-512|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_1)|PBKDF2 and SHA-1|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_224)|PBKDF2 and SHA-224|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256)|PBKDF2 and SHA-256|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_384)|PBKDF2 and SHA-384|
|PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_512)|PBKDF2 and SHA-512|
|PSA_ALG_PBKDF2_AES_CMAC_PRF_128|PBKDF2|
|PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))|ECDH and HKDF and SHA-X|

> **Note**:
> 
> - It should add the components for the derived key algorithm to implement the HKDF. For example, it requires the `CTR Mode` component if the derived key algorithm is `PSA_ALG_CTR`.
> - Refer to [Key Agreement (ECDH)](#key-agreement-ecdh) to add the ECDH components to derive the shared secret for the ECDH + HKDF algorithm (`PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))`).

**Single-Part Functions**

|**Mbed TLS**|**PSA Crypto**|
|---|---|
|int mbedtls_hkdf(…)|psa_status_t sl_psa_key_derivation_single_shot(…)|
|int mbedtls_pkcs5_pbkdf2_hmac(…)|psa_status_t sl_psa_key_derivation_single_shot(…)|

> **Note**: The `sl_psa_key_derivation_single_shot(…)` is a **Silicon Labs custom API**. It can only use on HSE-SVH devices.

**Multi-Part Operations**

|**Mbed TLS**|**PSA Crypto**|
|---|---|
|—|psa_key_derivation_operation_t psa_key_derivation_operation_init(void)|
|—|psa_status_t psa_key_derivation_setup(…)|
|—|psa_status_t psa_key_derivation_get_capacity(…)|
|—|psa_status_t psa_key_derivation_set_capacity(…)|
|—|psa_status_t psa_key_derivation_input_bytes(…)|
|—|psa_status_t psa_key_derivation_input_key(…)|
|—|psa_status_t psa_key_derivation_output_bytes(…)|
|—|psa_status_t psa_key_derivation_output_key(…)|
|—|psa_status_t psa_key_derivation_abort(…)|

> **Note**: The multi-part operation allows the data to be processed for KDF in fragments instead of all at once.

**Quick Reference Examples HKDF (SHA-256)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t hkdf_ikm[] = {
    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
  };
  uint8_t hkdf_salt[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c};
  uint8_t hkdf_info[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
  uint8_t key_buf[32];
  size_t key_len;
  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t hkdf_key_id;
  psa_key_attributes_t key_attr;
  psa_key_derivation_operation_t kdf_op;

  ret = psa_crypto_init();

  // Set up attributes for a volatile master plain key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_DERIVE);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_HKDF(PSA_ALG_SHA_256));

  // Import a volatile master plain key
  ret = psa_import_key(&key_attr, hkdf_ikm, sizeof(hkdf_ikm), &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (HKDF SHA256) a volatile plain key for AES CTR
  #if defined(SEMAILBOX_PRESENT) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)

  // Silicon Labs custom API for Secure Vault High devices
  ret = sl_psa_key_derivation_single_shot(PSA_ALG_HKDF(PSA_ALG_SHA_256), master_key_id,
                                          hkdf_info, sizeof(hkdf_info),
                                          hkdf_salt, sizeof(hkdf_salt),
                                          0, &key_attr, &hkdf_key_id);
  #else
  kdf_op = psa_key_derivation_operation_init();
  ret = psa_key_derivation_setup(&kdf_op, PSA_ALG_HKDF(PSA_ALG_SHA_256));
  ret = psa_key_derivation_set_capacity(&kdf_op, sizeof(key_buf));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SALT, hkdf_salt, sizeof(hkdf_salt));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_info, sizeof(hkdf_info));
  ret = psa_key_derivation_input_key(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, master_key_id);
  ret = psa_key_derivation_output_key(&key_attr, &kdf_op, &hkdf_key_id);
  ret = psa_key_derivation_abort(&kdf_op);
  #endif

  // Export derived volatile plain key (expected value of HKDF SHA256):
  // 3c b2 5f 25 fa ac d5 7a 90 43 4f 64 d0 36 2f 2a 2d 2d 0a 90 cf 1a 5a 4c 5d b0 2d 56 ec c4 c5 bf
  ret = psa_export_key(hkdf_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(hkdf_key_id);
}
```

**PBKDF2-HMAC-SHA256 (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t pbkdf2_ikm[] = {0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64};
  uint8_t pbkdf2_salt[] = {0x73, 0x61, 0x6c, 0x74};
  uint8_t key_buf[32];
  size_t key_len;
  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t pbkdf2_key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();
  // Set up attributes for a volatile master plain key

  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_DERIVE);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256));

  // Import a volatile master plain key
  ret = psa_import_key(&key_attr, pbkdf2_ikm, sizeof(pbkdf2_ikm), &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (PBKDF2 SHA256 with 4096 iterations) a volatile plain key for AES CTR
  // Silicon Labs custom API for Secure Vault High devices
  ret = sl_psa_key_derivation_single_shot(PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA_256), master_key_id,
                                          NULL, 0,
                                          pbkdf2_salt, sizeof(pbkdf2_salt),
                                          4096, &key_attr, &pbkdf2_key_id);

  // Export derived volatile plain key (expected value of PBKDF2 SHA256 with 4096 iterations):
  // c5 e4 78 d5 92 88 c8 41 aa 53 0d b6 84 5c 4c 8d 96 28 93 a0 01 ce 4e 11 a4 96 38 73 aa 98 13 4a
  ret = psa_export_key(pbkdf2_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(pbkdf2_key_id);
}
```

> **Note**: The PBKDF2-HMAC implementation of PSA Crypto is not yet available.

**PBKDF2-AES-CMAC-PRF-128 (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t pbkdf2_ikm[] = {0x4a, 0x30, 0x31, 0x4e, 0x4d, 0x45};
  uint8_t pbkdf2_salt[] = {
    0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x37, 0x33, 0x35, 0x63, 0x38, 0x37, 0x62, 0x34, 0x4f, 0x70,
    0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x44, 0x65, 0x6d, 0x6f
  };
  uint8_t key_buf[16];
  size_t key_len;
  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t pbkdf2_key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile master plain key
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_DERIVE);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PBKDF2_AES_CMAC_PRF_128);

  // Import a volatile master plain key
  ret = psa_import_key(&key_attr, pbkdf2_ikm, sizeof(pbkdf2_ikm), &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (PBKDF2 AES_CMAC_PRF_128 with 16384 iterations) a volatile plain key for AES CTR
  // Silicon Labs custom API for Secure Vault High devices
  ret = sl_psa_key_derivation_single_shot(PSA_ALG_PBKDF2_AES_CMAC_PRF_128, master_key_id,
                                          NULL, 0,
                                          pbkdf2_salt, sizeof(pbkdf2_salt),
                                          16384, &key_attr, &pbkdf2_key_id);

  // Export derived volatile plain key (expected value of PBKDF2 AES_CMAC_PRF_128 with 16384 iterations):
  // 8b 27 be ed 7e 7a 4d d6 c5 31 38 c8 79 a8 e3 3c
  
  ret = psa_export_key(pbkdf2_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(pbkdf2_key_id);
}
```

> **Note**:
> 
> - The PBKDF2-AES-CMAC-PRF-128 implementation of PSA Crypto is not yet available.
> - EFR32xG21B (HSE-SVH) devices do not support PBKDF2-AES-CMAC-PRF-128.

**ECDH and HKDF**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t client_private_key[] = {
    0xc8, 0x8f, 0x01, 0xf5, 0x10, 0xd9, 0xac, 0x3f, 0x70, 0xa2, 0x92, 0xda, 0xa2, 0x31, 0x6d, 0xe5,
    0x44, 0xe9, 0xaa, 0xb8, 0xaf, 0xe8, 0x40, 0x49, 0xc6, 0x2a, 0x9c, 0x57, 0x86, 0x2d, 0x14, 0x33
  };
  uint8_t client_public_key[] = { // Uncompressed point format
    0x04, 0xda, 0xd0, 0xb6, 0x53, 0x94, 0x22, 0x1c, 0xf9, 0xb0, 0x51, 0xe1, 0xfe, 0xca, 0x57, 0x87, 0xd0,
    0x98, 0xdf, 0xe6, 0x37, 0xfc, 0x90, 0xb9, 0xef, 0x94, 0x5d, 0x0c, 0x37, 0x72, 0x58, 0x11, 0x80,
    0x52, 0x71, 0xa0, 0x46, 0x1c, 0xdb, 0x82, 0x52, 0xd6, 0x1f, 0x1c, 0x45, 0x6f, 0xa3, 0xe5, 0x9a,
    0xb1, 0xf4, 0x5b, 0x33, 0xac, 0xcf, 0x5f, 0x58, 0x38, 0x9e, 0x05, 0x77, 0xb8, 0x99, 0x0b, 0xb3
  };
  uint8_t server_private_key[] = {
    0xc6, 0xef, 0x9c, 0x5d, 0x78, 0xae, 0x01, 0x2a, 0x01, 0x11, 0x64, 0xac, 0xb3, 0x97, 0xce, 0x20,
    0x88, 0x68, 0x5d, 0x8f, 0x06, 0xbf, 0x9b, 0xe0, 0xb2, 0x83, 0xab, 0x46, 0x47, 0x6b, 0xee, 0x53
  };
  uint8_t server_public_key[] = { // Uncompressed point format
    0x04, 0xd1, 0x2d, 0xfb, 0x52, 0x89, 0xc8, 0xd4, 0xf8, 0x12, 0x08, 0xb7, 0x02, 0x70, 0x39, 0x8c, 0x34,
    0x22, 0x96, 0x97, 0x0a, 0x0b, 0xcc, 0xb7, 0x4c, 0x73, 0x6f, 0xc7, 0x55, 0x44, 0x94, 0xbf, 0x63,
    0x56, 0xfb, 0xf3, 0xca, 0x36, 0x6c, 0xc2, 0x3e, 0x81, 0x57, 0x85, 0x4c, 0x13, 0xc5, 0x8d, 0x6a,
    0xac, 0x23, 0xf0, 0x46, 0xad, 0xa3, 0x0f, 0x83, 0x53, 0xe7, 0x4f, 0x33, 0x03, 0x98, 0x72, 0xab
  };
  uint8_t hkdf_salt[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c};
  uint8_t hkdf_info[] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9};
  uint8_t key_buf[32];
  size_t key_len;

  psa_status_t ret;
  psa_key_id_t master_key_id;
  psa_key_id_t hkdf_key_id;
  psa_key_attributes_t key_attr;
  psa_key_derivation_operation_t kdf_op;

  ret = psa_crypto_init();

  // Set up attributes for a volatile master plain key (algorithm for ECDH and HKDF)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));

  // Import a volatile master plain key (client private key)
  ret = psa_import_key(&key_attr, client_private_key, sizeof(client_private_key),
  &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (HKDF SHA256) a volatile plain key from ECDH shared secret (server public key) for AES CTR
  kdf_op = psa_key_derivation_operation_init();
  ret = psa_key_derivation_setup(&kdf_op, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));
  ret = psa_key_derivation_set_capacity(&kdf_op, sizeof(key_buf));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SALT, hkdf_salt, sizeof(hkdf_salt));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_info, sizeof(hkdf_info));
  ret = psa_key_derivation_key_agreement(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, master_key_id, server_public_key,
  sizeof(server_public_key));
  ret = psa_key_derivation_output_key(&key_attr, &kdf_op, &hkdf_key_id);
  ret = psa_key_derivation_abort(&kdf_op);

  // Export derived volatile plain key (client shared secret):
  // B7 CA BD A7 42 60 DE D5 4C 4C 11 FA BC A3 56 4B 77 35 CC 9F 89 E9 BF E8 08 24 8A F3 54 99 B0 55
  ret = psa_export_key(hkdf_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(hkdf_key_id);

  // Set up attributes for a volatile master plain key (algorithm for ECDH and HKDF)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));

  // Import a volatile master plain key (server private key)
  ret = psa_import_key(&key_attr, server_private_key, sizeof(server_private_key),
                      &master_key_id);

  // Set up attributes for a volatile derived plain key (exportable for verification)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
  psa_set_key_bits(&key_attr, sizeof(key_buf) * 8);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
  psa_set_key_algorithm(&key_attr, PSA_ALG_CTR);

  // Derive (HKDF SHA256) a volatile plain key from ECDH shared secret (client public key) for AES CTR
  kdf_op = psa_key_derivation_operation_init();
  ret = psa_key_derivation_setup(&kdf_op, PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)));
  ret = psa_key_derivation_set_capacity(&kdf_op, sizeof(key_buf));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_SALT, hkdf_salt, sizeof(hkdf_salt));
  ret = psa_key_derivation_input_bytes(&kdf_op, PSA_KEY_DERIVATION_INPUT_INFO, hkdf_info, sizeof(hkdf_info));
  ret = psa_key_derivation_key_agreement(&kdf_op, PSA_KEY_DERIVATION_INPUT_SECRET, master_key_id, client_public_key,
                                        sizeof(client_public_key));
  ret = psa_key_derivation_output_key(&key_attr, &kdf_op, &hkdf_key_id);
  ret = psa_key_derivation_abort(&kdf_op);

  // Export derived volatile plain key (server shared secret):
  // B7 CA BD A7 42 60 DE D5 4C 4C 11 FA BC A3 56 4B 77 35 CC 9F 89 E9 BF E8 08 24 8A F3 54 99 B0 55
  ret = psa_export_key(hkdf_key_id, key_buf, sizeof(key_buf), &key_len);

  // Destroy the master and derived keys
  ret = psa_destroy_key(master_key_id);
  ret = psa_destroy_key(hkdf_key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image27](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image27.png)

The following table describes the implementation status of the PSA Crypto KDF platform example.

|**Algorithm**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|HKDF|Y|Y|Y|Hardware acceleration only on HSE-SVH devices with Silicon Labs custom API.|
|ECDH + HKDF|Y|Y|Y|Hardware acceleration (HKDF) only on HSE-SVH devices with Silicon Labs custom API.|

> **Note**:
> 
> - The PBKDF2 implementation of PSA Crypto is not yet available.
> - The ECDH + HKDF algorithm does not apply to the [wrapped key](04-key-management-in-psa-crypto#key-lifetimes).

###### Asymmetric Cryptographic Operation (heading level 7)

###### Asymmetric Signature (ECDSA and EdDSA) (heading level 8)

In modern cryptography, the Elliptic-Curve-based signatures (like ECDSA and EdDSA) are widely used because of shorter key lengths, shorter signature lengths, higher security levels (for the same key length), and better performance.

The Elliptic Curve Digital Signature Algorithm (ECDSA) is a cryptographically secure digital signature scheme based on the Elliptic Curve Cryptography (ECC). The Edwards-curve Digital Signature Algorithm (EdDSA) is a fast digital signature algorithm, using elliptic curves in Edwards form (like Ed25519 and Ed448).

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>ECDSA (SHA-1)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_ECDSA(PSA_ALG_SHA_1)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDSA (SHA-2)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_224)</code><br>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_256)</code><br>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_384)</code><br>
                    • <code>PSA_ALG_ECDSA(PSA_ALG_SHA_512)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDSA (Any hash algorithm)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>ECDSA (No hashing)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_ECDSA_ANY</code></p>
            </td>
        </tr>
        <tr>
            <td>
                <p>EdDSA</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p><code>PSA_ALG_PURE_EDDSA</code></p>
            </td>
        </tr>
    </tbody>
</table>

> **Note**: The hash-and-sign algorithms `(PSA_ALG_ECDSA(hash_alg)` and `PSA_ALG_ECDSA(PSA_ALG_ANY_HASH))` include the hashing step for ECDSA.

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>PSA_ALG_ECDSA_ANY</code></td>
            <td><code>PSA_ECC_FAMILY_SECP_R1</code></td>
            <td>
                secp192r1 : 192<br>
                secp224r1 : 224<br>
                secp256r1 : 256<br>
                secp384r1 : 384<br>
                secp521r1 : 521
            </td>
            <td>
                <code>PSA_KEY_USAGE_SIGN_HASH</code><br>
                <code>PSA_KEY_USAGE_VERIFY_HASH</code>
            </td>
        </tr>
        <tr>
            <td></td>
            <td><code>PSA_ECC_FAMILY_SECP_K1</code></td>
            <td>secp256k1 : 256</td>
            <td></td>
        </tr>
        <tr>
            <td>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_1)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_224)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_256)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_384)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_SHA_512)</code><br>
                <code>PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)</code>
            </td>
            <td><code>PSA_ECC_FAMILY_SECP_R1</code></td>
            <td>
                secp192r1 : 192<br>
                secp224r1 : 224<br>
                secp256r1 : 256<br>
                secp384r1 : 384<br>
                secp521r1 : 521
            </td>
            <td>
                <code>PSA_KEY_USAGE_SIGN_MESSAGE</code><br>
                <code>PSA_KEY_USAGE_VERIFY_MESSAGE</code>
            </td>
        </tr>
        <tr>
            <td></td>
            <td><code>PSA_ECC_FAMILY_SECP_K1</code></td>
            <td>secp256k1 : 256</td>
            <td></td>
        </tr>
        <tr>
            <td><code>PSA_ALG_PURE_EDDSA</code></td>
            <td><code>PSA_ECC_FAMILY_TWISTED_EDWARDS</code></td>
            <td>Edwards25519 : 255</td>
            <td>
                <code>PSA_KEY_USAGE_SIGN_MESSAGE</code><br>
                <code>PSA_KEY_USAGE_VERIFY_MESSAGE</code>
            </td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_ECDSA_ANY|ECDSA|
|PSA_ALG_ECDSA(PSA_ALG_SHA_1)|ECDSA and SHA-1|
|PSA_ALG_ECDSA(PSA_ALG_SHA_224)|ECDSA and SHA-224|
|PSA_ALG_ECDSA(PSA_ALG_SHA_256)|ECDSA and SHA-256|
|PSA_ALG_ECDSA(PSA_ALG_SHA_384)|ECDSA and SHA-384|
|PSA_ALG_ECDSA(PSA_ALG_SHA_512)|ECDSA and SHA-512|
|PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)|ECDSA and SHA-X|

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_PURE_EDDSA|EdDSA|

|**PSA_ECC_FAMILY_SECP_R1**|**Security Software Components**|
|---|---|
|secp192r1|secp192r1|
|secp224r1|secp224r1|
|secp256r1|secp256r1|
|secp384r1|secp384r1|
|secp521r1|secp521r1|

|**PSA_ECC_FAMILY_SECP_K1**|**Security Software Components**|
|---|---|
|secp256k1|secp256k1|

|**PSA_ECC_FAMILY_TWISTED_EDWARDS**|**Security Software Components**|
|---|---|
|Edwards25519|edwards25519|

|**Built-in Key**|**Security Software Components**|
|---|---|
|secp256r1 keys in SE OTP|Built-In Keys|

**Functions**

<table>
    <thead>
        <tr>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>Hash-and-sign<br>—</p>
            </td>
            <td>
                <p>Hash-and-sign<br>
                    <code>psa_status_t psa_sign_message(…)</code><br>
                    <code>psa_status_t psa_verify_message(…)</code>
                </p>
            </td>
        </tr>
        <tr>
            <td>
                <p>Precomputed hash<br>
                    <code>int mbedtls_ecdsa_write_signature(…)</code><br>
                    <code>int mbedtls_ecdsa_read_signature(…)</code>
                </p>
            </td>
            <td>
                <p>Precomputed hash<br>
                    <code>psa_status_t psa_sign_hash(…)</code><br>
                    <code>psa_status_t psa_verify_hash(…)</code>
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Quick Reference Examples**

**ECDSA on secp256r1 (Precomputed Hash)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t hash_data[] = {
    0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
    0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
  };
  uint8_t public_key[65]; // Uncompressed point format
  size_t pubkey_len;
  uint8_t signature_buf[64];
  size_t signature_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_bits(&key_attr, 256);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

  // Generate a random volatile private plain key
  ret = psa_generate_key(&key_attr, &key_id);

  // Sign a hash with a volatile private plain key
  ret = psa_sign_hash(key_id,
                      PSA_ALG_ECDSA_ANY,
                      hash_data,
                      sizeof(hash_data),
                      signature_buf,
                      sizeof(signature_buf),
                      &signature_len);

  // Verify a signature with a volatile private plain key
  ret = psa_verify_hash(key_id,
                        PSA_ALG_ECDSA_ANY,
                        hash_data,
                        sizeof(hash_data),
                        signature_buf,
                        signature_len);

  // Export a public key from a volatile private plain key and then destroy the private key
  ret = psa_export_public_key(key_id,
                              public_key,
                              sizeof(public_key),
                              &pubkey_len);

  ret = psa_destroy_key(key_id);

  // Set up attributes for a public key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

  // Import a public key
  ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

  // Verify a signature with a public key and then destroy the public key
  ret = psa_verify_hash(key_id,
                        PSA_ALG_ECDSA_ANY,
                        hash_data,
                        sizeof(hash_data),
                        signature_buf,
                        signature_len);

  ret = psa_destroy_key(key_id);
}
```

**ECDSA on secp256r1 (Hash-and-Sign)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t ecdsa_msg[] = {
    0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
  };
  uint8_t public_key[65];                                     // Uncompressed point format
  size_t pubkey_len;
  uint8_t signature_buf[64];
  size_t signature_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_bits(&key_attr, 256);
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));

  // Generate a random volatile private plain key
  ret = psa_generate_key(&key_attr, &key_id);

  // Hash-and-Sign (SHA-256) a message with a volatile private plain key
  ret = psa_sign_message(key_id,
                        PSA_ALG_ECDSA(PSA_ALG_SHA_256),
                        ecdsa_msg,
                        sizeof(ecdsa_msg),
                        signature_buf,
                        sizeof(signature_buf),
                        &signature_len);

  // Hash (SHA-256) a message and verify a signature with a volatile private plain key
  ret = psa_verify_message(key_id,
                          PSA_ALG_ECDSA(PSA_ALG_SHA_256),
                          ecdsa_msg,
                          sizeof(ecdsa_msg),
                          signature_buf,
                          signature_len);

  // Export a public key from a volatile private plain key and then destroy the private key
  ret = psa_export_public_key(key_id,
                              public_key,
                              sizeof(public_key),
                              &pubkey_len);

  ret = psa_destroy_key(key_id);

  // Set up attributes for a public key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));

  // Import a public key
  ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

  // Hash (SHA-256) and verify a signature with a public key and then destroy the public key
  ret = psa_verify_message(key_id,
                          PSA_ALG_ECDSA(PSA_ALG_SHA_256),
                          ecdsa_msg,
                          sizeof(ecdsa_msg),
                          signature_buf,
                          signature_len);

  ret = psa_destroy_key(key_id);
}
```

**ECDSA with Built-in Private Device Key (HSE-SVH only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
 uint8_t hash_data[] = {
  0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
  0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
 };
 uint8_t public_key[65];                                  // Uncompressed point format
 size_t pubkey_len;
 uint8_t signature_buf[64];
 size_t signature_len;

 psa_status_t ret;
 psa_key_id_t key_id;
 psa_key_attributes_t key_attr;

 ret = psa_crypto_init();

 // Sign a hash with a built-in private device key
 ret = psa_sign_hash(SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID,
                    PSA_ALG_ECDSA_ANY,
                    hash_data,
                    sizeof(hash_data),
                    signature_buf,
                    sizeof(signature_buf),
                    &signature_len);

 // Verify a signature with a built-in private device key
 ret = psa_verify_hash(SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID,
                      PSA_ALG_ECDSA_ANY,
                      hash_data,
                      sizeof(hash_data),
                      signature_buf,
                      signature_len);

 // Export a built-in public device key
 ret = psa_export_public_key(SL_SE_BUILTIN_KEY_APPLICATION_ATTESTATION_ID,
                            public_key,
                            sizeof(public_key),
                            &pubkey_len);

 // Set up attributes for a public device key
 key_attr = psa_key_attributes_init();
 psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
 psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
 psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA_ANY);

 // Import a public device key
 ret = psa_import_key(&key_attr, public_key, sizeof(public_key), &key_id);

 // Verify a signature with a public device key
 ret = psa_verify_hash(key_id,
                      PSA_ALG_ECDSA_ANY,
                      hash_data,
                      sizeof(hash_data),
                      signature_buf,
                      signature_len);

 // Destroy a public device key
 ret = psa_destroy_key(key_id);
#endif
}
```

**EdDSA on Ed25519 (HSE only)**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
#if defined(SEMAILBOX_PRESENT)
  uint8_t eddsa_msg[] = {
    0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
    0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
    0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
  };
  uint8_t ed25519_private[] = {
    0x83, 0x3f, 0xe6, 0x24, 0x09, 0x23, 0x7b, 0x9d, 0x62, 0xec, 0x77, 0x58, 0x75, 0x20, 0x91, 0x1e,
    0x9a, 0x75, 0x9c, 0xec, 0x1d, 0x19, 0x75, 0x5b, 0x7d, 0xa9, 0x01, 0xb9, 0x6d, 0xca, 0x3d, 0x42
  };
  uint8_t ed25519_public[] = {
    0xec, 0x17, 0x2b, 0x93, 0xad, 0x5e, 0x56, 0x3b, 0xf4, 0x93, 0x2c, 0x70, 0xe1, 0x24, 0x50, 0x34,
    0xc3, 0x54, 0x67, 0xef, 0x2e, 0xfd, 0x4d, 0x64, 0xeb, 0xf8, 0x19, 0x68, 0x34, 0x67, 0xe2, 0xbf
  };
  uint8_t signature_buf[64];
  size_t signature_len;

  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile private plain key (Ed25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA);

  // Import a volatile private plain key
  ret = psa_import_key(&key_attr, ed25519_private, sizeof(ed25519_private), &key_id);

  // Hash-and-Sign a message with a volatile private plain key (expected EdDSA signature):
  // dc 2a 44 59 e7 36 96 33 a5 2b 1b f2 77 83 9a 00 20 10 09 a3 ef bf 3e cb 69 be a2 18 6c 26 b5 89
  // 09 35 1f c9 ac 90 b3 ec fd fb c7 c6 64 31 e0 30 3d ca 17 9c 13 8a c1 7a d9 be f1 17 73 31 a7 04
  ret = psa_sign_message(key_id,
                        PSA_ALG_PURE_EDDSA,
                        eddsa_msg,
                        sizeof(eddsa_msg),
                        signature_buf,
                        sizeof(signature_buf),
                        &signature_len);

  // Destroy a volatile private plain key
  ret = psa_destroy_key(key_id);

  // Set up attributes for a public key (Ed25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_TWISTED_EDWARDS));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_PURE_EDDSA);

  // Import a public key
  ret = psa_import_key(&key_attr, ed25519_public, sizeof(ed25519_public), &key_id);

  // Hash a message and verify the signature with a public key
  ret = psa_verify_message(key_id,
                          PSA_ALG_PURE_EDDSA,
                          eddsa_msg,
                          sizeof(eddsa_msg),
                          signature_buf,
                          signature_len);

  // Destroy a public key
  ret = psa_destroy_key(key_id);
#endif
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image28](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image28.png)

The following table describes the implementation status of the PSA Crypto DSA platform example.

|**ECC Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Edwards25519|—|—|Y|Only on HSE devices with hardware acceleration.|
|Public Sign Key|—|—|Y|—|
|Public Command Key|—|—|Y|—|
|Private Device Key|—|—|Y|Only on HSE-SVH devices.|

> **Note**:
> 
> - This example does not include secp224r1 and secp256k1. The secp256k1 ECDSA on HSE devices is not yet implemented.
> - The PSA Crypto does not yet support software fallback on the Edwards25519.
> - The HSE-SVM devices require SE firmware v1.2.11 or higher (EFR32xG21) and v2.1.7 or higher (other HSE devices) to support hardware acceleration on Edwards25519. This feature also requires GSDK v4.0.1 or higher.

###### Key Agreement (ECDH) (heading level 7)

The Elliptic Curve Diffie-Hellman (ECDH) is an anonymous key agreement protocol that allows two parties, each having an elliptic-curve private-public key pair, to establish a shared secret over an insecure channel.

**Algorithms**

|**Algorithm**|**Mbed TLS**|**PSA Crypto**|
|---|---|---|
|ECDH|—|PSA_ALG_ECDH|
|ECDH and HKDF|—|PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(hash_alg))|

**Key Attributes in PSA Crypto**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Key Type</strong></th>
            <th><strong>Key Size in Bits</strong></th>
            <th><strong>Key Usage Flag</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>PSA_ALG_ECDH</p>
            </td>
            <td>
                <p>PSA_ECC_FAMILY_SECP_R1</p>
            </td>
            <td>
                <p>
                    • secp192r1 : 192<br>
                    • secp224r1 : 224<br>
                    • secp256r1 : 256<br>
                    • secp384r1 : 384<br>
                    • secp521r1 : 521
                </p>
            </td>
            <td>
                <p>PSA_KEY_USAGE_DERIVE</p>
            </td>
        </tr>
        <tr>
            <td></td>
            <td>
                <p>PSA_ECC_FAMILY_SECP_K1</p>
            </td>
            <td>
                <p>secp256k1 : 256</p>
            </td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td>
                <p>PSA_ECC_FAMILY_MONTGOMERY</p>
            </td>
            <td>
                <p>
                    • Curve25519 : 255<br>
                    • Curve448 : 448
                </p>
            </td>
            <td></td>
        </tr>
    </tbody>
</table>

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_ECDH|ECDH|

|**PSA_ECC_FAMILY_SECP_R1**|**Security Software Components**|
|---|---|
|secp192r1|secp192r1|
|secp224r1|secp224r1|
|secp256r1|secp256r1|
|secp384r1|secp384r1|
|secp521r1|secp521r1|

|**PSA_ECC_FAMILY_SECP_K1**|**Security Software Components**|
|---|---|
|secp256k1|secp256k1|

|**PSA_ECC_FAMILY_MONTGOMERY**|**Security Software Components**|
|---|---|
|Curve25519|Curve25519|
|Curve448|Curve448|

**Functions**

|**Mbed TLS**|**PSA Crypto**|
|---|---|
|int mbedtls_ecdh_compute_shared(…)|psa_status_t psa_raw_key_agreement(…)|
|—|psa_status_t psa_key_derivation_key_agreement(…)|

> **Note**: For the `psa_key_derivation_key_agreement(…)` function, refer to the PSA Crypto [KDF](#key-derivation) quick reference (ECDH and HKDF) and platform examples for details.

**Quick Reference Examples ECDH on secp256r1**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t client_private_key[] = {
    0xc8, 0x8f, 0x01, 0xf5, 0x10, 0xd9, 0xac, 0x3f, 0x70, 0xa2, 0x92, 0xda, 0xa2, 0x31, 0x6d, 0xe5,
    0x44, 0xe9, 0xaa, 0xb8, 0xaf, 0xe8, 0x40, 0x49, 0xc6, 0x2a, 0x9c, 0x57, 0x86, 0x2d, 0x14, 0x33
  };

  uint8_t client_public_key[] = { // Uncompressed point format
    0x04, 0xda, 0xd0, 0xb6, 0x53, 0x94, 0x22, 0x1c, 0xf9, 0xb0, 0x51, 0xe1, 0xfe, 0xca, 0x57, 0x87, 0xd0,
    0x98, 0xdf, 0xe6, 0x37, 0xfc, 0x90, 0xb9, 0xef, 0x94, 0x5d, 0x0c, 0x37, 0x72, 0x58, 0x11, 0x80,
    0x52, 0x71, 0xa0, 0x46, 0x1c, 0xdb, 0x82, 0x52, 0xd6, 0x1f, 0x1c, 0x45, 0x6f, 0xa3, 0xe5, 0x9a,
    0xb1, 0xf4, 0x5b, 0x33, 0xac, 0xcf, 0x5f, 0x58, 0x38, 0x9e, 0x05, 0x77, 0xb8, 0x99, 0x0b, 0xb3
  };

  uint8_t server_private_key[] = {
    0xc6, 0xef, 0x9c, 0x5d, 0x78, 0xae, 0x01, 0x2a, 0x01, 0x11, 0x64, 0xac, 0xb3, 0x97, 0xce, 0x20,
    0x88, 0x68, 0x5d, 0x8f, 0x06, 0xbf, 0x9b, 0xe0, 0xb2, 0x83, 0xab, 0x46, 0x47, 0x6b, 0xee, 0x53
  };

  uint8_t server_public_key[] = { // Uncompressed point format
    0x04, 0xd1, 0x2d, 0xfb, 0x52, 0x89, 0xc8, 0xd4, 0xf8, 0x12, 0x08, 0xb7, 0x02, 0x70, 0x39, 0x8c, 0x34,
    0x22, 0x96, 0x97, 0x0a, 0x0b, 0xcc, 0xb7, 0x4c, 0x73, 0x6f, 0xc7, 0x55, 0x44, 0x94, 0xbf, 0x63,
    0x56, 0xfb, 0xf3, 0xca, 0x36, 0x6c, 0xc2, 0x3e, 0x81, 0x57, 0x85, 0x4c, 0x13, 0xc5, 0x8d, 0x6a,
    0xac, 0x23, 0xf0, 0x46, 0xad, 0xa3, 0x0f, 0x83, 0x53, 0xe7, 0x4f, 0x33, 0x03, 0x98, 0x72, 0xab
  };

  // Expected shared secret:
  // d6 84 0f 6b 42 f6 ed af d1 31 16 e0 e1 25 65 20 2f ef 8e 9e ce 7d ce 03 81 24 64 d0 4b 94 42 de
  uint8_t shared_secret_buf[32];
  size_t shared_secret_len;
  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile client private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile client private plain key
  ret = psa_import_key(&key_attr, client_private_key, sizeof(client_private_key), &key_id);

  // Perform a key agreement with the server public key and then destroy the client private key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              server_public_key,
                              sizeof(server_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  ret = psa_destroy_key(key_id);

  // Set up attributes for a volatile server private plain key (secp256r1)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile server private plain key
  ret = psa_import_key(&key_attr, server_private_key, sizeof(server_private_key), &key_id);

  // Perform a key agreement with the client public key and then destroy the server private key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              client_public_key,
                              sizeof(client_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  ret = psa_destroy_key(key_id);
}
```

**ECDH on Curve25519**

```c++
#include "psa/crypto.h"

void app_process_action(void)
{
  uint8_t client_private_key[] = {
    0xB0, 0x76, 0x51, 0xEA, 0x20, 0xF0, 0x28, 0xA8,0x16, 0xEE, 0x01, 0xB0, 0xD1, 0x06, 0x2A, 0x7C,
    0x81, 0x58, 0xE8, 0x84, 0xE9, 0xBC, 0xC6, 0x1C, 0x5D, 0xAB, 0xDB, 0x4E, 0x38, 0x2F, 0x96, 0x69,
  };

  uint8_t client_public_key[] = {
    0x87, 0xD8, 0x6B, 0xDA, 0xAC, 0x38, 0x3C, 0x85, 0xA6, 0xBC, 0xF8, 0xFC, 0xC6, 0x26, 0xD6, 0x14,
    0x36, 0xE4, 0x8F, 0xDB, 0xFA, 0x5A, 0x45, 0xFE, 0x0C, 0x9E, 0xA8, 0x4B, 0x35, 0x3E, 0xF1, 0x37,
  };

  uint8_t server_private_key[] = {
    0x98, 0x2E, 0xB6, 0x7D, 0x0A, 0x01, 0x57, 0x90, 0xE1, 0x45, 0xF3, 0x67, 0xF6, 0xDA, 0xA6, 0x44,
    0x2C, 0x87, 0xC0, 0xED, 0x3C, 0x36, 0x71, 0xA6, 0x89, 0xC7, 0x49, 0xAC, 0x0D, 0xFE, 0x43, 0x6E,
  };

  uint8_t server_public_key[] = {
    0x0C, 0x04, 0x10, 0x5B, 0xE8, 0x7C, 0xAB, 0x37, 0x21, 0x15, 0x7A, 0x8D, 0x49, 0x85, 0x8C, 0x7A,
    0x9F, 0xC1, 0x46, 0xDA, 0xCC, 0x96, 0xEF, 0x6E, 0xD4, 0xDA, 0x71, 0xBF, 0xED, 0x32, 0x0D, 0x76,
  };

  // Expected shared secret:
  // F2 E6 0E 1C B7 64 BC 48 F2 9D BB 12 FB 12 17 31 32 1D 79 AF 0A 9F AB AD 34 05 A2 07 39 9C 5F 15
  uint8_t shared_secret_buf[32];
  size_t shared_secret_len;
  psa_status_t ret;
  psa_key_id_t key_id;
  psa_key_attributes_t key_attr;

  ret = psa_crypto_init();

  // Set up attributes for a volatile client private plain key (Curve25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile client private plain key
  ret = psa_import_key(&key_attr, client_private_key, sizeof(client_private_key), &key_id);

  // Perform a key agreement with server public key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              server_public_key,
                              sizeof(server_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  // Destroy the client private key
  ret = psa_destroy_key(key_id);

  // Set up attributes for a volatile server private plain key (Curve25519)
  key_attr = psa_key_attributes_init();
  psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY));
  psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_DERIVE);
  psa_set_key_algorithm(&key_attr, PSA_ALG_ECDH);

  // Import a volatile server private plain key
  ret = psa_import_key(&key_attr, server_private_key, sizeof(server_private_key), &key_id);

  // Perform a key agreement with client public key
  ret = psa_raw_key_agreement(PSA_ALG_ECDH,
                              key_id,
                              client_public_key,
                              sizeof(client_public_key),
                              shared_secret_buf,
                              sizeof(shared_secret_buf),
                              &shared_secret_len);

  // Destroy the server private key
  ret = psa_destroy_key(key_id);
}
```

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image29](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image29.png)

The following table describes the implementation status of the PSA Crypto ECDH platform example.

|**ECC Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Curve25519|Y|Y|Y|Hardware acceleration only on HSE devices.|
|Curve448|—|—|Y|Only on HSE-SVH devices with hardware acceleration.|

> **Note**:
> 
> - This example does not include secp224r1 and secp256k1. The secp256k1 ECDH on HSE devices is not yet implemented.
> - The PSA Crypto does not yet support software fallback on the Curve448.
> - The HSE-SVM devices require SE firmware v1.2.11 or higher (EFR32xG21) and v2.1.7 or higher (other HSE devices) to support hardware acceleration on Curve25519. This feature also requires GSDK v4.0.1 or higher.

###### X.509 Certificate (heading level 7)

An X.509 certificate is a digital certificate that uses the widely accepted international X.509 public key infrastructure (PKI) standard to verify that a public key belongs to the user, computer, or service identity contained within the certificate.

An X.509 certificate contains a public key and an identity (a hostname, an organization, an individual). It is either signed by a certificate authority or self-signed. When a certificate is signed by a trusted certificate authority or validated by other means, someone holding that certificate can rely on the public key it contains to establish secure communications with another party or validate documents digitally signed by the corresponding private key.

**Algorithms**

<table>
    <thead>
        <tr>
            <th><strong>Algorithm</strong></th>
            <th><strong>Mbed TLS</strong></th>
            <th><strong>PSA Crypto</strong></th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <p>ECDSA (SHA-2)</p>
            </td>
            <td>
                <p>—</p>
            </td>
            <td>
                <p>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_224)<br>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_256)<br>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_384)<br>
                    PSA_ALG_ECDSA(PSA_ALG_SHA_512)
                </p>
            </td>
        </tr>
    </tbody>
</table>

**Key Attributes in PSA Crypto**

|**Algorithm**|**Key Type**|**Key Size in Bits**|**Key Usage Flag**|
|---|---|---|---|
|• PSA_ALG_ECDSA(PSA_ALG_SHA_224)|PSA_ECC_FAMILY_SECP_R1|• secp192r1 : 192|• PSA_KEY_USAGE_SIGN_HASH|
|• PSA_ALG_ECDSA(PSA_ALG_SHA_256)| |• secp256r1 : 256|• PSA_KEY_USAGE_VERIFY_HASH|
|• PSA_ALG_ECDSA(PSA_ALG_SHA_384)| |• secp384r1 : 384| |
|• PSA_ALG_ECDSA(PSA_ALG_SHA_512)| |• secp521r1 : 521| |

> **Note**: The key usage flag must use PSA_KEY_USAGE_SIGN_HASH and PSA_KEY_USAGE_VERIFY_HASH.

**Security Software Components**

|**Algorithm**|**Security Software Components**|
|---|---|
|PSA_ALG_ECDSA(PSA_ALG_SHA_224)|ECDSA and SHA-224|
|PSA_ALG_ECDSA(PSA_ALG_SHA_256)|ECDSA amd SHA-256|
|PSA_ALG_ECDSA(PSA_ALG_SHA_384)|ECDSA and SHA-384|
|PSA_ALG_ECDSA(PSA_ALG_SHA_512)|ECDSA and SHA-512|

|**PSA_ECC_FAMILY_SECP_R1**|**Security Software Components**|
|---|---|
|secp192r1|secp192r1|
|secp256r1|secp256r1|
|secp384r1|secp384r1|
|secp521r1|secp521r1|

|**Built-in Key**|**Security Software Components**|
|---|---|
|secp256r1 keys in SE OTP|Built-In Keys|

|**Item**|**Security Software Components**|
|---|---|
|SHA-1 for X.509 certificate|SHA-1|

|**Item**|**Security Software Components**|
|---|---|
|X.509 certificate support|X.509|

**Using Opaque ECDSA Key to Generate Certificate Signing Request (CSR)**

1. Declare (and allocate) an object of type `mbedtls_pk_context` (PK context) and an object of type `psa_key_id_t` (key identifier).
2. Use the key identifier to generate an ECDSA key or load the built-in ECDSA key. Refer to the [Asymmetric Key](#asymmetric-key) for details.
3. Set up the PK context to wrap that PSA key by calling `mbedtls_pk_setup_opaque(mbedtls_pk_context \*ctx, const psa_key_id_t key)`.
4. Configure the pending CSR object to use that key by calling `mbedtls_x509write_csr_set_key(mbedtls_x509write_csr \*ctx, mbedtls_pk_context \*key)` on that PK context.
5. Call any other function that needs to configure and generate the CSR.
6. After generating the CSR, free the PK context using `mbedtls_pk_free(mbedtls_pk_context \*ctx)`. It only frees the PK context itself and leaves the key identifier untouched.
7. Either keep using the key identifier or call `psa_destroy_key()` on it, depending on the application flow.

**PSA Crypto Platform Example**

Click the `View Project Documentation` link to open the `readme` file.

![image30](/mbedtls-psa-crypto-porting-guide/0.1/images/sld817-image30.png)

The following table describes the implementation status of the PSA Crypto X.509 platform example.

|**ECDSA Key**|**Series 1**|**Series 2 - VSE**|**Series 2 - HSE**|**Remark**|
|---|---|---|---|---|
|secp192r1|Y|Y|Y|—|
|secp256r1|Y|Y|Y|—|
|secp384r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|secp521r1|Y|Y|Y|Hardware acceleration only on HSE-SVH devices.|
|Private Device Key|—|—|Y|Only on HSE-SVH devices.|

> **Note**: This example can select the Private Device Key (secp256r1) to generate the root certificate CSR.

### Network Performance

#### Network Performance

This section introduces ways to optimize a Wi-SUN network's performance.

- [**Using the Wi-SUN Network Measurement Application (PDF)**](https://www.silabs.com/documents/public/application-notes/an1364-wi-sun-network-performance-measurement-app.pdf): Describes how to use the Wi-SUN Network Measurement Application to test Silicon Labs Wi-SUN FAN stack performance.
- [**Silicon Labs Wi-SUN Mesh Network Performance (PDF)**](https://www.silabs.com/documents/public/application-notes/an1330-wi-sun-network-performance.pdf): Details methods for testing the Wi-SUN FAN stack network performance compared to other mesh networks available. When selecting a  
  network or device, designers need to know the network’s performance and behavior characteristics such as battery life, network connection time and latency, and the impact of network size on scalability and reliability.

#### Wi-SUN PAN Defect

##### Enhancing Silicon Labs Wi-SUN Networks' Reliability During Power Outages

In the world of wireless communication, ensuring uninterrupted connectivity is paramount. Wi-SUN networks, designed for robust and scalable IoT deployments, face unique challenges during power outages, particularly when the Border Routers lose their main power source. This topic introduces an innovative feature that empowers Silicon labs Wi-SUN Networks to handle Border Router power issues faster, and enables seamless transitions to alternative Personal Area Networks (PANs), ensuring reliability and performance under adverse conditions.

##### The Role of PAN Defect IE in Power Outage Management

The **PAN Defect Information Element (IE)** is a game-changer for Silicon Labs Wi-SUN networks. It acts as a network-wide alert, signaling routers that the Border Router has lost its primary power source. This feature prompts a proactive response, enabling routers to explore and transition to alternative PANs, thereby maintaining uninterrupted connectivity.

A common scenario involves equipping the border router with a backup battery to handle power outages. The PAN Defect IE plays a crucial role in this setup by providing two essential options that ensure smooth network transitions.

- **min_scan_duration_s**: This option specifies the minimum time the leaf nodes should wait before transitioning to another network.
- **max_scan_duration_s**: Once this duration is reached, all nodes will transition to another PAN if it exists, regardless of conditions.

The following figure illustrates a timeline of the backup battery life, highlighting the two PAN Defect IE options and the potential actions taken at each interval.

![Backup Battery life](/wisun-pan-defect/0.1/images/sld512-image1.png)

###### Key Considerations

- **Interoperability**: As the PAN Defect IE is a non-standard feature, non-Silicon Labs devices will not recognize it, but will forward it in PCs.
- **Optimized Timing**: Set `max_scan_duration_s` to less than the backup power's expected lifetime to ensure timely transitions without network interruptions.

##### PAN Defect in Action

In this section, we explore the different phases of nodes transition from the dying PAN to a well functioning alterative PAN. From the power issue detection by the Border Router application to the PAN transition, each step ensures resilience and continuity of the network.

###### 1. Detection

When the Border Router application detects a power issue, it incorporates the PAN Defect IE into the PAN Configuration packets (PC).

###### 2. Notification

The Border Router disseminates the PAN Defect IE across the network, halting new connections and notifying all routers of the issue.

###### 3. Nodes Response

Nodes receiving the PAN Defect IE take the following steps:

- **Forwarding the Alert**: The IE is shared across the network.
- **Scanning for Alternatives**: Nodes start searching for new parent routers with different PAN IDs.
- **Transitioning**: Nodes start transitioning to the alternative PAN or not, following the roaming procedure. The following section explains this step in detail.

##### Transitioning Scenarios

To ensure smooth transitioning, the nodes behave differently depending on if they are leaf nodes or if they are routers with children. This transition mechanism differentiation, guarantees an efficient gradual transition ensuring minimal disruption.

###### Leaf Nodes

When the `min_scan_duration_s` is reached, leaf nodes transition to an alternative PAN immediately upon finding a suitable parent in the new PAN and making sure that a PC has been sent.

###### Routers With Children

Routers with children keep their current PAN while they continue to scan for an alternative PAN until either:

- **`max_scan_duration_s` is reached**: At this point, they ensure at least one PC has been sent, and transition.
- **No alternative PAN is found**: The scan continues while maintaining the current PAN.

###### Fallback Mechanism

If no alternative PAN is available, routers will stay connected to the defective Border Router while it is alive and persistently scan for an alternative PAN.

##### PAN Defect Implementation

Because of its PAN wide nature, the PAN Defect IE configuration and enablement, solely relies on the Border router. To implement the the PAN Defect in your network, follow the steps below.

###### Monitor the BR Power Source

The Border Router application should monitor the Border Router's power status. When a power issue is detected, it should enable the PAN Defect IE advertisement.

###### Enable PAN Defect Advertisement

###### Using Wi-SUN - SoC Border Router (heading level 7)

On the **Wi-SUN - SoC Border Router**, use the API `sl_wisun_br_pan_defect_advertise()` to enable or disable the PAN Defect advertisement and configure the `min_scan_duration_s` and the `max_scan_duration_s`:

```c
sl_wisun_br_pan_defect_advertise(bool defect_advertise, uint32_t min_scan_duration_s, uint32_t max_scan_duration_s);
```

- `defect_advertise`: Enable or disable PAN defect advertisement.
- `min_scan_duration_s`: Minimum time before transitioning if conditions are met.
- `max_scan_duration_s`: Time after which routers must transition to an alternative PAN.

###### Using the Linux Border Router (heading level 7)

On the Linux Border Router, the Pan Defect can be managed either by the `wsbrd_cli` or dBus depending on the user preference.

**Via `wsbrd_cli`**:

Use the `wsbrd_cli` command to manage the PAN Defect IE:

- To start the IE advertisement and set the `max_scan_duration_s` and `max_scan_duration_s`, use the following command:  
  ```bash  
  sudo wsbrd_cli pan-defect start [min_scan_duration_] [max_scan_duration_s]  
  ```
- To stop the IE advertisement, use the following command:  
  ```bash  
  sudo wsbrd_cli pan-defect stop  
  ```

**Via dBus**:

The `wsbrd` dBus APIs allow setting a custom IE in the PAN Configuration packet using [`IeCustomInsert`](https://github.com/SiliconLabs/wisun-br-linux/blob/main/DBUS.md#iecustominsert-yyayay).

- Refer to the following command example to **enable** PAN Defect using dBus:  
  ```bash  
  sudo gdbus call --system --dest com.silabs.Wisun.BorderRouter --object-path /com/silabs/Wisun/BorderRouter --method com.silabs.Wisun.BorderRouter.IeCustomInsert -- 1 0x49  
  ```  
  - **1** to indicate nested short Wi-SUN payload IE (WP-IE).  
  - **0x49** is the id of the PAN defect IE.  
  - **[0x01,0x3C,0x00,0x00,0x00,0x58,0x02,0x00,0x00]** is the content of the IE described as follow:    
    - byte 0: enable1/disable:0 (in the example provided: 0x01)    
    - byte 1→ byte 4: min_scan_duration_s (in the example provided: 0x3C,0x00,0x00,0x00 → 60sec)    
    - byte 5 → byte 9: max_scan_duration_s (in the example provided: 0x58,0x02,0x00,0x00 → 600sec)  
  - **[0x02]** to include the IE in PC Wi-SUN frame types.
- The following command can be used to **stop** including the PAN defect IE in the PC packets:  
  ```bash  
  sudo gdbus call --system --dest com.silabs.Wisun.BorderRouter --object-path /com/silabs/Wisun/BorderRouter --method com.silabs.Wisun.BorderRouter.IeCustomInsert -- 1 0x49 [] []  
  ```

##### Simulation Results

To evaluate the performance and effectiveness of the PAN defect feature, Silicon Labs conducted a series of simulations using various network topologies and sizes. These tests aimed to compare two scenarios:

- With PAN Defect Feature: The border router proactively informs nodes before going offline.
- Without PAN Defect Feature: The border router abruptly goes offline without prior notification.

For each simulation, one key metric was analyzed:

- **Node Downtime**: The time each node remains disconnected during the recovery process.

The results highlight the significant advantages of the PAN defect feature in minimizing disruption.

###### Test Scenario

We will conduct two different tests, one with 150 nodes and the second with 300 nodes.

**Topology**

We adopted a mesh topology for the evaluation test with a distance of 300 meters between the nodes. The main Border Router is in the middle of the network, and the alternative Border router is placed in the corner in both tests. The following figures are for the 150 nodes test, we used the same topology for 300 nodes test.

![Network Topology](/wisun-pan-defect/0.1/images/sld512-image3.png)

**Network and PAN defect Configuration**

The network configuration is set to a _**medium**_ [profile](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-ffn-parameter-sets#sl-wisun-params-profile-medium). The supposed backup battery life is 30 minutes and the PAN Defect options are set to the following:

- `min_scan_duration_s`: Set to 300 seconds.
- `max_scan_duration_s`: Set to 1200 seconds.

Below is a summary of the simulation results:

###### Test Results (heading level 7)

The table below resumes the test results:

![Nodes Downtime Test Results](/wisun-pan-defect/0.1/images/sld512-image2.png)

##### Conclusion

By integrating the PAN Defect IE, Wi-SUN networks can maintain high performance and reliability during power outages, ensuring devices and applications remain connected. This proactive approach minimizes downtime, making Wi-SUN networks a trusted choice for resilient IoT deployments.

#### Performance Results

This page summarizes Wi-SUN network performance measured on a real physical setup with up to 1000 nodes. It focuses on the questions that usually matter first in a deployment.

- How quickly does the network form or reconnect?
- How stable is application traffic over time in terms of metering report success rate?
- What about network latency? What factors drive CoAP response latency?
- How long does firmware update over the air (FUOTA) take?

##### Test Setup

###### Hardware

- Linux Border Router (wsbrd) = Raspberry Pi 4B + RCP [BRD4271A](https://www.silabs.com/development-tools/wireless/proprietary/fg25-rb4271a-efr32fg25-radio-board?tab=overview)
- 750 EFR32FG25 radio boards [BRD4271A](https://www.silabs.com/development-tools/wireless/proprietary/fg25-rb4271a-efr32fg25-radio-board?tab=overview)
- 250 EFR32FG28 radio boards [BRD2705A](https://www.silabs.com/development-tools/wireless/efr32xg28-explorer-kit?tab=overview)

![hw-setup](/wisun-performance-results/0.1/images/resized-sld1089-hw-setup.png)

###### Software

- **wsbrd tag v2.9**
- FFN: Si-SDK 2025.12.2 [Node monitoring](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/README.md) application
- RCP: Si-SDK 2025.12.2 **Wi-SUN - RCP** application sample

###### Configuration

- PHY: Europe, Chan_planID 33, Phy_ModeID 1/3/5 (50 kbps / 100 kbps / 150 kbps)
- Network_size: SMALL, MEDIUM, LARGE
- Nodes traffic: Once connected, each node sends a ~500 B UDP packet to the BR every 15 minutes

##### Network formation

Network formation was measured in two scenarios:

- **Connection:** Occurs when a node has not saved the key or when there is a key mismatch with the Border Router. This typically happens during initial network formation or Border Router replacement.  
  - Test process: all nodes and the Border Router are powered down, caches are cleared, the Border Router restarts with a new PAN ID, then all nodes are powered up.
- **Reconnection:** Occurs when a node has already connected to the network and authenticated. This typically happens in case of device reboots after a power shutdown.  
  - Test process: all nodes are power cycled while the Border Router remains active.

The reconnection case is expected to be faster since join state 2 authentication is skipped.

###### Connection/Reconnection 1000 Nodes MEDIUM 100 kbps

![co-reco-1000-medium-100kbps](/wisun-performance-results/0.1/images/sld1089-co-reco-1000-medium-100kbps.png)

![co-reco-1000-medium-100kbps-avg](/wisun-performance-results/0.1/images/sld1089-co-reco-1000-medium-100kbps-avg.png)

With network size MEDIUM:

- First device to connect takes approximately 4 minutes
- First device to reconnect takes approximately 2 minutes

Network size defines connection parameters. The larger the network, the more connection timing parameters must be increased to avoid congestion.

Example:

- SMALL: Imin_PA = 15 s, Imax_PA = 60 s (same for PAS, PC, PCS)
- MEDIUM: Imin_PA = 60 s, Imax_PA = 960 s (same for PAS, PC, PCS)

This means that in MEDIUM, fewer PAS, PA, PCS, and PC messages are sent per node across the network. It reduces load on the air but adds latency in detecting PA/PC messages and initiating the join or rejoin process.

###### Connection/Reconnection 250 Nodes MEDIUM/SMALL 100 kbps

![co-reco-250-small](/wisun-performance-results/0.1/images/sld1089-co-reco-250-small.png)

With network size SMALL:

- First device to connect takes approximately 1 minute
- First device to reconnect takes approximately 40 seconds

![co-reco-250-vs-size-avg](/wisun-performance-results/0.1/images/sld1089-co-reco-250-vs-size.png)

###### Connection 500 Nodes MEDIUM vs PHY rate

![co-500-medium-vs-phy](/wisun-performance-results/0.1/images/sld1089-co-500-medium-vs-phy.png)

With the same connection parameters (network size), PHY rate has a significant impact on connection and reconnection timing. A higher bit rate reduces the time required to propagate the same information. The Border Router is highly solicited during network formation; increasing the PHY bit rate helps reduce its load.

###### Summary Matrix Result

The matrix below presents the average connection and reconnection times (based on four tests for each network configuration).

![matrix-result](/wisun-performance-results/0.1/images/sld1089-matrix-result.png)

Network formation timing depends on the following factors:

- Number of nodes in the network and topology
- Network size (connection parameters), which significantly impacts timing
- PHY bit rate

> **Note:** Network size SMALL provides better network formation timing for networks ≤ 250 nodes. For larger networks (e.g., 500 nodes), connection parameters become too aggressive relative to the number of nodes, leading to congestion and degraded performance.

The following summary graph shows results for different network node counts with a PHY rate of 100 kbps and the optimal network size configuration selected:

![network-formation-avg](/wisun-performance-results/0.1/images/sld1089-network-formation-avg.png)

##### Network stability

The following table represents a metering report use case for a test performed on a 1000-node network over more than 10 days:

|Running Time|Total Nodes|UDP packet RX|UDP packet lost|Success rate %|Parent Changes|
|---|---|---|---|---|---|
|10d 19:05:52|1000|1035398|555|99.947%|1063|

Once connected, each node sent a ~500 B UDP packet to the BR every 15 minutes.

The measured application packet success rate was **99.946%** over a period of **more than 10 days**.

##### Network latency

The objective is to evaluate the end-to-end latency of a CoAP transaction, from the moment a command is sent by the Border Router to a node until the corresponding response is successfully received.

- CoAP requests are sent individually to each node from the BR
- If a response is not received within a 4-second timeout, a new request is sent
- Node responds with a 322 B CoAP payload message
- All response time values presented are averages over 10 tests
- The Response Time (RT) corresponds to the total elapsed time from the first transmission attempt (including the time required to send the CoAP request) to the successful reception of the response. This measurement includes any retransmissions due to timeouts, as well as network propagation and node processing delays.

![latency-process](/wisun-performance-results/0.1/images/sld1089-latency-process.png)

Below are response time results as a function of five different networks with 50 / 100 / 250 / 500 / 1000 nodes and hop count:

![latency-vs-node-count](/wisun-performance-results/0.1/images/sld1089-latency-vs-node-count.png)

- Latency is independent of node count
- Latency depends on hop count

Another parameter to consider is the PHY bit rate:

![latency-vs-phy-rate](/wisun-performance-results/0.1/images/sld1089-latency-vs-phy-rate.png)

Latency depends on PHY bit rate.

##### Firmware upgrade OTA

###### OTA unicast TFTP

Test performed with component **Wi-SUN Over-The-Air Device Firmware Upgrade (OTA DFU)**.

**Setup:**

- 1000-node network - PHY rate 100 kbps
- 380 KB firmware GBL (LZMA compressed)
- Nodes pull firmware image from the Border Router in 1200 B chunks
- Measured on ~20 nodes with different hop counts

![OTA-unicast-tftp](/wisun-performance-results/0.1/images/sld1089-ota-unicast-tftp.png)

OTA using unicast TFTP ensures safe delivery of the full image to each node.

Average delivery time per node: 380 seconds → 6 minutes 20 seconds

- 100 nodes → ~10.5 hours
- 500 nodes → ~53 hours
- 1000 nodes → ~105 hours

> **Note:** Firmware delivery depends on hop count and PHY rate. OTA unicast TFTP impacts other application unicast traffic.

###### OTA multicast

Test performed following [Node monitoring OTA multicast readme](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_wisun_multicast_ota.md).

**Setup:**

- 1000-node network at 100 kbps PHY rate
- `broadcast_interval = 1020 ms`
- Network size MEDIUM with default MPL parameters
- 380 KB firmware GBL, LZMA compressed
- Border Router sends 1024 B chunks by multicast every 40 seconds
- After all chunks are propagated, a CoAP request is sent to all nodes to identify missing chunks
- Missing chunks are then resent by unicast
- Default MPL parameters:

```C
  .mpl = {
    .trickle = {
      .imin_s = 1,
      .imax_s = 32,
      .k = 8,
    },
    .seed_set_entry_lifetime_s = 576,
    .trickle_expirations = 2,
    .seed_id_type = 0,
  },
```

**Performance results:**

- Delivery time is predictable: **380 chunks** sent every **40 seconds**
- Total multicast delivery time: **254 minutes**, or **4 hours 14 minutes**
- Delivery time is independent of the number of nodes being updated
- Only a few chunks need to be resent to a small number of nodes by unicast

###### OTA Unicast vs Multicast comparison

Unicast TFTP averaged approximately **6 minutes 20 seconds per node**. Multicast takes a fixed **254 minutes** for the full fleet, so the effective time per node improves as the number of target nodes increases.

|Nodes Updated|Multicast Effective Time per Node|
|---|---|
|40|~6 min 21 sec|
|100|~2 min 35 sec|
|250|~1 min 1 sec|
|500|~30 sec|
|1000|~15 sec|

> **Note:** Broadcast uses dedicated time slots, so regular **unicast traffic is NOT impacted**. Delivery time in broadcast is independent of the number of nodes to update.

#### Using the Wi-SUN Network Measurement Application

##### Using the Wi-SUN Network Measurement Application

**NOTE: This section replaces _AN1364: Using the Wi-SUN Network Measurement Application_. Further updates to this application note will be provided here.**

The Wi-SUN Network Measurement Application provides a simple tool for testing Silicon Labs Wi-SUN FAN (Wireless Smart Ubiquitous Network, Field Area Network) stack performance. Using the IPv6 ping capability, the application can trigger round-trip latency tests within a Wi-SUN mesh network. It provides information about the packet error rate, Routing Protocol for Low-Power and Lossy Networks (RPL) routing metrics, average ping latencies with different neighbors, and more. To do so, the application exposes two interfaces: a Command Line Interface (CLI) and the WSTK mainboard LCD screen.

The Wi-SUN FAN stack is supported on the EFR32FG12 and EFR32MG12 devices. The radio boards used must support one of the sub-GHz bands.

Silicon Labs recommends that you review the [Quick Start Guide](/wisun/2.12.0/wisun-getting-started-development) to familiarize yourself with the Silicon Labs Wi-SUN stack and Simplicity Studio 5 before reading this document.

The following features are provided as part of the Wi-SUN Network Measurement application:

- Transmits pings and receives pong replies.
- Computes ping latencies.
- Configures the number of pings to be sent during a test.
- Configures the ping payload size.
- Configures the devices to target with the ping packets.
- Provides the minimum, maximum, and average ping latencies on a given test.
- Provides the ping error rate, the MAC-level packet error rate, and RPL metrics.
- Enables access to the previous features through an LCD screen or a CLI. In addition to these features the Wi-SUN Network Measurement application behaves like a standard Wi-SUN router once connected to a Wi-SUN network. During the connection steps, it automatically selects a suitable parent to connect to the network. When connected, it can be selected by another Wi-SUN device to be its parent.

The Wi-SUN Network Measurement application requires you to have at least two WSTK mainboards and two preferably from the following list of matching radio boards:

- brd4163a
- brd4164a
- brd4170a
- brd4172a
- brd4173a
- brd4253a
- brd4254a

##### Theory of Operation

This section discusses the operation of the Wi-SUN Network Measurement application independently from the interface. You can execute these either through the CLI or the LCD screen interface. Specific interface information is shared in the following sections.

For the first step you need to start a Wi-SUN network using one of these solutions:

- The Wi-SUN SoC Border Router demo available in the SiSDK through Simplicity Studio 5
- The [Wi-SUN Linux Border Router solution](/wisun/2.12.0/wisun-linux-border-router).

Follow the steps to get your border router up and running and move to the next chapter.

###### Flash the Application

In the Simplicity Studio 5 Launcher perspective, select the EFR32 evaluation kit you want to use to run the Wi-SUN Network Measurement application. In the **EXAMPLE PROJECTS & DEMOS** panel, find the **Wi-SUN - SoC Network Measurement** project, and click **CREATE** to add it to your workspace.

Finally, build the wisun_soc_network_measurement project and flash it on the selected EFR32. Refer to the [Quick Start Guide](/wisun/2.12.0/wisun-getting-started-development) for the detailed steps.

###### Connect to a Wi-SUN Network

By default, the Wi-SUN Network Measurement application tries to connect to the **Wi-SUN Network**. If a network with this name and a matching Wi-SUN PHY configuration is available nearby, the **Performance Measurement** node connects to it using the best parent node available (selected by the RPL routing protocol).

There are two solutions to change the default network name:

- Using Simplicity Studio 5 prior to building the project: open the wisun_soc_network_measurement.slcp file and go to the **SOFTWARE COMPONENTS** panel. After you select the **Wi-SUN/Application/Setting** component, you can configure the default connection settings. Under **Wi-SUN network configuration**, modify the **Network Name** parameter to match the name of your Wi-SUN network.
- Use the CLI available in the application. For more information, see [Command Line Interface](./04-command-line-interface).

Each EFR32 radio board reference number defaults to a specific Wi-SUN PHY configuration matching its radio capabilities. To change the Wi-SUN PHY used by the project, refer to [Wi-SUN Configurator](/wisun/2.12.0/wisun-configurator/#radio-panel).

###### Start a Ping Test

You can trigger a ping test using either interface of the Wi-SUN Network Measurement application (LCD screen or CLI). The test consists of emitting ping packets on the Wi-SUN network to an IPv6 target (other Wi-SUN nodes or external IPv6 devices). This device replies with pong packets for each ping received. When the pong is received by the **Performance Measurement** node, the Wi-SUN Network Measurement application computes a round-trip latency on the communication link. During the test, the Wi-SUN Network Measurement application monitors several metrics to provide insights into the Wi-SUN stack behavior.

###### Retrieve Test Results

After a ping test has ended, test results are available. They sum up the following information:

- Ping packet loss percentage
- Minimum ping latency in milliseconds
- Maximum ping latency in milliseconds
- Average ping latency in milliseconds

In addition to the ping test results, the Wi-SUN Network Measurement application also monitors metrics associated with the Wi-SUN stack.

###### Impact of Wi-SUN signaling on ping test results (heading level 7)

Due to the characteristics of a Wi-SUN network, where network management such as PAN advertising can take a certain time (it requires sending a PAN Advertisement on each channel, and there are often as much as 129 channels), using a ping to measure network latency needs to be taken cautiously.

Over several pings there will be mostly short ping durations, and some longer durations when network signaling takes precedence over data transmission. When network signaling occurs, the ping duration will be impacted.

The 'max' and 'average' ping results will be impacted by network management. To get a valid 'latency' value to compare between PHYs configurations, we'll only keep the 'min' ping duration of at least 100 pings in tables and graphs below. The ‘Wi-SUN SoC Network Measurement’ application is designed to allow this test.

> **Note**: The `network_size` parameter will have a significant impact on these 'signaling perturbations'. The smaller network sizes use more frequent network signaling and therefore have the highest impact.

###### Wi-SUN Metrics

To provide a better understanding on the Wi-SUN stack behavior the stack maintains internal statistics. The Wi-SUN Network Measurement application monitors several metrics during the tests:

- Lifetime
- MAC transmission count
- MAC transmission failed
- RPL rank
- Expected Transmission Count (ETX)
- Received Signal Level OUT (RSL out)
- Received Signal Level IN (RSL in)

The metrics are maintained for each neighbor device in the routed network (that is, the parent and all of the children in the RPL mesh tree). Each metric is described in the following sections.

###### Lifetime (heading level 7)

The lifetime is a counter maintained with each neighbor to evaluate the state of the connection with this device. After each successful unicast communication with the neighbor, the counter is reset to 2200 seconds. When no unicast communication is exchanged with the neighbor, the counter is decreased each second.

###### MAC Transmission Count (heading level 7)

The MAC transmission count (or MAC TX count) represents the number of packets transmitted over the air. A single ping attempt can result in several MAC-level transmission if the first attempts have not been successful. The number also considers packets not related to the ping test itself. Packets routed by the device to its parent and network maintenance related communications also increase this number.

###### MAC Transmission Failed (heading level 7)

The MAC transmit failed (or MAC TX failed) represents the number of unsuccessful transmission attempts. In the Wi-SUN FAN specification, the peer must acknowledge every unicast packet. If a packet is not acknowledged within a given timeout, the transmission is considered failed. The packet is retransmitted by the Wi-SUN stack MAC layer until it reaches the maximum number of transmission attempts.

###### RPL Rank (heading level 7)

The RPL rank represents the rank or hop distance from the tree root (that is, the Wi-SUN border router). For more information, see section 3.5 of [RFC 6550](https://datatracker.ietf.org/doc/html/rfc6550).

###### Expected Transmission Count (heading level 7)

The Expected Transmission Count (ETX) is an Exponentially Weighted Moving Average (EWMA) of the number of expected packet transmissions required for error-free reception at destination. The ETX is calculated as (frame transmission attempts)/(received frame acknowledgements) *128 with a maximum value of 1024, where 0 received frame acknowledgments sets ETX to the maximum value. This metric is maintained as part of the RPL protocol [RFC 6550](https://datatracker.ietf.org/doc/html/rfc6550) and participates in the best parent selection.

###### Received Signal Level OUT (heading level 7)

The Received Signal Level out (RSL out) is an EWMA of the received signal level for the node-to-neighbor direction. The RSL is calculated as the received signal level relative to standard thermal noise (290°K) at 1 Hz bandwidth or -174 dBm. This provides a range of -174 (0) to +80 (254) dBm.

###### Received Signal Level IN (heading level 7)

The Received Signal Level in (RSL_in) is an EWMA of the received signal level for the neighbor-to-node direction. The RSL is calculated as the received signal level relative to standard thermal noise (290°K) at 1 Hz bandwidth (= -174 dBm). This provides a range of -174 (0) to +80 (254) dBm in 1 dBm steps. The RSL_in value is communicated through an information element in the Wi-SUN packet exchanges between the device and its neighbor.

###### Test Configuration

The Wi-SUN Network Measurement application provides several settings to configure the ping test. The capabilities vary depending on the interface used but some of the configurations are shared:

- **Packet count**: Defines the number of ping packets sent per target during the tests (default value 10). If the test targets the border router and the parent, 10 ping attempts would be sent to the border router followed by 10 attempts targeting the parent.
- **Packet length**: Defines the payload size of the ping packet sent to the targets (default value 40). The size corresponds to the ICMPv6 payload including type field (1 byte), code (1 byte), checksum (2 bytes), identifier (2 bytes), sequence number (2 bytes), and finally data field (dependent on the packet length configuration).
- **Target devices**: Defines which Wi-SUN devices are targeted by the ping test. There are three options:  
  - Every known device, that is, the border router, the parent, and the device children  
  - The border router  
  - The parent

> **Note**: If the device running the Wi-SUN Network Measurement application is connected directly to the border router, the parent device and the border router are equivalent.

##### LCD Screen Interface

The first interface that can be used to interact with the Wi-SUN Network Measurement application is the mainboard LCD screen and two push buttons. They provide an easy-to-use interface to configure/start ping tests and consult the test results. The LCD interface can leverage most of the application features with few limitations related to the limited interface it offers (for example, it is not possible to input an IPv6 address to start a test with a “unknown” device).

> **Note**: When using the LCD screen interface, keep track of the actions associated with each push button because they can change depending on the context.

###### Connection Screen

The Wi-SUN Network Measurement application starts with a connection attempt to the Wi-SUN network configured in the project. The network name is displayed in the upper part of the screen. The connection steps are shown in the lower section (Wi-SUN connection steps 1 to 5 on the LCD screen).

![Connection Screen](/wisun-network-performance-measurement-app/0.2/images/sld726-image1.png)

When the node is successfully connected to the Wi-SUN network, the Wi-SUN Network Measurement application switches the screen to display the main menu.

**Note**: If the Wi-SUN Network Measurement application is stuck in the connection step 1 **Select PAN**, verify the configuration used matches the border router configuration (network name and Wi-SUN PHY used).

###### Main Menu

The Network Measurement main menu provides access to the Wi-SUN Network Measurement application main features. Scroll down through the options using push button 1 (**PB1**). Select a sub-menu using **PB0**.

![Main Menu](/wisun-network-performance-measurement-app/0.2/images/sld726-image2.png)

###### Node Info Screen

The Node Info screen displays information related to the Wi-SUN device and its configuration (network name, Wi-SUN PHY configuration, TX power, IPV6 addresses, and so on). You can scroll through the information available using **PB0**.

![Node Info Screen](/wisun-network-performance-measurement-app/0.2/images/sld726-image3.png)

###### Start Test Option

If you select **Start Test** on the main menu, the Wi-SUN Network Measurement application starts a ping test with the settings previously configured with the other menus. A progress bar indicates the number of ping packets sent over the packet count configured for the test. The test is replicated for each configured target device (border router, parent, and children).

![Test in Progress Screen](/wisun-network-performance-measurement-app/0.2/images/sld726-image4.png)

You can stop the test for a given target at any time by pressing **PB1**. When the tests are completed, pressing **PB0** opens the test results display.

###### Test Results Display

You can access the Test Results display either after a test or from the main menu. The results are split for each available target. When you select a target, you access its test results, including the ping packet loss and associated percentage, the minimum/maximum/average ping latency, the test settings, and the associated RPL metrics.

###### Neighbors Info Screen

The Neighbors Info screen provides access to metrics individualized per neighbor device. This includes the mandatory parent in the Wi-SUN network but also all the potential children using the device to communicate with the rest of the network. The information includes the device IPv6 address and numerous RPL-related metrics.

###### Settings Menu

The Settings menu enables you to configure the ping test settings like packet count, packet length, and target devices. In each sub-menu, the currently configured value is displayed in the upper black box. You can select a new value using the two push buttons.

In the following figure, the application packet count is currently configured to 10 packets.

![Packet Count Configuration Menu](/wisun-network-performance-measurement-app/0.2/images/sld726-image5.png)

##### Command Line Interface

The CLI provides an alternative interface to the LCD screen with additional features and test scripting. In addition to exposing a broader API, the CLI enables you to:

- Configure the network name, network size, and TX output power.
- Control the connection state.
- Connect or disconnect the Wi-SUN node.
- Input IPv6 addresses to perform ping tests with devices other than the border router, parent, and children.
- Configure IPv6 UDP iperf tests

The Wi-SUN Network Measurement application leverages the common Wi-SUN application CLI for standard Wi-SUN actions. It adds a specific “measure” command that can start ping tests equivalent to the one triggered from the LCD screen interface.

Three command domains are available: `about`, `wisun`, and `iperf`. You can list these by executing `help`:

```sh
> help

about                         Get info about the running app
iperf                         iPerf2 commands
wisun                         Wi-SUN commands
```

The `about` command domain is limited to displaying information about the current application (it is provided by the ‘app info’ component).

```sh
about
Wi-SUN Network Measurement Application
Versions:
  * Compiler (GCC): 10.3.1
  * Micrium OS kernel: 5.12.1
  * Wi-SUN: 1.1.0
  * mbed TLS: 3.1.0

\>
```

You can access the list of `wisun` commands by executing `wisun help` at the command prompt:

```C
> wisun help

join_fan10                    Connect to a Wi-SUN network using FAN1.0 settings
join_fan11                    Connect to a Wi-SUN network using FAN1.1 settings
join_explicit                 Connect to a Wi-SUN network using explicit PHY settings
disconnect                    Disconnect from the Wi-SUN network
set                           Set a variable
                              [*] empty | help | [string] Key [string] Value
get                           Get a variable
                              [*] empty | help | [string] Key
save                          Save variables to non-volatile storage
reset                         Reset variables to default settings
measure                       Measure a remote host or quick measurement
                              [string] Remote address or 'all' or 'parent' or 'br'
                              [uint16] Count of measurement packets
                              [uint16] Measurement packet length
ping                          Ping a remote host

                              [string] Remote address
```

And the list of `iperf` commands by executing `iperf help` at the command prompt:

```sh
> iperf help
  get                           Get configuration parameters
                                [*] empty | [string] Key
  set                           Set configuration parameters
                                [*] empty | [string] Key [string] Value
  server                        Start preconfigured iPerf Server test
                                [*] help
  client                        Start preconfigured iPerf Client test
                                [*] help
```

For `wisun` or `iperf` command domains, `set` and `get` functions are available to check (`<domain\> get`) or change (`<domain\> set`) current settings. To only list existing settings, use `<domain> get <subdomain> help`.

The Wi-SUN Network Measurement application maintains Wi-SUN network settings that you can access by executing `wisun get wisun`. This returns all the settings available in the Wi-SUN CLI component. You can check whether a setting is only readable by executing `wisun get wisun help` or if it can be modified (by executing `wisun set`) as shown in the following examples.

```sh
> wisun get wisun help

[rw] wisun.network_name
[rw] wisun.network_size
[rw] wisun.tx_power
[rw] wisun.regulatory_domain
[rw] wisun.operating_class
[rw] wisun.operating_mode
[ro] wisun.connection_state
[ro] wisun.ip_address_global
[ro] wisun.ip_address_link_local
[ro] wisun.ip_address_border_router
[rw] wisun.regulation                                         Regional regulation [uint8]
[rw] wisun.regulation_warning_threshold                       Transmission warning threshold in
                                                              percent (-1 to disable) [int8]

[rw] wisun.regulation_alert_threshold                         Transmission alert threshold in percent
                                                              (-1 to disable) [int8]
```

Similarly, the writable settings are listed when you execute `wisun set wisun help`.

```sh
> wisun set wisun help

[rw] wisun.network_name
[rw] wisun.network_size
[rw] wisun.tx_power
[rw] wisun.regulatory_domain
[rw] wisun.operating_class
[rw] wisun.operating_mode
[rw] wisun.regulation                                         Regional regulation [uint8]
[rw] wisun.regulation_warning_threshold                       Transmission warning threshold in
                                                              percent (-1 to disable) [int8]
[rw] wisun.regulation_alert_threshold                         Transmission alert threshold in percent

                                                              (-1 to disable) [int8]
```

This list is the same as the `get` list without the read-only ([ro]) values.

The `iperf` command domain has additional help about the possible parameters, accessible using `iperf get help`.

```sh
> iperf get help
Help of iperf 'get' and 'set' methods

Available sub-domains :
 options
 results

[csut]: corresponds to client/server/udp/tcp. Indicates in which case the parameter applies

Type 'iperf [get or set] \<sub-domain\> help'

eg. 'iperf get options help' to get the help of all options
    'iperf get options' for all current options values
    'iperf get results' for test results
    'iperf get options.\<option\>' for a specific option value
```

This shows that there are 2 `iperf` sub-domains: `options` and `results`.

Since options may differ depending on the test case (Client or Server, UDP or TCP), an indicator is added on each line:

```sh
[csut]: corresponds to client/server/udp/tcp. Indicates in which case the parameter applies
```

So, options can be displayed using `iperf get options help`.

```sh
iperf get options help
[csu ] options.port                     Server port to listen on/connect to [uint16] (default 5001)
[c u ] options.remote_addr              IPv6 remote host address  [string]
[c u ] options.bandwidth                Unused if packet_number is set. Otherwise used to compute
                                        Packet_number as bandwidth\*duration/buffer_length  [uint32]
                                        (default 20000)
[csu ] options.bw_format                Unused if packet_number is set. One of [bits/s, Kbits/s,
                                        Mbits/s, Gbits/s, bytes/s, Kbytes/s, Mbytes/s, Gbytes/s]
                                        [string] (default bits/s)
[c u ] options.packet_number            Number of packets to send. (Rules out bandwidth)  [uint16]
                                        (default 0=unset)
[c u ] options.buffer_length            buffer_length
[c u ] options.duration                 Test duration in seconds [uint16] (default 10)
[csu ] options.interval                 Seconds between periodic bandwidth reports  [uint16]
                                        (default 1)
>
```

Above, we see that the iperf server has only a limited number of options: `port`, `bw_format`, and `interval`, while the iperf client has more.

By default, `options.packet_number` is not set, and the actual value used during an iperf client test is computed based on `bandwidth`, `duration`, and `buffer_length`. This is used for most tests.

Similarly, results can be displayed using `iperf get results help`.

```sh
> iperf get results help
[csu ] results.json                     Last test result in json format
[csu ] results.text                     Last test result in text format
```

##### IPv6 UDP iperf Testing

It is possible to test iperf throughput in both direction:

Using **iperf client**, the Wi-SUN node is the client sending Datagrams to an iperf server which needs to be started on another IPv6 address.

Using **iperf server**, the Wi-SUN node is the server and is waiting for datagrams coming from another IPv6 address on the defined options.port (default 5001, the usual iperf port).

In both cases:

- The Border Router must be started
- The Wi-SUN node(s) need to be connected to the Wi-SUN network
- We test using nodes directly connected to the Border Router (single hop). With multiple hops, the throughput is to be divided by the number of hops.
- The iperf server must be started before the client

###### Add IPv6 address to Border Router tun0

To allow using Linux regular iperf (iperf2) on the Border Router, the `tun0` interface needs to have a known IPv6 address.

We use the `IPv6_prefix` set for `wsbrd` with suffix `::1`. It is visible in the tun0 Iv6 address or in the wsbrd configuration file.

Retrieving the `tun0 IPv6` prefix:

`ip address show tun0 | grep global`

`inet6 **fd00:6172:6d00**:0:4de2:8ac8:d8cb:780f/64 scope global dynamic mngtmpaddr stable-privacy`

Adding a fixed/known IPv6 address to `tun0`:

`sudo ip -6 address add \<IPv6\_prefix[0:14]\>::1 dev tun0`

example:

`sudo ip -6 address add **fd00:6172:6d00**::1 dev tun0`

Check:

`ip address show tun0 | grep global | grep ::1`

`inet6 **fd00:6172:6d00::1**/64 scope global`

Using this method, it is possible for any Wi-SUN node to know what this address is, checking its own `global` IPv6 address and replacing the last digits with `::1`.

###### Wi-SUN Node as client

We test the Wi-SUN node as a client (sending Datagrams to the server) using the Raspberry Pi supporting the Border Router application, wsbrd. The iperf server must be started first, then the client.

On the Linux Border Router:

- (One time) Install iperf2 (`apt-get install iperf`) if not already installed.
- (After each restart of wsbrd) Add a fixed/known IPv6 address to tun0 as described above.  
  - **Note**: You will need to set this IPv6 address on the client as `options.remote_addr`.
- Start iperf2 as a UDP IPv6 server:  
  `iperf --server --udp --ipv6\_domain --interval 1 –-format KBytes`  
  - or (using short arguments)  
  `iperf -s -u -V -i 1 -f KBytes`
- The iperf server will start waiting for incoming data:

```sh
------------------------------------------------------------
Server listening on UDP port 5001
UDP buffer size:  176 KByte (default)
------------------------------------------------------------
```

On the Wi-SUN Node:

> **Note**: Apart from the server’s IPV6 address, all default values should match a typical iperf test and can keep their default values.

- Check that the Wi-SUN Node is connected to the Wi-SUN network:  
  `> wisun get wisun.connection_state`  
  `wisun.join_state = Operational (5)`
- Check that the parent is the Border Router (to make sure we’re testing on a single hop):  
  _TBD (not available in current iperf app)_
- Set the IPv6 address to match the fixed server’s IPV6 address set above:  
  `wisun get wisun.ip_address_global`  
  `wisun.ip_address_global = **fd00:6172:6d00**:fe6d:5a15`  
  (where the IPV6 prefix is the 14 first characters)  
  `iperf set options.remote_addr <server’s IPV6 address>`  
  example:  
  `iperf set options.remote_addr* **fd00:6172:6d00::1**`
- (optionally) Set the bandwidth format. This is the unit used by `options.bandwidth`. we recommend setting it to `bits/s`.  
  `iperf set options.bw_format bits/s`
- (optionally) Set the number of payload bytes to the maximum before fragmentation occurs using UDP, i.e.1234. This is to maximize the throughput.  
  `iperf set options.buffer_length 1234`
- (optionally) Set the test duration in seconds (default = 10)  
  `iperf set options.duration 60`
- (optionally) Set the iperf port (default = 5001)  
  `iperf set options.port 5001`
- (optionally) Set the iperf bandwidth (default = 20000). The bandwidth should be in a range attainable by the selected Wi-SUN PHY. In our initial tests, we’re using Wi-SUN FAN, NA-915MHz, 1b (2FSK 50kbps mi=1.0), so 50 kbits/sec is the maximum we could expect if using 100% of the link as a permanent link (which is not the case, according to Wi-SUN specification). Half this is what we will reasonably expect to achieve.  
  `iperf set options.bandwidth 20000`
- (optionally) Set the display interval in seconds (default = 1):  
  `iperf set options.interval 1`
- (optionally) Set the number of packets to transmit (default = 0/unset).  
  - Set this only if you want to set an exact number of packets instead of `options.bandwidth` for `options.duration` seconds.  
  `iperf set options.packet_number 10`
- Check your options settings (only checking relevant options, marked with [c.u.])

```sh
   iperf get options
   [csu ] options.port = 5001
   [c u ] options.remote_addr = "**fd00:6172:6d00::1**"
   [c u ] options.bandwidth = 20000
   [csu ] options.bw_format = bits/s
   [c u ] options.packet_number = 0
   [c u ] options.buffer_length = 1234 bytes
   [c u ] options.duration = 60 s
   [csu ] options.interval = 1 s
```

- Start the iperf client test:  
  `iperf client`

> **Note**: In this setup, the iperf server being run on a Linux machine doesn’t need to be restarted upon each test. It can be left running.

Test results are displayed in the Wi-SUN Node’s console (Client) and in the Linux (Server) console in a format very similar to regular iperf2.

###### Wi-Sun Node as Server

Here we test the Wi-SUN node as an iperf server (receiving Datagrams from clients) using the Raspberry Pi supporting the Border Router application, wsbrd as the client. As before, the iperf server must be started first, then the client. The difference with regular iperf is that **iperf server** must be called once per test.

On the Wi-SUN Node:

> **Note**: Apart from the server’s IPV6 address, all default values should match a typical iperf test and can keep their default values.

- Check that the Wi-SUN Node is connected to the Wi-SUN network:  
  `> wisun get wisun.connection_state`  
  `wisun.connection_state = Operational (5)`
- Check that the parent is the Border Router (to make sure we’re testing on a single hop):  
  _TBD (not available in current iperf app)_
- (optionally) Set the bandwidth display format.  
  `iperf set options.bw_format bits/s`
- (optionally) Set the iperf port (default = 5001)  
  `iperf set options.port 5001`
- (optionally) Set the display interval in seconds (default = 1)  
  `iperf set options.interval 1`
- Check your options settings (only checking relevant options, marked with [.su.]):

```sh
   iperf get options
   [csu ] options.port = 5001
   [csu ] options.bw_format = bits/s
   [csu ] options.interval = 1 s
```

- Display the global IPv6 address:  
  `wisun get wisun.ip_address_global`  
  `wisun.ip_address_global = **fd00:6172:6d00:0:5e02:72ff:fe96:c6a3**`
- Start the iperf server test:  
  `iperf server`

> **Note**: In this setup, the iperf server is running on the Wi-SUN node and only accepts one test. **iperf server** needs to be relaunched for each test.

On the Linux Border Router:

- (One time) Install iperf2 (`apt-get install iperf`) if not already installed.
- Start iperf2 as a UDP IPv6 client using the Wi-SUN node’s global IPv6 address.  
  `iperf --client* **fd00:6172:6d00:0:5e02:72ff:fe96:c6a3** *--udp --ipv6_domain --interval 1 --time 10 --bandwidth 20 --format k`  
  - or (using short arguments)  
  `iperf -c **fd00:6172:6d00:0:5e02:72ff:fe96:c6a3** -u -V -i 1 -t 10 -b 20 -f k`  
  Test results are displayed in the Wi-SUN Node’s console (Client) and in the Linux (Server) console in a format very similar to regular iperf2.

###### Wi-SUN Throughput Measurement

###### Maximizing Throughput (heading level 7)

To maximize the iperf throughput, we set on the Wi-SUN node `options.buffer_length` to the maximum size before fragmentation occurs of 1234 bytes. In this case, the Wi-SUN overhead (on top of UDP) is minimal, and user throughput is maximum.

Again, to maximize the iperf throughput, the iperf implementation in the Wi-SUN Network Measurement application uses the UDP protocol (TCP would require acknowledges which would negatively impact the throughput).

###### Finding the Throughput Limit (heading level 7)

Due to the characteristics of a Wi-SUN network, where PAN advertising can take a certain time (it requires sending a PAN Advertisement on each channel, and there are often as much as 129 channels), using an iperf test to measure network throughput needs to be taken cautiously.

During the iperf test there will be periods of time when iperf data flows without interruption, leading to a momentary 'best case' throughput.

There will also be periods when network signaling takes precedence over data transmission. When network signaling occurs, the iperf throughput will be negatively impacted.

To get a valid throughput value to compare between PHY configurations, we look for the **max sustainable throughput without packet loss** on a long duration iperf test of **at least 60 seconds**. The idea is that a 60 second test with a given bandwidth will fill up the buffers up to overflowing if the stack is unable to cope with the requested throughput.

The effect of such overflowing is regularly lost packets during the duration of the test, reflecting in the final server report as a non-zero lost packets count.

The test consists in finding the maximum `options.bandwidth` which allows 0 lost packet over 60 sec. We approach this limit through several consecutive iperf client tests. The figure we look for is the number of lost packets on the server side (since we’re using UDP, the client doesn’t know if the data passes through).

- If the number of lost packets is 0, the Wi-SUN PHY can withstand such a throughput. Increase the `options.bandwidth` and retest.
- If the number of lost packets is NOT 0, the Wi-SUN PHY is unable to withstand such a throughput. Decrease the `options.bandwidth` and retest.

Do this in decreasing steps until you have a small enough `options.bandwidth` step (we used a 1000 bit step in our tests).

The value we keep is the maximum `options.bandwidth` without packet loss.

Below is an illustration of such a limit search, where the limit is 42000 bit/s:

![Limit search illustration](/wisun-network-performance-measurement-app/0.2/images/sld726-iperf-options-bandwidth.png)

##### CoAP Communication Between the Linux Border Router and the Network Performance Application

The Network Measurement Application supports a CoAP server to allow the Wi-SUN Border Router to get data from the node using the linux libcoap client. Follow the steps below to get CoAP network performance data on your Border Router, without the need to directly access the CLI on the Wi-SUN node.

###### Install the libcoap library on the Border Router

```sh
$ sudo apt-get install libcoap-1-0
$ sudo apt-get install libcoap-1-0-bin
```

###### Get your node’s global address

From the node cli, make sure that you are connected to the network.

```sh
> wisun get wisun.connection_state
wisun.connection_state = Operational (5)
```

Then, get your global IPv6 address:

```sh
> wisun get wisun.ip_address_global
wisun.ip_address_global = fd12:3456::20d:6fff:fe20:be0a
```

###### Discover the Available Resources

The CoAP protocol supports an interoperable discovery feature. A CoAP client can request the attributes hosted by a CoAP server. In the case of the Network Performance application, the available resources can be retrieved using the libcoap GET method with the standard discovery entry-point.

```sh
$ coap-client -m get -N coap://[fd12:3456::20d:6fff:fe20:be0a]:5683/.well-known/core
v:1 t:NON c:GET i:32bf {} [ ]
</cli>;ct=40,</cli/nbrinfo>;rt="nbrinfo";if="cli",</cli/iperf>;rt="iperf";if="cli",</cli/ping>;rt="ping";if="cli"
```

The above shows that we have access to the following commands:

```sh
</cli>;ct=40,

</cli/nbrinfo>;rt="nbrinfo";if="cli",

</cli/iperf>;rt="iperf";if="cli",

</cli/ping>;rt="ping";if="cli"
```

Check the node and Border Router info using:

```sh
**$ coap-client -m get -N  coap://[fd00:6172:6d00:0:b6e3:f9ff:fea6:3aa]:5683/cli/nbrinfo**

v:1 t:NON c:GET i:ff62 {} [ ]
{
"Border Router":
{"addr":"fd00:6172:6d00:0:92fd:9fff:fe6d:5a15","lt":0,"txc":0,"txf":0,"txmsc":0,"txmsf":0,"rplr":0,"etx":0,"rslo":0,"rsli":0},
"Primary Parent":
{"addr":"fd00:6172:6d00:0:92fd:9fff:fe6d:5a15","lt":2037,"txc":2096,"txf":9,"txmsc":0,"txmsf":0,"rplr":128,"etx":150,"rslo":142,"rsli":138},
"Child0":
{"addr":"fd00:6172:6d00:0:5e02:72ff:fe96:c97f","lt":2159,"txc":162,"txf":0,"txmsc":0,"txmsf":0,"rplr":65535,"etx":276,"rslo":152,"rsli":151}
}
```

###### Calling iperf using CoAP

It is possible to get the available iperf options using the `-e` text payload coap-client parameter:

**$ coap-client -m get -N -e "iperf help" coap://[fd00:6172:6d00:0:b6e3:f9ff:fea6:3aa]:5683/cli/iperf**

```sh
v:1 t:NON c:GET i:4807 {} [ ]

iPerf Remote Control CLI Help.

  Writable options:
    -options.remote_addr
    -options.bandwidth
    -options.duration
    -options.interval
  Example: iperf set options.bandwidth 10000

  Start iPerf command: iperf <client|server>
```

Set the iperf options using:

**$ coap-client -m get -N -e "iperf set options.bandwidth 10000" coap://[fd00:6172:6d00:0:b6e3:f9ff:fea6:3aa]:5683/cli/iperf**

```sh
v:1 t:NON c:GET i:d665 {} [ ]
10000
```

**$ coap-client -m get -N -e "iperf set options.remote_addr fd00:6172:6d00:0:92fd:9fff:fe6d:5a15" coap://[fd00:6172:6d00:0:b6e3:f9ff:fea6:3aa]:5683/cli/iperf**

```sh
v:1 t:NON c:GET i:4c8a {} [ ]
fd00:6172:6d00:0:92fd:9fff:fe6d:5a15
```

Launch the iperf test using:

**$ coap-client -m get -N -e "iperf client" coap://[fd00:6172:6d00:0:b6e3:f9ff:fea6:3aa]:5683/cli/iperf**

```sh
v:1 t:NON c:GET i:10d8 {} [ ]
{
  "Test-3": {
    "id":     3,
    "status": "DONE",
    "error":  "NONE",
    "options": {
      "mode":        "CLIENT",
      "protocol":    "IPV6_UDP",
      "port":        5001,
      "remote_addr": "fd00:6172:6d00::192fd:9fff:fe6d:5a15",
      "bandwidth":   10000,
      "packet_nbr":  10,
      "buf_len":     1234,
      "duration_ms": 10000,
      "win_size":    0,
      "persistent":  false,
      "interval_ms": 1000,
      "bw_format": "bits/s"
    },
    "statistic": {
      "nbr_calls":             10,
      "bytes":                 12340,
      "tot_packets":           10,
      "nbr_rcv_snt_packets":   10,
      "errs":                  0,
      "transitory_error_cnts": 0,
      "last_recv_pkt_cnt":     0,
      "ts_curr_recv_ms":       0,
      "ts_prev_recv_ms":       0,
      "ts_curr_sent_ms":       19794004,
      "ts_prev_sent_ms":       0,
      "udp_jitter":            0,
      "udp_rx_last_pkt":       0,
      "udp_lost_pkt":          0,
      "udp_out_of_order":      0,
      "udp_dup_pkt":           0,
      "udp_async_error":       false,
      "end_err":               false,
      "ts_start_ms":           19783880,
      "ts_end_ms":             19794012,
      "bandwidth":             9743,
      "finack_tot_len":        0,
      "finack_duration_ms":    0,
      "finack_pkt":            0
    }
  }
}
```

##### Ping Latency Improvement

Using the Wi-SUN Network Measurement application in its default configuration (Lowest speed Wi-SUN PHY, Network size set to _small,_ and default broadcast dwell interval), the ping latency performance is not optimal. This chapter describes ways to optimize the solution ping latency and explains some of the trade-offs associated with the modifications.

###### AN1330 Application Note

_AN1330: Silicon Labs Wi-SUN Mesh Network Performance_ reports the ping latency internal tests performed by Silicon Labs in real-world deployments. The tests focus on characterizing the expected Wi-SUN stack latency in point-to-point communications but also in round trip messages traveling over several hops. The tests are performed with the Wi-SUN stack default (non-optimized) configuration using the 50 Kbps North America Wi-SUN PHY. The results provide a good reference point to compare your own test results. Keep in mind that using a different region PHY impacts the results in the following figure.

![Neighbor Ping Latency Histogram](/wisun-network-performance-measurement-app/0.2/images/sld726-image6.png)

###### Wi-SUN PHY Impact

The first critical configuration impacting the ping latency is the Wi-SUN PHY which is used by every device in a Wi-SUN network. A point-to-point ping is composed of four messages over the air. A ping with a payload of 512 bytes triggers 1332 bytes exchanged on the air. It represents approximately 30 milliseconds spent sending messages on the radio medium (see the following figure).

![512-byte Ping Diagram](/wisun-network-performance-measurement-app/0.2/images/sld726-image7.png)

The Wi-SUN PHY also impacts the transmissions triggered to manage the Wi-SUN network. Both the speed and number of channels available in the PHY factor into the penalty that is applied to a ping latency sent close to a network management event. The two main time-consuming network management mechanisms are the PAN advertisement and PAN configuration events. For example, a PAN advertisement sent using the 50 kbps North America PHY using 128 channels holds the radio for approximately two seconds (about 15 milliseconds spent on each channel). The PAN advertisement and configuration events explain the periodical delays that can be noticed during a long ping test. Using a Wi-SUN PHY with a higher modulation speed and fewer channels highly reduces the impact of those network management events on the ping latency (for example, 300 kbps North America PHY with 41 channels). The drawback or trade-offs are the effective distance for a good communication between nodes in the network is reduced. Finally, you need to consider how changing the network size setting can affect the network management event intervals. See _Network Configuration and Size Setting_ below.

In addition to the PHY speed itself, the frequency hopping mechanism and the associated channel switches can delay transmissions of packets to prevent sending a message on a channel change. The default unicast dwell interval is 255 milliseconds.

###### Network Configuration and Size Setting

The network configuration plays an integral role in the way packets flow through the Wi-SUN network. These network configurations impact the ping latency:

- The border router broadcast interval defines at which interval a broadcast dwell interval happens. By default, the border router broadcast interval is set to 1 seconds and 20 milliseconds. You can modify it on the border router side. The configuration of the border router broadcast interval propagates throughout the Wi-SUN network and every device part of the network uses the same interval. If an application focuses on unicast messages, Silicon Labs recommends that you increase the border route broadcast interval.
- The broadcast dwell interval defines the time of a broadcast frequency hopping slot (by default, 255 milliseconds equal to the unicast default dwell interval). The longer the broadcast dwell interval, the less time remains for unicast communications. Silicon Labs recommends that you reduce the broadcast dwell interval for a unicast-focused application. You change this configuration on the border router side.
- The network size setting dictates the intervals between network management events among other things. To optimize the ping latency, Silicon Labs recommends that you use the _large_ or _medium_ configuration depending on your network deployment size to increase the network management exchanges interval. Be aware of the potential trade-off with the network connection speed and network configuration update speed.

Considering all the options available for a Wi-SUN solution developer, you can greatly improve the ping latency from the initial results retrieved from the default solution configuration. Keep in mind that every setting change is a trade-off with another Wi-SUN network performance component.

### SiLabs Tools

#### Wi-SUN Configurator

When creating a new Wi-SUN project, a Wi-SUN Configurator is added to it by default. The Wi-SUN Configurator provides an interface to the Wi-SUN application's main settings through three panels: Application, Security, and Radio. For some examples, the Wi-Sun Configurator only displays the Radio panel. These examples do not have the application and security infrastructure.

The Wi-SUN Configurator tab can be displayed by opening **/config/wisun/wisun_settings.wisunconf**.

##### Application Panel

The Application panel exposes multiple Wi-SUN stack settings associated with the application, such as:

- The network name the device will try to connect to
- The network size setting
- The device’s TX output power
- The unicast dwell interval

![Application Panel](/wisun-configurator/0.1/images/application-panel.png)

The device type dropdown allows you to set the device to be either an FFN or an LFN. Setting the device type to LFN exposes the device profile dropdown, which adjusts the LFN internal behavior for better performance and battery life.

![LFN Device Type](/wisun-configurator/0.1/images/lfn-device-type.png)

The MAC address filtering feature provides a way to force a topology on a Wi-SUN network. It is a simpler alternative than spacing out the Wi-SUN devices or tweaking the Tx power levels to achieve the desired topology. The device interacts only with other Wi-SUN devices part or not (depending on the allow/deny option) of the list.

##### Security Panel

The Security panel displays the private key and certificates used by the device to authenticate itself when connecting to a Wi-SUN network. By default, it uses the Silicon Labs demonstration samples. They can be modified to use a distinct certificate infrastructure aligned with the border router or authenticator certificate.

The **Generate Device Key and Certificate** button helps generate a new device key and certificate different from those used by default with the Silicon Labs Wi-SUN sample applications. This button is disabled in case of invalid CA Key or Certificate. CA Key and Certificate can also be generated using the button **Generate CA Key and Certificate**.

Generating new device key and certificate imply changing the default key and certificate on the Border router with new ones generated with the same CA Key and Certificate used to generate the device key and certificate.

![Security Panel](/wisun-configurator/0.1/images/security-panel.png)

##### Radio Panel

The Radio panel is an interface to configure the radio profiles included in the application. It provides a user interface to access any specified Wi-SUN FAN 1.0 PHY or FAN 1.1 PHY. A radio button allows the user to choose between the FAN 1.0 or FAN 1.1 context.

The complete list can be filtered to help you find the right PHY configuration. An application can embed several PHYs from different regions. The PHY used by the stack is defined by the `sl_wisun_join()` API call.

![Radio Panel](/wisun-configurator/0.1/images/radio-panel.png)

The Application’s Default PHY input defines the PHY that the application starts with. The default value depends on the EFR32 radio board used to create the project. You can open the dropdown and select another default PHY.

Every selected Wi-SUN PHY can be edited in the Radio Configurator by clicking the pen icon. This action opens the Radio Configurator user interface on the selected Wi-SUN PHY. Moreover, non Wi-SUN FAN PHY are listed under **Other Custom Profile** for information.

The radio panel also embeds a section to modify the list of the device allowed channel. By default, the device operates in all the PHY's channels. Modifying the list does not affect the asynchronous frames. The changes are only applied on unicast and broadcast frames for the border router.

The channel mask will not affect asynchronous frames, as it is only applied on unicast traffic. For broadcast frames, the routers follow the border router's configuration.

#### Wi-SUN Border Router GUI

The Wi-SUN border router GUI is a companion tool for Silicon Labs' Wi-SUN border router reference design, wsbrd. The tool helps manage the network by enabling a remote border router configuration and provides a visual representation of the connected Wi-SUN devices. For more information about the installation of the tool and the quick start guide, refer to the [**wisun-br-gui**](https://github.com/SiliconLabs/wisun-br-gui) repository.

##### Wi-SUN Dashboard

The Wi-SUN border router GUI provides a user interface to configure the border router by modifying the wsbrd.conf file and allows the user to start, restart, and stop the Wi-SUN border router service. In the same interface, the tool shows the running configuration on the border router (Network name, PanID, Size, Domain, Class, Mode, and the GAK/GTK Keys).

![Wi-SUN Dashboard](/wisun-border-router-gui/0.1/images/sld395-image33.png)

##### Wi-SUN Topology

The Wi-SUN Topology tool draws your implemented Wi-SUN network in the form of a graph constructed of nodes and edges linking each child to its parent. The tool also lists properties of each device when it is selected in a separate box.

![Wi-SUN Topology](/wisun-border-router-gui/0.1/images/sld395-image34.png)

#### SiLicon Labs Direct Connect Tool

In the fast-paced world of industrial IoT and on-site debugging, maintaining reliable and direct communication with devices is critical. Yet, traditional methods often depend on the device’s integration within its network, adding layers of complexity when immediate access is needed. Direct Connect is a groundbreaking interface designed to bridge that gap through a seamless wireless link that supports IPv6 traffic.

What sets Direct Connect apart is its independence from the Wi-SUN network. Whether the device is fully joined, in the process of joining, or completely disconnected from the network, Direct Connect ensures uninterrupted access. This capability makes it an invaluable tool for industrial implementations, where devices often operate in dynamic environments with evolving network conditions.

With Direct Connect, technicians and engineers can directly interface with Wi-SUN devices to perform diagnostics, deploy updates, or test configurations without the need to rely on the device's network status. This Silicon Labs solution not only simplifies on-site debugging but also enhances operational efficiency by eliminating the downtime associated with network dependencies.

> **Limitations**Direct Connect Tool is only supported on FFNs, LFNs do not support this feature.

![Direct Connect Architecture](/wisun-direct-connect/0.2/images/sld510-image2.png)

##### Prerequisites

Direct connect well functioning relies on two main entities, the Direct Connect client that runs on a Linux host plus the RCP, and the Direct Connect Server that runs on the targeted Wi-SUN node.
For this user guide we will need:

- 2x [Wi-SUN Compatible Radio Boards](https://www.silabs.com/wireless/wi-sun?tab=kits)
- A Linux host that can be a Raspberry Pi

And on the software side, we will use:

- [Simplicity Studio v5](https://www.silabs.com/developer-tools/simplicity-studio) with SiSDK v2024.12.0 or later
- [wisun-br-linux](https://github.com/SiliconLabs/wisun-br-linux) v2.2.0 or later

##### Setup Preparation

###### Linux Host

The Direct Connect tool is delivered with the wisun-br-linux tools package and called `silabs-ws-dc`.

To install `silabs-ws-dc` on the Linux host, start by cloning the wisun-br-linux repository.

```c
git clone https://github.com/SiliconLabs/wisun-br-linux.git
```

After cloning the repository, refer to [Compiling](https://github.com/SiliconLabs/wisun-br-linux/blob/main/README.md#compiling) section in `wsbrd-br-linux` to install the necessary dependencies and mbedTLS. Then, run the following `cmake` command instead of the one in the readme to install `silabs-ws-dc`.

```c
mkdir build && cd build && cmake -G Ninja -DCOMPILE_DEVTOOLS=true ..
ninja
sudo ninja install
```

###### Wi-SUN RCP

The `silabs-ws-dc` tool uses the same RCP that works with wsbrd that is delivered in SiSDK 2024.12.0. To get the RCP project, install [Simplicity Studio v5](https://www.silabs.com/developer-tools/simplicity-studio) and follow this guide to install the [SiSDK Package](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/install-ss-5-and-software).

After installing Studio and the required SDK follow those steps to flash the Wi-SUN RCP to the board.

###### Flashing the Wi-SUN RCP (heading level 7)

1. In the **Debug Adapters** view, select the device to be used as the Wi-SUN RCP.
2. Navigate to the **EXAMPLE PROJECTS & DEMOS** tab and turn off the **Example Projects** filter.
3. Click **RUN** next to the **Wi-SUN – RCP** project.  
   ![Screenshot showing the Wi-SUN - RCP Project](/wisun-direct-connect/0.2/images/sld510-image1.png)

###### Wi-SUN Node

The _**Wi-SUN - CLI example**_ provide a set of command lines to evaluate the Direct Connect tool.
The following steps explains how to flash the _**Wi-SUN - CLI example**_ to the board.

###### Flashing the _Wi-SUN - CLI example_ (heading level 7)

1. In the **Debug Adapters** view, select the device to be used as the Wi-SUN CLI.
2. Navigate to the **EXAMPLE PROJECTS & DEMOS** tab and turn off the **Example Projects** filter.
3. Click **RUN** next to the _**Wi-SUN - CLI example**_ project.

##### Direct Connect Configuration

Configuring the Direct Connect tool involves setting up two key components: the **Direct Connect server** and the **Direct Connect client**. For a successful and secure connection, it’s critical that both the server and client configurations are synchronized, particularly regarding the Pairwise Master Key (PMK) and the Wi-SUN node MAC address.

The PMK is the encryption key that ensures secure communication between the server and the client. Both sides must use the same PMK to establish a trusted and encrypted link. A mismatch in the PMK will result in connection failure, as the Direct Connect tool relies on this shared key for authentication and data protection.

Having the same PMK on both sides allows to establish a direct connection without performing the Wi-SUN authentication flow (EAP-TLS), removing the need of an authentication server and additional certificates.

###### Direct Connect Client

The Direct Connect client’s configuration is managed through the `silabs-ws-dc` configuration file, allowing precise customization to establish a secure link with a Wi-SUN device. This connection is built around two critical parameters: the MAC address (EUI-64) of the target device and the Pairwise Master Key (PMK). These elements ensure that communication is uniquely tied to the intended device, providing robust security and preventing unauthorized access.

An example configuration file is provided in the `wisun-br-linux/examples` directory. You can use this example as a starting point by either modifying it directly or creating a new configuration file based on your specific setup requirements.

Below is an example configuration that highlights key settings:

```c
#### Path of the serial port connected to the RCP.
uart_device=/dev/ttyACM0

#### Serial baudrate in bps
uart_baudrate=115200

#### PHY Configuration
domain=EU
chan_plan_id=32
phy_mode_id=1

#### Target MAC address
target_eui64=b4:35:22:ff:fe:98:29:ff

#### Pairwise Master Key
target_pmk=34:ba:32:26:a0:b2:ad:66:7c:9f:66:02:e5:db:75:77:dd:bd:5d:2b:34:3a:93:06:2b:90:c0:7b:e2:8e:4e:54 
```

###### Direct Connect Server

The server-side configuration must mirror the client in terms of the PMK value. While the MAC address identifies the target device on the client side, the server only needs the shared PMK and the same PHY configuration of `silabs-ws-dc` to establish a secure session.

To configure the Wi-SUN Node, connect to the console in Simplicity Studio. In the **Debug Adapters** view, right click on the Wi-SUN node board and select **launch Console**. To get a prompt on the Console, go to the _Serial 1_ tab and press Enter.

###### Setting the Pairwise Master Key (heading level 7)

Run the following command in the Wi-SUN node console to set the PMK:

```c
wisun set wisun.direct_connect_pmk 34:ba:32:26:a0:b2:ad:66:7c:9f:66:02:e5:db:75:77:dd:bd:5d:2b:34:3a:93:06:2b:90:c0:7b:e2:8e:4e:54
```

###### Enable Direct Connect (heading level 7)

Once the PMK is set, you need to explicitly enable the Direct Connect feature on the server. This step activates the feature, allowing the Direct Connect server to connect with the Direct Connect client.

Run the following command to enable Direct Connect:

```c
wisun set_direct_connect_state 1 (1 to enable, 0 to disable)
```

##### Direct Connect in Action

###### Establishing the Direct Connect Link

To establish a Direct Connect link, the process begins with the Direct Connect client initiating communication with the target device.

###### Run `silabs-ws-dc` to Initiate the Connection (heading level 7)

On the Linux host execute the following command:

```c
sudo silabs-ws-dc -F ./silabs-ws-dc.conf
```

This command starts the Direct Connect client using the configuration file _silabs-ws-dc.conf_ and sends a Direct Connect Solicit frame to the target device. This frame serves as a request for the device to establish a connection with the client.

###### Receiving the Direct Connect Request (heading level 7)

On the targeted Wi-SUN device, the _Wi-SUN - CLI example_ will indicate receipt of the request with a message like:

```c
[Direct Connection request from fe80::b635:22ff:fe98:29b2]
```

> The `fe80::b635:22ff:fe98:29b2` is the link-local IPv6 address used by `silabs-ws-dc`. This address will vary depending on your specific setup.

###### Accepting the Direct Connect Link (heading level 7)

To accept the incoming connection request, run the following command on the _Wi-SUN - CLI example_:

```c
wisun accept_direct_connect_link fe80::b635:22ff:fe98:29b2
```

If successful, the _Wi-SUN - CLI example_ will display:

```c
[Accepted connection request]
```

###### Confirmation of a Successful Connection (heading level 7)

Once the connection is fully established, both the _Wi-SUN - CLI example_ and the `silabs-ws-dc` tool will provide confirmation messages:

- **On the Wi-SUN CLI example:**  
  ```c  
  [Direct Connect Link fe80::b635:22ff:fe98:29b2: connected]  
    
  ```
- **On the `silabs-ws-dc` logs:**  
  ```c  
  Direct Connection established with b4:35:22:ff:fe:98:29:ff  
  b4:35:22:ff:fe:98:29:ff reachable at fe80::b635:22ff:fe98:29ff  
  ```

###### Using and Managing the Direct Connect Link

Once the Direct Connect link is established, it provides a secure, point-to-point communication channel that supports UDP, TCP, and ICMP traffic. This enables a wide range of networking operations such as testing, debugging, and data exchange between the Direct Connect Client and the Direct Connect Server.

###### Using the Link (heading level 7)

- **Versatility:** The link operates independently of the Wi-SUN network status, meaning it functions whether the device is connected to a Wi-SUN network or not.
- **Direct Communication:** Communication is exclusively between the Direct Connect Client and Server. Routing to other devices within the Wi-SUN network is not supported. This ensures that the connection remains private and direct, focusing solely on the configured devices.

This direct access is particularly useful for performing device-specific diagnostics, deploying configurations, or running network tests without relying on the broader Wi-SUN infrastructure.

###### Frame Counter Handling (heading level 7)

Direct Connect uses a 32-bit frame counter that is incremented for each transmitted frame. Because Direct Connect sessions do not perform periodic key rotation, the frame counter must not wrap.

In the event of frame counter exhaustion during secure communication, either the Direct Connect Client or Server will tear down the connection to prevent nonce reuse. A new session may then be started safely, which generates a fresh encryption key.

###### Closing the Link (heading level 7)

To terminate the Direct Connect link, simply stop the `silabs-ws-dc` process on the client using `Ctrl+C` or the following command if the client is running in the background:

```c
sudo pkill silabs-ws-dc
```

Once the client stops, the link will disconnect automatically. After 60 seconds, the _Wi-SUN - CLI example_ will display the following message, confirming the disconnection:

```c
[Direct Connect Link fe80::b635:22ff:fe98:29b2: disconnected]
```

###### Connection Troubleshooting

###### Connection loss (heading level 7)

If the Direct Connect client loses connection with the server, it will automatically try to reconnect by sending Direct Connect Solicit frames again and indicate the following:

```c
Direct Connection with b4:35:22:ff:fe:98:29:ff lost, attempting to reconnect...
```

###### Connection failure (heading level 7)

If the `silabs-ws-dc` is unable to establish a Direct Connection with the server, it will indicate the following:

```c
b4:35:22:ff:fe:98:29:ff is unreachable, please check your configuration
```

In that case, make sure that the used parameters are set accordingly on both sides, refer to [Direct Connect Configuration](#direct-connect-configuration).

The Wi-SUN CLI may also indicate the following after accepting the direct connection:

```c
[Direct Connect Link fe80::b635:22ff:fe98:29b2: error]
```

In that case, make sure the PMK used is the same on both sides and restart `silabs-ws-dc`.

##### Final Thoughts

The Direct Connect link offers a powerful and secure way to interact with Wi-SUN devices, making it an essential tool for industrial IoT applications. Its independence from the Wi-SUN network ensures flexibility, while its direct communication channel guarantees simplicity and reliability. Managing the link, from initiation to closure, is straightforward, making it a valuable asset for engineers and developers.

#### Wi-SUN Dynamic Data Provisioning

Dynamic Data Provisioning (DDP) is a powerful tool designed to streamline the generation and injection of Wi-SUN certificates and device keys. This innovative solution, comprising a set of Python scripts available in the wisun application repo repository, interacts seamlessly with Wi-SUN devices. The core of this tool is the **Wi-SUN - DDP** application that can run in RAM, to provide a robust and flexible approach to device provisioning. In the following sections, we explore the tool by providing a step by step guide to generate the Wi-SUN certificates and provision the Wi-SUN devices with the generated keys.

[wisun application repo](https://github.com/SiliconLabs/wisun_applications)

##### Prerequisites

The following requirements are key to start using the Wi-SUN Dynamic Data Provisioning tool:

- The DDP tool scripts hosted in [wisun_applications](https://github.com/SiliconLabs/wisun_applications).
- The **Wi-SUN - DDP** application delivered with [Simplicity Studio v5](https://www.silabs.com/developer-tools/simplicity-studio) SiSDK 2024.12.0 or later.
- One [Wi-SUN Compatible Radio Board](https://www.silabs.com/wireless/wi-sun?tab=kits).

##### Getting Started

###### Wi-SUN - DDP project

To start using the DDP tool, first install [Simplicity Studio v5](https://www.silabs.com/developer-tools/simplicity-studio) and follow this guide to install the [SiSDK Package](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/install-ss-5-and-software). Once installed, create and build the Wi-SUN DDP application following the next steps:

1. Open Simplicity Studio v5 and plug the Wi-SUN device to your laptop.
2. In the **Debug Adapters** view, select the device that will be provisioned.
3. Navigate to the **EXAMPLE PROJECTS & DEMOS** tab and write **DDP** in the _**Filter on Keywords**_ box.
4. Click **Create** next to the _**Wi-SUN - DDP**_ project.  
   ![Wi-SUN DDP](/wisun-dynamic-device-provisioning/0.1/images/sld511-image1.png)
5. After creating the project, follow this [guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-building-and-flashing/building#simple-build) to build your project.

> **Note**: Don't flash the project to the Board. The built binary will be used by the the DDP scripts.

###### DDP Tool Scripts

The DDP Tool scripts works in combination with the **Wi-SUN - DDP** project. Use the following command to clone the [wisun_applications][wisun application repo] repository:

```c
git clone https://github.com/SiliconLabs/wisun_applications.git
```

##### DDP in Action

###### Example Scripts: SigningServer.py and provision.py

The repository includes two example scripts: SigningServer.py and provision.py. These scripts serve as practical demonstrations of how to use the Dynamic Data Provisioning (DDP) tool.

- `SigningServer.py`: This script uses OpenSSL to generate a certificate chain, including an intermediate certificate. It showcases the process of creating a secure certificate hierarchy.
- `provision.py`: This script generates a private and public key pair, exports the public key, signs it with the previously generated certificate chain, and then loads the entire chain along with the new certificate. It illustrates the steps involved in key generation and certificate signing.

> Note that these scripts are provided as examples to help you understand the usage of the DDP tool.

###### Start using the DDP Tool

Now that all elements are prepared, start using the DDP tool to provision the device by following the next steps:

- Use the following commands to install the DDP tool requirements:  
  ```c  
  cd wisun_applications/ddp  
  python3 -m pip install -r requirements.txt  
  ```
- Next, use the `SigningServer.py` script to generate the certificates chain. Following is an example using Silicon labs OID. Use the command with the parameters suiting your use case:  
  ```c  
  python3 SigningServer.py SetupCerts --co "Silicon Labs" --cu FR --oid 1.3.6.1.4.1.39873.1  
  ```  
  - **--co:** The name of the OEM, Used for certificate content.  
  - **--cu:** The country of the OEM, Used for certificate content.  
  - **--oid:** The OID of the product, used for certificate content.
- After generating the certificates, provision the device. In this step, use `provisioning.py`, which takes as arguments the device serial number and the DDP application binary that was built previously:  
  ```c  
  python3 provision.py --soc xg25 --jlink_ser <JLink serial number> --prov_img [path to DDP application binary]  
  ```

##### Conclusion

In conclusion, Dynamic Data Provisioning (DDP) is a valuable tool for the Wi-SUN Networks development, providing a straightforward and secure method for generating and injecting Wi-SUN certificates and device keys. Using the ddp python scripts and the **Wi-SUN - DDP** application, this tool ensures efficient and reliable device provisioning.

#### Real Time Traces (RTT)

##### Introduction

The Wi-SUN stack provides a logging mechanism based on the Segger RTT feature, which uses a ring buffer in RAM.<br />For more details, see the [RTT Knowledge Base page](https://kb.segger.com/RTT).

APIs are available to set the trace level of different Wi-SUN groups, allowing finer control over tracing.

> **Note**: These logs can be used to report issues to Silicon Labs Support.

##### Installation

Install and open the [J-Link RTT Viewer](https://www.segger.com/products/debug-probes/j-link/tools/rtt-viewer/).

![RTT viewer configuration](/wisun-rtt-traces/0.1/images/sld980-rtt-viewer.png)

1. In the **Configuration** panel, under **Connection to J-Link**, select **USB**.
2. In the **Specify Target Device** list, select the connected part (for example: `EFR32FG25BXXXF1920`).
3. In the **Target Interface & Speed** panel, select **SWD** and **4000 kHz**.
4. In the **RTT Control Block** panel, select **Auto Detection**.
5. Click **OK**.
6. If several boards are connected, a list appears. To monitor multiple devices, open a separate RTT Viewer instance for each device.
7. Select a WSTK board running the Wi-SUN stack (border router or node).
8. Click **OK**.

A terminal window opens, and the Wi-SUN stack traces are displayed as shown below:

```c
[DBG ][wisun]: net_init_core: 0
[DBG ][wisun]: sli_wisun_task_event_handler_id: 2
[DBG ][SLRF]: sli_wisun_driver_register()
[DBG ][SLRF]: sli_wisun_driver_register() - driver_id: 0
[DBG ][SLRF]: rf_address_write: PHY_MAC_64BIT: 00:0d:6f:ff:fe:20:bd:95
[DBG ][mlme]: SW-MAC driver support rf extension 50000 symbol/seconds 20 us symbol time length
[DBG ][swm ]: Set MAC mode to IEEE 802.15.4-2011, MTU size: 127
[DBG ][SLRF]: rf_address_write: PHY_MAC_64BIT: 00:0d:6f:ff:fe:20:bd:95
[DBG ][wisun]: arm_nwk_interface_lowpan_init: 1
```

> **Note**: The RTT Viewer must be disconnected from the device before flashing it again.<br />The quickest way to disconnect is to press **F3**, perform the flash, and then press **F2** to reconnect.<br />By default, RTT Viewer automatically restores the previous settings.

##### Configuration

The application must install the **Wi-SUN Stack Debug & Traces Plugin** component.<br />This automatically installs the **SEGGER RTT** component.

Wi-SUN provides APIs for stack trace levels and filters.<br />For more information, see the [Wi-SUN Stack Traces and Debug API](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-trace-api).

Example: setting the trace level to **DEBUG** for the **MAC** group:

```C
sl_status_t ret;
sl_wisun_trace_group_config_t trace_config;

trace_config.group_id = SL_WISUN_TRACE_GROUP_MAC;
trace_config.trace_level = SL_WISUN_TRACE_LEVEL_DEBUG;
ret = sl_wisun_set_trace_level(1, &trace_config);
```

##### Final Thoughts

Wi-SUN stack traces provide an efficient and flexible way to understand and debug the network.<br />The main limitation of RTT is that it requires a debugger.<br />If the debugger adapter port is not accessible during network testing, the [Direct Connect](/wisun/2.12.0/wisun-direct-connect) solution can forward Wi-SUN traces over the air.

#### Network Analyzer

##### Introduction

Silicon Labs Network Analyzer is a packet capture and debugging tool used to analyze connectivity between wireless nodes running the Wi-SUN stack on the EFR32 platform.<br />It significantly accelerates network and application development by providing graphical views of network traffic, activity, and duration.

Once a capture is complete, it can be exported to formats compatible with external tools such as Wireshark.

##### Packet Trace Interface (PTI)

The Packet Trace application captures the packets directly from the Packet Trace Interface (PTI) available on the Wireless Gecko SoCs and modules. It therefore provides a more accurate capture of the packets compared to air-based capture.

To capture Wi-SUN packets using the Silicon Labs Network Analyzer, in the Debug Adapters view, first make sure you are connected and then right-click the device that is running on a Wi-SUN network and select **Start capture**.

![Adapters menu Start capture](/wisun-pti-wireshark/0.1/images/sld981-pti-start-capture.png)

You should now be able to see the Wi-SUN traffic as shown below. Click the packets to see more details about its contents in the **Event Detail** view (on the right).

![Network analyzer showing network traffic](/wisun-pti-wireshark/0.1/images/sld981-network-analyzer-traffic-overview.png)

> **Note**: If you don't see packets being captured, you may have a mismatch between your project's **PTI Baud Rate (Hertz)** setting in the **RAIL Utility, PTI** component and your **Debug Adapter's PTI Bitrate** settings (which you can access by right-clicking your **Debug Adapter**, selecting **Device Configuration**, then opening the **Packet Trace** tab).

In the current state, the Network Analyzer does not decrypt the Wi-SUN Upper Layer Application Data. To decrypt the packet and analyze the complete payload including the data, the external tool Wireshark is recommended. To export PTI captures in readable Wireshark's pcapng format, follow these steps:

1. When you have traced the communication, click **Export**.  
   ![export capture](/wisun-pti-wireshark/0.1/images/sld981-pti-export-button.png)
2. Under **Select export format**, select **PCAP NG exporter**.
3. Enter a path and a file name in which the trace will be stored.
4. In **Export** mode, select **Wi-SUN (auto-detect protocol)**.
5. Click **OK**.  
   ![export capture](/wisun-pti-wireshark/0.1/images/sld981-pti-export-pcapng.png)

Once .pcapng is created, it can easily be opened in Wireshark.

> **Note**: PTI captures may occasionally contain corrupted packets that cannot be analyzed or decrypted. This is due to bit-shifting issues between the Wi-SUN preamble and PTI. However, this problem only affects the capture process. Frames are still correctly transmitted and received by the devices. Therefore, this issue should not prevent the use of PTI or Wireshark for analysis.

##### Wireshark

Wireshark is the recommended network protocol analyzer for use with Wi-SUN networks. Download instructions are provided for [Windows/Mac users](https://www.wireshark.org/download.html) or [Linux users](https://www.wireshark.org/docs/wsug_html_chunked/ChBuildInstallUnixInstallBins.html). Simplicity Studio 5 supports [live interaction](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-testing-and-debugging/using-wireshark) between the application running on a Silicon Labs device and Wireshark.

To decrypt the communications, the GAK key and key index set information are required. They can be retrieved on the border router CLI by issuing the following command:

```c
> wisun get wisun

wisun.state = started (2)
wisun.network_name = "Wi-SUN Network"
(...)
wisun.allowed_channels = "0-255"
wisun.gak1 = 76:ab:9f:ce:8a:08:b8:88:6d:fc:56:fa:0e:6f:1e:ce
wisun.gak2 = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
wisun.gak3 = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
wisun.gak4 = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
wisun.lfn_gak1 = 7b:92:f2:9e:68:a5:41:37:b3:5e:e7:14:04:be:37:04
wisun.lfn_gak2 = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
wisun.lfn_gak3 = 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
(...)
```

On Wi-SUN Border Router Linux, the GAK Key can be retrieved using `wsbrd_cli` command or directly from /var/lib/wstk/network-keys:

```c
> wsbrd_cli status
network_name: Wi-SUN Network
(...)
size: SMALL
GAK[0]: eb:7b:11:dd:f0:23:c3:7e:36:64:c5:9b:5b:ed:c6:c7
GAK[1]: fc:d3:1f:a7:4c:c8:c4:0f:96:7e:d0:5d:0e:a1:01:fc
GAK[2]: fc:d3:1f:a7:4c:c8:c4:0f:96:7e:d0:5d:0e:a1:01:fc
GAK[3]: fc:d3:1f:a7:4c:c8:c4:0f:96:7e:d0:5d:0e:a1:01:fc
GTK[0]: a8:d6:dc:7c:66:14:2f:b8:db:dd:af:fb:c2:27:0c:18
GTK[1]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
GTK[2]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
GTK[3]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
84:fd:27:ff:fe:fe:55:bd
```

Silicon Labs Wi-SUN devices in the network use `wisun.gak1` as the GAK key. In the first capture the GAK key is
`76:ab:9f:ce:8a:08:b8:88:6d:fc:56:fa:0e:6f:1e:ce` and in the second capture the GAK key is
`eb:7b:11:dd:f0:23:c3:7e:36:64:c5:9b:5b:ed:c6:c7`. The key index to use in Wireshark is 1 in both cases, for the first GAK
in the list.

In Wireshark:

1. Click **Edit**.
2. Click **Preferences...**.
3. Expand the **Protocols** list and select **IEEE 802.15.4**.
4. Next to **Decryption Keys**, click **Edit**.
5. In the **Keys** window, click [+].
6. Under **Decryption key** enter the GAK key, and under **Decryption key index**, enter the key index (starting at 1 for GAKs, starting at 5 for LFN-GAKs).
7. Click **OK**.  
   ![Set decryption key](/wisun-pti-wireshark/0.1/images/sld981-wireshark-set-key.png)

Wireshark is now able to decrypt the traces and the higher-level protocols (ICMP, TCP, UDP...). The following example of traces shows
a router pinging its border router.

![wireshrk decrypted traffic](/wisun-pti-wireshark/0.1/images/sld981-wireshark-decrypted-traffic.png)

#### Crash Handler

The [Wi-SUN Node Monitoring application](https://github.com/SiliconLabs/wisun_applications/tree/main) includes a crash handler component that reports and recovers from application asserts and crashes. The crash handler’s information can be printed to RTT traces or sent over the air.

Before the board is reset, the assert file name and line number are saved.

```c
Info on previous crash: [ASSERT in wisun_mac.c on line 1234]
```

If a hard fault occurs, the core registers (including the LR) are also saved.

```c
Info on previous crash: [FAULT CFSR: 0x00008200
R0:   0x20001234, R1:    0x00000000, R2:   0x20004567, R3:   0xE000ED28
R12:  0xDEADBEEF, LR:    0x08012345, RET:  0x0800ABCD, XPSR: 0x21000000
HFSR: 0x40000000, MMFAR: 0x00000000, BFAR: 0x20005000, AFSR: 0x00000000]
```

##### Using Wi-SUN Crash Handler in Another Project

1. Copy [sl_wisun_crash_handler.c](https://github.com/SiliconLabs/wisun_applications/blob/main/component/crash_handler/sl_wisun_crash_handler.c) and [sl_wisun_crash_handler.h](https://github.com/SiliconLabs/wisun_applications/blob/main/component/crash_handler/sl_wisun_crash_handler.h) to the project, and add them to compilation.
2. Add **RMU (emlib_rmu)** component to the project.
3. Add linker flags below to the project. In Studio, go to **Project -> Properties -> C/C++ Build -> Settings -> GNU ARM C Linker -> Miscellaneous**. The component will work without them, but it will be unable to capture some asserts on GCC.  
   ```c  
   -Wl,--wrap=__stack_chk_fail,--wrap=__assert_func  
   ```
4. Call crash handler initialization in **app_init**.  
   ```C  
   #include "sl_wisun_crash_handler.h"  
   ...  
   void app_init(void)  
   {  
       sl_wisun_crash_handler_init();  
   }  
   ```
5. After initialization, read crash reason.  
   ```C  
   #include "sl_wisun_crash_handler.h"  
   ...  
   const sl_wisun_crash_t *crash;  
   ...  
   crash = sl_wisun_crash_handler_read();  
   if (crash) {  
       switch (crash->type) {  
       case SL_WISUN_CRASH_TYPE_XXX:  
           break;  
       ...  
       }  
       sl_wisun_crash_handler_clear();  
   }  
   ```
6. Alternatively, call `sl_wisun_check_previous_crash()` to fill the `crash_info_string`, and then print the string. This string will be available during the entire application runtime. (The Wi-SUN Node Monitoring application makes it available via a CoAP request.)  
   ```C  
   #include "sl_wisun_crash_handler.h"  
   ...  
   int crash_type;  
   ...  
   crash_type = sl_wisun_check_previous_crash();  
   if (crash_type) {  
       printf("%s\n", crash_info_string);  
   }  
   ```

> **WARNING**: If the project uses Gecko Bootloader, the bootloader's `bss` section may overlap with the application's `noinit` section, causing the crash handler to not function properly. In the Wi-SUN Node Monitoring application, this is avoided by increasing the stack size **SL_STACK_SIZE**, which pushes the application's `noinit` section further into RAM. Another possibility is to modify the generated linker script and swap the placement of application's `bss` and `noinit` sections.

### Development Walkthrough

#### Wi-SUN Development Walkthrough

The purpose of this Wi-SUN Development Walkthrough is to help Wi-SUN application developers start their application development based on **Wi-SUN SoC Empty**, and to build a final production-ready application, after initial evaluation of the Wi-SUN example applications.

The Development Walkthrough is organized in the following sections:

- [Build an Application and Connect to a Wi-SUN Network](/wisun/2.12.0/wisun-building-connecting/index)
- [Wi-SUN API Calls to Connect to a Wi-SUN Network](/wisun/2.12.0/wisun-connection-details/index)
- [Add a Custom Application to a Wi-SUN Network](/wisun/2.12.0/wisun-custom-application/index)
- [Add OTA DFU (Over-The-Air Device Firmware Upgrade) Capability](/wisun/2.12.0/wisun-ota-dfu/index)

Silicon Labs expects that developers have evaluated some of the Wi-SUN example applications prior to beginning this walkthrough to get a basic understanding of Wi-SUN. These applications are available in Simplicity Studio through the Launcher perspective on the **EXAMPLE PROJECTS & DEMOS** tab. The intended uses of these Wi-SUN example applications are:

- An application to build a stand-alone Wi-SUN Border Router on an evaluation kit  
  - **Wi-SUN - SoC Border Router**    
    - Also available as a 'demo' in binary format for easy evaluation. It is convenient for quick testing, while being limited in terms of features. Moving to the Linux Border Router (below) is recommended to start communicating with the Wi-SUN network from the outside.
- An application to build a Linux Wi-SUN Border Router using an evaluation kit as the RCP (Radio Co-Processor) and a Linux platform as the host (more details on the Linux Border Router on [GitHub for `wsbrd`](https://github.com/SiliconLabs/wisun-br-linux) and [the corresponding GUI](https://github.com/SiliconLabs/wisun-br-gui)).  
  - **Wi-SUN - RCP**    
    - Also available as a 'demo' in binary format for easy evaluation
- An application to test most [Wi-SUN Stack API commands](https://docs.silabs.com/wisun/latest/wisun-stack-api/): **Wi-SUN - CLI example**  
  - Also available as a 'demo' in binary format for easy evaluation    
    - Each Radio Board has a matching 'demo' binary, depending on its Frequency Band. This means all PHYs will not be available for a given Radio Board, only the ones compatible with the Radio Board Frequency Band.
- An application to evaluate LFN device: **Wi-SUN - LFN CLI example**  
  - Also available as a 'demo' in binary format for easy evaluation
- Applications to evaluate Wi-SUN  
  - ping    
    - **Wi-SUN - SoC Ping**  
  - TCP/UDP    
    - **Wi-SUN - SoC Socket**  
  - CoAP    
    - **Wi-SUN - SoC CoAP Meter**    
    - **Wi-SUN - SoC CoAP Collector**  
  - Network Performance (ping/iperf)    
    - **Wi-SUN SoC Network Measurement**      
      - Also available as a 'demo' in binary format for easy evaluation
- An application to provide support for run-time provisioning of device-specific Wi-SUN data, such as private keys and certificates.  
  - **Wi-SUN DDP**
- An application to start final development, after the evaluation phase is complete  
  - **Wi-SUN Soc Empty**

These applications allow quick evaluation of Wi-SUN without the need to compile anything for the first level of testing, thanks to the pre-compiled 'demo' binaries. Applications not delivered as binaries can be created easily, built, and flashed to the evaluation kits.

After this evaluation phase is achieved, actual application development starts, based on the minimal **Wi-SUN SoC Empty** example application. It is minimal is the sense that it allows connecting to the Wi-SUN network and doesn't contain application code, which will be added by the customer.

#### Build Wi-SUN - SoC Empty and Connect to any Wi-SUN Network

The Development Walkthrough begins with Simplicity Studio.

##### Starting Simplicity Studio

It is best to keep the code separate from other projects for the sake of clarity. For this reason, start by creating a `Development_Walkthrough` folder to serve as a workspace folder for Simplicity Studio.

In Windows, the default path for Simplicity Studio workspaces is `C:\Users\username\SimplicityStudio`, so create `C:\Users\username\SimplicityStudio\Development_Walkthrough`.

Now, start Simplicity Studio and switch to the workspace, if not already selected, by selecting **File > Switch Workspace**.

![Switch Workspace](/wisun-building-connecting/0.2/images/switch-workspace.png)

Once in the new workspace, you see the Simplicity Studio Welcome Screen.

![Welcome Screen](/wisun-building-connecting/0.2/images/welcome-to-simplicity-studio.png)

##### Connecting a Wi-SUN Development Kit

At this point, you have no Adapter Board connected, so fit a Wi-SUN compatible Radio Board to a Silicon Labs WSTK/WPK from a [Wi-SUN Development Kit](https://www.silabs.com/wireless/wi-sun?tab=kits) and plug it into a USB port on the PC to get it displayed in the **Debug Adapters** frame.

![Plug Kit](/wisun-building-connecting/0.2/images/plug-kit.png)

You can expand the Adapter information to check the kit's information, including the Radio Board reference, the exact part number, and the Main board information.

![kit info](/wisun-building-connecting/0.2/images/kit-info.png)

> **TIP**: Additional information on the Wi-SUN kits is available on the Silicon Labs [Wi-SUN webpage](https://www.silabs.com/wireless/wi-sun?tab=kits).

##### Creating the Wi-SUN - SoC Empty Application

Wi-SUN - SoC Empty is the recommended application to start development from, since it contains the necessary resources to easily connect Wi-SUN devices to any Wi-SUN network.

In this example:

- Use console `printf` calls to help follow the application progress. It makes application development easier to get console traces. Any C developer will know how to make these optional in a 'release' build, if required, although minimal traces are always helpful for maintenance reasons, if only to display the application and version information at startup.
- Don't add a CLI (Command Line Interface) through the console, because:  
  - In a Wi-SUN network, the only access to the devices is through the Wi-SUN network itself.  
  - Generally, access to a device console will not be possible. It requires physical access to the device.  
  - Not adding a CLI makes the console impossible to use to take control of the device, making the application more secure.

> **TIP**: A typical WI-SUN device also requires [OTA DFU](/wisun/2.12.0/wisun-ota-dfu/index) capability for updates/upgrades. Silicon Labs recommends adding OTA DFU once the Wi-SUN SoC Empty application is working as expected.

After connecting a Wi-SUN Development Kit and selecting it, Simplicity Studio opens the !['Launcher'](/wisun-building-connecting/0.2/images/launcher.png) perspective, where information on the selected Adapter is displayed, and Simplicity Studio is ready to help create matching projects.

Simplicity Studio only displays information relevant to the context it is in, so here, because the target Debug Adapter is selected, it shows the Launcher perspective and the **OVERVIEW** tab for the evaluation kit. You also have easy access to the corresponding documentation and tools.

![Overview](/wisun-building-connecting/0.2/images/overview.png)

> **TIP**: When the **General Information** box indicates the need to update the Adapter FW or the Secure FW to newer versions, it is recommended to do so. New releases generally improve stability.

![update](/wisun-building-connecting/0.2/images/update.png)

To get started with the Wi-SUN SoC Empty application, select the **EXAMPLE PROJECTS & DEMOS** tab, still in the **Launcher** perspective, and wait for Simplicity Studio to display the examples. It can take a couple seconds.

![Examples](/wisun-building-connecting/0.2/images/examples.png)

Filter the projects by clicking the following items:

- Under **Wireless Technology**: **Wi-SUN**
- Under **Device Type**: **SoC**

To further limit to items containing 'empty', type 'empty' in the **Filter on keywords** box, and press **Enter**.

![Empty](/wisun-building-connecting/0.2/images/empty.png)

This makes it easy to locate the **Wi-SUN - SoC Empty** project.

Now click **CREATE** in the **Wi-SUN - SoC Empty** box to start creating your project.

![Finish](/wisun-building-connecting/0.2/images/create.png)

Since you are happy with the default project name and location, click **FINISH** to create the project.

> **TIP**: An alternate path to project creation is **File > New > Silicon Labs Project Wizard**. If you use this path after selecting your development kit in the **Debug Adapter** window, the settings will be pre-filled for it as well. You will be at the **Target/SDK** selection step ![target sdk step](/wisun-building-connecting/0.2/images/target-sdk-step.png) in this case, two steps higher in the process than the **Configuration** step above (![configuration step](/wisun-building-connecting/0.2/images/configuration-step.png)). When using the Launcher path just described, you can still click the **Back** button twice to go back to the **Target/SDK** selection step, which allows you to select an IDE (to edit your code) and a toolchain (to compile your code) if the default IDE (Simplicity IDE) and toolchain (GNU ARM) are not what you want to use.

###### Notes on the 'With project files' Options

![with project files](/wisun-building-connecting/0.2/images/with-project-files.png)

- Part of the code in the application is the Wi-SUN Stack. This is delivered as pre-compiled libraries matching each Stack_application/Part/Compiler/Configuration combination. Customers don't have access to the source code for this part, to keep it under control by Silicon Labs. It's complex, and the Wi-SUN stack developers are responsible for keeping it working and up to date, and they add new features over time. These will be linked with the rest of the object files in the project. You will check this after compiling your first project.
- Another part of the code is the SiSDK (Simplicity Software Development Kit) code which is common to all projects. Customers are given access to this code. When a new project is created in your workspace, the preferred method consists of creating symbolic links to those 'sdk' sources, to save space and allow updating the SiSDK version in the future. It ensures that all the projects use the same Wi-SUN Stack code, and it can be easily updated.
- The final part of the code is the application code. Customers need to add their own application code there. The preferred method here is to copy the 'project sources' code from the SiSDK to your project's folder, such that changing it will keep changes local to your project. This is why the default option is **Link sdk and copy project sources**, which is fine for most cases.  
  ![Creation](/wisun-building-connecting/0.2/images/creation.png)

##### Created Project

Once project creation is complete, Simplicity Studio switches to the !['Simplicity IDE'](/wisun-building-connecting/0.2/images/simplicity-ide-icon.png) perspective (see the top-right corner), and is ready for project configuration and compilation.

![Simplicity IDE](/wisun-building-connecting/0.2/images/simplicity-ide.png)

Three tabs are present in this perspective:

- **Wi-SUN Configurator**: Used to set your Network / Security / Radio options via three tabs.  
  - TIP: You can always get access to the Wi-SUN Configurator by double-clicking on `config/wisun/wisun_settings.wisunconf`, if you ever close it.
- **wisun_soc_empty.slcp**: Your access to the previous view with the **Overview** / **Software Components** / **Configuration Tools** tabs.  
  - TIP: Similarly, you can always access this tab by double-clicking on the `wisun_soc_empty.slcp` file in the **Project Explorer** tab.
- **readme.md**: The project's documentation, with links to the Quick Start guide and additional details on [docs.silabs.com](https://docs.silabs.com/wisun/latest/wisun-start/).  
  - TIP: Open the `readme.md` file in the **Project Explorer** tab to re-open it.

You can see the pre-compiled libraries, which will be linked with your object files.

![underlying libs](/wisun-building-connecting/0.2/images/underlying-libs.png)

##### Project Explorer

Now look at what you have in your **Project Explorer** view when selecting the project.

![Project](/wisun-building-connecting/0.2/images/project.png)

This matches the files in your workspace folder, since it's a file view. Note that, if using the **Show hidden files, folders, and drives** folder option in Windows, you also see the .* folders and files below.

![Files](/wisun-building-connecting/0.2/images/files.png)

###### Project Sub-Folders

- `includes` contains links to the sdk and stack API header files relevant to your project.
- `autogen` contains all files copied from the SiSDK which contain the application code you may want to customize, plus component configuration files.
- `config` contains the files giving access to the Wi-SUN Configurator and to the RAIL configuration, plus some low-level stack configuration files.
- `simplicity_sdk_x.y.z` contains links to the SiSDK files required by your project. Only links to files relevant to your use case are included, not the entire SiSDK.

> **TIP**: If you want to modify one of the SiSDK files, the IDE will ask you whether you want to edit the SiSDK file or create a copy of the file (i.e. replacing the symbolic link to the file by a copy of the file). With the first option, changes you make will be shared with all other projects, and possibly lost with SiSDK updates. The second option will keep your changes local to the current project.

##### First Compilation

Back to Simplicity Studio's **Simplicity IDE** perspective, with your project selected, build your project with all settings by default.

> **TIP**: Click either on the project or in any of its opened files to select it. Check that it's the current project in the top bar.

![Project](/wisun-building-connecting/0.2/images/project.png)

> **TIP**: Open the **Progress** view to check what Simplicity Studio is working on, and check when compilation is complete. Undock this window and move it next to Simplicity Studio to see progress at any time, while reducing the window dimensions. For multi-screen users, move it to a second screen.

![progress](/wisun-building-connecting/0.2/images/progress.png)

###### Time to Build

Use **Project > Build Project** to launch your first build of the project.

![Build](/wisun-building-connecting/0.2/images/build.png)

![Building](/wisun-building-connecting/0.2/images/building.png)

Hopefully, the project compiles without errors. Since this was a first-time full build, it takes approximately 1 min. Subsequent builds are generally smaller, if only adding minor changes to a couple files (only files impacted by the changes are recompiled).

![Compiled](/wisun-building-connecting/0.2/images/compiled.png)

###### What Happened

![Build Result](/wisun-building-connecting/0.2/images/build-result.png)

- Two new folders were added to your project folder:  
  - `Binaries` contains the executable files in various formats.  
  - `GNU ARM vx.y.z - Default` contains all the `.o` files corresponding to the `.c` files compiled. There are a lot of files in there, but you don't need to look at them. It's a storage area for the compiler.
- The **Console** window shows the results of the compilation.  
  - This is where you will need to check for any compilation issue.    
    ![Console](/wisun-building-connecting/0.2/images/console.png)

You can see all 'build' commands (there are many, one per .c files) starting with:

```bash
Invoking: GNU ARM C Compiler
arm-none-eabi-gcc ...
```

You can see the 'link' command (there is only one link command) starting with:

```bash
Invoking: GNU ARM C Linker
arm-none-eabi-gcc ...
```

You can see the creation of all binary files (those stored in `Binaries`):

```bash
Building target: wisun_soc_empty.axf
Invoking: GNU ARM C Linker
arm-none-eabi-gcc -g3 -gdwarf-2 -mcpu=cortex-m33 -mthumb ...
Finished building target: wisun_soc_empty.axf
 
Building out file: wisun_soc_empty.out
arm-none-eabi-objcopy "wisun_soc_empty.axf" "wisun_soc_empty.out"
 
Building hex file: wisun_soc_empty.hex
arm-none-eabi-objcopy -O ihex "wisun_soc_empty.axf" "wisun_soc_empty.hex"
 
Building bin file: wisun_soc_empty.bin
arm-none-eabi-objcopy -O binary "wisun_soc_empty.axf" "wisun_soc_empty.bin"
 
Building s37 file: wisun_soc_empty.s37
arm-none-eabi-objcopy -O srec "wisun_soc_empty.axf" "wisun_soc_empty.s37"
 
```

Last, a check is done on the code size using the `arm-none-eabi-size` tool:

```bash
Running size tool
arm-none-eabi-size "wisun_soc_empty.axf" -A
wisun_soc_empty.axf  :
section                   size        addr
.text                   617712   134217728
.ARM.exidx                   8   134835440
.copy.table                 12   134835448
.zero.table                  0   134835460
.stack                    4096   536870912
.data                     4728   536875008
.bss                     30836   536879736
text_application_ram         0   536910572
.heap                    54272   536910576
.nvm                     40960   134835460
.ARM.attributes             54           0
.comment                    69           0
.debug_line_str            713           0
.debug_info            3207643           0
.debug_abbrev           257437           0
.debug_loc              630169           0
.debug_aranges           44648           0
.debug_ranges            25360           0
.debug_line            1059997           0
.debug_str              365703           0
.debug_frame            147496           0
.debug_loclists         362184           0
.debug_rnglists          36380           0
Total                  6890477
```

> **TIP**: To find the FLASH footprint of your application, add `.text` to `.data`. For the RAM usage, add `.bss` to `.data` (`.data` is used in both cases since it is copied from FLASH to RAM before execution).

You can run this same command on the `.axf` file whenever you want. `arm-none-eabi-size.exe` is normally installed with Simplicity Studio, under `C:\SiliconLabs\SimplicityStudio\v5\developer\toolchains\gnu_arm\12.2.rel1_2023.7\bin` (the `gnu_arm` release may vary).

> **TIP**: To get the values displayed in hex, use the '-x' flag. This can be convenient to understand where each piece of code will reside in Flash.

###### Checking the Linker Command

In the linker command, you can see several interesting things.

The command line is very long, so only an abstract is provided below, with line breaks for easier reading.

```bash
Invoking: GNU ARM C Linker
arm-none-eabi-gcc
 -g3
 -gdwarf-2
 -mcpu=cortex-m33
 -mthumb
 -T "C:\Users\username\SimplicityStudio\Development_Walkthrough\wisun_soc_empty\autogen\linkerfile.ld" 
-Xlinker
 --gc-sections
  -Xlinker 
  -Map="wisun_soc_empty.map" 
  -mfpu=fpv5-sp-d16 
  -mfloat-abi=hard 
  --specs=nano.specs
 -o wisun_soc_empty.axf
 -Wl,--start-group "./app.o" "./app_init.o" "./main.o"... <all `.o` files having been previously compiled from `.c` files>
  "C:/Users/username/SimplicityStudio/SDKs/simplicity_sdk/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a"
  "C:/Users/username/SimplicityStudio/SDKs/simplicity_sdk/platform/radio/rail_lib/autogen/librail_release/librail_efr32xg25_gcc_release.a"
  "C:/Users/username/SimplicityStudio/SDKs/simplicity_sdk/protocol/wisun/stack/libwisun_router_efr32xg2x_micriumos_gcc_debug.a"
   -lgcc -lc -lm -lnosys -Wl,--end-group -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
```

- All linker configuration flags (refer to [GCC GNU DOC](https://gcc.gnu.org/onlinedocs/) for details on these flags).  
  - Among these, you see that, by default, Simplicity Studio compiles with `-g3`, which means 'optimize for debugging'.
- The name of the linked file, here `-o wisun_soc_empty.axf`.  
  - You see in the Console output that the other binary files are copied from this file using various `arm-none-eabi-objcopy` options.
- A very long list of all `.o` files, compiled from your project's `.c` files.
- Three `.a` files matching your project's configuration. These correspond to pre-compiled libraries found in various libraries:  
  - The NVM library `libnvm3_CM33_gcc.a`  
  - The RAIL library for your hardware `librail_efr32xg25_gcc_release.a`  
  - The Wi-SUN library managed by Silicon Labs R&D: `libwisun_router_efr32xg2x_micriumos_gcc_debug.a`    
    - Looking in `C:/Users/username/SimplicityStudio/SDKs/simplicity_sdk/protocol/wisun/stack/`, you see that there is a dedicated pre-compiled library per device_type/part/OS/Compiler/debug_or_release. Here, you linked with the library matching your project's default configuration.

##### Flashing the Binary to the Adapter Board

To run the binary you just compiled, you need to flash (copy) it to your Radio Board, with the following steps.

###### Open the Serial 1 UART Console

1. In the **Debug Adapters** frame, select the Radio Board.
2. Select **Launch Console** to open a communication console with the Adapter Board.  
   ![Launch Console](/wisun-building-connecting/0.2/images/launch-console.png)  
   A new tab will open, with the name of the J-Link adapter and it's ID.
3. In this new tab, select the **Serial 1** tab to access the application's UART console. This will show all strings printed from the application using `printf()`.  
   > **TIP**: Strings printed by the Wi-SUN Stack will not be sent to the **Serial 1** console. These are accessible as RTT traces, using J-Link RTT Viewer.  
   When the **Serial 1** console opens, it's in a non-connected state by default, as shown by the small icon in the bottom left corner.  
   ![New Console](/wisun-building-connecting/0.2/images/new-console.png)
4. Select the console's text area and press **Enter** to connect to the application. The icon changes to indicate a connected state.  
   ![Connected Console](/wisun-building-connecting/0.2/images/connected-console.png)  
   The Console is now connected. You can flash your application, but you need to start a Border Router first to be able to connect over your Wi-SUN network.

> **TIP**: Having the Serial 1 console ready to print the application output is important to check messages indicating proper application start. Most example applications will display the application's name at startup.

###### Time to Start a Border Router Demo

To make your development walkthrough more pleasant, it's time now to start a Border Router with default settings, such that your Empty application will be able to connect to an existing Wi-SUN network.

1. Plug a second Development Kit.
2. Select it in the **Debug Adapters** view.
3. As above, open the **Serial 1** console for this Development Kit.
4. Drag and drop the new console to the left side of the first one to see them side by side.  
   ![consoles side by side](/wisun-building-connecting/0.2/images/consoles-side-by-side.png)
5. Click **Enter** in the new console to connect the UART.
6. Click **Launcher** at the top right to open the Launcher perspective.
7. Select the **EXAMPLE PROJECTS AND DEMOS**.
8. Leave only **Demos** selected.
9. Filter on **Wi-SUN**.
10. Filter on **SoC**.  
    Only three applications match.
11. Move to the **Wi-SUN - SoC Border Router** frame and click **RUN**.  
    ![border router demo](/wisun-building-connecting/0.2/images/border-router-demo.png)  
    This immediately triggers flashing the corresponding pre-compiled binary to the target.  
    ![run border router demo](/wisun-building-connecting/0.2/images/run-border-router-demo.png)
12. Go back to the **Simplicity IDE** perspective.
13. Check the Border Router Demo console, which should show the Border Router CLI initial message.  
    ![border router console](/wisun-building-connecting/0.2/images/border-router-console.png)
14. In this console, use `wisun start_fan11` to start the Border Router with default FAN1.1 settings.  
    ![wisun start fan11](/wisun-building-connecting/0.2/images/wisun-start-fan11.png)

###### Flashing the Binary

1. In the **Project Explorer** view select the wisun_soc_empty project, open the `Binaries` folder and right-click the `.s37` file.
2. Select **Flash To Device**.  
   ![Flash to Device](/wisun-building-connecting/0.2/images/flash-to-device.png)
3. Select the device. Make sure not to select the one used as a Border Router.  
   > **TIP**: For a first flash of a new application on a Radio Board where other application may have been running before, use the **Erase** button to clear any data possibly stored in flash. A progress bar appears and closes when done.  
   ![Erase](/wisun-building-connecting/0.2/images/erase.png)
4. Use the **Program** button to flash the selected binary. A progress bar appears and closes when done.  
   ![Program](/wisun-building-connecting/0.2/images/program.png)
5. Close the Flash Programmer window.

##### Verifying Console Output

The Device Console now shows the startup message.

![Startup Message](/wisun-building-connecting/0.2/images/startup-message.png)

- The name of the application is printed.  
  - This comes from `app.c/app_task()`, the entry point for the application code.    
    ![Application Name](/wisun-building-connecting/0.2/images/application-name.png)
- Then, you see the first message generated by the application: `[Join state: Select PAN (1)]`  
  - This comes from the **Application Core** component, which is tracking join state change events.  
  - A similar message will be printed every time the join state will change.

> **TIP**: When a component is present in the project, the corresponding code is shown with normal colors. If a component is not present, the corresponding code is grayed out in the editor, meaning that it is not compiled and can be ignored.

- Here, the fact that the `sl_wisun_on_event()` function is grayed out indicates that this code is not compiled, meaning that `SL_CATALOG_WISUN_EVENT_MGR_PRESENT` is not defined.  
  - This means that the **Wi-SUN Event Manager** component is not installed in your project.
- Similarly, the fact that the `sl_wisun_app_core_util_connect_and_wait()` function call is displayed with normal colors indicates that this code is compiled, meaning that `SL_CATALOG_WISUN_APP_CORE_PRESENT` is defined.  
  - This means that the **Wi-SUN Application Core** component is installed in your project.
- Last, you see a message coming from the application indicating the name of the Wi-SUN network that you are trying to connect to.
- If a Wi-SUN Border Router is within range with a Wi-SUN network named `Wi-SUN Network` and the same PHY settings as your application defaults, you will connect.

##### Tracking the Connection Message

For users not familiar with Simplicity Studio and C code in general, the following are some elementary code checks:

- In `app.c/app_task()`, you see that there is a call to `sl_wisun_app_core_util_connect_and_wait();`.
- Select `sl_wisun_app_core_util_connect_and_wait` and right-click to get access to the declaration of this function.  
  ![track sl_wisun_app_core_util_connect_and_wait()](/wisun-building-connecting/0.2/images/track-app-wisun-connect-and-wait.png)
- You end up in `/wisun_soc_empty/simplicity_sdk_x.y.z/app/wisun/component/app_core/sl_wisun_app_core_util.c`, in the code implementing `sl_wisun_app_core_util_connect_and_wait()`.  
  ![in sl_wisun_app_core_util_connect_and_wait()](/wisun-building-connecting/0.2/images/in-app-wisun-connect-and-wait.png)
- You find two function calls here. Given the function names, you get a pretty good idea of what they do. Since the **Connecting to...** message probably comes from `sl_wisun_app_core_network_connect()`, look for it's declaration as well.  
  ![track sl_wisun_app_core_network_connect](/wisun-building-connecting/0.2/images/track-app-wisun-network-connect.png)
- You end up in `/wisun_soc_empty/simplicity_sdk_x.y.z/app/wisun/component/app_core/sl_wisun_app_core.c/sl_wisun_app_core_network_connect()`, which is a longer function.  
  ![in sl_wisun_app_core_network_connect](/wisun-building-connecting/0.2/images/in-app-wisun-network-connect.png)
- You can find the `Connecting to` message.

While you are looking at `sl_wisun_app_core_network_connect()`, you can see that there are several steps during the connection preparation:

- Preparation of the PHY and network settings
- Check of the current join state
- Setting the network settings (to your project defaults)
- Setting Security
- Joining a network with a given name and PHY settings  
  - So far, rely on the application components (i.e. Wi-SUN Application Core here) to do that.  
  - More details on this later.
- An alternative method to follow the function calls is to use the **Open Call hierarchy** for the `sl_wisun_app_core_util_connect_and_wait()` function.  
  ![Open Call Hierarchy](/wisun-building-connecting/0.2/images/open-call-hierarchy.png)
- The Call Hierarchy view proposes two modes, selectable using the 'tree' icons.  
  - The **Show Callers** view shows which functions are calling `sl_wisun_app_core_util_connect_and_wait()`:    
    - Here, a single function: `app_task()`, as you've already seen.    
    - Using the Call Hierarchy, you are now sure that `sl_wisun_app_core_util_connect_and_wait()` is called from a single location, information you didn't have before.      
      ![Show Callers](/wisun-building-connecting/0.2/images/show-callers.png)  
  - The **Show Callees** view shows which functions are called by `sl_wisun_app_core_util_connect_and_wait()`:    
    ![Show Callees](/wisun-building-connecting/0.2/images/show-callees.png)    
    - Here, two functions are called, as you've already seen:      
      - `sl_wisun_app_core_network_connect()`      
      - `sl_wisun_app_core_util_wait_for_connection()`      
      - Using the Call Hierarchy, you can expand `sl_wisun_app_core_network_connect()` and check which functions it calls.        
        ![Open sl_wisun_app_core_network_connect](/wisun-building-connecting/0.2/images/open-app-wisun-network-connect.png)    
    - This view still shows that `sl_wisun_app_core_network_connect()` calls `printf`, the function called to print your message.

> **TIP**: Depending on the user, everyone prefers a method to find the call hierarchy based on personal preferences and the situation. The method above proposes two ways to follow the function calls in a Wi-SUN application.<br />**TIP**: When going down the call hierarchy, you will end in a situation where you can't go further and are left with the definition of a given function in a header file. It means that you have reached the tip of the Wi-SUN Stack API, that part of the Wi-SUN code which is under the responsibility of Silicon Labs R&D and where you don't have access to the source code.

##### SiSDK Code vs User Code

> **TIP**: All files under `/wisun_soc_empty/simplicity_sdk_x.y.z/` are SiSDK files, common to all projects. Consider that for all your projects, `/<project_name>/simplicity_sdk_x.y.z/` is the same content. This is why there are blocks of code conditionally compiled depending on the project's configuration (settings and components). These files should normally not be modified. User code and changes should stay out of `<project_name>/simplicity_sdk_x.y.z/`, since changing this code will impact all your projects the next time you build them.

##### Checking the Wi-SUN Connection

While you were looking at the source code, time passed and there is a good chance that your device connected to the Wi-SUN Border Router. This should be visible in the Device's Serial 1 console.

![Operational](/wisun-building-connecting/0.2/images/operational.png)

- Once connected, the IPv6 addresses are displayed:  
  - GLOBAL is the device's IPv6 to connect to it from anywhere, provided that IPv6 forwarding is allowed on the Border Router, which is not the case with the Border Router SoC Demo. To test pinging the device from the Border Router, Silicon Labs recommends [our open source Linux Border Router](https://github.com/SiliconLabs/wisun-br-linux).  
  - LINK_LOCAL is the device's IPv6 address to communicate with its neighbors.  
  - BORDER_ROUTER is the Border Router's IPv6 address. You can check this on the Border Router Demo using 'wisun get wisun.ip_addresses'. It is listed as the 'dodagid' address.

###### What's Next

If you achieved a Wi-SUN connection, everything is fine in terms of Wi-SUN connectivity. The Wi-SUN stack will now maintain the connection, using the self-healing features of Wi-SUN to select an alternative path if the current parent fails or if there is a better option.

You can flash exactly the same application to many similar Adapter Boards. They will all end up connected to the Wi-SUN network. If you move the devices apart or you start more devices than what the Border Router can support directly, they will start creating hops to connect to the Border Router.

Basically, you have a working Wi-SUN network where you can add your custom application code to do whatever you need to.

There are still, however, a number of limitations in this approach:

- All devices use the same security credentials. In production devices, each device should have its own set of device key/device certificate.
- You didn't control the network name.
- You used the default PHY settings (with lowest throughput).
- You may not be using a PHY matching your region, so you may be transmitting in a forbidden frequency band.

It's time to learn how to check and change the settings, and then how to add your custom application.

##### Checking and Changing the Settings

###### Border Router Settings

To illustrate how to change the settings, using something different from the defaults regulatory_domain/chan_plan_id/phy_mode_id (NA/2/1 in our example), you will use BZ/3/1.

> **Note**: The previous steps are valid for all Wi-SUN development kits, with default settings, because Simplicity Studio selected the proper libraries to match the Radio Boards. There are several frequency ranges used for Wi-SUN, with only some valid for a given country. The first part of the Development Walkthrough used Radio Boards with the 902-928 MHz frequency range valid for North America (NA), Mexico (MX), and Brazil (BZ). Selecting BZ/3/1 is only possible when using Radio Boards for these regions. With 'EU' Radio Boards or any other region, it is necessary to select a valid PHY for the Radio Boards to go through the following part.

Using the Wi-SUN Border Router Demo, use the following to change the settings.

Hardware reset on the Border Router (to stop the Border Router):

```bash
> Wi-SUN Border Router CLI Application
wisun get wisun.state
wisun.state = initialized (0)
```

> TIP: If the wisun.state is not `initialized (0)` at this step, the new settings won't be applicable. Make sure you reset the Border Router.

```bash
> wisun set wisun.regulatory_domain BZ
wisun.regulatory_domain = BZ
> wisun set wisun.phy_mode_id 3
wisun.phy_mode_id = 3
> wisun set wisun.chan_plan_id 1
wisun.chan_plan_id = 1
> wisun start_fan11
[Using built-in trusted CA #0]
[Using built-in device credentials]
[Border router started]
> wisun get wisun.state
wisun.state = operational (1)
```

> **TIP**: The Border Router can store its configuration settings in non-volatile memory (NVM). After executing the `wisun save` command, the Border Router retains its configuration even after a software reset or a power cycle.
> To restore the default parameters, use the `wisun reset` command.

> **Troubleshoot**: If an error occurs during wisun start, ensure phy settings `BZ_3_1` is available on Wi-SUN radio configurator of the Border Router application. If not it can be added manually like demonstrated further in this documentation for empty application.

###### Wi-SUN Router Settings

###### Checks (heading level 7)

First observe what you have by default:

1. Open the Wi-SUN Configurator (double-click the `.slcp` file).
2. Open the `autogen/sl_wisun_config.h` file, and move it aside to get a view on both.
3. Open the `config/wisun_settings.wisunconf` file with the option **Open With > Text Editor**, and move it below to see it also.

In the Wi-SUN Configurator, the **Application** tab gives access to:

- The network name, which corresponds to `WISUN_CONFIG_NETWORK_NAME` in `autogen/sl_wisun_config.h` and `"networkName"` in `config/wisun/wisun_settings.wisunconf`
- The network size, which corresponds to `WISUN_CONFIG_NETWORK_SIZE` in `autogen/sl_wisun_config.h` and `"networkSize"` in `config/wisun/wisun_settings.wisunconf`
- The device type, i.e. `WISUN_CONFIG_DEVICE_TYPE`
- The broadcast retransmission, i.e. `WISUN_CONFIG_BROADCAST_RETRIES`  
  ![Open Configurator](/wisun-building-connecting/0.2/images/open-configurator.png)

No Tx Output Power in the files?

- This is because the default GUI value is set to the code's default value (200 d-dBm). If you change the Tx Output Power in the GUI, you will see new items added to the files:  
  - `WISUN_CONFIG_TX_POWER` in `autogen/sl_wisun_config.h` and `"txOutputPower"` in `config/wisun/wisun_settings.wisunconf`  
  ![tx output power](/wisun-building-connecting/0.2/images/tx-output-power.png)
- A quick search for `WISUN_CONFIG_TX_POWER` will show how this is handled by `simplicity_sdk_x.y.z/app/wisun/component/app_core/sl_wisun_app_core.c`:  
  ![tx output power default](/wisun-building-connecting/0.2/images/tx-output-power-default.png)

> **TIP**: The code default Tx Output Power is 20. As explained by the helptext, when you click the ![question mark](/wisun-building-connecting/0.2/images/question-mark.png) icon, the actual output power is generally less than that. Indeed, for best MCS6 performance (OFDM MCS6 uses a 16-QAM modulation) with EFR32xG25, do not go above 14 dBm to avoid clipping the outer edges of the constellation and get better performances.

![tx output power helptext](/wisun-building-connecting/0.2/images/tx-output-power-helptext.png)

There are close relationships between:

- The GUI (the Wi-SUN Configurator)
- It's control file `config/wisun_settings.wisunconf`
- Some of the `.h` and `.c` files which you will ultimately use to compile your application

The **Security** tab gives access to:

- The Device Private Key, i.e. `wisun_config_device_private_key[];`  
  - You can see its current value by hovering over it, as shown above.  
  - You can also right-click it and select **Open Declaration**. This opens `autogen/sl_wisun_config.c`, where `wisun_config_device_private_key[]` is declared.  
  - You can check that the text string:    
    - Is identical to the one in the GUI    
    - Starts with `-----BEGIN PRIVATE KEY-----`    
    - Ends with `-----END PRIVATE KEY-----`
- The Device Certificate, i.e. `wisun_config_device_certificate[];`
- The CA Certificate, i.e. `wisun_config_ca_certificate[];`  
  ![Security](/wisun-building-connecting/0.2/images/security.png)

You can cross-check these three values.

> **TIP**: As already stated, in a production application, these will need to be different per device. The CA certificate may be shared, but the Device key and certificate should be device-specific.

Open the `config/rail/radio_settings.radioconf` file with **Open With > Text Editor**, and move it in the same frame as `config/wisun/wisun_settings.wisunconf`.

- The **Radio** tab gives access to:  
  - In the **Selected Wi-SUN PHYs** frame, the list of currently selected PHYs. Here, only the default `NA - 2 -1` PHY is selected.  
  - In the **Application's Default PHY Configuration** frame, the default PHY.    
    - Obviously, this needs to be present in the selected PHYs, and in your case (using a single PHY) is also `NA - 2 -1`.  
  - In **Reference PHYs**, tools to select the PHYs.    
    ![Radio](/wisun-building-connecting/0.2/images/radio.png)

Observing `config/rail/radio_settings.radioconf`, you can check that `<phy_name_override>` matches the select PHY.

Once again, you see some relationship between the GUI, the control files, and the file used to compile.

###### Changes (heading level 7)

Move to the **Radio** tab, since you won't change the security settings yet.

On the right side of the **Radio** tab, you see that you have by default only the `NA - 2 - 1` PHY in the list.

Now add the `BZ - 3 - 1` PHY.

1. Slide left to see the **Reference PHYs** area.
2. Select the **FAN 1.1** radio button. This changes the content of the frame to match FAN 1.1 parameters.
3. Select the **Brazil (BZ)** option in the **Regulatory Domain** dropdown.  
   ![Brazil](/wisun-building-connecting/0.2/images/brazil.png)  
   You may have noticed that the list of possible PHYs at the bottom is now reduced to 'BZ' PHYs.
4. Select **phy_mode_id_3** in the **PHY Operating Mode ID** dropdown.  
   ![PHY mode id 3](/wisun-building-connecting/0.2/images/phy-mode-id-3.png)  
   The list of possible PHYs at the bottom is further reduced to only those with '3' as their PHY Operating Mode ID (a single one).
5. You can continue by selecting **1 (902-928MHz - Channel Spacing 600 kHz)** in the **Channel Plan ID** list.  
   This is not really required, since the above operations were used to reduce the list of possible PHYs, making it easy to select the desired PHY.  
   ![chan plan id 1](/wisun-building-connecting/0.2/images/chan-plan-id-1.png)
6. Click the blue ![Add PHY](/wisun-building-connecting/0.2/images/add-phy.png) icon on the PHY line to add it to the **Selected Wi-SUn PHYs** list.  
   ![Added PHY](/wisun-building-connecting/0.2/images/added-phy.png)  
   - The icon you just clicked turns light gray, indicating that this PHY is already in the list.  
   - A message is present in **Selected Wi-SUN PHYs** to indicate unsaved changes.  
   - A message informs you that you should save your new configuration by clicking the **Apply Configuration** button.  
   - Once saved, you can check in the `config/rail/radio_settings.radioconf` file that you now have two PHYs.  
   - In most cases, your Wi-SUN device will be targeting a single PHY, so also delete the `NA - 2 - 1` PHY from the list, using the ![delete](/wisun-building-connecting/0.2/images/delete.png) icon. Confirm the deletion and save the configuration again.    
     ![default phy](/wisun-building-connecting/0.2/images/default-phy.png)  
   - Only one PHY is now in `config/rail/radio_settings.radioconf`, your 'BZ' PHY.
7. A red box appears around the **Default PHY**, because the selected default is not part of the list anymore, so select **FAN 1.1 | BZ - 3 - 1** and save as instructed.  
   ![bz_3_1](/wisun-building-connecting/0.2/images/bz-3-1.png)
8. You can check in `config/wisun/wisun_settings.wisunconf` that your settings are now in the GUI control file, and also in `autogen/sl_wisun_config.h` that the following items match your selection:  
   - WISUN_CONFIG_DEFAULT_PHY_FAN11  
   - WISUN_CONFIG_REGULATORY_DOMAIN  
   - WISUN_CONFIG_CHANNEL_PLAN_ID  
   - WISUN_CONFIG_PHY_MODE_ID

Now, you can rebuild your project, and it will attempt to connect to your new **BZ - 3 - 1** Phy Wi-SUN network.

Take a minute to flash your new application to the Router to see if it can connect to your new Wi-SUN network.

> **TIP**: Before reloading, it's often useful to click the ![clear console](/wisun-building-connecting/0.2/images/clear-console.png) icon in the Serial 1 Console to clear old messages.

The most convenient feature in Simplicity Studio to flash the same application after recompiling it is **Redo last upload** when selecting a Debug Adapter.

> **TIP**: You can even select multiple targets and trigger the last upload for all in a click. It will work even if the binaries are different, reloading the previous binary for each target.

![redo last upload](/wisun-building-connecting/0.2/images/redo-last-upload.png)

> **TIP**: Understand 'redo last upload' as 'reload the binary from the same location, with the same name'. If the binary content changed (your case), it will be updated.

While it's connecting, you can review the traces.

Once the joining process completes, the following logs are displayed in the console:

```c
Wi-SUN Empty Application
[Join state: Select PAN (1)]

[Connecting to "Wi-SUN Network"]
[Join state: Authenticate (2)]
[Join state: Acquire PAN Config (3)]
[Join state: Configure Routing (4)]
[Join state: Operational (5)]

Addresses:
[GLOBAL        : fd12:3456::62a4:23ff:fe37:a52e]
[LINK_LOCAL    : fe80::62a4:23ff:fe37:a52e]
[BORDER_ROUTER : fd12:3456::862e:14ff:fee2:61ff]
[85 s]
```

If the device is connected to the Wi-SUN network, the Wi-SUN specific part of the application is complete.

###### Resources Once Wi-SUN SoC Empty is Connected

- PING capability
- Listening to IPv6 Broadcast addresses:  
  - The following IPv6 addresses are ready to receive broadcast messages:

|Scope|IPv6|nanostack #define|Send to|
|---|---|---|---|
|Link Local (= neighbors)|FF02::1|ADDR_LINK_LOCAL_ALL_NODES|BR + FFN (1 hop) + LFN (1 hop)|
|Link Local (= neighbors)|FF02::2|ADDR_LINK_LOCAL_ALL_ROUTERS|BR + FFN (1 hop)|
|Realm Local (= all network)|FF03::1|ADDR_REALM_LOCAL_ALL_NODES|BR + FFN (n hops) + LFN (n hops)|
|Realm Local (= all network)|FF03::2|ADDR_REALM_LOCAL_ALL_ROUTERS|BR + FFN (n hops)|

From this point, your device will:

- Reconnect to your Wi-SUN network automatically in case it's powered down then up.
- Regularly check for connection options within the surrounding Wi-SUN routers, and select a new parent if there is a better one or the current parent goes down. That is the self-healing part of Wi-SUN.
- Once connected, advertise the Wi-SUN network for other routers to connect, and become a parent for other devices if need be.
- If the Border Router goes down but another Border Router with the same Network name and credentials is within range, connect to this Border Router.  
  - Adding several Border Routers to a Wi-SUN network (with Ethernet IPv6 connectivity between such Border Routers) is a good way to share the load within the network.

You can flash the same binary to several Evaluation kits. They will all connect in a tree-like fashion to the Border Router, routers being direct children of the Border Router acting as parents for devices located further away, and so on.

As explained earlier, in a production environment the credentials will need to be unique per device, but for development purposes, it is sufficient to use the same credentials for a number of devices.

> **TIP**: On the Linux Border Router, you can use `watch wsbrd_cli status` to monitor the network topology. You can also use the [wsbrd GUI](https://github.com/SiliconLabs/wisun-br-gui) to get a graphical representation of this Wi-SUN network topology.

It's now time to look at the [Wi-SUN connection process](/wisun/2.12.0/wisun-connection-details/index) in detail.

#### Wi-SUN API Calls to Connect to a Wi-SUN Network

In the [first part of this series](/wisun/2.12.0/wisun-building-connecting/index), you connected to a Wi-SUN Network without looking at how this is achieved.

Connection was easy because you relied on the Wi-SUN Configurator GUI and the underlying **Wi-SUN Application Core component**.

This is a lecture on how the **Wi-SUN Application Core component** uses the Wi-SUN Stack API functions to achieve successful connection. Key points to understand are:

- Some general principles used when developing a Wi-SUN application
- Details of the connection process

##### Wi-SUN Application Core Component

There are at least four ways to check that the Wi-SUN Application Core component is part of the project.

1. Check the installed components in the **SOFTWARE COMPONENT** tab. You get access to an abstract of the component's readme, indicating the use of `sl_wisun_app_core_init()` to initialize it.  
   ![application core software components](/wisun-connection-details/0.1/images/application-core-software-components.png)
2. Check the content of `wisun_soc_empty.slcp` with a text editor.  
   ![application core in slcp](/wisun-connection-details/0.1/images/application-core-in-slcp.png)
3. In the source code, you can see that the `main()` function calls `sl_main_second_stage_init()`, which calls `sl_internal_app_init()`, which calls `sl_wisun_app_core_init()`. This code is automatically added when adding the component via the GUI.  
   ![application core flow](/wisun-connection-details/0.1/images/application-core-flow.png)
4. In `app.c/app_task()`, you see that the code surrounded by `SL_CATALOG_WISUN_APP_CORE_PRESENT` is not grayed out, indicating that `SL_CATALOG_WISUN_APP_CORE_PRESENT` is defined and the corresponding code will be compiled.  
   ![application_core_in_app_c.png](/wisun-connection-details/0.1/images/application-core-in-app-c.png)

The Wi-SUN Application Core component uses the Wi-SUN Configurator settings to achieve connection to a Wi-SUN Network with only GUI actions. This is the simplest way to connect to any Wi-SUN Network.

Now consider which function calls are required to connect to a Wi-SUN Network.

##### Wi-SUN Network Connection Walkthrough

You saw earlier the connection process in `/wisun_soc_empty/simplicity_sdk_x.y.z/app/wisun/component/app_core/sl_wisun_app_core.c`, with several steps during the connection preparation.

![in sl_wisun_app_core_network_connect.png](/wisun-connection-details/0.1/images/in-app-wisun-network-connect.png)

###### Preparation of the PHY and Network Settings

The grayed out part is not compiled.

```C
  memcpy(&_setting, &_app_default_settings, sizeof(app_setting_wisun_t));
```

This line copies the `_app_default_settings` into `_setting`, a `app_setting_wisun_t` structure defined earlier as:

```C
/// Internal setting storage
static app_setting_wisun_t _setting = { 0 };
```

###### `app_setting_wisun_t` structure (heading level 7)

You can check the declaration of the `app_setting_wisun_t` structure by selecting the **Open Declaration** menu item.

![app_setting_wisun_t open declaration.png](/wisun-connection-details/0.1/images/app-setting-wisun-t-open-declaration.png)

This brings you higher up in `/wisun_soc_empty/simplicity_sdk_x.y.z/app/wisun/component/app_core/sl_wisun_app_core.c` to the declaration of the structure.

![app_setting_wisun_t declaration.png](/wisun-connection-details/0.1/images/app-setting-wisun-t-declaration.png)

You can see here that the structure stores:

- The network name (as a string, which always end up with an additional `0x00` byte as the string terminator, hence the `+ 1` in the array definition)
- The network_size
- The Tx power
- The device type
- The LFN profile (only used for LFNs)
- A flag indicating if the device is using the default PHY
- Another `sl_wisun_phy_config_t` structure  describing the PHY

> TIP: You can also check the definition of a structure by hovering over it until a pop-up appears with the definition.

![app_setting_wisun_t popup](/wisun-connection-details/0.1/images/app-setting-wisun-t-popup.png)

###### `sl_wisun_phy_config_t` structure (heading level 7)

![sl_wisun_phy_config_t declaration](/wisun-connection-details/0.1/images/sl-wisun-phy-config-t-declaration.png)

The `sl_wisun_phy_config_t` structure is a more complex `union` type, which requires clarification for people not familiar with C coding.

A `union` is a place where several underlying structures can be stored, but to save memory, only one will be stored at a time. In your example, you know which underlying structures can be used by looking at each `struct {} <STRUCT_NAME>;` block. You can locate:

- `fan10`
- `fan11`
- `explicit`

![sl-wisun-phy-config-t-subs](/wisun-connection-details/0.1/images/sl-wisun-phy-config-t-subs.png)

Usually, unions start with a `type` information, which is used to select the underlying structure.

In your example application, you're using `fan11`, so the `type` will be set accordingly and the FAN 1.1 values will be accessed as:

- `phy.fan11.reg_domain`
- `phy.fan11.chan_plan_id`
- `phy.fan11.phy_mode_id`

if `phy` is a `sl_wisun_phy_config_t`

or

- `phy->fan11.reg_domain`
- `phy->fan11.chan_plan_id`
- `phy->fan11.phy_mode_id`

if `phy` is a pointer to a `sl_wisun_phy_config_t`

> TIP: When moving around files in Simplicity Studio, use **Alt+left_arrow** or **Alt+Right_arrow** to move between recent locations.

###### Check of the Current Join State

Back to `sl_wisun_app_core_network_connect()`, you see that there is a check of the current join state. This is because, before calling the join function, the device must be disconnected so that it properly starts using the new parameters and clears its state machine.

![check join state](/wisun-connection-details/0.1/images/check-join-state.png)

Here it's worth looking at what the `__CHECK_FOR_STATUS` is doing, since you may see it used often. Use the pop-up since it's relatively short.

![check for status macro](/wisun-connection-details/0.1/images/check-for-status-macro.png)

You can understand looking at the macro definition that an error message will be printed with the error number when the `ret` value is not `0x0000`, and if `ret` is `0x0000`, nothing will happen. If an error message will be printed, it will also contain the name of the function from where it is originating, (here `sl_wisun_app_core_network_connect`), as a replacement for the `__PRETTY_FUNCTION__` identifier. Defining macros such as these is a good way to avoid repeating the same code block in your code. It makes the code more compact and less error prone (once the macros are properly tested).

> TIP: Generally, in C code, specific identifiers such as those declared by the compilers are prefixed and suffixed with `__`. Avoid using this in your own variable names to avoid confusion. Here, using the C++ `__PRETTY_FUNCTION__` is not necessary, since the code is compiled as C code, not C++. Using `__FUNCTION__` is sufficient.

###### `_app_wisun_mutex_acquire()` and `_return_and_mtx_release()`

You see `_app_wisun_mutex_acquire()` and `_return_and_mtx_release()` in the code around some code blocks.

The `_app_wisun_mutex_acquire()` name is a bit more explicit. It indicates that you are acquiring a 'mutex', i.e, a mutual-exclusion flag. This is commonly used in C code when several parts of the code (from different threads) may need to access common variables.

Whenever the code needs to access such data, you want to make sure no other function is changing it at the same time, which could lead to unexpected results.

When calling `_app_wisun_mutex_acquire()`, you're waiting for the number of current users of the flag to be `0`. Until the flag is `0`, you wait. Once it is `0`, the underlying system sets it to `1` and gives you the access. From this point on, you 'own' the mutex flag and the right to access the shared data.

This means that, if you never release it, all other users (including yourself) will never get access to the shared data!

When you're done, release the mutex by calling `_return_and_mtx_release()`, which, if you look into it, starts by releasing the mutex and then returns.

A typical pattern when using a mutex is:

- Acquiring the mutex at the beginning of the function
- Releasing the mutex before every return

> TIP: You can see several occurrences of `_return_and_mtx_release()` in a single function, because you need to release the mutex before returning. To achieve this, all `return` calls are replaced by `_return_and_mtx_release()` on every place in the function where you return from.

###### Filling the Network Settings

Next you get to the application settings.

![application settings](/wisun-connection-details/0.1/images/application-settings.png)

You see here that the code calls `_app_wisun_application_setting` with the content of `_setting` from the [preparation of the PHY and Network settings](#preparation-of-the-phy-and-network-settings).

Now look into this function (only showing code which is not grayed out, i.e. compiled code).

![application settings func](/wisun-connection-details/0.1/images/application-settings-func.png)

The `sl_wisun_get_conn_param_by_nw_size()` function is called to set the `conn_param` structure with values matching the network size selected by the user.

`conn_param` is a [`sl_wisun_connection_params_t`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-connection-params-t) structure, defined as:

![connection_params_t](/wisun-connection-details/0.1/images/connection-params-t.png)

As you can see, there are several underlying structures, used to store:

- [discovery parameters](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-discovery)
- [configuration parameters](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-configuration)
- [eapol parameters](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-eapol)
- [rpl parameters](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-rpl)
- [misc parameters](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-misc)

Your current **Network Size** setting is **Small**.

![network_size](/wisun-connection-details/0.1/images/network-size.png)

`sl_wisun_get_conn_param_by_nw_size` simply selects the corresponding settings based on this selection:

![network_size case](/wisun-connection-details/0.1/images/network-size-case.png)

In the declaration of `SL_WISUN_PARAMS_PROFILE_SMALL`, you see all parameters and their values.

![network_size small](/wisun-connection-details/0.1/images/network-size-small.png)

> TIP: By default, the [Wi-SUN Stack API](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-params-predefined-profiles) defines three Network Sizes for general use: SMALL, MEDIUM, and LARGE. Each set of parameters corresponds to a good compromise for most applications. The application may customize these or add more if required; it's up to the user. An application not using the Wi-SUN Application Core component will need to define its own `sl_wisun_connection_params_t` structure.
> 
> TIP: If you want to customize the connection parameters and start editing the file, Simplicity Studio will ask you whether you want to create a copy of the file inside your project or edit the SiSDK file. (Remember that SiSDK files are normally only logical links to the SiSDK files.) If you opt for the copy, the logical link will be replaced by a copy of the SiSDK file, and your changes will be local to your project. If you opt for editing the SiSDK file, your changes will affect all your Wi-SUN projects, but may be 'lost' when you update the SiSDK. (They are not really lost, since they will still be present in the previous SiSDK folder, but you will need to patch the new SiSDK files with similar changes.)

###### Setting Security

Next you get to the security settings.

![security settings](/wisun-connection-details/0.1/images/security-settings.png)

Going to the declaration of `_app_wisun_security_setting()`, you find the calls to set:

- The CA (Certification Authority) certificate
- The Device's certificate
- The Device Private Key

![CA certificate](/wisun-connection-details/0.1/images/ca-certificate.png)

Hovering over the corresponding variables, you can check their values. You can also open their declarations, which you find in `autogen/sl_wisun_config.c`. As you've already seen, these can be set on the Wi-SUN Configurator's **Security** tab.

> TIP: For a production environment, the Device certificate and Private Key need to be unique per device.

###### Joining a Network with a Given Name and PHY Settings

Finally, you reach the point where you call the [Wi-SUN Stack API `sl_wisun_join()` function](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-join) and check its return value.

This is where you use the Network Name you set earlier (using the Wi-SUN Configurator) in `autogen/sl_wisun_config.h` as `WISUN_CONFIG_NETWORK_NAME`.

![sl_wisun_join](/wisun-connection-details/0.1/images/sl-wisun-join.png)

As you see in the code, the `sl_wisun_join()` function returns rapidly, before connection is complete, and then there is a check of the `sl_wisun_join()` return value.

- If the call is successful, it means that your network settings are all okay and match the available PHY(s) that you added using the Wi-SUN Configurator.  
  - A timestamp is set to the current time to indicate how much time it takes to connect.
- If there is an error, most probably the PHY you selected is not in the list of PHYs in your configuration.  
  - If you have been using the Wi-SUN Configurator and the default PHY, this should not happen.

##### Waiting for Connection

To check the connection state, follow the join state of the Wi-SUN device. This is done by `sl_wisun_app_core_util_wait_for_connection()`.

![wait](/wisun-connection-details/0.1/images/wait.png)

![wait_for_connection](/wisun-connection-details/0.1/images/wait-for-connection.png)

The application waits for an OS event to proceed. This event is posted when the Wi-SUN stack raises a connection indication, specifically the SL_WISUN_MSG_CONNECTED_IND_ID event.
For more details on event handling, refer to the [Event Handling with the Event Manager Component](#event-handling-with-the-event-manager-component) section.

Join_state can be returned thanks `sl_wisun_app_core_get_join_state`, once connected `SL_WISUN_JOIN_STATE_OPERATIONAL` = (`5`) should be returned.

![get_join_state](/wisun-connection-details/0.1/images/get-join-state.png)

`sl_wisun_app_core_get_join_state()` acquires the mutex to read `_join_state` (note that there is a `_` prefix, indicating that `_join_state` is an internal variable), stores it into `join_state`, releases the mutex, and returns `join_state`.

Using the mutex means that `_join_state` is set by another part of the code. To see how, look for occurrences of `_join_state`.

First, it's declared and initialized with `SL_WISUN_JOIN_STATE_DISCONNECTED`.

![_join_state_declaration](/wisun-connection-details/0.1/images/join-state-declaration.png)

Possible join state values are defined in [`simplicity_sdk/protocol/wisun/stack/inc/sl_wisun_types.h`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-types#sl-wisun-join-state-t).

![join states](/wisun-connection-details/0.1/images/join-states.png)

The `sl_wisun_join_state_t` enumeration tells us what steps are used for connecting (re-ordered below by chronological order):

|Join state|enum|meaning|actions|
|---|---|---|---|
|0|SL_WISUN_JOIN_STATE_DISCONNECTED|Disconnected|Device not attempting to connect. Border Router and connected routers send 'PAN Advert' on all channels|
|1|SL_WISUN_JOIN_STATE_SELECT_PAN|Select PAN|Device listens for 'PAN Advert'. Sends 'PAN Advert Solicit' to shorten the transmission delay|
|2|SL_WISUN_JOIN_STATE_AUTHENTICATE|Authenticate|Security key exchange between device and Border Router (can use an external Radius server)|
|3|SL_WISUN_JOIN_STATE_ACQUIRE_PAN_CONFIG|Acquire PAN config|Device listens for 'PAN Config'. Sends 'PAN Advert Solicit' to shorten the transmission delay|
|4|SL_WISUN_JOIN_STATE_CONFIGURE_ROUTING|Configure routing|Network Route Selection (see sub-steps below)|
|41|SL_WISUN_JOIN_STATE_PARENT_SELECT|Preferred parent selection|Comparison between potential parents. Selection of 'best parent'|
|42|SL_WISUN_JOIN_STATE_DHCP|DHCP address acquisition|DHCP address received from Border Router|
|43|SL_WISUN_JOIN_STATE_EARO|Address registration| |
|44|SL_WISUN_JOIN_STATE_DAO|DAO registration| |
|5|SL_WISUN_JOIN_STATE_OPERATIONAL|Operational|Device is operational. Starts sending 'PAN Advert' for other nodes to connect (if FFN/router)|

- By default, Wi-SUN SoC Empty doesn't track the intermediate 41-44 sub-steps between join state 4 and join state 5.
- When reconnecting, provided that the credentials are still valid, the connection process is sped up by avoiding steps 1 and 2.

Now look at how events are handled, and the concepts behind the Wi-SUN Stack API.

###### Wi-SUN Stack API Concepts

As stated in the [Wi-SUN Stack API documentation](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-on-event):

- Wi-SUN Stack API is based on **requests from the application** to the stack and **events from the stack** to the application.
- Requests are made using function calls, where a function call either performs the required action immediately or initiates an internal operation within the stack, which terminates with an event. All events contain a status code, indicating the result of the requested operation. Events are also used by the stack to notify the application of any important information, such as the state of the connection.
- **The application is expected to override `sl_wisun_on_event()` to handle events from the stack**. Because all events share a common header, the function may be implemented as a switch statement. The event-specific data can be accessed through the `sl_wisun_evt_t::evt` union.

###### Event Handling with the Event Manager Component

[`simplicity_sdk/protocol/wisun/stack/inc/sl_wisun_events.h`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-evt-t) contains the list of possible events from the stack.

![sl_wisun_evt_t](/wisun-connection-details/0.1/images/sl-wisun-evt-t.png)

The first member of the `sl_wisun_event_t` structure is a `sl_wisun_msg_header_t` header.

![sl_wisun_msg_header_t](/wisun-connection-details/0.1/images/sl-wisun-msg-header-t.png)

From this header, the application needs to check the `id` value to know what the `evt` corresponds to, and then use the rest of the structure to get access to the event data.

Now see how this is implemented in `simplicity_sdk/app/wisun/component/event_manager/sl_wisun_event_mgr.c/sl_wisun_on_event()`.

![sl_wisun_on_event](/wisun-connection-details/0.1/images/sl-wisun-on-event.png)

The `_decode_ind()` function is checking the `evt->header.id` with the list of the events your application has decided to process (i.e. 'handle').

![_decode_ind](/wisun-connection-details/0.1/images/decode-ind.png)

> TIP: See the last value in the table, clearly indicating that any value not matching the preceding lines will return `EVENT_IDX_NOTVALID`.

In `sl_wisun_on_event()`:

- A message is printed whenever an 'invalid' (i.e. unprocessed) event is received for information purposes. Since this is informational, it's only displayed as an `Unknown event`.
- If the event is one of those that the application decided to handle, the corresponding callback function in the Application Core Component is called with the `evt` data.  
  - If a 'custom callback' function exists in the customer application , it is also called.

In `simplicity_sdk/app/wisun/component/event_manager/sl_wisun_event_mgr.c`:

- You see all `.callback` functions
- You see that no `custom_callback` is defined by default

![wisun_events](/wisun-connection-details/0.1/images/wisun-events.png)

The Wi-SUN Event Manager component provides `app_wisun_em_custom_callback_register()` to register custom callbacks.

If you want to add some custom processing on join state changes:

- You create a custom callback function and add into this function your custom actions.

```C
void join_state_custom_callback(sl_wisun_evt_t *evt) {
  sl_wisun_join_state_t join_state;
  join_state = (sl_wisun_join_state_t)evt->evt.join_state.join_state;
  printf("Join State %d\n", join_state);
}
```

- You call `app_wisun_em_custom_callback_register(SL_WISUN_MSG_JOIN_STATE_IND_ID, join_state_custom_callback);` to register it.

The callback function for join state changes is `sl_wisun_join_state_event_hnd()`.

You can see it in three places:

![sl_wisun_join_state_event_hnd](/wisun-connection-details/0.1/images/sl-wisun-join-state-event-hnd.png)

- Defined in `simplicity_sdk/app/wisun/component/event_manager/sl_wisun_event_mgr.h` (describing the prototype of the function).
- Declared as `SL_WEAK` in `simplicity_sdk/app/wisun/component/event_manager/sl_wisun_event_mgr.c`.  
  - A 'weak' declaration (i.e. implementation) of a function is a default implementation, which can be superseded by another located elsewhere in the code.  
  - Most 'weak' functions do nothing. They are there to avoid compilation errors when there is no other implementation.
- Declared as a normal function in `simplicity_sdk/app/wisun/component/app_core/sl_wisun_app_core.c`.  
  - This implementation supersedes the 'weak' implementation.

Finally, check the `sl_wisun_join_state_event_hnd()` function in `simplicity_sdk/app/wisun/component/app_core/sl_wisun_app_core.c` to follow what it does.

![join_state_event](/wisun-connection-details/0.1/images/join-state-event.png)

- This 'event handler' is called only when there are changes to the internal join state.
- `_join_state` is set in the 'event handler' function `sl_wisun_join_state_event_hnd()`, as `evt->evt.join_state.join_state`.
- If there is a change of the join_state, the `app_wisun_trace_util_conn_state_to_str()` function returns a valid string to translate the state's decimal value into a human-readable string. If this string is not empty, it is traced in the application's console.  
  - Printing a message is useful to follow the connection process when having access to the device's UART console. It's not actually required to achieve connection, but it is convenient.

##### Remarks on Function Names

- All Wi-SUN Stack API functions are prefixed with `sl_wisun_`.  
  - Customers can't read the underlying Stack source code, which is under the responsibility of the Wi-SUN Stack developers.  
  - The `OK` return code is `SL_STATUS_OK` = `0x0000`.  
  - All return codes are defined in `simplicity_sdk/platform/common/inc/sl_status.h`. Checking this file in case of an error can help get minimal information on the error.  
  - Wi-SUN Stack functions don't print traces in the device's UART console, instead in the form of RTT traces, accessible using J-LINK connected to the device via an evaluation kit (which embed SEGGER debug capabilities) or a external debugger.
- SiSDK functions ultimately use the `sl_wisun_` Wi-SUN Stack API functions.
- SiSDK component top-level API functions are also prefixed with `sl_wisun_`.
- If there are 'Simplicity-SDK-internal' functions in the components, they are prefixed with `sli_`, the `i` meaning 'internal'.
- Additional API functions provided by SiSDK components to be called by customer application code are prefixed with `app_`.
- As is common usage in C coding, functions that are internal to a single source file are prefixed with `_`, meaning that they are not intended to be called by other parts of the code.
- Customers have access to the SiSDK function's source code.

##### Takeaway

What you have accomplished in this session is the join process available when you add the **Wi-SUN Application Core Component** to your project.

- The Wi-SUN Application Core Component uses calls to these [Wi-SUN Stack API functions](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api), in the following order (minimal set of calls for connecting to a basic Wi-SUN network as FFN). It also checks the return values for all calls to raise errors if needed:  
  - [`sl_wisun_set_device_type()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-device-type)  
  - [`sl_wisun_set_connection_parameters()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-connection-parameters)  
  - [`sl_wisun_set_tx_power()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-tx-power)  
  - [`sl_wisun_set_trusted_certificate()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-trusted-certificate)  
  - [`sl_wisun_set_device_certificate()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-device-certificate)  
  - [`sl_wisun_set_device_private_key()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-device-private-key)  
  - [`sl_wisun_join()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-join)
- If the call to `sl_wisun_join()` fails, most probably there is an issue with your PHY selection.  
  - If you use a single PHY and the Wi-SUN Configurator, this should not happen.
- Once the join call is made, connection starts. The customer application should wait for the connection before acting, since it can't communicate with the rest of the Wi-SUN network until it's connected.
- An application can directly use the Wi-SUN Stack API functions, while using the **Wi-SUN Application Core Component** makes the join process much easier.
- Calling `sl_wisun_join()` returns rapidly, once connection settings are set.
- The application communicates with the Wi-SUN Stack using function calls.
- The Wi-SUN Stack communicates with the application using events.
- As a consequence, following the connection process from the application  is done using the `SL_WISUN_MSG_JOIN_STATE_IND_ID` event message.  
  - Triggered by the Wi-SUN Stack.  
  - That the application can monitor using an event-specific handler.

It's now time to add a [custom application to a Wi-SUN network](/wisun/2.12.0/wisun-custom-application/index).

#### Over-The-Air Device Firmware Upgrade

To upgrade an application on a device, you need to:

- Once only (on the Border Router platform):  
  - Install libcoap2 & libcoap2-bin  
  - Install a TFTP server  
  - Start a CoAP notification server (optional, used to monitor the upgrade process)  
  - Start a Linux Border Router    
    - Add known IPv6 addresses to the Border Router `tun0` interface
- Once per device hardware:  
  - Create an OTA-capable bootloader, with the compression algorithm(s) of your choice
- Once per project:  
  - Add the OTA DFU component    
    - This will add the CoAP and TFTP components  
  - Set the Wi-SUN network to auto-connect to the Border Router (Optional. If not, you will need to trigger connection on the device)
- Once per device:  
  - Flash the OTA-capable bootloader to the device, with the compression algorithm(s) of your choice  
  - Flash an initial OTA-capable application to the device  
  - Have the device connect to the Wi-SUN network
- For every upgrade:  
  - Build the project  
  - Create a `.gbl` file from the `.s37` file (optionally using compression)  
  - Copy the `.gbl` to the expected name in the TFTP server folder  
  - Trigger the OTA upgrade using a coap-client 'post' method  
  - Check file download results  
  - Trigger the reboot on the new firmware (the initial version of the OTA DFU component uses auto-reboot)

The following explains how to perform these steps based on the 'Wi-SUN SoC Empty' example application. OTA DFU can be applied using the same steps to all Wi-SUN example projects.

It is recommended to set an initial startup message in the application to show that the upgrade worked.

> On more recent linux kernels, use libcoap3 and the commands with the `-notls` suffix to keep it simple (without TLS authentication), considering that your Wi-SUN network already supports encryption.

##### Prerequisites

###### `libcoap2` Installation

`libcoap2` is used for:

- The (optional) CoAP notification server
- The CoAP client used to trigger and monitor the firmware update

Both can be installed on separate machines, as long as they can be reached using IPv6. For the sake of simplicity, use the Linux platform supporting `wsbrd` for both functions. You will add a separate IPv6 address to the Border Router Wi-SUN interface to demonstrate this capability.

```bash
sudo apt-get install libcoap2
```

```bash
sudo apt-get install libcoap2-bin
```

###### TFTP Server Installation on the Linux Border Router

On the selected file server, install a TFTP server through the following steps. Here also you use the Linux platform used as the Border Router for this purpose, with a separate IPv6 address.

###### TFTP Daemon Installation (heading level 7)

```bash
sudo apt-get install tftpd-hpa tftp-hpa
```

###### TFTP Service Configuration (heading level 7)

```bash
sudo nano /etc/default/tftpd-hpa

#### /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
```

(optional) Set the `TFTP_USERNAME` and `TFTP_DIRECTORY` to match you setup, if it differs from the defaults.

###### Restart the TFTPD Service (heading level 7)

```bash
/etc/init.d/tftpd-hpa restart
```

From this point, files stored under the `TFTP_DIRECTORY` are accessible using TFTP.

###### Start a Linux Border Router

Start a Border Router set to allows connecting your devices. The devices should connect before adding OTA DFU to their application.

###### Add known IPv6 addresses to the Border Router (acting as CoAP server and Notification Server) (heading level 7)

What you need here is:

- A TFTP server, such that your devices can send TFTP requests for the `.gbl` files.
- A (optional, highly recommended) CoAP Notification Server such that your devices can send progress notifications during OTA DFU download.

The TFTP and CoAP servers may not be on the Border Router platform, as long as they can be reached by your Wi-SUN devices via the Border Router. For the sake of simplicity in this first setup, use the same Linux platform as for `wsbrd` (i.e, your Wi-SUN Border Router) for both uses.

Using separate IPv6 addresses makes it clear that the three entities (Border Router, TFTP server, CoAP Notification Server) can be on different platforms. Since the Border Router application is 'wsbrd', you have control over the IPv6 prefix used by your Wi-SUN network (set in your `wsbrd.conf` file).

`ipv6_prefix = fd00:6172:6d00::/64`

You can then add a first IPv6 address to the `tun0` interface using this IPv6 prefix for the 'OTA DFU HOST' role:

```bash
sudo ip -6 address add fd00:6172:6d00::1/64 dev tun0
```

Add a second IPv6 address to the `tun0` interface 'OTA DFU NOTIFY HOST' role:

```bash
sudo ip -6 address add fd00:6172:6d00::2/64 dev tun0
```

Then check that you now have two IPv6 addresses for the 'tun0' interface:

```bash
ip address show tun0 | grep global'
```

```bash
    inet6 fd00:6172:6d00::1/64 scope global
    inet6 fd00:6172:6d00::2/64 scope global
    inet6 fd00:6172:6d00:0:92fd:9fff:fe00:333a/64 scope global
```

You will later set the IPv6 `OTA_DFU_HOST` and `OTA_DFU_NOTIFY_HOST` addresses in the OTA component code to match these fixed (`fd00:6172:6d00::1` and `fd00:6172:6d00::2`, respectively) addresses.

###### Start the CoAP Notification Server

The CoAP Notification server is optional, but it's useful to follow the upgrade process. Silicon Labs highly recommends using it.

###### Checking `coap-server` Options (heading level 7)

Use `coap-server --help` to get the help. Below is an abstract with the version info and options used.

```bash
coap-server: invalid option -- '-'
coap-server v4.2.1 -- a small CoAP implementation
(c) 2010,2011,2015-2018 Olaf Bergmann <bergmann@tzi.org> and others

TLS Library: None

Usage: coap-server [-d max] [-g group] [-l loss] [-p port] [-v num]
                [-A address] [-N]
                [[-k key] [-h hint]]
                [[-c certfile][-C cafile] [-n] [-R root_cafile]]
General Options
        -d max          Allow dynamic creation of up to a total of max
                        resources. If max is reached, a 4.06 code is returned
                        until one of the dynamic resources has been deleted
        -g group        Join the given multicast group
        -p port         Listen on specified port
        -v num          Verbosity level (default 3, maximum is 9). Above 7,
                        there is increased verbosity in GnuTLS logging
        -A address      Interface address to bind to
        -N              Make "observe" responses NON-confirmable. Even if set
                        every fifth response will still be sent as a confirmable
                        response (RFC 7641 requirement)
```

###### Starting the COAP Notification Server (heading level 7)

Start the CoAP notification server with `-d 10` to allow dynamic resource creation:

```bash
coap-server -A fd00:6172:6d00::2 -p 5685 -d 10
```

###### Bootloader Application

You need a Bootloader Application using SPI Flash for a single image of max 1024k bytes. This is to be manually flashed **once** to the part to allow OTA.

> TIP:If you use the **Erase** option before **Program** when flashing the Wi-SUN application, you will need to re-flash the bootloader.

In Simplicity Studio:

1. Select the board you want to flash the bootloader to in the **Debug Adapter** window.
2. Open the **Launcher** perspective.
3. Select the **EXAMPLE PROJECTS & DEMOS** tab.
4. On the projects filtering section, under **MCU**, check **Bootloader** to reduce the list of available projects.
5. Further reduce by filtering on SPI, single and 1024. Enter these strings in the **Filter on keywords** box, pressing **Enter** after each string.
6. 'Create' a **Bootloader - SoC SPI Flash Storage (single image with slot size of 1024k)** project.  
   ![creation](/wisun-ota-dfu/0.2/images/bootloader-creation.png)

###### Bootloader Configuration (heading level 7)

The Bootloader settings are defined in `config/btl_storage_cfg.h`. No need to change anything here, the default values are fine.

- The Base Address is defined as `BTL_STORAGE_BASE_ADDRESS`.
- The memory slots to store the images are defined as well.
- Only `SLOT0` is enabled, with a `SLOT0_SIZE` of `1048576` = `1024 * 1024` = 1024 kBytes, starting at `SLOT0_START 0`.

###### Add LZ4 Compression to Bootloader (heading level 7)

By default, the bootloader projects don't include the LZ4 compression algorithm, so install it if you want to use it.

> TIP: Use lzma instead of lz4, lzma has better compression performance.

![add lz4](/wisun-ota-dfu/0.2/images/add-lz4.png)

###### Add LZMA Compression to Bootloader (heading level 7)

By default, the bootloader projects don't include the most efficient LZMA compression algorithm, so install it if you want to use it.

> TIP: Using lzma to compress `.gbl` files to save transmission time and therefore power when transmitting data.

![add lzma](/wisun-ota-dfu/0.2/images/add-lzma.png)

###### Build the Bootloader Project (heading level 7)

![build](/wisun-ota-dfu/0.2/images/bootloader-build.png)

or

![build](/wisun-ota-dfu/0.2/images/bootloader-hammer.png)

See [Simplicity Studio 5 Users Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-building-and-flashing/building#simple-build) for details.

###### Flash the Bootloader Binary to the Debug Adapter (heading level 7)

A new `Binaries` folder appeared in the project. This corresponds to the binaries present under `GNU ARM v10.3.1 - Default`.

- On Series 1 (xG12, for example), select the `<projectname>-combined.s37` binary (see [Silicon Labs Gecko Bootloader User’s Guide for SiSDK 4.0 and Higher (series 1 and 2 devices)](/wisun/2.12.0/bootloader-user-guide-gsdk-4) for details) or [Silicon Labs Gecko Bootloader User’s Guide for Series 3 and Higher](/wisun/2.12.0/bootloader-user-guide-series3-and-higher).
- On Series 2 (xG25 or xG28, for example), select the `<projectname>.s37` binary.  
  ![flash menu](/wisun-ota-dfu/0.2/images/bootloader-flash.png)

If you have several devices in your **Debug Adapters** window, you will be asked to select the device.

![select device](/wisun-ota-dfu/0.2/images/bootloader-select-device.png)

> TIP: It's always better to erase the part before flashing a bootloader. As opposed to this, do not erase before flashing the Wi-SUN application; otherwise, you will need to re-flash the bootloader.

![erase](/wisun-ota-dfu/0.2/images/bootloader-erase.png)

Finally, click the **Program** button.

![flash](/wisun-ota-dfu/0.2/images/bootloader-programming-device.png)

##### Application Project Creation (if not already existing)

If you have no previous application to flash to the device for testing, you can create a new 'Wi-SUN SoC Empty' project as described in [Building and Connecting to a Wi-SUN Network](/wisun/2.12.0/wisun-building-connecting/index). Otherwise, use your working Wi-SUN project.

##### Adding the 'Wi-SUN Over-The-Air Device Firmware Upgrade (OTA DFU)' Component

To perform OTA upgrades:

- The bootloader on your device must support OTA DFU.
- The application running on your device must support OTA DFU.

In the **Simplicity IDE** perspective, open `wisun_soc_empty.slcp` and select the **SOFTWARE COMPONENTS** tab. Ensure `Evaluation`is checked in `Quality` panel:

![eval quality](/wisun-ota-dfu/0.2/images/eval-quality.png)

Filter on _DFU_, and look for the **Wi-SUN Over-The-Air Device Firmware Upgrade (OTA DFU)** component.

###### Install the OTA DFU Component

![install_ota_dfu](/wisun-ota-dfu/0.2/images/install-ota-dfu.png)

###### Check the OTA DFU Settings

> NOTE: It will take ~30 seconds for the **Configure** button to be active after installing the OTA DFU component.

There are two ways to change the OTA DFU component settings. The first way is through the **SOFTWARE COMPONENTS** view.

1. In the **SOFTWARE COMPONENTS** view, click **Configure** to access the corresponding GUI. Changes you make here will be reflected in `config/sl_wisun_ota_dfu_config.h`.  
   - Verbose mode is enabled by default to follow the upgrade process in the device's console.  
   - Host notifications are enabled by default to follow the upgrade process from the Border Router.  
   - The **OTA DFU service stack size in CPU word** is set to 360 words (1440 bytes) to avoid stack overflow.
2. Set the **TFTP service listening address** to match the TFTP server IPv6.
3. Set the **OTA DFU notification server address** to match the notification server IPv6.

Optionally, you can change the **Firmware image (gbl) file name on TFTP server** to match your hardware. This can make it easier to manage various devices in the future. For the time being, keep using `wisun_firmware.gbl`.

![OTA DFU GUI](/wisun-ota-dfu/0.2/images/ota-dfu-gui.png)

- The OTA DFU GUI reflects in `config/sl_wisun_ota_dfu_config.h`. You can open it from the GUI, using the **View Source** button.

![OTA DFU config](/wisun-ota-dfu/0.2/images/ota-dfu-config.png)

The settings must match between:

- The TFTP server IPv6 (`fd00:6172:6d00::1`)
- The `.gbl` file name
- The CoAP Notification server IPv6 (`fd00:6172:6d00::2`)
- The OTA DFU component
- The `coap-server` command
- The `coap-client` commands

> TIP: Use the [OTA DFU cheat sheet](#ota-dfu-cheat-sheet) to check your settings.

###### Enable OTA DFU Verbose Mode

- In `config/sl_wisun_ota_dfu_config.h`, `SL_WISUN_OTA_DFU_VERBOSE_MODE_ENABLED` is set to `1U` to get messages traced in the device's console during download. Once you get familiar with OTA DFU, you can disable verbose mode.

```bash
[wisun-btl] (0) Storage info: version: 196608, capabilities: 0, storageType: 0, numStorageSlots: 1
[wisun-btl] (7) Firmware upgrade started
[wisun-btl] (17) TFTP init done
[wisun-btl] (27) TFTP download started: tftp://[fd00:6172:6d00::1]:69/wisun_firmware.gbl
[wisun-btl] (429) download: received chunk 1, offset: 0x00000000
[wisun-btl] (853) download: received chunk 2, offset: 0x00000200
[wisun-btl] (1077) download: received chunk 3, offset: 0x00000400
[wisun-btl] (1302) download: received chunk 4, offset: 0x00000600
[wisun-btl] (1526) download: received chunk 5, offset: 0x00000800
[wisun-btl] (1949) download: received chunk 6, offset: 0x00000a00
[wisun-btl] (2174) download: received chunk 7, offset: 0x00000c00
```

###### Enable OTA DFU Notifications

- In `config/sl_wisun_ota_dfu_config.h`, `SL_WISUN_OTA_DFU_HOST_NOTIFY_ENABLED` is set to `1U` to get notification CoAP messages sent by the device to the notification server during download, every `SL_WISUN_OTA_DFU_NOTIFY_DOWNLOAD_CHUNK_CNT` chunks (default `10U`). This can be changed later on to a larger value to reduce the amount of notification messages. Setting it to a very large number will avoid all intermediate notifications while still keeping the final notification message, which is important to indicate file download completion and the validity of the new firmware.  
  - The notification server doesn't need to be the Border Router. It can be any other machine. Use a dedicated IPv6 address to make this clear.

##### Version 1 Application with OTA DFU Support

Now that you have OTA DFU configured, you can set your Wi-SUN network to match your Border Router. Do this with the **Wi-SUN Configurator**.

###### Set the Wi-SUN Configuration

Set the Wi-SUN Configuration to match the Border Router setup.

###### Add a Startup Text Indicating the Version of the Application

Here, add the following to `app.c/app_task()` to get minimal information on your application and make sure you can tell which version is running through the startup messages that you'll get in the Serial 1 console when you reset the device.

```C
  printf("Version 1. Compiled on %s at %s\n", __DATE__, __TIME__);
```

![version info 1](/wisun-ota-dfu/0.2/images/version-info-1.png)

###### (Optional) Add a Startup Text Indicating OTA DFU Support

Since it's interesting to know if OTA DFU is supported, add a second message if OTA DFU is supported.

To locate where active components are declared, select in `app.c/app_task()` the `SL_CATALOG_WISUN_APP_CORE_PRESENT` text on line 83, right-click, and select **Open Declaration**.

![open declaration](/wisun-ota-dfu/0.2/images/open-declaration.png)

You end up in `autogen/sl_component_catalog.h`, where `SL_CATALOG_WISUN_OTA_DFU_PRESENT` is declared on line 33.

![component catalog](/wisun-ota-dfu/0.2/images/component-catalog.png)

> TIP: You also see that `SL_CATALOG_WISUN_COAP_PRESENT` is declared on line 27, indicating that the CoAP component is also present. CoAP is a dependency for the OTA DFU component, so it has been installed automatically when you added OTA DFU (if not previously installed).

Back to `app.c/app_task()`, add the following code below your previous message:

```C
#ifdef SL_CATALOG_WISUN_OTA_DFU_PRESENT
  printf("OTA DFU is supported\n");
#endif
```

![OTA check](/wisun-ota-dfu/0.2/images/ota-check.png)

###### (Optional) Add More Information on OTA DFU Once Connected

Once the device is connected to the Wi-SUN network the application can retrieve it's IPv6 global address and display information on how OTA DFU can be used.

This is interesting to add for the first OTA DFU tests, to get you familiar with the commands and the parameters.

In `app.c`, add the following code in the `#include` area:

```C
#include "sl_wisun_ota_dfu_config.h"
```

and the following code before the `while (1)` loop in `app_task()`

```C
#ifdef SL_CATALOG_WISUN_OTA_DFU_PRESENT
  sl_wisun_ip_address_t global_ipv6;

  printf("OTA DFU will download chunks of '<TFTP_DIRECTORY>/%s' from %s/%d\n",
         SL_WISUN_OTA_DFU_GBL_FILE,
         SL_WISUN_OTA_DFU_HOST_ADDR,
         SL_WISUN_OTA_DFU_TFTP_PORT
       );

  sl_wisun_get_ip_address(SL_WISUN_IP_ADDRESS_TYPE_LINK_LOCAL, &global_ipv6);
  printf("OTA DFU 'start' command:\n");
  printf(" coap-client -m post -N -B 10 -t text coap://[%s]:%d%s -e \"start\"\n",
         app_wisun_trace_util_get_ip_str(&global_ipv6),
         5683,
         SL_WISUN_OTA_DFU_URI_PATH
       );
  printf("Follow OTA DFU progress (from node, intrusive) using:\n");
  printf(" coap-client -m get -N -B 10 -t text coap://[%s]:%d%s\n",
       app_wisun_trace_util_get_ip_str(&global_ipv6),
       SL_WISUN_COAP_RESOURCE_HND_SERVICE_PORT,
       SL_WISUN_OTA_DFU_URI_PATH
  );

  if (SL_WISUN_OTA_DFU_HOST_NOTIFY_ENABLED) {
      printf("OTA DFU notifications enabled (every %d chunks)\n",
        SL_WISUN_OTA_DFU_NOTIFY_DOWNLOAD_CHUNK_CNT
      );
      printf("OTA DFU notifications will be POSTed to notification server coap://[%s]:%d%s\n",
         SL_WISUN_OTA_DFU_NOTIFY_HOST_ADDR,
         SL_WISUN_OTA_DFU_NOTIFY_PORT,
         SL_WISUN_OTA_DFU_NOTIFY_URI_PATH
      );
    printf("Follow OTA DFU progress (from notification server) using:\n");
    printf(" coap-client -m get -N -B 1 -t text coap://[%s]:%d%s\n",
       SL_WISUN_OTA_DFU_NOTIFY_HOST_ADDR,
       SL_WISUN_OTA_DFU_NOTIFY_PORT,
       SL_WISUN_OTA_DFU_NOTIFY_URI_PATH
    );
  }
#endif
```

![OTA DFU Info](/wisun-ota-dfu/0.2/images/ota-dfu-info.png)

###### Rebuild the 'Version 1' Application

![build soc empty](/wisun-ota-dfu/0.2/images/build-soc-empty.png)

Unfortunately, with SiSDK 4.3.0, this will fail because of an assert from `<simplicity_sdk>/app/wisun/component/ftp_posix_port/sl_wisun_ftp_posix_port.c` line `160`.  The root cause is not the assert. The assert is here to stop you at this point such that you correct the underlying code and safely compile with no runtime issue to expect. If you don't solve the assert, you may get issues when running your code.

The point is that the TFTP code is using a data block size of 512 bytes by default, while the socket buffer is using 128 bytes per default. As a consequence, the TFTP packets won't fit in the socket buffer, so the socket buffer needs to be bigger.

With SiSDK 4.3.0, setting this was not done automatically in the generation flow when adding TFTP and the OTA DFU component, so this change needs to be done manually. This is improved in later SiSDK versions using the following condition in the `.slcp` file:

![socket buffer size ota dfu](/wisun-ota-dfu/0.2/images/sl-socket-buffer-size-ota-dfu.png)

With SiSDK 4.3.0, you will experience this error:

![build soc empty failing](/wisun-ota-dfu/0.2/images/build-soc-empty-failing.png)

As the error message indicates, the solution consists of increasing `SL_SOCKET_BUFFER_SIZE` to be higher than `SL_TFTP_DATA_BLOCK_SIZE + 4`.

- You find the value of `SL_TFTP_DATA_BLOCK_SIZE` using **Open Declaration (F3)**.

`#define SL_TFTP_DATA_BLOCK_SIZE          512UL`

- Go to the `SL_SOCKET_BUFFER_SIZE` declaration and set it to 512 + 4 = 516.

`#define SL_SOCKET_BUFFER_SIZE                                        516U`

Now you can compile without errors.

![build soc empty](/wisun-ota-dfu/0.2/images/build-soc-empty.png)

![build soc empty compiled](/wisun-ota-dfu/0.2/images/ota-dfu-compiled.png)

###### Manually Install the 'Version 1' Application

1. Flash it manually (if it's the first OTA-capable application you flash, it needs to be flashed manually, since resources to flash it using OTA DFU are not present yet).  
   > NOTE: If you use the **Erase** Feature, you will need to re-flash the bootloader then flash the application.  
   ![version 1 flash](/wisun-ota-dfu/0.2/images/version-1-flash.png)
2. Open a console on the device.
3. Select **Serial 1** and press **Enter** to connect.
4. Reset the device (using the **RESET** button on the WSTK/WPK).  
   - The startup message indicates that:    
     - You're running 'Version 1'    
     - OTA DFU is supported

The 'Wi-SUN SoC Empty' example application is set for auto-connection to the Wi-SUN Network, so you see it starting to connect.

![version info 1 serial1](/wisun-ota-dfu/0.2/images/version-info-1-serial1.png)

###### Rename the 'Version 1'Binary to Keep It

Add `_version_1` to the file name to clearly identify it.

![rename version_1](/wisun-ota-dfu/0.2/images/rename-version-1.png)

![renaming version_1](/wisun-ota-dfu/0.2/images/renaming-version-1.png)

![renamed version_1](/wisun-ota-dfu/0.2/images/renamed-version-1.png)

##### Version 2 Application with OTA DFU Support

###### Change the Startup Text for 'Version 2'

```C
  printf("Version 2. Compiled on %s at %s\n", __DATE__, __TIME__);
```

![version 2](/wisun-ota-dfu/0.2/images/version-info-2.png)

###### Rebuild the 'Version 2' Application

![build soc empty](/wisun-ota-dfu/0.2/images/build-soc-empty.png)

The `wisun_soc_empty.s37` file is back in the `Binaries` folder. It now corresponds to your 'Version 2' application.

###### Rename the 'Version 2' Binary to Keep It

Add `_version_2` to the file name to clearly identify it.

![rename version_2](/wisun-ota-dfu/0.2/images/rename-version-2.png)

##### Convert the 'Version 2' Binary to GBL Format

The 'Version 2' binary needs to be converted to the GBL (Gecko BootLoader) format using Simplicity Commander. It will have a `.gbl` extension after conversion.

On Windows platforms, Simplicity Commander is by default installed under `C:\SiliconLabs\SimplicityStudio\v5\developer\adapter_packs\commander`.

> TIP: To access Simplicity Commander easily, it's a good option to add the path to the `commander.exe` in your environment variables. Remember that command line windows only check environment variables upon starting, so you need to re-open them to benefit from the change.

- Open a command window in the `C:\Users\username\SimplicityStudio\v5_workspace\wisun_soc_empty\GNU ARM v10.3.1 - Default` folder where binaries are stored.
- Check that the `.s37` files are present:

```bash
C:\Users\username\SimplicityStudio\v5_workspace\wisun_soc_empty\GNU ARM v10.3.1 - Default>dir *.s37

29/06/2023  15:00         1 888 290 wisun_soc_empty_version_1.s37
29/06/2023  15:12         1 888 290 wisun_soc_empty_version_2.s37
```

- Create the GBL file for the application to transfer over OTA DFU  
  - `commander gbl create  --app wisun_soc_empty_version_2.s37  wisun_soc_empty_version_2.gbl`  
  - To reduce the size of the file to be transferred, you can compress the resulting file with either `--compress lz4` or `--compress lzma`    
    - `commander gbl create  --app wisun_soc_empty_version_2.s37  wisun_soc_empty_version_2_lz4.gbl  --compress lz4`    
    - `commander gbl create  --app wisun_soc_empty_version_2.s37  wisun_soc_empty_version_2_lzma.gbl --compress lzma`

> CAUTION: Only compress with the algorithms supported by your bootloader, otherwise the verification step will fail once downloaded.

```bash
C:\Users\username\SimplicityStudio\OTA\wisun_soc_empty\GNU ARM v10.3.1 - Default>commander gbl create  --app wisun_soc_empty_version_2.s37 wisun_soc_empty_version_2.gbl
Parsing file wisun_soc_empty_version_2.s37...
Initializing GBL file...
Adding application to GBL...
Writing GBL file wisun_soc_empty_version_2.gbl...
DONE

C:\Users\username\SimplicityStudio\OTA\wisun_soc_empty\GNU ARM v10.3.1 - Default>commander gbl create  --app wisun_soc_empty_version_2.s37 wisun_soc_empty_version_2_lz4.gbl --compress lz4
Parsing file wisun_soc_empty_version_2.s37...
Initializing GBL file...
Adding application to GBL...
Compressing using lz4...
Writing GBL file wisun_soc_empty_version_2_lz4.gbl...
DONE

C:\Users\username\SimplicityStudio\OTA\wisun_soc_empty\GNU ARM v10.3.1 - Default>commander gbl create  --app wisun_soc_empty_version_2.s37 wisun_soc_empty_version_2_lzma.gbl --compress lzma
Parsing file wisun_soc_empty_version_2.s37...
Initializing GBL file...
Adding application to GBL...
Compressing using lzma...
Writing GBL file wisun_soc_empty_version_2_lzma.gbl...
DONE
```

As you can see, the best compression method is `lzma`:

|Compression|Size (bytes)|None/Compressed ratio|
|---|---|---|
|None|629476|100 %|
|lz4|544424|86 %|
|lzma|385996|61 %|

```bash
C:\Users\username\SimplicityStudio\v5_workspace\wisun_soc_empty\GNU ARM v10.3.1 - Default>dir *version_2*.gbl

29/06/2023  15:17           629 476 wisun_soc_empty_version_2.gbl
29/06/2023  15:18           544 424 wisun_soc_empty_version_2_lz4.gbl
29/06/2023  15:18           385 996 wisun_soc_empty_version_2_lzma.gbl
```

At this point, you have all the resources you need to start using OTA DFU to upgrade from 'Version 1' (manually flashed) to 'Version 2' (using OTA DFU).

- A running TFTP server on the Linux Border Router.
- A bootloader with OTA DFU support, flashed to your device.
- A 'Version 1' application with OTA DFU support, flashed to your device.
- A 'Version 2' file in GBL format (you'll use the lzma-compressed file).  
  - The 'Version 2' binary also has OTA DFU support, to get ready to accept future upgrades to a 'Version 3' application.

And you can follow the process using the notifications, which will be sent to the notification server by the device.

![both versions](/wisun-ota-dfu/0.2/images/both-versions.png)

###### Transfer the 'Version 2' `.gbl` Files to the Linux Border Router

From the machine where the `.gbl` files were created, use `scp` to copy the files to the Linux Border Router host. You can use your preferred file copy method.

```bash
scp wisun_soc_empty_*.gbl <linux_user>@<linux_hostname>:/tmp/
```

> NOTE: The rest of the operations will occur on the Linux Border Router.

##### Check 'Version 1' Connection to the Border Router

###### On the Border Router

In `wsbrd_cli status`, the MAC address of the device should be visible:

```batch
network_name: Linux_BZ_3_8
fan_version: FAN 1.1
domain: BZ
phy_mode_id: 8
chan_plan_id: 3
panid: 0xd4ec
size: CERT
GAK[0]: 36:b6:1e:81:fa:c4:88:b4:03:f7:b4:9b:38:b3:41:47
GAK[1]: 79:8b:b2:98:7f:ef:d3:55:4a:b8:cf:23:d4:a2:8f:5b
GAK[2]: 79:8b:b2:98:7f:ef:d3:55:4a:b8:cf:23:d4:a2:8f:5b
GAK[3]: 79:8b:b2:98:7f:ef:d3:55:4a:b8:cf:23:d4:a2:8f:5b
GTK[0]: 00:10:20:30:40:50:60:70:80:90:a0:b0:c0:d0:e0:f0
GTK[1]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
GTK[2]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
GTK[3]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
LGAK[0]: 62:80:53:11:03:45:b6:f5:16:67:e6:14:65:21:e4:99
LGAK[1]: 79:8b:b2:98:7f:ef:d3:55:4a:b8:cf:23:d4:a2:8f:5b
LGAK[2]: 79:8b:b2:98:7f:ef:d3:55:4a:b8:cf:23:d4:a2:8f:5b
LGTK[0]: 66:70:4e:08:8c:ce:82:c9:d2:aa:c7:62:83:18:97:b9
LGTK[1]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
LGTK[2]: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
90:fd:9f:ff:fe:00:33:3a
  `- 60:a4:23:ff:fe:37:a5:1d
```

###### On the Device

- Check the content of 'Serial 1'. By now, it should be connected if the Border Router and the device settings match and both are working as expected.  
  ![version 1 connected](/wisun-ota-dfu/0.2/images/version-1-connected.png)
- Since it's now connected, the information strings you prepared are now visible, providing hints to the user.  
  - Information on TFTP settings    
    - `OTA DFU will download chunks of '<TFTP_DIRECTORY>/wisun_firmware.gbl' from fd00:6172:6d00::1/69`  
  - Information on the OTA start command (to be executed on the Border Router)    
    - `coap-client -m post -N -B 10 -t text coap://[fe80::62a4:23ff:fe37:a51d]:5683/ota/dfu -e "start"`  
  - Information on the notification settings    
    - `OTA DFU notifications enabled (every 10 chunks)`    
    - `OTA DFU notifications will be POSTed to notification server coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify`  
  - Information on how to follow the OTA progress    
    - `Follow OTA DFU progress (from notification server) using:`    
    - `coap-client -m get -N -B 1 -t text coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify`

##### Store the Device's IPv6 GLOBAL Address

Copy the `GLOBAL` IPv6 address either from the **Addresses** `[GLOBAL   : <IPv6>]` section, or from the above info on the "start" command. This is the device's IPv6 address you will need to use for OTA DFU as the `WISUN_NODE_IPV6_ADDR` value.

On the Border Router, set a command line variable to make it easier to repeat the OTA process for other devices:

`WISUN_NODE_IPV6_ADDR=fd00:6172:6d00:0:62a4:23ff:fe37:a51d` (in the example)

> TIP: You need to do this for each bash window you open.

##### Store the Border Router's IPv6 Address

Copy the `BORDER_ROUTER` IPv6 address from the **Addresses** `[BORDER_ROUTER   : <IPv6>]` section.

On the Border Router, set a command line variable to make it easier to repeat the OTA process for other devices:

`WISUN_BR_IPV6_ADDR=fd00:6172:6d00:0:92fd:9fff:fe00:333a` (in the example)

> TIP: You need to do this for each bash window you open.

##### OTA DFU on the Linux Border Router

###### Copy the `.gbl` file to the TFTP Server Directory

- Check the TFTP server directory from its config file:

```bash
sudo cat /etc/default/tftpd-hpa
```

```bash
#### /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
```

- Copy the `.gbl` files in the `TFTP_DIRECTORY` folder:

```bash
sudo cp /tmp/*.gbl /srv/tftp/.
```

```bash
ls -l /srv/tftp/*.gbl
```

```bash
-rw-r--r-- 1 root root 629476 Jun 29 15:38 /srv/tftp/wisun_soc_empty_version_2.gbl
-rw-r--r-- 1 root root 544424 Jun 29 15:38 /srv/tftp/wisun_soc_empty_version_2_lz4.gbl
-rw-r--r-- 1 root root 385996 Jun 29 15:38 /srv/tftp/wisun_soc_empty_version_2_lzma.gbl
```

- Copy the `.gbl` file of your choice to the name set as `SL_WISUN_OTA_DFU_GBL_FILE` in `config/sl_wisun_ota_dfu_config.h`.
- First, start testing with the un-compressed file.

```bash
sudo cp /srv/tftp/wisun_soc_empty_version_2.gbl /srv/tftp/wisun_firmware.gbl
```

- Check the presence of the `.gbl` file:

```bash
ls -al /srv/tftp/*.gbl
```

```bash
-rw-r--r-- 1 root root 629476 Jun 29 15:41 /srv/tftp/wisun_firmware.gbl
-rw-r--r-- 1 root root 629476 Jun 29 15:38 /srv/tftp/wisun_soc_empty_version_2.gbl
-rw-r--r-- 1 root root 544424 Jun 29 15:38 /srv/tftp/wisun_soc_empty_version_2_lz4.gbl
-rw-r--r-- 1 root root 385996 Jun 29 15:38 /srv/tftp/wisun_soc_empty_version_2_lzma.gbl
```

See that the file sizes for `wisun_firmware.gbl` and `wisun_soc_empty_version_2.gbl` match, indicating that you're using the uncompressed file for the time being.

###### Check that you can Ping the Border Router

```bash
ping $WISUN_BR_IPV6_ADDR -c 1
```

```bash
PING fd00:6172:6d00:0:92fd:9fff:fe00:333a(fd00:6172:6d00:0:92fd:9fff:fe00:333a) 56 data bytes
64 bytes from fd00:6172:6d00:0:92fd:9fff:fe00:333a: icmp_seq=1 ttl=64 time=0.214 ms

--- fd00:6172:6d00:0:92fd:9fff:fe00:333a ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.214/0.214/0.214/0.000 ms
```

Successfully pinging the Border Router means that it's started and the IPv6 address that you retrieved from the device is correct.

###### Check that you can Ping the TFTP Server

```bash
ping fd00:6172:6d00::1
```

Successfully pinging the TFTP server means that it's IPv6 has been added to `tun0`and it is accessible from your devices.

###### Check that you can Ping the Notification Server

```bash
ping fd00:6172:6d00::2
```

Successfully pinging the notification server means that it's IPv6 has been added to `tun0`and it is accessible from your devices and from the Border Router.

- Your devices will use coap 'POST' messages to store their OTA status.
- You'll use coap 'GET' messages to check the devices status.
- Note that:  
  - You're not directly asking the devices for status, because:    
    - Doing so, you reduce the traffic on your Wi-SUN network.    
    - If a device reboots after the upgrade, it will not be able to respond anymore to CoAP requests, while the notification server will be able to tell if OTA was successful, since the last notification message will show the last notification received from the device.

###### Check that you can Ping the Node

```bash
ping $WISUN_NODE_IPV6_ADDR -c 1
```

```bash
PING fd00:6172:6d00:0:62a4:23ff:fe37:a51d(fd00:6172:6d00:0:62a4:23ff:fe37:a51d) 56 data bytes
64 bytes from fd00:6172:6d00:0:62a4:23ff:fe37:a51d: icmp_seq=1 ttl=63 time=74.9 ms

--- fd00:6172:6d00:0:62a4:23ff:fe37:a51d ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 74.892/74.892/74.892/0.000 ms
```

Successfully pinging the device means that it's connected to the Wi-SUN network and is working as expected. You can now test OTA DFU.

###### Check that CoAP is Running on the Node

Send your `coap-client` GET method with `-v 6` to get some level of debug information.

```bash
coap-client -m get coap://[$WISUN_NODE_IPV6_ADDR]:5683/ota/dfu -v 6
```

> TIP: Here add `-v 6` to add verbosity and get more details on the CoAP command. Once you get used to the procedure, you may not want to keep using this method.

```bash
v:1 t:CON c:GET i:ded0 {} [ Uri-Path:ota, Uri-Path:dfu ]
v:1 t:ACK c:2.01 i:ded0 {} [ Content-Format:application/json ] :: '{\x0A"elapsed_t":"00:23:44",\x0A"downl_bytes":0,\x0A"flags": "0x00000000",\x0A"fw_update_started": 0,\x0A"fw_downloaded": 0,\x0A"fw_verified": 0,\x0A"fw_set": 0,\x0A"fw_stopped": 0,\x0A"fw_download_error": 0,\x0A"fw_verify_error": 0,\x0A"fw_set_error": 0\x0A}\x0A'
{
"elapsed_t":"00:23:44",
"downl_bytes":0,
"flags": "0x00000000",
"fw_update_started": 0,
"fw_downloaded": 0,
"fw_verified": 0,
"fw_set": 0,
"fw_stopped": 0,
"fw_download_error": 0,
"fw_verify_error": 0,
"fw_set_error": 0
}
```

> TIP: The `"elapsed_t"` value is the time since connection to the Wi-SUN network, as long as OTA DFU hasn't been started.

On the device console, you see the CoAP 'Received packet' and 'Response packet'.

```c
[CoAP-RHND-Service: Received packet]
{
  "token_len": 0,
  "coap_status": 0,
  "msg_code": 1,
  "msg_type": 0,
  "content_format": 4294967295,
  "msg_id": 57040,
  "payload_len": 0,
  "uri_path_len": 7,
  "token": "n/a",
  "uri_path": "ota/dfu",
  "payload": "n/a",
}
[CoAP-RHND-Service: Response packet]
{
  "token_len": 0,
  "coap_status": 0,
  "msg_code": 65,
  "msg_type": 32,
  "content_format": 50,
  "msg_id": 57040,
  "payload_len": 224,
  "uri_path_len": 0,
  "token": "n/a",
  "uri_path": "n/a",
  "payload": 
{
"elapsed_t":"00:23:44",
"downl_bytes":0,
"flags": "0x00000000",
"fw_update_started": 0,
"fw_downloaded": 0,
"fw_verified": 0,
"fw_set": 0,
"fw_stopped": 0,
"fw_download_error": 0,
"fw_verify_error": 0,
"fw_set_error": 0
}

}
```

> TIP: You can check that the message index `i:ded0` in `v:1 t:CON c:GET i:ded0` matches the `"msg_id": 57040` in the Device's console (`57040 = 0xded0`).

###### Start OTA DFU for the Wi-SUN Device

At this point, you can trigger an OTA DFU for the device.

###### Checking `coap-client` Options (heading level 7)

Use `coap-client --help` to get the help. Below is an abstract with the version info and options used.

```bash
coap-client --help
```

```bash
coap-client v4.1.2 -- a small CoAP implementation
(c) 2010-2015 Olaf Bergmann <bergmann@tzi.org>

usage: coap-client [-A type...] [-t type] [-b [num,]size] [-B seconds] [-e text]
                [-m method] [-N] [-o file] [-P addr[:port]] [-p port]
                [-s duration] [-O num,text] [-T string] [-v num] [-a addr] [-U] URI

        URI can be an absolute or relative coap URI,
        -B seconds      break operation after waiting given seconds
                        (default is 90)
        -e text         include text as payload (use percent-encoding for
                        non-ASCII characters)
        -m method       request method (get|put|post|delete), default is 'get'
        -N              send NON-confirmable message
        -v num          verbosity level (default: 3)

```

###### Starting Firmware Download using `coap-client` (heading level 7)

```bash
coap-client -m post -N -B 3 -t text coap://[$WISUN_NODE_IPV6_ADDR]:5683/ota/dfu -e "start" -v 6
```

###### OTA DFU Starting on the Border Router (heading level 8)

```bash
v:1 t:NON c:POST i:4186 {} [ Uri-Path:ota, Uri-Path:dfu, Content-Format:text/plain ] :: 'start'
v:1 t:NON c:2.01 i:0000 {} [ Content-Format:application/json ] :: '{\x0A"elapsed_t":"00:00:00",\x0A"downl_bytes":0,\x0A"flags": "0x00000001",\x0A"fw_update_started": 1,\x0A"fw_downloaded": 0,\x0A"fw_verified": 0,\x0A"fw_set": 0,\x0A"fw_stopped": 0,\x0A"fw_download_error": 0,\x0A"fw_verify_error": 0,\x0A"fw_set_error": 0\x0A}\x0A'
{
"elapsed_t":"00:00:00",
"downl_bytes":0,
"flags": "0x00000001",
"fw_update_started": 1,
"fw_downloaded": 0,
"fw_verified": 0,
"fw_set": 0,
"fw_stopped": 0,
"fw_download_error": 0,
"fw_verify_error": 0,
"fw_set_error": 0
}
```

The `"fw_update_started": 1` flag is set!

###### OTA DFU Starting on the Device (heading level 8)

```c
[CoAP-RHND-Service: Received packet]
{
  "token_len": 0,
  "coap_status": 0,
  "msg_code": 2,
  "msg_type": 16,
  "content_format": 0,
  "msg_id": 16774,
  "payload_len": 5,
  "uri_path_len": 7,
  "token": "n/a",
  "uri_path": "ota/dfu",
  "payload": "start"}
[CoAP-RHND-Service: Response packet]
{
  "token_len": 0,
  "coap_status": 0,
  "msg_code": 65,
  "msg_type": 16,
  "content_format": 50,
  "msg_id": 0,
  "payload_len": 224,
  "uri_path_len": 0,
  "token": "n/a",
  "uri_path": "n/a",
  "payload": 
{
"elapsed_t":"00:00:00",
"downl_bytes":0,
"flags": "0x00000001",
"fw_update_started": 1,
"fw_downloaded": 0,
"fw_verified": 0,
"fw_set": 0,
"fw_stopped": 0,
"fw_download_error": 0,
"fw_verify_error": 0,
"fw_set_error": 0
}

}
[wisun-btl] (0) Storage info: version: 196608, capabilities: 0, storageType: 0, numStorageSlots: 1
[wisun-btl] (7) Firmware upgrade started
[wisun-btl] (11) notify: coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify
[wisun-btl] (18) TFTP init done
[wisun-btl] (21) notify: coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify
[wisun-btl] (27) TFTP download started: tftp://[fd00:6172:6d00::1]:69/wisun_firmware.gbl
[wisun-btl] (442) download: received chunk 1, offset: 0x00000000
[wisun-btl] (866) download: received chunk 2, offset: 0x00000200
[wisun-btl] (1090) download: received chunk 3, offset: 0x00000400
[wisun-btl] (1315) download: received chunk 4, offset: 0x00000600
[wisun-btl] (1739) download: received chunk 5, offset: 0x00000800
[wisun-btl] (1964) download: received chunk 6, offset: 0x00000a00
[wisun-btl] (2189) download: received chunk 7, offset: 0x00000c00
[wisun-btl] (2414) download: received chunk 8, offset: 0x00000e00
[wisun-btl] (2920) download: received chunk 9, offset: 0x00001000
[wisun-btl] (3128) notify: coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify
[wisun-btl] (3153) download: received chunk 10, offset: 0x00001200
[wisun-btl] (3377) download: received chunk 11, offset: 0x00001400
[wisun-btl] (3802) download: received chunk 12, offset: 0x00001600
```

- The `"ota/dfu"` `"start"` command has been received
- The OTA DFU process started
- The first chunks of `wisun_firmware.gbl` have been received
- The first two notifications have been sent to the notification server's IPV6

###### Monitoring OTA DFU Progress on Notification Server

```bash
coap-client -m get -N -B 1 -t text coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify
```

> TIP: A more convenient way to follow the process is to use `watch` as follows:

`watch --interval 2 coap-client -m get -N -B 1 -t text coap://[fd00:6172:6d00::2]:5685/ota/dfu_notify`

![ota dfu watch](/wisun-ota-dfu/0.2/images/ota-dfu-watch.png)

- The `"elapsed_t"` and `"downl_bytes"` will increase during image download
- The `"fw_update_started"` flag is `1` from the start
- The `"fw_downloaded"` flag will be `1` when download is complete (several minutes at 50 kbps/1 Hop)
- The `"fw_verified"` flag will be `1` when verification is complete (this can take an additional ~20 sec)
- The `"fw_set"` flag will be `1` when reboot is about to be triggered (using the NVIC_SystemReset() low-level function)  
  - Note that the device will send its last notification with `"fw_set"` then reboot, so whatever you retrieve from the notification server is this message until you start a new upgrade.

###### Monitoring OTA DFU Progress on Device (intrusive!)

You can also check the progress using a CoAP GET method on the device, but because this is using the Wi-SUN network, it has an impact on the OTA DFU duration if used frequently. The device will also stop responding for a while while rebooting and reconnecting, then respond with `"fw_update_started": 0` once reconnected.

```bash
coap-client -m get coap://[$WISUN_NODE_IPV6_ADDR]:5683/ota/dfu
```

```bash
{
"elapsed_t":"00:01:59",
"downl_bytes":204800,
"flags": "0x00000001",
"fw_update_started": 1,
"fw_downloaded": 0,
"fw_verified": 0,
"fw_set": 0,
"fw_stopped": 0,
"fw_download_error": 0,
"fw_verify_error": 0,
"fw_set_error": 0
}
```

> TIP: Using `watch --interval 10  coap-client -m get coap://[$WISUN_NODE_IPV6_ADDR]:5683/ota/dfu`, you can get the request sent to the device every 10 seconds. This is a convenient way to follow the upgrade process, but it's even more intrusive than not using `watch`.

###### Checking OTA DFU Success on the Device

In the device console, check the startup message, looking for **'Version 2'**.

```bash
Wi-SUN Empty application
Version 2. Compiled on Jul  6 2023 at 13:27:37
OTA DFU is supported
[Join state: Acquire PAN Config (3)]

[Connecting to "Linux_BZ_3_8"]

[Join state: Configure Routing (4)]
[Join state: Operational (5)]

Addresses:
[GLOBAL        : fd00:6172:6d00:0:b635:22ff:fe98:2527]
[LINK_LOCAL    : fe80::b635:22ff:fe98:2527]
[BORDER_ROUTER : fd00:6172:6d00:0:92fd:9fff:fe00:333a]
[25 s]
```

##### OTA DFU Cheat Sheet

Below are all items used for OTA DFU that need to match between various parts of the setup. Check these in case of issues.

- The TFTP server
- The `.gbl` file
- The CoAP Notification server
- The OTA DFU component
- The `coap-server` command
- The `coap-client` commands
- The bootloader

Below are the relationships between the settings:

|Configuration|Setting on Linux Host|Setting on Node project|
|---|---|---|
|TFTP Server IPv6 address|Command line: `sudo ip address add fd00:6172:6d00::2/64 dev tun0`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_NOTIFY_HOST_ADDR "fd00:6172:6d00::2"`|
|TFTP Server Port|TFTP Server configuration file: `/etc/default/tftpd-hpa` `TFTP_ADDRESS=":69"`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_TFTP_PORT "69U"`|
|TFTP Directory|TFTP Server configuration file: `/etc/default/tftpd-hpa` `TFTP_DIRECTORY="/srv/tftp"`|Location of `.gbl` files: `/srv/tftp/`|
|`.gbl` file  name|Command line: `ls -l /srv/tftp/*.gbl`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_GBL_FILE "wisun_firmware.gbl"`|
|OTA DFU Notifications|Command line: `coap-server...` started|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_HOST_NOTIFY_ENABLED` `1U`|
|Notification server IPv6 address|Command line: `sudo ip -6 address add fd00:6172:6d00::2/64 dev tun0`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_NOTIFY_HOST_ADDR "fd00:6172:6d00::2"`|
|OTA DFU notify URI path|Command line: `coap-client -m get ... coap://[<node_ipv6>]:<port>/ota/dfu_notify`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_NOTIFY_URI_PATH "/ota/dfu_notify"`|
|CoAP Notification server IPv6|Command line: `coap-server -A fd00:6172:6d00::2 ...`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_NOTIFY_HOST_ADDR "fd00:6172:6d00::2"`|
|CoAP Notification server UDP port|Command line: `coap-server ... -p 5685 ...`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_NOTIFY_PORT 5685U`|
|CoAP Notification server dynamic resources count|Command line: `coap-server ... -d 10` (dynamic resources)|Number of devices concurrently performing OTA DFU|
|OTA DFU control port|Command line: `coap-client -m post ... coap://[<node_ipv6>]:5683...`|CoAP Configuration file:    `config/sl_wisun_coap_config.h`    `SL_WISUN_COAP_RESOURCE_HND_SERVICE_PORT 5683U`|
|OTA DFU control URI path|Command line: `coap-client -m post ... coap://[<node_ipv6>]:<port>/ota/dfu ...`|OTA DFU Configuration file: `config/sl_wisun_ota_dfu_config.h` `SL_WISUN_OTA_DFU_URI_PATH "/ota/dfu"`|
|OTA DFU start command|Command line: `coap-client -m post ... -e "start"`|OTA DFU Source file: `<SiSDK>\app\wisun\component\ota_dfu\sl_wisun_ota_dfu.c` `SL_WISUN_OTA_DFU_START_PAYLOAD_STR`   `"start"`|
|OTA DFU stop command|Command line: `coap-client -m post ... -e "stop"`|OTA DFU Source file: `<SiSDK>\app\wisun\component\ota_dfu\sl_wisun_ota_dfu.c` `SL_WISUN_OTA_DFU_STOP_PAYLOAD_STR`    `"stop"`|
|OTA DFU install command|Command line: `coap-client -m post ... -e "install"`|OTA DFU Source file: SL_WISUN_OTA_DFU_PAYLOAD_STR_REBOOT_AND_INSTALL `<SiSDK>\app\wisun\component\ota_dfu\sl_wisun_ota_dfu.c` (not implemented in SiSDK 4.3.0, uses 'auto-reboot')|

Below are other items that need to be selected correctly:

|Configuration|Compression component|project `.gbl` file creation|
|---|---|---|
|no compression|Bootloader Compression: `none`|`commander gbl create  --app <projectname>.s37  <projectname>.gbl`|
|lz4 compression|Bootloader Component: `GBL Compression (LZ4)`|`commander gbl create  --app <projectname>.s37  <projectname>.gbl --compress lz4`|
|lzma compression|Bootloader Component: `GBL Compression (LZMA)`|`commander gbl create  --app <projectname>.s37  <projectname>.gbl --compress lzma`|

|Configuration|Part|Bootloader Binary|
|---|---|---|
|Bootloader binary for Series 1|xG12|`<projectname>-combined.s37`|
|Bootloader binary for Series 2|xG25 or xG28|`<projectname>.s37`|

> NOTE: An application with OTA DFU support will crash during OTA if no OTA-capable bootloader is flashed to the device, because the application expects certain low-level functions to be available in the bootloader. This is a common pitfall when customers experiment with OTA DFU and start flashing their OTA DFU application to multiple devices: if they forget to also flash an OTA-capable bootloader they end up having unexpected crashes while their first test device works fine.

|Application configuration|Bootloader configuration|Expected behavior|
|---|---|---|
|Application with OTA DFU|Bootloader without OTA DFU|Crashes|
|Application with OTA DFU|Bootloader with OTA DFU|Okay|
|Application without OTA DFU|Bootloader without OTA DFU|Okay|
|Application without OTA DFU|Bootloader with OTA DFU|Okay|

#### Wi-SUN Mode Switch

##### Introduction

###### Overview

Mode Switch allows Wi-SUN nodes to temporarily use a **higher data rate PHY** (FSK or OFDM) for unicast data while keeping the network stable.

- The network always operates with a **Base PHY (FSK)** for control and broadcast
- Nodes can switch to a **faster PHY** only for **unicast data**
- Switching is **per neighbor** and is only possible if both nodes (or a node and a border router) support the same PHY

In short:

> Base PHY equals reliability<br />Mode Switch PHY equals performance boost (when possible)

###### How Mode Switch Works

1. Nodes advertise supported PHYs using **POM-IE**
2. Each node determines compatible PHYs with neighbors
3. A PHY is selected (PhyModeID) by the application
4. Mode switch is triggered at PHY level (PHR field)
5. Data is exchanged using the new PHY
6. If failures occur → fallback to Base PHY

###### Key Rules

- Mode Switch only applies to **unicast traffic**
- Broadcast always uses **Base PHY**
- Requires **mutual PHY support**

---

##### Supported PHYs for Mode Switch

Wi-SUN supports PHY Mode Switch, allowing nodes to dynamically switch from a configured **base PHY operating mode** to other PHY operating modes supported by both peers.

The **base PHY**:

- is the **locally configured** PHY on each device used to join the Network
- is **not included** in the set of mode-switch candidate PHYs

The **mode switch candidate PHYs**:

- are  the PHYs advertised using the **POM-IE**
- may include both **FSK** and **OFDM PHYs** depending on regulatory domain and device capabilities

Mode switching can occur between FSK PHYs, or from an FSK base PHY to OFDM PHYs where supported.
In practice, deployments typically select a robust low-rate FSK PHY (e.g. 50 kbps) as the base PHY to maximize coverage, while higher-rate PHYs are used opportunistically via mode switching.

###### Regulatory Domain NA (North America)

###### Example base PHY (informative) (heading level 7)

A commonly used base PHY is:

- PhyModeID 0x02 — FSK — 50 kbps

> Note: Other FSK PHYs defined for NA may also be used as base PHY depending on configuration.

###### Mode switch candidate PHYs (NA) (heading level 7)

Nodes may switch to any mutually supported PHY among the following.

###### FSK PHYs (heading level 8)

- PhyModeID 0x03 — mode #2a — 100 kbps
- PhyModeID 0x05 — mode #3  — 150 kbps
- PhyModeID 0x06 — mode #4a — 200 kbps
- PhyModeID 0x08 — mode #5  — 300 kbps

###### OFDM PHYs (heading level 8)

- PhyModeID 0x22 — Option 1, MCS2 — 400 kbps
- PhyModeID 0x23 — Option 1, MCS3 — 800 kbps
- PhyModeID 0x24 — Option 1, MCS4 — 1200 kbps
- PhyModeID 0x25 — Option 1, MCS5 — 1600 kbps
- PhyModeID 0x26 — Option 1, MCS6 — 2400 kbps
- PhyModeID 0x33 — Option 2, MCS3 — 400 kbps
- PhyModeID 0x34 — Option 2, MCS4 — 600 kbps
- PhyModeID 0x35 — Option 2, MCS5 — 800 kbps
- PhyModeID 0x36 — Option 2, MCS6 — 1200 kbps
- PhyModeID 0x44 — Option 3, MCS4 — 300 kbps
- PhyModeID 0x45 — Option 3, MCS5 — 400 kbps
- PhyModeID 0x46 — Option 3, MCS6 — 600 kbps
- PhyModeID 0x54 — Option 4, MCS4 — 150 kbps
- PhyModeID 0x55 — Option 4, MCS5 — 200 kbps
- PhyModeID 0x56 — Option 4, MCS6 — 300 kbps

###### Regulatory Domain EU (Europe)

###### Example base PHY (informative) (heading level 7)

A commonly used base PHY is PhyModeID 0x01 — FSK — 50 kbps

> Note: Any supported FSK PHY for the EU domain may be configured as the base PHY.

###### Mode switch candidate PHYs (EU) (heading level 7)

###### FSK PHYs (heading level 8)

- PhyModeID 0x03 — mode #2a — 100 kbps
- PhyModeID 0x05 — mode #3  — 150 kbps

###### OFDM PHYs (heading level 8)

- PhyModeID 0x54 — Option 4, MCS4 — 150 kbps
- PhyModeID 0x55 — Option 4, MCS5 — 200 kbps
- PhyModeID 0x56 — Option 4, MCS6 — 300 kbps

###### Mode Switch PHYs in the Radio Configurator

Before configuring mode switch PHYs in the application with the mode switch APIs, add all PHYs that may be used for mode switching to the **Radio Configurator**.

After adding the PHYs, either directly in the **Radio Configurator** or through the **Wi-SUN Configurator**, verify that all PHYs the application may switch between are in the same Protocol Group, as shown in the following screenshot.

This is important because mode switch can only occur between PHYs that belong to the same Protocol Group.

In the following radio configuration example:

- It is possible to switch between the PHYs in **WiSUNConf Protocol Configuration 1**
- It is not possible to switch between a PHY in **WiSUNConf Protocol Configuration 1** and another in **WiSUNConf Protocol Configuration 2**

![radio configuration](/wisun-mode-switch/0.1/images/sld1088-radio-conf-protocol-groups.png)

---

##### Fallback Mechanism

Mode Switch is automatically disabled for a neighbor if failures significantly exceed successes (4 times more retries than successes over time).

Result:

- Node falls back to **Base PHY**
- The `SL_WISUN_MSG_MODE_SWITCH_FALLBACK_IND_ID` indication is raised with the MAC address of the neighbor

---

##### Wi-SUN Mode Switch with SoC Sample Apps

To test Mode Switch for OFDM or FSK modulations with the Wi-SUN stack on SoC:

- Use **Wi-SUN - SoC Border Router** project for the border router
- Use **Wi-SUN - SoC CLI** project for the node devices

###### Mode switch Command

The mode switch feature can be used from the `wisun_cli` and `wisun_brcli` applications with the following command:

```bash
wisun mode_switch [Mode Switch mode] [PhyModeID] [MAC Address]
```

###### Command Parameters

###### Mode Switch Mode (heading level 7)

**`0` — Mode Switch Disabled**

Disables mode switching for the selected neighbor(s)

```bash
wisun mode_switch 0 PhyModeID [MAC Address]
```

**Parameters:**

- `PhyModeID` is ignored in this case
- `MAC Address` can be:  
  - A single neighbor  
  - `ff:ff:ff:ff:ff:ff:ff:ff` for all neighbors

**`1` — Mode Switch Enabled with Specific PhyModeID**

- Enables mode switching with a specific `PhyModeID` for the selected neighbor(s)

```bash
wisun mode_switch 1 PhyModeID ff:ff:ff:ff:ff:ff:ff:ff

```

- Required before using Mode `2`
- When `MAC Address` is `ff:ff:ff:ff:ff:ff:ff:ff`, the global `PhyModeID` is set for all neighbors

```bash
wisun mode_switch 1 PhyModeID [MAC Address]
```

**Parameters:**

- `PhyModeID`: PhyModeID to switch to
- `MAC Address`: MAC address of the neighbor(s)  
  - A single neighbor  
  - Or `ff:ff:ff:ff:ff:ff:ff:ff` for all neighbors

**`2` — Mode Switch Enabled with Global PhyModeID (Single Neighbor)**

Enables mode switching using the global `PhyModeID` for a single neighbor

```bash
wisun mode_switch 2 PhyModeID [MAC Address]
```

**Parameters:**

- `PhyModeID` is ignored in this case
- `ff:ff:ff:ff:ff:ff:ff:ff` cannot be used
- The global `PhyModeID` must be set beforehand using:  
  ```bash  
  wisun mode_switch 1 PhyModeID ff:ff:ff:ff:ff:ff:ff:ff  
  ```
- `MAC Address`: MAC address of the neighbor

---

##### Examples

Assume 3 neighbors:

1. 01:02:03:04:05:06:07:08
2. 11:12:13:14:15:16:17:18
3. 21:22:23:24:25:26:27:28

- To use PhyModeId 34 (OFDM option 1, MCS2) globally (for all existing neighbors), the command is:

```bash
wisun mode_switch 1 34 ff:ff:ff:ff:ff:ff:ff:ff
```

- To use PhyModeID 52 (OFDM option 2, MCS4) for the first and second neighbors only, two commands are necessary:

```bash
wisun mode_switch 1 52 01:02:03:04:05:06:07:08
wisun mode_switch 1 52 11:12:13:14:15:16:17:18
```

- To use the global PhyModeID (without the need to specify it) for the second neighbor, the command is:

```bash
wisun mode_switch 2 xx 11:12:13:14:15:16:17:18
```

- To disable mode switch for the first neighbor, the command is:

```bash
wisun mode_switch 0 xx 01:02:03:04:05:06:07:08
```

- To disable mode switch for all neighbors using the global PhyModeID, the command is:

```bash
wisun mode_switch 0 xx ff:ff:ff:ff:ff:ff:ff:ff
```

---

##### Mode Switch in wsbrd

Mode switch in wsbrd is configured through the PHY configuration in wsbrd.conf and dynamically controlled via the D-Bus API.

Refer to the official configuration file [wsbrd.conf](https://github.com/SiliconLabs/wisun-br-linux/blob/main/examples/wsbrd.conf), the relevant parameter for mode switch is `phy_operating_modes`.

For dynamic control via D-Bus, refer to [`SetLinkModeSwitch`](https://github.com/SiliconLabs/wisun-br-linux/blob/main/DBUS.md#setlinkmodeswitch-ayuy) official documentation and example.

---

##### Mode Switch implementation using the APIs

###### sl_wisun_set_mode_switch

[`sl_wisun_set_mode_switch()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-mode-switch) is the runtime API used to actually enable and control mode switching. It tells the Wi-SUN stack which PHY to use for high data rate communication and whether the feature is enabled for a given neighbor or for all neighbors. You typically call it **after the device has joined the network**, because mode switch operates on established neighbor relationships. Using the broadcast MAC applies the configuration globally,and using a specific MAC applies it to one neighbor. This API directly maps to the CLI `wisun mode_switch` command and is the only API required to make mode switching happen in practice.

```C
sl_status_t sl_wisun_set_mode_switch (uint8_t mode, uint8_t phy_mode_id, const sl_wisun_mac_address_t * neighbor_address)
```

###### sl_wisun_set_pom_ie

[`sl_wisun_set_pom_ie()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-pom-ie) API controls which PHYs the node advertises to its neighbors through the POM-IE (PHY Operating Mode Information Element). Mode switching can only occur if both peers advertise a common PHY, so this API effectively defines the capability set of the device. By default (if sl_wisun_set_pom_ie() is not called), the advertised list will contain first 15 PhyModeId listed in the radio multi-PHY configuration. You can use this API to reduce or customize the default advertised PHY list. It can be used before or after the connection, if called after the connection the list is applied immediately.

```C
sl_status_t sl_wisun_set_pom_ie (uint8_t phy_mode_id_count, uint8_t phy_mode_ids, uint8_t is_mdr_command_capable)
```

###### Implementation examples

###### Limit advertised PHYs (heading level 7)

By default, the stack may advertise a larger PHY list depending on the PhyModeIds listed in the radio multi-PHY configuration. The following example restricts advertisement to only two PHYs: base PHY (2) and OFDM PHY (34).

```c
#include "sl_wisun_api.h"

void configure_pom_ie(void)
{
  uint8_t phy_mode_ids[] = {2, 34};

  sl_wisun_set_pom_ie(sizeof(phy_mode_ids), phy_mode_ids,0);
}
```

###### Enable mode switch after connection (heading level 7)

After the following call, the stack will automatically start using the higher data rate PHY for unicast traffic when conditions allow, while keeping multicast and asynchronous traffic on the base PHY.

```C
#include "sl_wisun_api.h"

static const uint8_t broadcast_mac[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

void sl_wisun_on_event(sl_wisun_evt_t *evt)
{
  if (evt->header.id == SL_WISUN_MSG_CONNECTED_IND_ID) {
    // Enable global mode switch to OFDM PHY (ID 34)
    sl_wisun_set_mode_switch(SL_WISUN_MODE_SWITCH_ENABLE,
                             34,
                             broadcast_mac);
  }
}
```

#### Add a Custom Application

##### Add a Custom Application

The example is the **Wi-SUN Node Monitoring** example application
The reference code is provided on [GitHub](https://github.com/SiliconLabs/wisun_applications/tree/main/wisun_node_monitoring).

The example code being available on GitHub, it is recommended to:

- [Add the 'Wi-SUN Applications' repository to Simplicity Studio](https://github.com/SiliconLabs/wisun_applications/tree/main#add-the-wi-sun-applications-repository-to-simplicity-studio-5)
- [Create a Wi-SUN Node Monitoring project](https://github.com/SiliconLabs/wisun_applications/tree/main#create-the-wi-sun-applications-example-projects) after selecting the **wisun_applications** provider.

![node monitoring](/wisun-custom-application/0.1/images/node-monitoring-create.png)

Using the **Wi-SUN Node Monitoring** project removes the difficulties related to adding pieces of code along the way to reach a compilable project.

The goal of this application is to:

- Follow the device connections from the Border Router.  
  - The devices will send a UDP connection message to the Border Router on port 1237 after connecting for the first time.  
  - The devices will automatically send a connection status message to the Border Router every `auto_send` seconds.    
    - The default `auto_send` period is 30 seconds.    
    - The `auto_send` period can be checked remotely via a CoAP `get` command for `settings\auto_send`.    
    - It can be modified using the same CoAP command if adding `-e <n>` as the command payload, `<n>` being the new value.    
    - This can be used as an example for sensor monitoring or actuator control in a final application.    
    - The connection message contains time values in `dd-hh:mm:ss` format.    
    - The start point of these time values is the moment the application is started.    
    - The first connection message can be used to check the connection time.
- Follow the device join state changes.  
  - The history of these changes can be retrieved from the Border Router once connected.
- Monitor application statistics.  
  - Application statistics can be retrieved from the Border Router using CoAP requests.  
  - A very important statistic is the availability rate, computed from the total connected and disconnected times, which should be as close to 100% as possible (counting starts on the very first connection).
- Monitor Wi-SUN Stack statistics.  
  - All statistics provided by the Wi-SUN Stack are available via CoAP requests.
- Use OTA DFU to remotely update the WI-SUN devices via the Wi-SUN network.

###### Prerequisites

###### Compile and Run Wi-SUN Node Monitoring App (heading level 7)

Refer to the [Node Monitoring README](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/README.md). As outlined in the README, this application is intended to run alongside a Linux-based Border Router application.

###### Software Components (heading level 7)

The following software components are required to compile the application with the added code:

- Third-Party / Segger / SEGGER RTT printf
- Wi-SUN / Wi-SUN Services / CoAP
- Wi-SUN / Wi-SUN Services / PoSIX-compliant Socket
- Wi-SUN / Wi-SUN Services / Over-The-Air Firmware Upgrade (OTA DFU)

> Note: It is possible to check which components are installed in a project looking at the `.slcp` file and the **SOFTWARE COMPONENTS** tab, checking the **Installed** box.

Using the **Wi-SUN Node Monitoring** example application, all components should already be installed. Just check their presence to get familiar with components used. Install the components now if they are not present.

![Installed components](/wisun-custom-application/0.1/images/install-components.png)

Installed Wi-SUN components are listed in `autogen\sl_component_catalog.h`:

![component catalog](/wisun-custom-application/0.1/images/component-catalog.png)

###### Custom Application

The Custom Application pages explain how the custom application features are added to a Wi-SUN project. These features can be added to multiple projects if needed.

- In the Device Application  
  - [Add time stamping and tracing functions](01-timestamping)  
  - [Register a custom callback to follow join state changes](02-custom-callback-join-state)  
  - [Prepare JSON connection strings](03-connection-strings)  
  - [Send status strings to the Border Router's IPv6 on UDP port 1237](04-send-status-udp)  
  - [Add CoAP resources to the Device Application](05-adding-coap-resources)
- On the Border Router  
  - [Retrieve UDP notifications on the Border Router](06-retrieve-udp-notifications)  
  - [Retrieve device information on the Border Router Using CoAP](07-retrieve-device-information)

##### One Second Timestamping

Because Wi-SUN network changes are rare while connection times are in days or months, the underlying unit of time measurement used by the Wi-SUN Stack down to the microsecond is not necessary for long-term observability of network connection. We therefore:

- Set up a 1-second timer to count seconds
- Add functions to format current time and delays as dd-hh:mm:ss

To get a 1-second timestamp, do the following steps.

> Note: This is all done in [`app_timestamp.c`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c) and [`app_timestamp.h`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.h), which you can use by copy/pasting both files next to your `app.c` file.

_Simplicity Studio will automatically compile any `.c` file present under the project folder, so no action is required to add `app_timestamp.c` to the compilation once the file is copied._

###### Declaration of a 64-bit [`app_timestamp`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L54) Variable

```C
sl_sleeptimer_timestamp_64_t app_timestamp;
```

###### Creation of a [Callback Function](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L88) to Increment the Timestamp by 1

```C
void app_timer_callback(sl_sleeptimer_timer_handle_t *handle, void *data) {
  (void)handle;
  (void)data;
  app_timestamp++;
}
```

###### Protect Access to the Variable Using a Mutex

- [Mutex declaration](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L66):

```C
static const osMutexAttr_t _app_timestamp_mutex_attr = {
  .name      = "AppTimestampMutex",
  .attr_bits = osMutexRecursive,
  .cb_mem    = NULL,
  .cb_size   = 0U
};
```

- [Mutex acquire function](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L77):

```C
__STATIC_INLINE void _app_timestamp_mutex_acquire(void)
{
  assert(osMutexAcquire(_app_timestamp_mutex, osWaitForever) == osOK);
}
```

- [Mutex release function](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L83):

```C
__STATIC_INLINE void _app_timestamp_mutex_release(void)
{
  assert(osMutexRelease(_app_timestamp_mutex) == osOK);
}
```

###### [Timestamp Init](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L97)

```C
sl_status_t app_timestamp_init(void) {
  sl_status_t status;
  uint32_t app_timer_timeout;

  // init mutex
  _app_timestamp_mutex = osMutexNew(&_app_timestamp_mutex_attr);
  assert(_app_timestamp_mutex != NULL);

  app_timestamp =  0;

  status = sl_sleeptimer_init();
  if (status != SL_STATUS_OK) {
      printf("Error initializing sleeptimer. Status %lu\n", status);
      return status;
  }
  app_timer_timeout = (uint32_t)1.0*sl_sleeptimer_get_timer_frequency();
  status = sl_sleeptimer_start_periodic_timer(&app_timer,
                                              app_timer_timeout,
                                              app_timer_callback,
                                              NULL, 0, 0);
  if (status != SL_STATUS_OK) {
      printf("Error starting periodic timer 'app_timer'. Status %lu\n", status);
      return status;
  }
  return status;
}
```

Following this:

- `app_timestamp` is set to `0` when `app_timestamp_init()` is called
- `app_timer_callback()` is called every second  
  - `app_timestamp` is increased by `1` every second
- You can retrieve it safely using the mutex

###### Retrieve the [Current Timestamp Decimal Value](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.c#L168)

```C
uint64_t     now_sec      (void) {
  sl_sleeptimer_timestamp_64_t current_sec;
  _app_timestamp_mutex_acquire();
  current_sec = app_timestamp;
  _app_timestamp_mutex_release();
  return (uint64_t)current_sec;
}
```

You can use `now_sec()` to store the current time in decimal values:

```C
  uint64_t current_time_secs;
  current_time_secs = now_sec();
```

###### Utility Functions to Process Timestamp Values

###### Transform a Timestamp in days/hours/mins/secs Units (heading level 7)

Mainly used as a convenience function, this should rarely be used from outside this code:

```C
sl_status_t  d_h_m_s_total(sl_sleeptimer_timestamp_64_t timestamp_secs,
                    uint16_t* days,
                    uint64_t* hours,
                    uint64_t* mins,
                    uint64_t* secs
) {
  *days  = timestamp_secs / 60 / 60 / 24;
  *hours = timestamp_secs / 60 / 60;
  *mins  = timestamp_secs / 60;
  *secs  = timestamp_secs;
  return SL_STATUS_OK;
}
```

###### Transform a Timestamp as days:hours:mins:secs Decimal Values (heading level 7)

```C
sl_status_t  d_h_m_s      (sl_sleeptimer_timestamp_64_t timestamp_secs,
                    uint16_t* days,
                    uint8_t* hours,
                    uint8_t* mins,
                    uint8_t* secs) {
  uint64_t hours_total;
  uint64_t mins_total;
  uint64_t secs_total;

  d_h_m_s_total(timestamp_secs, days, &hours_total, &mins_total, &secs_total);

  *days = *days;
  *hours = hours_total % 24;
  *mins  = mins_total  % 60;
  *secs  = secs_total  % 60;

  return SL_STATUS_OK;
}
```

###### Format a Timestamp as a days:hours:mins:secs Text String (heading level 7)

```C
char*        dhms         (sl_sleeptimer_timestamp_64_t timestamp_secs) {
  uint16_t days;
  uint8_t  hours, mins, secs;

  d_h_m_s(timestamp_secs, &days, &hours, &mins, &secs);

  snprintf(time_str, TIME_STRING_LEN, "%3d:%02d:%02d:%02d", days, hours, mins, secs);

  return time_str;
}
```

This can be used in traces as follows:

```C
printf("Current time is %s\n", now_str());
```

With a `Current time is   0:01:23:45` result, if the application has been running for 0 day, 1 hour, 23 minutes and 45 seconds.

###### Get `app_timestamp` as a Text String (heading level 7)

```C
char*        now_str     (void) {
  return dhms(now_sec());
}
```

###### Trace Timestamping and Routing Macros

A [set of macros](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_timestamp.h#L78) are defined to allow sending traces to the console, the RTT traces, or both:

```C
#define printfTime(...)     printf("[%s] ", now_str()); printf(__VA_ARGS__)
#define printfRTT(...)      SEGGER_RTT_printf(0, __VA_ARGS__)
#define printfTimeRTT(...)  SEGGER_RTT_printf(0, "[%s] ", now_str()); SEGGER_RTT_printf(0, __VA_ARGS__)
#define printfBoth(...)     SEGGER_RTT_printf(0, __VA_ARGS__); printf(__VA_ARGS__)
#define printfBothTime(...) SEGGER_RTT_printf(0, "[%s] ", now_str()); SEGGER_RTT_printf(0, __VA_ARGS__); printf("[%s] ", now_str()); printf(__VA_ARGS__)
```

The above makes it easy in the application to:

- Select to add a timestamp or not to traces.
- Print a trace to the console or the RTT traces, or both.

###### Use the Timestamp

In `app.c`, `#include "app-timestamp.h"` to get access to the timestamping resources.

In `app.c/app_task()`, initialize the one second timestamp:

![timestamp init](/wisun-custom-application/0.1/images/timestamp-init.png)

It is convenient to declare variables to store various time values:

```C
uint64_t connect_time_sec;           // time stamp of Wisun connect call
uint64_t connection_time_sec;        // last connection time stamp
uint64_t disconnection_time_sec;     // last disconnection time stamp
```

These can be used as follows (example code, not part of the sample application):

```C
  printfBothTime("running since %s\n", now_str());
  connect_time_sec = now_sec();
  app_wisun_connect_and_wait();
  /* Some time will pass until we're connected... */
  connection_time_sec = now_sec();
  printfBothTime("Connected in %s\n", dhms(connection_time_sec - connect_time_sec));
```

##### Register a Custom Callback to Follow the Join State

As described in [Event Handling with the Event Manager](sld71-wisun-connection-details-index#event-handling-with-the-event-manager-component), it is possible to register custom callbacks for indications listed in [`sl_wisun_events.h/sl_wisun_msg_ind_id_t`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-evt#sl-wisun-msg-ind-id-t).

> Note: This is all done in [`app.c`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app.c).

To follow what is happening on your Wi-SUN network, a dedicated function is added to do whatever you need and is registered to be called on each join state change.

It is registered with the Event Manager in [`app.c/app_task()`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app.c#L317) as follows:

```C
  // Register our join state custom callback function with the event manager (aka 'em')
  app_wisun_em_custom_callback_register(SL_WISUN_MSG_JOIN_STATE_IND_ID, _join_state_custom_callback);
```

The callback function itself is [`app.c/_join_state_custom_callback()`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app.c#459), relying on [our 1-second timestamping](01-timestamping) to store time information. The function uses other parts of the code, so replacing the original `app.c` by this file is an easy way to get compilable code.

###### Code Behavior

- Check the join state.
- Only do something when there is a join state change.  
  - Do nothing for intermediate join states (with values above 5), which the Stack also handles. These are mainly intermediate stages between join state 4 and join state 5, such as DHCP and DNS, with code between 41 and 49.  
  - Trace the previous and current join state when it changed.  
  - Store the current time in `app_join_state_sec[join_state]`. This will be used in traces and to compute the `app_join_state_delay_sec[join_state]` values, indicating how much time was spent moving to the new join state.  
  - If the join state is 'OPERATIONAL' (i.e. 'connected'):    
    - Store the time in `connection_time_sec`.    
    - Increase the number of connections.    
    - If this is the first connection, clear `disconnected_total_sec`; otherwise, set it to the time spent since the disconnection.    
    - Trace the duration spent connecting.    
    - Because it is possible to retrieve the parent MAC address, set the `parent_tag` from it. This is a convenient way to identify devices using a shorter string than their entire MAC or IPv6 address. It also has the advantage of being visible in both the MAC and IPv6 addresses.    
    - If a UDP socket has been opened with the Border Router, send it a connection message with all interesting values. It looks like: `{ "device":"8486", "chip":"xG25", "parent":"333a", "running":"0:00:00:23", "join_states_sec":[0,0,9,1,12] }`. This simple message allows:      
      - Identifying which devices are connected, and which part they are built on.      
      - Knowing which device is their parent.        
        - It becomes possible to draw the network topology based on this.      
      - Knowing how much time has been spent moving between join states.        
        - In the above example, we see that:          
          - No time has been spent to reach join states 1 and 2, due to Wi-SUN stack optimizations allowing reuse of credentials if they are still valid.          
          - It took `9 + 1 + 12 = 22` seconds to reconnect. No time spent in join states 1 and 2 means it was a reconnection with previously saved credentials.  
  - If the previous join state was 'OPERATIONAL':    
    - Store the time in `disconnection_time_sec`.    
    - Trace the duration spent before disconnecting.    
    - Add this to 'connected_total_sec'.  
  - Set `previous_join_state` to the new join state.

Using the `app_join_state_sec[]` array, it becomes possible for the application to compute the values in the connection message.

Using the various timestamp values, it is possible to compute an availability ratio equal to:

`availability = 100.0*(connected_total_sec)/(connected_total_sec + disconnected_total_sec)`.

This value gives an interesting indication on the network availability, even if it is 100+ days long, which should be common in Wi-SUN.

##### Prepare JSON Connection Strings

Using the values set by the [custom callback to follow the join state](02-custom-callback-join-state), you can easily print connection/disconnection information using the [1-second timestamping](01-timestamping), and compute the network availability ratio.

> Note: This is all done in [`app.c`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app.c).

Two messages are used:

###### Initial Connection Message

```JSON
{
"device":"8486",
"chip":  "xG25",
"parent":"333a",
"running":     "  0:22:21:17",
"join_states_sec":[0,0,9,1,12]
}
```

**This message is printed in the device console and sent to the Border Router right after connecting.**

- "device" is the `device_tag` string, formatted from the MAC address of the device. This is a convenient way to identify devices using a shorter string than their entire MAC or IPv6 address. It has also the advantage of being visible in both the MAC and IPv6 addresses. This is fixed and set once only in `app.c/app_task()`.
- "chip" is the type of the part used, based on the following code (which can easily be extended to support more parts):

```C
#ifdef  _SILICON_LABS_32B_SERIES_1
  #ifdef _SILICON_LABS_32B_SERIES_1_CONFIG_2
    #define CHIP "xG12"
  #endif
#endif

#ifdef  _SILICON_LABS_32B_SERIES_2
  #ifdef _SILICON_LABS_32B_SERIES_2_CONFIG_5
    #define CHIP "xG25"
  #endif
  #ifdef _SILICON_LABS_32B_SERIES_2_CONFIG_8
    #define CHIP "xG28"
  #endif
#endif

#ifndef CHIP
  #define CHIP SL_BOARD_NAME
#endif

```

- "parent" is the `parent_tag` string, formatted from the MAC address of the parent as soon as connection is achieved. This can change over time, when the device selects a different parent, which is normal in a Wi-SUN network depending on the reception conditions. It is set inside the custom callback following join state changes.
- The "device" and "parent" information allow building the network topology, to compare it to what `wsbrd_cli status` shows. The topology in this case is using information from the devices, not information retrieved using DBus from wsbrd. Both topology graphs should match.
- "running" is the amount of time elapsed since the timestamp has been initialized in `app.c/app_task()`, calling `app_timestamp_init()`. In the example, it shows a 22+ hour run. _Note that the very first value is a days count, required for long-term monitoring in a Wi-SUN network_.
- "join_state_sec" is an array of delays between join state changes, starting with join state 1. Five values are present, each corresponding to the time required to reach the corresponding join state. In the example, we can say that:  
  - The device took 9 + 1 + 12 = 22 seconds to connect.  
  - No time was spent going to join states 1 and 2, meaning that the device could reuse already existing credentials, thus saving time by skipping the authentication exchanges in steps 1 and 2. This is part of Wi-SUN stack optimizations for faster reconnection. If `sl_wisun_clear_credential_cache()` is called before connecting, authentication is required to retrieve credentials.

###### Status Message

```JSON
{
"device":"8486",
"chip":  "xG25",
"parent":"333a",
"running":     "  0:22:21:17",
"connected":   "  0:22:20:35",
"disconnected":"no",
"connections": "1",
"availability":"100.00",
"connected_total":   "  0:22:20:35",
"disconnected_total":"  0:00:00:00"
}
```

**This message is printed in the console and sent to the Border Router every `auto_send_sec` seconds.**

By default, `auto_send_sec` is set to 60 seconds. This can be customized in the source code. It is also possible with the example application to change it remotely using a dedicated CoAP message. Obviously, if the device is not connected, the message is only printed in the console.

- "device", "chip", and "running" are exactly the same as in the [initial connection message](#initial-connection-message).
- "connected" is the duration of the current connection. This is reset when reconnecting, such that it monitors only the last connection last. It is "no" when not connected.
- "disconnected" is the duration since the last disconnection. It is "no" when connected.
- "availability" is the ratio between the connected time and the total time since the first connection. It is computed as `100.0*(connected_total_sec)/(connected_total_sec + . disconnected_total_sec)`.
- "connected_total" is the sum of the connected times since the very first connection, used to compute the availability ratio.
- "disconnected_total" is the sum of the disconnected times since the very first connection, used to compute the availability ratio. When "disconnected_total" is `"  0:00:00:00"`, the availability rate is 100%.

> Note: To get a fair value of the availability ratio, disconnection and connection times accumulation only starts on the very first connection. Otherwise, the statistics would be impacted when the Border Router is started after the devices. With this configuration, the availability ratio should be very close to 100% under normal conditions, with devices quickly reconnecting following a disconnection.

If the Border Router is ever stopped and restarted, the devices will reconnect and send their status messages again, all showing a "disconnected" duration in the same range. This is a clear indication that the disconnection was due to the Border Router, and debugging should be oriented towards the Border Router.

When a single device has issues, its next status messages will show a "disconnected" value different from all other nodes. In this situation, debugging should be oriented at the device itself.

If a device is disconnected, printing the messages into its console (and RTT traces) still allows debugging up to a certain level, as long as access to the console or to RTT traces is possible (only in a lab environment in this case):

- If the messages don't appear in the console, the application is probably stalled and debugging is required, starting with RTT traces (which keep a bit of history on the last traces).
- If the messages still appear in the console, the application is still running. Further debugging may be possible looking at RTT traces for any error message coming from the Wi-SUN stack.

###### Code Walkthrough

Three macros are used to format the first part of both messages and to add JSON start and end strings:

```C
// JSON common format strings
#define START_JSON "{\n"

#define END_JSON   "}\n"

#define DEVICE_PARENT_RUNNING_JSON \
  "\"device\":\"%s\",\n"           \
  "\"chip\":  \"%s\",\n"           \
  "\"parent\":\"%s\",\n"           \
  "\"running\":     \"%s\",\n"
```

The initial connection message is formatted in `_connection_json_string()`.

```C
char* _connection_json_string () {
  #define CONNECTION_JSON_FORMAT_STR                   \
    START_JSON                                         \
    DEVICE_PARENT_RUNNING_JSON                         \
    "\"join_states_sec\":[%llu,%llu,%llu,%llu,%llu]\n" \
    END_JSON

  char sec_string[20];
  sprintf(sec_string, "%s", now_str());
  snprintf(json_string, SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE,
     CONNECTION_JSON_FORMAT_STR,
     device_tag,
     CHIP,
     parent_tag,
     sec_string,
     app_join_state_delay_sec[1],
     app_join_state_delay_sec[2],
     app_join_state_delay_sec[3],
     app_join_state_delay_sec[4],
     app_join_state_delay_sec[5]
  );
  return json_string;
};
```

The status message is formatted in `_status_json_string()`.

```C
char* _status_json_string (char * start_text) {
  #define CONNECTED_JSON_FORMAT_STR        \
    "%s"                                   \
    START_JSON                             \
    DEVICE_PARENT_RUNNING_JSON             \
    "\"connected\":   \"%s\",\n"           \
    "\"disconnected\":\"%s\",\n"           \
    "\"connections\": \"%d\",\n"           \
    "\"availability\":\"%6.2f\",\n"        \
    "\"connected_total\":   \"%s\",\n"     \
    "\"disconnected_total\":\"%s\"\n"      \
    END_JSON

  char running_sec_string[20];
  char current_sec_string[20];
  char connected_sec_string[20];
  char disconnected_sec_string[20];

  uint64_t current_state_sec;

  sprintf(running_sec_string, "%s", now_str());

  if (join_state == SL_WISUN_JOIN_STATE_OPERATIONAL) {
    current_state_sec = now_sec() - connection_time_sec;
    sprintf(current_sec_string,     "%s", dhms(current_state_sec));
    sprintf(connected_sec_string,   "%s", dhms(connected_total_sec + current_state_sec));
    sprintf(disconnected_sec_string,"%s", dhms(disconnected_total_sec));
    snprintf(json_string, SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE,
       CONNECTED_JSON_FORMAT_STR,
       start_text,
       device_tag,
       CHIP,
       parent_tag,
       running_sec_string,
       current_sec_string,
       "no",
       connection_count,
       100.0*(connected_total_sec + current_state_sec)/(connected_total_sec + current_state_sec + disconnected_total_sec),
       connected_sec_string,
       disconnected_sec_string
    );
  } else {
    current_state_sec = now_sec() - disconnection_time_sec;
    sprintf(current_sec_string,     "%s", dhms(current_state_sec));
    sprintf(connected_sec_string,   "%s", dhms(connected_total_sec));
    sprintf(disconnected_sec_string,"%s", dhms(disconnected_total_sec + current_state_sec));
    snprintf(json_string, SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE,
       CONNECTED_JSON_FORMAT_STR,
       start_text,
       device_tag,
       CHIP,
       parent_tag,
       running_sec_string,
       "no",
       current_sec_string,
       connection_count,
       100.0*(connected_total_sec)/(connected_total_sec + disconnected_total_sec + current_state_sec),
       connected_sec_string,
       disconnected_sec_string
    );
  }

  return json_string;
}
```

##### Send Status Strings to the Border Router on UDP Port 1237

Status strings are prepared as in [JSON Connection Strings](03-connection-strings), getting ready to be sent to the Border Router or any other IPv6 address. To send them to their destination, the following steps are needed.

> Note: This is all done in [`app.c`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app.c), which you can use as a replacement for the original code.

###### Set the Destination IPv6

###### IPv6 Declaration (heading level 7)

What you want is to automatically select the Border Router IPv6, which the device will only know once it is connected, or set a static IPv6 if your system is set with a different destination for network monitoring messages.

- A text string is defined in `app.c`. It should be set to a valid IPv6.

```C
#define UDP_NOTIFICATION_DEST  "fd00:6172:6d00::1" // fixed IPv6 string
```

- Once connected, a part of `app.c/_select_destinations()` takes care of setting the intended IPv6.

```C
  // Set the UDP notification destination (Border Router by default)
  printfBothTime("UDP_NOTIFICATION_DEST: %s\n", UDP_NOTIFICATION_DEST);
  if (sl_strcasecmp(UDP_NOTIFICATION_DEST, "border_router") == 0) {
    memcpy(udp_notification_ipv6.address,   border_router_ipv6.address, sizeof(device_global_ipv6.address));
  } else {
    sl_wisun_stoip6(UDP_NOTIFICATION_DEST    , SL_WISUN_IP_ADDRESS_SIZE, udp_notification_ipv6.address);
  }
  sl_wisun_ip6tos(udp_notification_ipv6.address       , udp_notification_ipv6_string);
  printfBothTime("UDP  Notification destination: %s\n", udp_notification_ipv6_string);
```

Convenience functions `sl_wisun_stoip6()` and `sl_wisun_ip6tos()` are used here to convert between IPv6s and strings. Both are defined in `sl_wisun_ipv6string.h`.

###### Set the Destination UDP Port

The destination port is hardcoded in `app.c` as `UDP_NOTIFICATION_PORT`. It can be customized here:

```C
#define UDP_NOTIFICATION_PORT  1237
```

###### Open and Connect the UDP Socket

Each socket id is stored in a [`sl_wisun_socket_id_t`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-types#sl-wisun-socket-id-t), so `udp_notification_socket_id` is declared in `app.c`:

```C
// Notification sockets
sl_wisun_socket_id_t udp_notification_socket_id = 0;
```

Once the device is connected to the Wi-SUN network, it becomes possible to open the UDP socket and connect it to the desired destination and port, as in `app.c/_open_udp_sockets_with_Border_Router()`:

```C
  // UDP Notifications (autonomously sent by the device)
  ret = sl_wisun_open_socket (SL_WISUN_SOCKET_PROTOCOL_UDP, &udp_notification_socket_id);
  NO_ERROR(ret, "Opened    the UDP  notification socket (%ld)\n", udp_notification_socket_id);
  IF_ERROR_RETURN(ret, "[Failed: unable to open the UDP notification socket: 0x%04x]\n", (uint16_t)ret);

  ret = sl_wisun_connect_socket(udp_notification_socket_id, &udp_notification_ipv6, UDP_NOTIFICATION_PORT);
  NO_ERROR(ret, "Connected the UDP  notification socket (%ld %s/%d)]\n",
           udp_notification_socket_id, udp_notification_ipv6_string, UDP_NOTIFICATION_PORT);
  IF_ERROR_RETURN(ret, "[Failed: unable to connect the UDP notification socket: 0x%04x]\n", (uint16_t)ret);
```

###### Print and Send Status Messages

###### Auto Send Loop (heading level 7)

In `app.c/app_task()`, the code enters an endless loop after initial connection, with a pause of `auto_send_sec` seconds after each loop. Inside this loop, a call to `_print_and_send_messages()` is used to send the string formatted by `_status_json_string()`:

```C
void app_task(void *args)
{
. . .
  bool with_time, to_console, to_rtt, to_udp, to_coap;
. . .
  with_time = to_console = to_rtt = true;
  to_udp = to_coap = false;
. . .
  while (1) {
    ///////////////////////////////////////////////////////////////////////////
    // Put your application code here!                                       //
    ///////////////////////////////////////////////////////////////////////////

    // We can only send messages outside if connected
    if (join_state == SL_WISUN_JOIN_STATE_OPERATIONAL) {
      to_udp = to_coap = true;
    } else {
      to_udp = to_coap = false;
    }

    // Print status message every auto_send_sec seconds
    _print_and_send_messages (_status_json_string(""),
               with_time, to_console, to_rtt, to_udp, to_coap);
    osDelay(auto_send_sec*1000);

  }
}
```

###### Messages Print Out and Transmission (heading level 7)

In `app.c/_print_and_send_messages()`, the flags are used to select where to send the message, including to the selected UDP port:

```C
uint8_t _print_and_send_messages (char *in_msg, bool with_time,
                            bool to_console, bool to_rtt, bool to_udp, bool to_coap) {
  sl_status_t ret = SL_STATUS_OK;
  uint8_t messages_processed = 0;
  uint16_t udp_msg_len;
  uint16_t coap_msg_len;

  if (to_console == true) { // Print to console
      if (with_time == true) {
        printfTime(in_msg);
      } else {
        printf(in_msg);
      }
    messages_processed++;
  }
  if (to_rtt == true) {     // Print to RTT traces
      if (with_time == true) {
        printfTimeRTT(in_msg);
      } else {
        printfRTT(in_msg);
      }
    messages_processed++;
  }
  if (to_udp == true) {     // Send to UDP port
    udp_msg_len  = snprintf(udp_msg,  1024, "%s", in_msg);
    ret = sl_wisun_send_on_socket(udp_notification_socket_id, udp_msg_len, (uint8_t *)udp_msg);
    IF_ERROR(ret, "[Failed (line %d): unable to send to the UDP notification socket (%ld %s/%d): 0x%04x. Check sl_status.h] udp_msg_len %d\n",
             __LINE__, udp_notification_socket_id, udp_notification_ipv6_string , UDP_NOTIFICATION_PORT, (uint16_t)ret, udp_msg_len);
    if (ret == SL_STATUS_OK) messages_processed++;
  }
. . .
  return messages_processed;
}
```

##### Add CoAP Resources to the Device Application

Using the [Send status](04-send-status-udp) / [Retrieve UDP notifications](06-retrieve-udp-notifications) technique, the devices are automatically sending messages to the Border Router (by default, another destination is possible). In a large Wi-SUN network, this may not be convenient, or the `auto_send_sec` value would be set to a very high value, such that these messages act as 'keep alive' messages, used to make sure the devices are still active and connected.

An approach more fitting for large networks consists of adding the capability for the nodes to reply with the status messages to CoAP 'get' messages. With this approach, the network management machine is responsible for regularly checking the node status, potentially infrequently. This is described in the next paragraphs.

If the devices are monitoring critical sensors, such as temperature values, they can be set to send notification messages if the monitored values pass above pre-determined thresholds, or enter critical zones. This is application-specific, out of scope of the current example application.

###### Add CoAP to the Project

The demonstration code is in [`app_coap.c`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_coap.c) and  [`app_coap.h`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/app_coap.h). It uses the **Wi-SUN CoAP**  service, available in **SOFTWARE COMPONENTS > Wi-SUN > Wi-SUN Services > CoAP**.

![CoAP Component](/wisun-custom-application/0.1/images/coap-service-component.png)

Because the demonstration application uses a lot of CoAP resources, the `Maximum capacity of the CoAP Resource Table` is set to `30` in `/wisun_soc_empty_stability/config/sl_wisun_coap_config.h`, instead of the default of `10`.

```C//
// <o SL_WISUN_COAP_RESOURCE_HND_MAX_RESOURCES> Maximum capacity of the CoAP Resource Table
// <i> Default: 10
#define SL_WISUN_COAP_RESOURCE_HND_MAX_RESOURCES        30U
```

The `Resource handler service socket communication buffer size` is left to its default value of `1024`, declared as `SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE` in `sl_wisun_coap_config.h`. This will limit the length of the JSON text string we can send.

```C
// <o SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE> Resource handler service socket communication buffer size
// <i> Default: 1024
#define SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE       1024UL
```

###### Definition of CoAP Resources

One of the most difficult parts of coding a CoAP application is setting correct names for resources, i.e. names that feel logical for most users, and present a consistent hierarchy for those resources.

In the demonstration application, Silicon Labs used:

- 'info/' for parameters that will not change for a given device:  
  - device_tag  
  - chip  
  - board  
  - 'info/all' returns a json string with all of the above
- 'status/' for parameters varying with time and not part of the statistics  
  - running  
  - parent (which can change if selecting a different parent)  
  - neighbor (access to neighbor count if no payload, otherwise adding `-e <n>` returns info for neighbor `n`)  
  - connected (not accumulated connection time)  
  - 'status/all' returns a json string with all of the above
- 'statistics/' for values accumulated by the application, or retrieved from the stack  
  - 'statistic/app/'    
    - join_states_sec    
    - disconnected_total    
    - connections    
    - connected_total    
    - availability    
    - 'statistics/app/all' returns a json string with all of the above. Adding `-e reset` resets these statistics.  
  - 'statistics/stack/'    
    - phy (statistics from [sl-wisun-statistics-phy-t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-statistics-phy-t). Adding `-e reset` resets these statistics)    
    - mac (statistics from [sl-wisun-statistics-mac-t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-statistics-mac-t). Adding `-e reset` resets these statistics)    
    - fhss (statistics from [sl-wisun-statistics-fhss-t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-statistics-fhss-t). Adding `-e reset` resets these statistics)    
    - wisun (statistics from [sl-wisun-statistics-wisun-t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-statistics-wisun-t). Adding `-e reset` resets these statistics)    
    - network (statistics from [sl-wisun-statistics-network-t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-statistics-network-t). Adding `-e reset` resets these statistics)    
    - regulation (statistics from [sl-wisun-statistics-regulation-t](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-statistics-regulation-t). Adding `-e reset` resets these statistics)    
    - No 'all' option here, because some of the resources already return very long strings. Adding all together would overflow the json string limit.
- 'settings/' for parameters of the application we want to change via CoAP  
  - auto_send (returns the current `auto_send_sec` value if no payload, otherwise adding `-e <s>` sets `auto_send_sec` to `s`))

###### Declare a CoAP Callback Function for each CoAP Resource

The application needs to know which function to execute when a CoAP `get` request is received. There is **one function per resource**. We will only document some of them. Adding more is straightforward once the first ones are clearly explained.

###### CoAP Callback Prototype

Each CoAP callback function has the same return type and parameters:

- return type `sl_wisun_coap_packet_t *`, a pointer to the response packet
- parameter `const  sl_wisun_coap_packet_t *const req_packet`, the CoAP request packet, defined in `sl_wisun_coap.h` as:

```C
/**
 * \brief Main CoAP message struct
 */
typedef struct sn_coap_hdr_ {
  uint8_t                 token_len;            /**< 1-8 bytes. */

  sn_coap_status_e        coap_status;          /**< Used for telling to User special cases when parsing message */
  sn_coap_msg_code_e      msg_code;             /**< Empty: 0; Requests: 1-31; Responses: 64-191 */

  sn_coap_msg_type_e      msg_type;             /**< Confirmable, Non-Confirmable, Acknowledgment or Reset */
  sn_coap_content_format_e content_format;      /**< Set to COAP_CT_NONE if not used */

  uint16_t                msg_id;               /**< Message ID. Parser sets parsed message ID, builder sets message ID of built coap message */
  uint16_t                uri_path_len;         /**< 0-255 bytes. Repeatable. */
  uint16_t                payload_len;          /**< Must be set to zero if not used */

  uint8_t                *token_ptr;            /**< Must be set to NULL if not used */
  uint8_t                *uri_path_ptr;         /**< Must be set to NULL if not used. E.g: temp1/temp2 */
  uint8_t                *payload_ptr;          /**< Must be set to NULL if not used */

  /* Here are not so often used Options */
  sn_coap_options_list_s *options_list_ptr;     /**< Must be set to NULL if not used */
} sn_coap_hdr_s;
. . .
typedef sn_coap_hdr_s sl_wisun_coap_packet_t;
```

The above shows that there is a possible payload, corresponding to `payload_ptr` with a size of `payload_len`. The code can therefore check the payload to act differently. This payload corresponds to the `-e <payload>` the user can add to each CoAP request.

The `settings` resource is interesting to look at, since it can be used to **retrieve** the `auto_send_sec` value and also to **change** it.

###### CoAP Reply Function

To more easily reply to a CoAP request with a text string as the result, the `app_coap_reply()` function is added to `app_coap.c`:

```C
sl_wisun_coap_packet_t * app_coap_reply(char *response_string,
                  const sl_wisun_coap_packet_t *const req_packet) {

  sl_wisun_coap_packet_t* resp_packet = NULL;
  // Prepare CoAP response packet with default response string
  resp_packet = sl_wisun_coap_build_response(req_packet, COAP_MSG_CODE_RESPONSE_BAD_REQUEST);
  if (resp_packet == NULL) {
    return NULL;
  }

  resp_packet->msg_code       = COAP_MSG_CODE_RESPONSE_CONTENT;
  resp_packet->content_format = COAP_CT_TEXT_PLAIN;
  resp_packet->payload_ptr    = (uint8_t *)response_string;
  resp_packet->payload_len    = (uint16_t)sl_strnlen(response_string, COAP_MAX_RESPONSE_LEN);

  return resp_packet;
}
```

The CoAP component provides the `sl_wisun_coap_build_response()` function, which can be used to prepare most of the reply. Then the payload is set to the `response_string` input string.

###### CoAP Resource Handler

The CoAP Resource Handler is the only part of the CoAP component you need to interact with. It will then perform the following tasks whenever a CoAP request is received:

- Check that there is a known resource `uri_path` matching the request's `uri_path_ptr`.  
  - If yes, call the resource's `auto_response` function.  
  - If the `auto_response` function is coded to send a reply, the reply will be sent to the IPv6 address at the origin of the request.
- If the request is `".well-known/core"`, return a JSON array with all resource set as `discoverable`

###### `settings/auto_send` Example

The `settings/auto_send` resource is interesting to look at, since it can be used to **retrieve** the `auto_send_sec` value and also to **change** it.

###### `settings/auto_send` CoAP Callback Function (heading level 7)

```C
sl_wisun_coap_packet_t * coap_callback_auto_send (
      const  sl_wisun_coap_packet_t *const req_packet)  {
  int sec = 0;
  int res;
  if (req_packet->payload_len) {
    res = sscanf((char *)req_packet->payload_ptr, "%d", &sec);
    if (res) { auto_send_sec = sec; }
  }
  snprintf(coap_response, COAP_MAX_RESPONSE_LEN, "auto_send_sec: %d", auto_send_sec);
return app_coap_reply(coap_response, req_packet); }
```

The one-before-last line of the function is formatting the text string corresponding to the reply's payload (`req_packet->payload_ptr`), then `app_coap_reply()` is called to send the reply to the sender. The reply is in the form `auto_send_sec: 60`.

Before this, the request payload has been checked, and if it contains a decimal value, this is used as the new `auto_send_sec` if it exists, so the reply will always contain the current value.

###### `settings/auto_send` CoAP Resource Registration (heading level 8)

To have the CoAP component handle this new resource, a part of the `app_coap_resources_init()` function provides a corresponding `sl_wisun_coap_rhnd_resource_t` to the CoAP Resource Handler:

```C
uint8_t app_coap_resources_init() {
  sl_wisun_coap_rhnd_resource_t coap_resource = { 0 };
  uint8_t count = 0;

  // Add CoAP resources (one per item)
. . .
  coap_resource.data.uri_path = "/settings/auto_send";
  coap_resource.data.resource_type = "sec";
  coap_resource.data.interface = "settings";
  coap_resource.auto_response = coap_callback_auto_send;
  coap_resource.discoverable = true;
  assert(sl_wisun_coap_rhnd_resource_add(&coap_resource) == SL_STATUS_OK);
    count++;
. . .
  printf("  %d/%d CoAP resources added to CoAP Resource handler\n", count, SL_WISUN_COAP_RESOURCE_HND_MAX_RESOURCES);
  return count;
}
```

_A check has been added at the end of `app_coap_resources_init()` on the number of CoAP resources registered with the CoAP Resource Handler. This allows you to check if `SL_WISUN_COAP_RESOURCE_HND_MAX_RESOURCES` is correctly set, and if it needs to be increased._

###### CoAP Resources Initialization by the Application (heading level 7)

The `app_coap_resources_init()` function is called once at startup from `app-init.c/app_init()`, adding all CoAP resources to the CoAP Resource Handler:

```C
void app_init(void)
{
  app_coap_resources_init();

  /* Creating App main thread */
. . .
```

With the above, from the Border Router console, you can:

- Discover the available CoAP resources on the device, using

`coap-client -m get -N -B 3 coap://[<device_IPv6>]:5683/.well-known/core`

- Retrieve a CoAP resource using

`coap-client -m get -N -B 3 coap://[<device_IPv6>]:5683/<resource>`

Details about the possibilities are provided in the `app_coap.c/print_coap_help()` function once connected, because at this moment the device has obtained an IPv6 address:

```C
void  print_coap_help (char* device_global_ipv6_string, char* border_router_ipv6_string) {
  printf("\n");
  printf("To start a CoAP server on the linux Border Router:\n");
  printf("  coap-server -A %s -p %d -d 10\n", border_router_ipv6_string, 5685);
  printf("CoAP discovery:\n");
  printf("  coap-client -m get -N -B 3 coap://[%s]:5683/.well-known/core\n", device_global_ipv6_string);
  printf("CoAP GET requests:\n");
  printf("  coap-client -m get -N -B 3 coap://[%s]:5683/<resource>, for the following resources:\n", device_global_ipv6_string);
  sl_wisun_coap_rhnd_print_resources();
  printf("  '/settings/auto_send'         returns the current notification duration in seconds\n");
  printf("  '/settings/auto_send' -e <d>' changes the notification duration to d seconds\n");
  printf("  '/status/neighbor'            returns the neighbor_count\n");
  printf("  '/status/neighbor -e <n>'     returns the neighbor information for neighbor at index n\n");
  printf("  '/statistics/stack/<group> -e reset' clears the Stack statistics for the selected group\n");
  printf("  '/statistics/app/all       -e reset' clears all statistics\n");
  printf("\n");
}
```

###### `status/all` Example

The `status/all` resource is used to retrieve the `running`, `connected`, and `parent` information.

###### `status/all` CoAP Callback Function (heading level 7)

```C
sl_wisun_coap_packet_t * coap_callback_all_statuses (
      const  sl_wisun_coap_packet_t *const req_packet)  {
  #define JSON_ALL_STATUSES_FORMAT_STR      \
    "{\n"                                 \
    "  \"running\": \"%s\",\n"            \
    "  \"connected\": \"%s\"\n"           \
    "  \"parent\": \"%s\",\n"             \
    "}\n"

  char running_str[40];
  char connected_str[40];

  snprintf(running_str  , 40, dhms(now_sec()) );
  snprintf(connected_str, 40, dhms(now_sec() - connection_time_sec) );

  snprintf(coap_response, COAP_MAX_RESPONSE_LEN, JSON_ALL_STATUSES_FORMAT_STR,
            running_str,
            connected_str,
            parent_tag
  );
  return app_coap_reply(coap_response, req_packet);
}
```

###### `status/all` CoAP Resource Registration (heading level 7)

To have the CoAP component handle this new resource, a part of the `app_coap_resources_init()` function provides a corresponding `sl_wisun_coap_rhnd_resource_t` to the CoAP Resource Handler:

```C
uint8_t app_coap_resources_init() {
  sl_wisun_coap_rhnd_resource_t coap_resource = { 0 };
  uint8_t count = 0;

  // Add CoAP resources (one per item)
. . .
  coap_resource.data.uri_path = "/status/all";
  coap_resource.data.resource_type = "json";
  coap_resource.data.interface = "node";
  coap_resource.auto_response = coap_callback_all_statuses;
  coap_resource.discoverable = true;
  assert(sl_wisun_coap_rhnd_resource_add(&coap_resource) == SL_STATUS_OK);
  count++;
. . .
  printf("  %d/%d CoAP resources added to CoAP Resource handler\n", count, SL_WISUN_COAP_RESOURCE_HND_MAX_RESOURCES);
  return count;
}
```

As visible above, there are very few differences between the block of code used to register `"/settings/auto_send"` or `"/status/all"`, so adding more is easy.

Before looking at adding CoAP to the Border Router, below is an example of the output you can get on the Border Router when monitoring multiple devices:

###### `status/all` in use (heading level 7)

To send a CoAP request to all the connected nodes in unicast this [coap_all script](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/linux_border_router_wsbrd/coap_all) can be used:

```bash
git clone https://github.com/SiliconLabs/wisun_applications.git
cd wisun_applications/wisun_node_monitoring/linux_border_router_wsbrd
```

This folder [Linux_border_router_wsbrd](https://github.com/SiliconLabs/wisun_applications/tree/main/wisun_node_monitoring/linux_border_router_wsbrd) contains useful script for the **Node Monitoring** application. Some script have to be made executable, which can be achieved with the following commands:

```bash
chmod a+x coap_all
chmod a+x ipv6s
chmod a+x *.sh
```

```bash
coap_all /status/all
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51c]:5683/status/all : { "running": " 8-05:37:43", "connected": " 0:01:49:55" "parent": "2527", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51d]:5683/status/all : { "running": " 0-23:00:55", "connected": " 0:22:59:53" "parent": "a901", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a527]:5683/status/all : { "running": " 8-05:37:35", "connected": " 0:02:05:35" "parent": "333a", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a8ff]:5683/status/all : { "running": " 8-05:37:38", "connected": " 0:21:05:04" "parent": "333a", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/status/all : { "running": " 1-02:44:11", "connected": " 1:02:43:16" "parent": "333a", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2191]:5683/status/all : { "running": " 1-05:50:51", "connected": " 1:05:49:47" "parent": "333a", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2527]:5683/status/all : { "running": " 1-05:50:50", "connected": " 1:05:49:37" "parent": "a8ff", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2853]:5683/status/all : { "running": " 1-05:50:53", "connected": " 0:05:10:54" "parent": "333a", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8486]:5683/status/all : { "running": " 1-05:43:48", "connected": " 0:00:47:53" "parent": "333a", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8493]:5683/status/all : { "running": " 1-02:45:43", "connected": " 0:10:37:17" "parent": "2853", }
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8503]:5683/status/all : { "running": " 1-02:43:29", "connected": " 0:07:51:09" "parent": "333a", }
```

> NOTE: Remember that timestamping is in `dd-hh:mm:ss` format, meaning that in the example above `" 8-05:37:43` means more than 8 days of connection time, corresponding to a group of 3 devices, while others have been started only a day ago, with about 3 hours between them. This shows how interesting it is to use this time stamping format.

##### Retrieve UDP Notifications on the Border Router

Note that **this part is executed on the Linux Border Router**.

If the application flashed on the Wi-SUN devices is sending notification messages to the Border Router, a convenient way to retrieve them from the Border Router is via a python script such as [`udp_notification_receiver.py`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/Border_Router_scripts/udp_notification_receiver.py).

###### Setup IPV6 addresses

The **Node Monitoring** application running on the SoC is aware of the Border Router's address. However, it is designed to simulate a real-world scenario, where it can send status messages outside the Wi-SUN mesh network.

So by default, the UDP destination address is set to:

```C
#define UDP_NOTIFICATION_DEST  "fd00:6172:6d00::1" // fixed IPv6 string
```

To receive UDP message on linux border router, `fd00:6172:6d00::1` must be added:

- Get and run Node Monitoring border router script `wsbrd_add.sh`

```bash
git clone https://github.com/SiliconLabs/wisun_applications.git
cd wisun_applications/wisun_node_monitoring/linux_border_router_wsbrd
```

This folder contains useful script for **Node Monitoring** application, some script shall be made executable:

```bash
chmod a+x coap_all
chmod a+x ipv6s
chmod a+x *.sh
```

To set BR linux address accordingly to **Node Monitoring** default UDP destination address:

```bash
wsbrd_add.sh
```

- Or open a bash and run below command:

```bash
sudo ip address add fd00:6172:6d00::1/64 dev eth0
```

###### Call the Script

```bash
 python udp_notification_receiver.py 1237 " "
```

- The first parameter is the UDP port to listen to, `rcv_port` in the script.
- The second parameter is an optional `newline` parameter used to replace the newline characters from the incoming message. It's useful to display one message per line, since otherwise they would be displayed in json format on multiple lines. You can use a different character as a separator.
- The script is also suppressing all spaces from the incoming message, for a more compact display.

###### Script Output

```c
python udp_notification_receiver.py 1237 " "
Receiving on ::/1237...
[2023-08-18 14:07:28] Rx 1237:   { "device":"a901", "chip":"xG25", "parent":"333a", "running":"0:22:47:30", "connected":"0:22:46:35", "disconnected":"no", "connections":"1", "availability":"100.00", "connected_total":"0:22:46:35", "disconnected_total":"0:00:00:00" }
[2023-08-18 14:07:44] Rx 1237:   { "device":"8486", "chip":"xG25", "parent":"333a", "running":"1:01:47:22", "connected":"1:01:46:40", "disconnected":"no", "connections":"1", "availability":"100.00", "connected_total":"1:01:46:40", "disconnected_total":"0:00:00:00" }
[2023-08-18 14:07:46] Rx 1237:   { "device":"a51d", "chip":"xG25", "parent":"a901", "running":"0:19:04:32", "connected":"0:19:03:30", "disconnected":"no", "connections":"1", "availability":"100.00", "connected_total":"0:19:03:30", "disconnected_total":"0:00:00:00" }
[2023-08-18 14:07:58] Rx 1237:   { "device":"a51c", "chip":"xG25", "parent":"333a", "running":"8:01:41:33", "connected":"1:20:54:38", "disconnected":"no", "connections":"6", "availability":"97.34", "connected_total":"7:20:32:26", "disconnected_total":"0:05:08:36" }
[2023-08-18 14:08:03] Rx 1237:   { "device":"2191", "chip":"xG25", "parent":"333a", "running":"1:01:54:45", "connected":"1:01:53:41", "disconnected":"no", "connections":"1", "availability":"100.00", "connected_total":"1:01:53:41", "disconnected_total":"0:00:00:00" }
[2023-08-18 14:08:04] Rx 1237:   { "device":"2853", "chip":"xG25", "parent":"333a", "running":"1:01:54:47", "connected":"0:01:14:48", "disconnected":"no", "connections":"2", "availability":"99.88", "connected_total":"1:01:51:49", "disconnected_total":"0:00:01:52" }
```

###### Code Walkthrough

The script is as follows:

```Python
##### Used to receive UDP notifications strings
##### Call with
##### python udp_notification_receiver.py 1237 " "

import socket
import sys
import datetime

HOST_IP = "::" # Host own address (tun0 IPv6 address)

rcv_port = int(sys.argv[1])
newline = " "

if (len(sys.argv) > 2):
  newline = sys.argv[2]
  space = ""

PORT = rcv_port # Port used by the peer

sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.bind((HOST_IP, PORT))

print(f"Receiving on {HOST_IP}/{PORT}...")

while True:
  data, addr = sock.recvfrom(2048) # buffer size is 2048 bytes
  now = datetime.datetime.now()
  now_str = str(now.strftime('%Y-%m-%d %H:%M:%S'))

  try:
    message_string = data.decode("utf-8").replace(" ", space).replace("\n", newline)
  except Exception as e:
    print(f"Exception {e} (from {addr})")

  print (f"[{now_str}] Rx {PORT}: {newline}", message_string)

```

It goes through:

- Import of the required python packages
- Retrieving the `rcv_port` value from the first argument
- Retrieving the `newline` replacement, if any, from the second argument
- Opening a socket to listen to the `rcv_port` on all IPv6 addresses
- Infinite loop with:  
  - Reception from the UDP socket  
  - Formatting the current date and time  
  - Removing all spaces from the received message  
  - Replacing all `\n` from the received message by `newline`  
  - Printing the modified string

##### Retrieve the Device Information from the Border Router using CoAP

###### Install `libcoap2-bin` on the Border Router

- The application requires libcoap binaries to be installed on the Border Router, so install the `-bin` package.
- If using CoAP notifications instead of UDP notifications, `coap-server` will be used, and requires the `-d` option to define the max number of resources the coap-server can listen to. This is only available in `libcoap` as from `libcoap2`, so install `libcoap` as follows:

`sudo apt-get install libcoap2-bin`

> On more recent linux kernels, use libcoap3 and the commands with the `-notls` suffix to keep it simple (without TLS authentication), considering that your Wi-SUN network already supports encryption.

Check the installed binaries using:

`ls -al /usr/bin/coap*`

```bash
-rwxr-xr-x 1 root root 26236 Nov  9  2019 /usr/bin/coap-client
-rwxr-xr-x 1 root root 26236 Nov  9  2019 /usr/bin/coap-client-gnutls
-rwxr-xr-x 1 root root 26236 Nov  9  2019 /usr/bin/coap-client-openssl
-rwxr-xr-x 1 root root 18016 Nov  9  2019 /usr/bin/coap-rd
-rwxr-xr-x 1 root root 18016 Nov  9  2019 /usr/bin/coap-rd-gnutls
-rwxr-xr-x 1 root root 18016 Nov  9  2019 /usr/bin/coap-rd-openssl
-rwxr-xr-x 1 root root 22124 Nov  9  2019 /usr/bin/coap-server
-rwxr-xr-x 1 root root 22124 Nov  9  2019 /usr/bin/coap-server-gnutls
-rwxr-xr-x 1 root root 22124 Nov  9  2019 /usr/bin/coap-server-openssl
```

The example uses `coap-client` and optionally `coap-server` (if using COAP notifications).

###### List Connected Devices' IPv6 Addresses

`wsbrd_cli status` returns the connected devices' MAC addresses, while CoAP requires the IPv6 addresses.

The dbus resources related to the Wi-SUN Border Router are available to dbus as `com.silabs.Wisun.BorderRouter`:

```bash
busctl introspect  SERVICE                        OBJECT                          [INTERFACE]
busctl introspect  com.silabs.Wisun.BorderRouter  /com/silabs/Wisun/BorderRouter  com.silabs.Wisun.BorderRouter
```

```c
NAME                                TYPE      SIGNATURE  RESULT/VALUE                             FLAGS
com.silabs.Wisun.BorderRouter       interface -          -                                        -
.IeCustomClear                      method    -          -                                        -
.IeCustomInsert                     method    yyayay     -                                        -
.InstallGtk                         method    ay         -                                        -
.InstallLgtk                        method    ay         -                                        -
.JoinMulticastGroup                 method    ay         -                                        -
.LeaveMulticastGroup                method    ay         -                                        -
.RevokeGroupKeys                    method    ayay       -                                        -
.RevokePairwiseKeys                 method    ay         -                                        -
.SetModeSwitch                      method    ayi        -                                        -
.SetSlotAlgorithm                   method    y          -                                        -
.Gaks                               property  aay        4 16 54 182 30 129 250 196 136 180 3 24… emits-change
.Gtks                               property  aay        4 16 0 16 32 48 64 80 96 112 128 144 16… emits-change
.HwAddress                          property  ay         8 144 253 159 255 254 0 51 58            -
.Lgaks                              property  aay        3 16 159 29 31 16 211 121 13 120 93 104… emits-change
.Lgtks                              property  aay        3 16 205 198 155 180 84 17 14 130 116 6… emits-change
.Nodes                              property  a(aya{sv}) 3 8 144 253 159 255 254 0 51 58 3 "is_b… emits-invalidation"
.WisunChanPlanId                    property  u          3                                        const
.WisunClass                         property  u          0                                        const
.WisunDomain                        property  s          "BZ"                                     const
.WisunFanVersion                    property  y          2                                        const
.WisunMode                          property  u          0                                        const
.WisunNetworkName                   property  s          "Linux_BZ_3_8"                           const
.WisunPanId                         property  q          59418                                    const
.WisunPhyModeId                     property  u          8                                        const
.WisunSize                          property  s          "CERT"                                   const
org.freedesktop.DBus.Introspectable interface -          -                                        -
.Introspect                         method    -          s                                        -
org.freedesktop.DBus.Peer           interface -          -                                        -
.GetMachineId                       method    -          s                                        -
.Ping                               method    -          -                                        -
org.freedesktop.DBus.Properties     interface -          -                                        -
.Get                                method    ss         v                                        -
.GetAll                             method    s          a{sv}                                    -
.Set                                method    ssv        -                                        -
.PropertiesChanged                  signal    sa{sv}as   -                                        -
```

What you are looking for is the `Nodes` property, which you can 'get' using:

`busctl introspect  com.silabs.Wisun.BorderRouter  /com/silabs/Wisun/BorderRouter  com.silabs.Wisun.BorderRouter  Nodes`

```bash
a(aya{sv}) 3 8 144 253 159 255 254 0 51 58 3 "is_border_router" b true "node_role" y 0 "ipv6" aay 2 16 254 128 0 0 0 0 0 0 146 253 159 255 254 0 51 58 16 253 0 97 114 109 0 0 0 146 253 159 255 254 0 51 58 8 96 164 35 255 254 55 168 255 8 "is_authenticated" b true "node_role" y 1 "parent" ay 8 144 253 159 255 254 0 51 58 "is_neighbor" b true "rssi" i -46 "rsl" i -41 "rsl_adv" i -37 "ipv6" aay 2 16 254 128 0 0 0 0 0 0 96 164 35 255 254 55 168 255 16 253 0 97 114 109 0 0 0 98 164 35 255 254 55 168 255 8 96 164 35 255 254 55 169 1 4 "is_authenticated" b true "node_role" y 1 "parent" ay 8 96 164 35 255 254 55 165 29 "ipv6" aay 2 16 254 128 0 0 0 0 0 0 96 164 35 255 254 55 169 1 16 253 0 97 114 109 0 0 0 98 164 35 255 254 55 169 1
```

The underlying structure is detailed in [wsbrd-br-linux/DBUS.md](https://github.com/SiliconLabs/wisun-br-linux/blob/4cbabbab288354cdbeba12c831e20d518c698f34/DBUS.md?plain=1#L91):

```c
- `ay`: EUI64
- `a{sv}`: list of properties identified by a string, as described in the
  following table. Not all properties are guaranteed to be present per node
  (ex: a node without parent has no `parent` field)

| Key              |Signature| Comment                                                                  |
|------------------|---------|--------------------------------------------------------------------------|
|`is_border_router`|`b`      |Deprecated. Use `node_role` instead.                                      |
|`node_role`       |`y`      |Semantics from Wi-SUN (`0`: BR, `1`: FFN-FAN1.1, `2`: LFN, none: FFN-FAN1.0)|
|`ipv6`            |`aay`    |Array of IPv6 addresses (usually link-local and GUA)                      |
|`parent`          |`ay`     |EUI-64 of the preferred parent                                            |
|`is_authenticated`|`b`      |                                                                          |
|`is_neighbor`     |`b`      |Only nodes that use direct unicast traffic to the border router are listed|
|`rssi`            |`i`      |Received Signal Strength Indication (RSSI) of the last packet received in dBm (neighbor only)|
|`rsl`             |`i`      |Exponentially Weighted Moving Average (EWMA) of the Received Signal Level (RSL) in dBm (neighbor only)|
|`rsl_adv`         |`i`      |EWMA of the RSL in dBm advertised by the node in RSL-IE (neighbor only)   |
```

Although it's possible, using the above to retrieve IPv6 addresses is quite complex, and is better done using the `pydbus` Python package and a short script.

###### Install `pydbus` Python Package (heading level 7)

`pip3 install pydbus`

###### `get_nodes_ipv6_address.py` Python Script (heading level 7)

```python
from pydbus import SystemBus
import re

"""
get_nodes_ipv6_address.py
Prints the IPv6 address of each node connected to the running WSBRD instance.

USAGE:
    python3 get_nodes_ipv6_address.py

NOTES:
    - This script can only be used with the WSBRD + RCP setup and must be executed on the host.
"""

bus = SystemBus()
proxy = bus.get("com.silabs.Wisun.BorderRouter", "/com/silabs/Wisun/BorderRouter")
nodes = proxy.Nodes

def sliceIPv6(source):
    return [source[i : i + 4] for i in range(0, len(source), 4)]

for node in nodes:
    if len(node[1]["ipv6"]) != 2:
        continue
    if "parent" not in node[1] and (
        "node_role" not in node[1] or node[1]["node_role"] != 2
    ):
        continue

    ipv6 = bytes(node[1]["ipv6"][1]).hex()
    ipv6 = ":".join(sliceIPv6(ipv6))
    ipv6 = re.sub("0000:", ":", ipv6)
    ipv6 = re.sub(":{2,}", "::", ipv6)
    print(ipv6)
```

For a more convenient use from bash, this Python script can be called from the [`ipv6s`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/Border_Router_scripts/ipv6s) bash script.

```bash
#!/bin/bash
##### usage: listing IPv6 addresses of all nodes currently connected
##### ./ipv6s

ipv6s=$(python /home/pi/get_nodes_ipv6_address.py)
for ipv6 in $ipv6s
do
    echo $ipv6
done
```

This script needs to be set as an executable using `chmod a+x ipv6s`.

###### Use `ipv6s` (heading level 7)

`./ipv6s`

```bash
fd00:6172:6d00::62a4:23ff:fe37:a8ff
fd00:6172:6d00::62a4:23ff:fe37:a901
```

> NOTE: The IPv6 addresses obtained from wsbrd via DBus reflect the vision of the network from wsbrd.

It takes a while for a device lifetime to expire, so even after a device is switched off, it may still appear as part of the network from wsbrd's perspective. If a device is off for a while and then turned on in a relatively short term, it may even reconnect before wsbrd considers it as disconnected. With the initial connection message in the demonstration application, you will know this because:

- You will receive a notification when the device will reconnect.
- You can ask via CoAP for the device status and statistics, which will tell you when the reconnection occurred.

###### Typical CoAP 'get' Request

`coap-client` uses port `5683` by default. This is the default CoAP UDP port, and is set in the application code.

An abstract of `coap-client --help` with the options used in the example is:

```bash
coap-client v4.2.1 -- a small CoAP implementation
Copyright (C) 2010-2019 Olaf Bergmann <bergmann@tzi.org> and others

TLS Library: None

Usage: coap-client [-e text] [-m method] [-N]  [-B seconds] URI

        URI can be an absolute URI or a URI prefixed with scheme and host

General Options
        -e text         Include text as payload (use percent-encoding for non-ASCII characters)
        -m method       Request method (get|put|post|delete|fetch|patch|ipatch), default is 'get'
        -N              Send NON-confirmable message
        -B seconds      Break operation after waiting given seconds (default is 90)
```

The typical `coap-client` request for the example application takes the following form:

`coap-client -m get -N -B 3 coap://[<IPV6>]:5683<COAP_URI> [-e <PAYLOAD>]`

where `COAP_URI` is the CoAP resource, starting with `/`

###### Discover CoAP Resources

When a device supports CoAP, it generally supports discovery using the `/.well-known/core` URI:

`coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/.well-known/core`

```json
</settings>;ct=40,</statistics>;ct=40,</status>;ct=40,</info>;ct=40,</settings/auto_send>;rt="sec";if="settings",</statistics/stack/regulation>;rt="json";if="regulation",</statistics/stack/network>;rt="json";if="network",</statistics/stack/wisun>;rt="json";if="wisun",</statistics/stack/fhss>;rt="json";if="fhss",</statistics/stack/mac>;rt="json";if="mac",</statistics/stack/phy>;rt="json";if="phy",</history>;rt="text";if="node",</statistics/app/availability>;rt="ratio";if="node",</statistics/app/connected_total>;rt="dhms";if="node",</statistics/app/connections>;rt="int";if="node",</statistics/app/disconnected_total>;rt="dhms";if="node",</statistics/app/join_states_sec>;rt="array";if="node",</statistics/app/all>;rt="json";if="node",</status/connected>;rt="dhms";if="node",</status/neighbor>;rt="json";if="node",</status/parent>;rt="tag";if="node",</status/running>;rt="dhms";if="node",</status/all>;rt="json";if="node",</info/version>;rt="text";if="node",</info/application>;rt="text";if="node",</info/chip>;rt="tag";if="node",</info/device>;rt="tag";if="node",</info/all>;rt="json";if="node"
```

The above shows four groups of resources (splitting on `,`, with `ct=40`):

```json
</settings>;ct=40,
</statistics>;ct=40,
</status>;ct=40,
</info>;ct=40,
```

And the resources you can access for each group (splitting the remaining text on `,`):

```json
</settings/auto_send>;rt="sec";if="settings",
</statistics/stack/regulation>;rt="json";if="regulation",
</statistics/stack/network>;rt="json";if="network",
</statistics/stack/wisun>;rt="json";if="wisun",
</statistics/stack/fhss>;rt="json";if="fhss",
</statistics/stack/mac>;rt="json";if="mac",
</statistics/stack/phy>;rt="json";if="phy",
</history>;rt="text";if="node",
</statistics/app/availability>;rt="ratio";if="node",
</statistics/app/connected_total>;rt="dhms";if="node",
</statistics/app/connections>;rt="int";if="node",
</statistics/app/disconnected_total>;rt="dhms";if="node",
</statistics/app/join_states_sec>;rt="array";if="node",
</statistics/app/all>;rt="json";if="node",
</status/connected>;rt="dhms";if="node",
</status/neighbor>;rt="json";if="node",
</status/parent>;rt="tag";if="node",
</status/running>;rt="dhms";if="node",
</status/all>;rt="json";if="node",
</info/version>;rt="text";if="node",
</info/application>;rt="text";if="node",
</info/chip>;rt="tag";if="node",
</info/device>;rt="tag";if="node",
</info/all>;rt="json";if="node"
```

These match what the application provides, since it's filled by the CoAP Resource Manager based on registered CoAP resources.

###### Send a CoAP Request to All Connected Devices (heading level 7)

The [`coap_all`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/Border_Router_scripts/coap_all) bash script can be used to send the same request to all devices. It uses [`get_nodes_ipv6_addresses.py`](https://github.com/SiliconLabs/wisun_applications/blob/main/wisun_node_monitoring/Border_Router_scripts/get_nodes_ipv6_address.py) to get the IPv6 addresses and traces the CoAP command, such that you can easily copy/paste it for a specific device if needed.

```bash
./coap_all /settings/auto_send
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51c]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51d]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a527]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a8ff]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2191]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2527]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2853]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8486]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8493]:5683/settings/auto_send : auto_send_sec: 60
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8503]:5683/settings/auto_send : auto_send_sec: 60
```

Based on the `coap_callback_auto_send()` implementation in the Wi-SUN device, `coap_all` can also be used to change the `auto_send` period for all nodes in a row:

```bash
./coap_all /settings/auto_send -e 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51c]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a51d]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a527]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a8ff]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::62a4:23ff:fe37:a901]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2191]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2527]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b635:22ff:fe98:2853]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8486]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8493]:5683/settings/auto_send -e 120 : auto_send_sec: 120
  coap-client -m get -N -B 3 coap://[fd00:6172:6d00::b6e3:f9ff:fec5:8503]:5683/settings/auto_send -e 120 : auto_send_sec: 120
```

## Wi-SUN PHY

### Wi-SUN PHY

The content in this section is related to Wi-SUN PHY and system aspects provided by the Radio Configurator and RAIL. This is particularly of interest for customers not using the Silicon Labs stack. It explains how to configure the Wi-SUN PHY using the Radio Configurator provided with Simplicity Studio and how to use this using RAILtest commands.

- [**Wi-SUN on EFR32FG25: Getting Started with RAILtest**](/wisun/2.12.0/wisun-phy-quick-start): Describes how to program EFR32FG25 devices to enable Wi-SUN OFDM modulation and how to enable Wi-SUN FSK modulation.
- [**Wi-SUN Mode Switch on EFR32FG25 with RAILtest**](/wisun/2.12.0/wisun-phy-mode-switch-with-railtest): Explains how to program EFR32FG25 devices to enable the Wi-SUN Mode Switch feature.
- [**Wi-SUN Concurrent Detection on EFR32FG25 with RAILtest**](/wisun/2.12.0/wisun-concurrent-mode-with-railtest): Explains how to program EFR32FG25 devices to enable the Wi-SUN concurrent detection feature.

### Wi-SUN Mode Switch

#### Introduction

##### Overview

Mode Switch allows Wi-SUN nodes to temporarily use a **higher data rate PHY** (FSK or OFDM) for unicast data while keeping the network stable.

- The network always operates with a **Base PHY (FSK)** for control and broadcast
- Nodes can switch to a **faster PHY** only for **unicast data**
- Switching is **per neighbor** and is only possible if both nodes (or a node and a border router) support the same PHY

In short:

> Base PHY equals reliability<br />Mode Switch PHY equals performance boost (when possible)

##### How Mode Switch Works

1. Nodes advertise supported PHYs using **POM-IE**
2. Each node determines compatible PHYs with neighbors
3. A PHY is selected (PhyModeID) by the application
4. Mode switch is triggered at PHY level (PHR field)
5. Data is exchanged using the new PHY
6. If failures occur → fallback to Base PHY

##### Key Rules

- Mode Switch only applies to **unicast traffic**
- Broadcast always uses **Base PHY**
- Requires **mutual PHY support**

---

#### Supported PHYs for Mode Switch

Wi-SUN supports PHY Mode Switch, allowing nodes to dynamically switch from a configured **base PHY operating mode** to other PHY operating modes supported by both peers.

The **base PHY**:

- is the **locally configured** PHY on each device used to join the Network
- is **not included** in the set of mode-switch candidate PHYs

The **mode switch candidate PHYs**:

- are  the PHYs advertised using the **POM-IE**
- may include both **FSK** and **OFDM PHYs** depending on regulatory domain and device capabilities

Mode switching can occur between FSK PHYs, or from an FSK base PHY to OFDM PHYs where supported.
In practice, deployments typically select a robust low-rate FSK PHY (e.g. 50 kbps) as the base PHY to maximize coverage, while higher-rate PHYs are used opportunistically via mode switching.

##### Regulatory Domain NA (North America)

###### Example base PHY (informative)

A commonly used base PHY is:

- PhyModeID 0x02 — FSK — 50 kbps

> Note: Other FSK PHYs defined for NA may also be used as base PHY depending on configuration.

###### Mode switch candidate PHYs (NA)

Nodes may switch to any mutually supported PHY among the following.

###### FSK PHYs (heading level 7)

- PhyModeID 0x03 — mode #2a — 100 kbps
- PhyModeID 0x05 — mode #3  — 150 kbps
- PhyModeID 0x06 — mode #4a — 200 kbps
- PhyModeID 0x08 — mode #5  — 300 kbps

###### OFDM PHYs (heading level 7)

- PhyModeID 0x22 — Option 1, MCS2 — 400 kbps
- PhyModeID 0x23 — Option 1, MCS3 — 800 kbps
- PhyModeID 0x24 — Option 1, MCS4 — 1200 kbps
- PhyModeID 0x25 — Option 1, MCS5 — 1600 kbps
- PhyModeID 0x26 — Option 1, MCS6 — 2400 kbps
- PhyModeID 0x33 — Option 2, MCS3 — 400 kbps
- PhyModeID 0x34 — Option 2, MCS4 — 600 kbps
- PhyModeID 0x35 — Option 2, MCS5 — 800 kbps
- PhyModeID 0x36 — Option 2, MCS6 — 1200 kbps
- PhyModeID 0x44 — Option 3, MCS4 — 300 kbps
- PhyModeID 0x45 — Option 3, MCS5 — 400 kbps
- PhyModeID 0x46 — Option 3, MCS6 — 600 kbps
- PhyModeID 0x54 — Option 4, MCS4 — 150 kbps
- PhyModeID 0x55 — Option 4, MCS5 — 200 kbps
- PhyModeID 0x56 — Option 4, MCS6 — 300 kbps

##### Regulatory Domain EU (Europe)

###### Example base PHY (informative)

A commonly used base PHY is PhyModeID 0x01 — FSK — 50 kbps

> Note: Any supported FSK PHY for the EU domain may be configured as the base PHY.

###### Mode switch candidate PHYs (EU)

###### FSK PHYs (heading level 7)

- PhyModeID 0x03 — mode #2a — 100 kbps
- PhyModeID 0x05 — mode #3  — 150 kbps

###### OFDM PHYs (heading level 7)

- PhyModeID 0x54 — Option 4, MCS4 — 150 kbps
- PhyModeID 0x55 — Option 4, MCS5 — 200 kbps
- PhyModeID 0x56 — Option 4, MCS6 — 300 kbps

##### Mode Switch PHYs in the Radio Configurator

Before configuring mode switch PHYs in the application with the mode switch APIs, add all PHYs that may be used for mode switching to the **Radio Configurator**.

After adding the PHYs, either directly in the **Radio Configurator** or through the **Wi-SUN Configurator**, verify that all PHYs the application may switch between are in the same Protocol Group, as shown in the following screenshot.

This is important because mode switch can only occur between PHYs that belong to the same Protocol Group.

In the following radio configuration example:

- It is possible to switch between the PHYs in **WiSUNConf Protocol Configuration 1**
- It is not possible to switch between a PHY in **WiSUNConf Protocol Configuration 1** and another in **WiSUNConf Protocol Configuration 2**

![radio configuration](/wisun-mode-switch/0.1/images/sld1088-radio-conf-protocol-groups.png)

---

#### Fallback Mechanism

Mode Switch is automatically disabled for a neighbor if failures significantly exceed successes (4 times more retries than successes over time).

Result:

- Node falls back to **Base PHY**
- The `SL_WISUN_MSG_MODE_SWITCH_FALLBACK_IND_ID` indication is raised with the MAC address of the neighbor

---

#### Wi-SUN Mode Switch with SoC Sample Apps

To test Mode Switch for OFDM or FSK modulations with the Wi-SUN stack on SoC:

- Use **Wi-SUN - SoC Border Router** project for the border router
- Use **Wi-SUN - SoC CLI** project for the node devices

##### Mode switch Command

The mode switch feature can be used from the `wisun_cli` and `wisun_brcli` applications with the following command:

```bash
wisun mode_switch [Mode Switch mode] [PhyModeID] [MAC Address]
```

##### Command Parameters

###### Mode Switch Mode

**`0` — Mode Switch Disabled**

Disables mode switching for the selected neighbor(s)

```bash
wisun mode_switch 0 PhyModeID [MAC Address]
```

**Parameters:**

- `PhyModeID` is ignored in this case
- `MAC Address` can be:  
  - A single neighbor  
  - `ff:ff:ff:ff:ff:ff:ff:ff` for all neighbors

**`1` — Mode Switch Enabled with Specific PhyModeID**

- Enables mode switching with a specific `PhyModeID` for the selected neighbor(s)

```bash
wisun mode_switch 1 PhyModeID ff:ff:ff:ff:ff:ff:ff:ff

```

- Required before using Mode `2`
- When `MAC Address` is `ff:ff:ff:ff:ff:ff:ff:ff`, the global `PhyModeID` is set for all neighbors

```bash
wisun mode_switch 1 PhyModeID [MAC Address]
```

**Parameters:**

- `PhyModeID`: PhyModeID to switch to
- `MAC Address`: MAC address of the neighbor(s)  
  - A single neighbor  
  - Or `ff:ff:ff:ff:ff:ff:ff:ff` for all neighbors

**`2` — Mode Switch Enabled with Global PhyModeID (Single Neighbor)**

Enables mode switching using the global `PhyModeID` for a single neighbor

```bash
wisun mode_switch 2 PhyModeID [MAC Address]
```

**Parameters:**

- `PhyModeID` is ignored in this case
- `ff:ff:ff:ff:ff:ff:ff:ff` cannot be used
- The global `PhyModeID` must be set beforehand using:  
  ```bash  
  wisun mode_switch 1 PhyModeID ff:ff:ff:ff:ff:ff:ff:ff  
  ```
- `MAC Address`: MAC address of the neighbor

---

#### Examples

Assume 3 neighbors:

1. 01:02:03:04:05:06:07:08
2. 11:12:13:14:15:16:17:18
3. 21:22:23:24:25:26:27:28

- To use PhyModeId 34 (OFDM option 1, MCS2) globally (for all existing neighbors), the command is:

```bash
wisun mode_switch 1 34 ff:ff:ff:ff:ff:ff:ff:ff
```

- To use PhyModeID 52 (OFDM option 2, MCS4) for the first and second neighbors only, two commands are necessary:

```bash
wisun mode_switch 1 52 01:02:03:04:05:06:07:08
wisun mode_switch 1 52 11:12:13:14:15:16:17:18
```

- To use the global PhyModeID (without the need to specify it) for the second neighbor, the command is:

```bash
wisun mode_switch 2 xx 11:12:13:14:15:16:17:18
```

- To disable mode switch for the first neighbor, the command is:

```bash
wisun mode_switch 0 xx 01:02:03:04:05:06:07:08
```

- To disable mode switch for all neighbors using the global PhyModeID, the command is:

```bash
wisun mode_switch 0 xx ff:ff:ff:ff:ff:ff:ff:ff
```

---

#### Mode Switch in wsbrd

Mode switch in wsbrd is configured through the PHY configuration in wsbrd.conf and dynamically controlled via the D-Bus API.

Refer to the official configuration file [wsbrd.conf](https://github.com/SiliconLabs/wisun-br-linux/blob/main/examples/wsbrd.conf), the relevant parameter for mode switch is `phy_operating_modes`.

For dynamic control via D-Bus, refer to [`SetLinkModeSwitch`](https://github.com/SiliconLabs/wisun-br-linux/blob/main/DBUS.md#setlinkmodeswitch-ayuy) official documentation and example.

---

#### Mode Switch implementation using the APIs

##### sl_wisun_set_mode_switch

[`sl_wisun_set_mode_switch()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-mode-switch) is the runtime API used to actually enable and control mode switching. It tells the Wi-SUN stack which PHY to use for high data rate communication and whether the feature is enabled for a given neighbor or for all neighbors. You typically call it **after the device has joined the network**, because mode switch operates on established neighbor relationships. Using the broadcast MAC applies the configuration globally,and using a specific MAC applies it to one neighbor. This API directly maps to the CLI `wisun mode_switch` command and is the only API required to make mode switching happen in practice.

```C
sl_status_t sl_wisun_set_mode_switch (uint8_t mode, uint8_t phy_mode_id, const sl_wisun_mac_address_t * neighbor_address)
```

##### sl_wisun_set_pom_ie

[`sl_wisun_set_pom_ie()`](https://docs.silabs.com/wisun/latest/wisun-stack-api/sl-wisun-api#sl-wisun-set-pom-ie) API controls which PHYs the node advertises to its neighbors through the POM-IE (PHY Operating Mode Information Element). Mode switching can only occur if both peers advertise a common PHY, so this API effectively defines the capability set of the device. By default (if sl_wisun_set_pom_ie() is not called), the advertised list will contain first 15 PhyModeId listed in the radio multi-PHY configuration. You can use this API to reduce or customize the default advertised PHY list. It can be used before or after the connection, if called after the connection the list is applied immediately.

```C
sl_status_t sl_wisun_set_pom_ie (uint8_t phy_mode_id_count, uint8_t phy_mode_ids, uint8_t is_mdr_command_capable)
```

##### Implementation examples

###### Limit advertised PHYs

By default, the stack may advertise a larger PHY list depending on the PhyModeIds listed in the radio multi-PHY configuration. The following example restricts advertisement to only two PHYs: base PHY (2) and OFDM PHY (34).

```c
#include "sl_wisun_api.h"

void configure_pom_ie(void)
{
  uint8_t phy_mode_ids[] = {2, 34};

  sl_wisun_set_pom_ie(sizeof(phy_mode_ids), phy_mode_ids,0);
}
```

###### Enable mode switch after connection

After the following call, the stack will automatically start using the higher data rate PHY for unicast traffic when conditions allow, while keeping multicast and asynchronous traffic on the base PHY.

```C
#include "sl_wisun_api.h"

static const uint8_t broadcast_mac[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

void sl_wisun_on_event(sl_wisun_evt_t *evt)
{
  if (evt->header.id == SL_WISUN_MSG_CONNECTED_IND_ID) {
    // Enable global mode switch to OFDM PHY (ID 34)
    sl_wisun_set_mode_switch(SL_WISUN_MODE_SWITCH_ENABLE,
                             34,
                             broadcast_mac);
  }
}
```

### Getting Started with Wi-SUN PHY

#### Getting Started with Wi-SUN PHY Configuration

This section is a quick start guide to configuring Wi-SUN PHYs and features using the Radio Configurator and RAILtest. It describes:

- How to configure Wi-SUN PHYs using the Radio Configurator
- How to use Wi-SUN FSK or OFDM modulation through RAILtest
- Known issues

_Proprietary is supported on all EFR32FG devices, although OFDM modulation is available only on EFR32FG25 devices. In this document, only the RAILtest example application is used._

#### How to Use Wi-SUN FAN 1.1 on EFR32FG25

This section assumes that you have downloaded Simplicity Studio 5 and the SiSDK and are familiar with creating a project. If not, see the [Getting Started](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-getting-started/) section in the Simplicity Studio v5 User’s Guide.

##### Set Up the Wi-SUN FAN 1.1 Configuration

For the best performance with EFR32FG25, use the following radio board:

- BRD4270B revA06 for North America or Japan regions (902-928 MHz)
- BRD4271A revA06 for Europe region (863-876 MHz)
- BRD4272A revA03 for China (470-510 MHz)

###### Configure the Radio by a Radio Configurator-Generated Config

Create a project based on the RAILTest example. Once a new RAILtest project is created, the Radio Configurator opens automatically. Here you can select the Wi-SUN FAN 1.1 Profile and browse among the available PHY definitions, including both Frequency Shift Keying (FSK) and Orthogonal frequency-division multiplexing (OFDM) PHYs, as defined in Wi-SUN PHY Technical Profile Specification 2V03.

1. For the Protocol Configuration, the Radio Configurator provides all Wi-SUN FAN 1.1 PHYs as part of the Wi-SUN FAN 1.1 profile. Select the Wi-SUN FAN 1.1 profile. For more information about the Radio Configurator see the section in the [Simplicity Studio v5 User’s Guide](https://docs.silabs.com/simplicity-studio-5-users-guide/latest/ss-5-users-guide-developing-with-project-configurator/proprietary-radio-configurator).  
   ![Radio Configurator General Settings](/wisun-phy-quick-start/0.3/images/radio-config-gen-settings.png)
2. Select the Wi-SUN Regulatory Domain (NA, JP, EU, CN, IN, MX, BZ, AU-NZ, KR, PH, MY, HK, SG, TH, VN).  
   ![Radio Configurator Regulatory Domain](/wisun-phy-quick-start/0.3/images/radio-config-regulatory-domain.png)
3. In **Channel Group**, select the **Wi-SUN PHY Operating Mode ID** according to Wi-SUN FAN 1.1 PhyModeID and the Wi-SUN Channel Plan ID.  
   ![Wi-SUN PHY Operating Mode ID](/wisun-phy-quick-start/0.3/images/wisun-phy-operating-mode-id.png)  
   **Note:** For OFDM PHYs, only one PhyModeID is listed using the lowest Modulation and Coding Scheme (MCS) allowed. This allows you to select the OFDM option (1, 2, 3 or 4). The MCS is selected through the RAILtest command set802154PHR as described in [Set Up PHR and TX FIFO](./03-wi-sun-configuration-with-railtest-for-efr32fg25#set-up-phr-and-tx-fifo).
4. Select the **Wi-SUN Channel Plan ID,** which is available with the selected Wi-SUN PHY Operating Mode ID:  
   ![Wi-SUN Channel Plan ID](/wisun-phy-quick-start/0.3/images/wisun-channel-plan-id.png)
5. Save the _radio_settings.radioconf_ file and build the RAILtest project.

###### RF Frequency Planning in Multi-PHY Radio Configuration for Different Regions

RF Frequency Planning (RFFPLL) settings are optimized to provide the best performance for a given band. By default, the Radio Configurator automatically selects these optimized settings when generating the PHYs. These settings are the same for the 9xx MHz band and the 868 MHz band with a 39 MHz crystal oscillator used in BRD4270B and BRD4271A, but they are different for the 470 MHz Band.

The RFFPLL is configured at boot time with the best settings depending on the board reference and its targeted band. Only the PHYs generated with the same RFFPLL configuration can then be loaded. Otherwise, RAIL returns the following error: RAIL_ASSERT_INVALID_RFFPLL_CONFIGURATION = 73.

To select the desired RF Frequency planning setting, turn on **Customized** and select the band, for example BAND_928 as shown.

![Radio Configurator Customized parameters](/wisun-phy-quick-start/0.3/images/radio-config-customized-parameters.png)

**Note**: If all PHYs are in the same band, Silicon Labs does not recommend customizing the RF Frequency Planning settings.

The recommended usage for the RF Frequency Planning enumerate is as described below:

- 'BAND_928': for channels from 928MHz up to 960MHz
- 'BAND_9xx': for channels from 902MHz up to 928MHz
- 'BAND_896': for channels from 896MHz up to 901MHz
- 'BAND_863': for channels from 863MHz up to 870MHz
- 'BAND_780': for channels from 779MHz up to 787MHz
- 'BAND_470': for channels from 470MHz up to 510MHz
- 'BAND_450': for channels below 470MHz

#### Wi-SUN Configuration with RAILtest for EFR32FG25

##### Wi-SUN FSK Configuration

###### Set Up PHR and TX FIFO

Wi-SUN FSK PHYs are configured to variable length packet encoding. Also, other configurable parameters are stored in the PHR field according to the standard. It might be difficult to set it up correctly. Therefore, a helper function – the set802154PHR CLI command – has been implemented in the RAILtest project, which simplifies configuration of a valid PHR field and the payload.

Using the RAILtest example, the transmitted packet length should be defined first with the `setTxLength` CLI command, including the PHR's size (2 bytes). This command sets up the Tx FIFO's length and allocates memory for it.

The `set802154PHR` CLI command for the FSK case sets the FCS type, Whitening bit, and Length fields of the PHR:

1. The first argument selects the PHR format (1, 2, 4 bytes). For FSK, this should be always set to 1, which selects 2 bytes.
2. The second argument sets the FCS type (it should be 0 for Wi-SUN FAN for 4 bytes FCS and 1 for ECHONET/HAN).
3. The third argument specifies the payload whitening (0 for payload whitening disabled and 1 for payload whitening enabled). The payload whitening is mandatory for Wi-SUN, but some Wi-SUN conformance tests could require disabling it. The whitening mode must also be set in the _radio_setting.radioconf_.

See an example use case in [A Complete FSK Configuration Example](#a-complete-fsk-configuration-example).

The Frame Length field of the PHR is configured according to the length that previously was configured by the setTxLength command. The payload will be padded by autogenerated data.

**Warning:** `setTxLength` must always precede the `set802154PHR` command when the Tx packet's length is changed.

**Note:** To comply with IEEE 802.15.4, the `set802154PHR` command should be used according to the configured PHY in the Radio Configurator. The command only changes the PHR field in the Tx frames. No FSK modem configurations are made through this command.

###### Configure PA for FSK

The FSK PA (RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE) is configured by the `RAIL_ConfigTxPower()` RAIL API. This function is wrapped by the `setPowerConfig` CLI command.

###### A Complete FSK Configuration Example

In this section, a complete example is presented of how to transmit FSK-modulated packets with the EFR32FG25 radio using the RAILtest application. It assumes the EFR32FG25 is flashed with an image with a Wi-SUN FSK configuration with whitening enabled set with the Radio Configurator.

The following CLI commands are used:

- Set up the radio to use the FSK PA (only needed when also using OFDM PA).
- Set the desired PA level (check the maximum level depending on the radio board).
- Set the transmitted packet's length to 250 (= framelength field in the PHR of 252 – 4-byte FCS + 2 bytes of PHR).
- Configure the PHR.
- Transmit 10 packets.

```C
    > rx 0
    {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:3295762881}}
    > setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
    {{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE}{modeIndex:0}{voltage:3600}{rampTime:7}}
    > setpower 140
    {{(setpower)}{powerLevel:72}{power:140}}
    > setchannel 0
    {{(setchannel)}{channel:0}}
    > rx 1
    {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time: 329573470724420}}
    > setTxLength 250
    {{(setTxLength)}{TxLength:250}{TxLength Written:250}}
    > Set802154phr 1 0 1
    {{(Set802154phr)}{PhrSize:2}{PHR: 0x3f10}}
    {{(Set802154phr)}{len:250}{payload: 0x10 0x3f 0x11 0x22 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee
     0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26
     0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d
     0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54
     0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b
     0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f 0x80 0x81 0x82
     0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99
     0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf 0xb0
     0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb 0xbc 0xbd 0xbe 0xbf 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7
     0xc8 0xc9 0xca 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 0xda 0xdb 0xdc 0xdd 0xde
     0xdf 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed 0xee 0xef 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5
     0xf6 0xf7 0xf8 0xf9}}
    > tx 10
    {{(tx)}{PacketTx:Enabled}{None:Disabled}{Time:3294056593}}
    {{(appMode)}{None:Enabled}{PacketTx:Disabled}{Time:3296735316}}
    {{(txEnd)}{txStatus:Complete}{transmitted:10}{lastTxTime:3296735238}{timePos:6}{lastTxStart:3296692963}{ccaSuccess:0}{failed:0}{lastTxStatus:0x000000000}{txRemain:0}{isAck:False}}
```

**Notes:**

- The maximum framelength value in the PHR is 2047. Therefore, in Wi-SUN FSK, this provides a setTxLength RAILtest command of 2045 (= 2047 – 4 bytes FCS + 2 bytes of PHR).
- Use `setConfigIndex` to select the appropriate Wi-SUN FSK mode available in the _radio_settings.radioconf_.
- Use the `help` command for a full list of CLI command options.

###### Diagnostic Signals

Both stream mode (PN9) and CW signal generation are supported.

PN9 stream mode also requires setting up PHR (with the set802154PHR command).

As an example, the following CLI commands configure and enable the PN9 stream transmission mode on the radio.

```C
    > set802154Phr 1 0 1
    > setTxStream 1
```

Example:

```C
    > set802154Phr 1 0 1
      {{(set802154Phr)}{PhrSize:2}{PHR:0x6010}}
      {{(set802154Phr)}{len:4}{payload: 0x10 0x60 0x00 0x00}}
    > setTxStream 1
    {{(setTxStream)}{Stream:Enabled}{StreamMode:PN9}{Time:2158238801}}
```

Use the following command to send a tone at the carrier frequency.

`> setTxTone 1`

Examples:

```C
    # To Start the tone
    > setTxTone 1
      {{(setTxTone)}{Stream:Enabled}{None:Disabled}{StreamMode:Tone}{Time:1293513244}}
    # To Stop the tone
    > setTxTone 0
    {{(setTxTone)}{None:Enabled}{Stream:Disabled}{Time:1298384979}}
```

##### Wi-SUN OFDM Configuration

###### Set Up PHR and TX FIFO

Wi-SUN OFDM PHYs are configured to variable packet length encoding. Also, other configurable parameters are stored in the PHR field according to the standard 802.15.4-2020 (detailed in section 20.2.4). It might be difficult to set it up correctly. Therefore, a helper function – the set802154PHR CLI command – has been implemented in the RAILtest project, which simplifies configuration of a valid PHR field and the payload.

Using the RAILtest example, first the transmitted packet’s length should be defined with the `setTxLength` CLI command, including the PHR’s size (4 bytes). This command sets up the TX FIFO’s length and allocates memory for it.

The `set802154PHR` CLI command sets the Rate, Scrambler, and Length fields of the PHR:

1. The first argument selects the PHR format (1, 2, 4 bytes). For OFDM, this should be always set to 2, selecting 4 bytes.
2. The second argument sets the data Rate (“the numerical value of the MCS” as described in the standard in section 20.4).
3. The third argument specifies the scrambling seed (both MSB and LSB bits), according to table 20-20 in the standard.

See an example use case in [A Complete OFDM Configuration Example](#a-complete-ofdm-configuration-example).

The Frame Length field of the PHR is configured according to the length that previously was configured by the setTxLength command. The payload will be padded by autogenerated data.

**Note:**

- `setTxLength` must always precede the `set802154PHR` command when the TX packet’s length is changed.
- Use the `help` command for a full listing of the CLI command options.
- To comply with IEEE 802.15.4, the `set802154PHR` command should be used according to the configured OFDM option set in the Radio Configurator. The command changes the PHR field in the TX packet and for OFDM PHY selects the used MCS in TX.

###### Configure OFDM PA

OFDM modulation uses a separate PA (Power Amplifier), which should be selected manually before the transmission.

The OFDM PA (RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE) is configured by the `RAIL_ConfigTxPower()` RAIL API. This function is wrapped by the `setPowerConfig` CLI command.

This configuration is useful only when changing from FSK modulation to OFDM modulation. It only needs to be done once at initialization.

For an example Multi-PHY configuration with FSK (channel 512) and OFDM (channel 21504), the recommended PA configuration with IR calibration (see [IR Calibration Initialization for FSK or OFDM](#ir-calibration-initialization-for-fsk-or-ofdm)) is:

```C
    > rx 0
    > setchannel 512
    > rx 1
    > rx 0
    > setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
    > setpower 100
    > setchannel 512
    > rx 1
    > rx 0
    > setchannel 21504
    > rx 1
    > rx 0
    > setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
    > setpower 100
    > setchannel 21504
    > rx 1
```

###### A Complete OFDM Configuration Example

This section contains a complete example of how to transmit OFDM modulated packets with the EFR32FG25 radio using the RAILtest application. It assumes the EFR32FG25 is flashed with an image with a Wi-SUN OFDM configuration set with the Radio Configurator.

The following CLI commands are used:

- Set up the radio to use the OFDM PA (only done once when starting to use OFDM modulation).
- Set the recommended PA level (check the maximum level depending on the radio board, 16 dBm for EFR32FG25).
- Set the transmitted packet’s length to 250 (=246-byte payload including the 4-byte FCS field plus 4-byte PHR field).
- Configure the PHR with MCS 6 with OFDM Option depending on the _radio_settings.radioconf_ and using Wi-SUN 0b00010111 scrambling seed (value 0 in the PHR field).
- Transmit 10 packets.

```C
    > rx 0
    {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:3470713331}}
    > setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
    {{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE}{modeIndex:2}{voltage:3600}{rampTime:7}}
    > setpower 140
    {{(setPower)}{powerLevel:151}{power:140}}
    > setchannel 0
    {{(setchannel)}{channel:0}}
    > rx 1
    {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time: 3470724420}}
    > setTxLength 250
    {{(setTxLength)}{TxLength:250}{TxLength Written:250}}
    > Set802154phr 2 6 0
    {{(Set802154phr)}{PhrSize:4}{PHR:0xde0c00}}
    {{(Set802154phr)}{len:250}{payload: 0x00 0x0c 0xde 0x00 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee
     0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26
     0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d
     0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54
     0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b
     0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f 0x80 0x81 0x82
     0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99
     0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf 0xb0
     0xb1 0xb2 0xb3 0xb4 0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb 0xbc 0xbd 0xbe 0xbf 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7
     0xc8 0xc9 0xca 0xcb 0xcc 0xcd 0xce 0xcf 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 0xda 0xdb 0xdc 0xdd 0xde
     0xdf 0xe0 0xe1 0xe2 0xe3 0xe4 0xe5 0xe6 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed 0xee 0xef 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5
     0xf6 0xf7 0xf8 0xf9}}
    > tx 10
    {{(tx)}{PacketTx:Enabled}{None:Disabled}{Time:3116912126}}
    {{(appMode)}{None:Enabled}{PacketTx:Disabled}{Time:3117028916}}
    {{(txEnd)}{txStatus:Complete}{transmitted:10}{lastTxTime:3117028845}{timePos:6}{lastTxStart:3117026790}{ccaSuccess:0}{failed:0}{lastTxStatus:0x000000000}{txRemain:0}{isAck:False}}
```

**Notes:**

- `setConfigIndex` can be used to select the appropriate OFDM option available in the _radio_settings.radioconf_.
- For Wi-SUN, the maximum framelength value in the PHR is 2047. So, in Wi-SUN OFDM, this provides a setTxLength RAILtest command of 2051 (= 2047 bytes including the 4 bytes FCS field + 4 bytes of PHR).
- After `set802154phr`, the 4-byte FCS is not added in the packet payload replacing the 4 trailing bytes, but it will be added in the transmitted packet. At the receiving side, the Rx frame has the 4-byte FCS removed.

```C
    > {{(rxPacket)}{len:246}{timeUs:48492691}{timePos:5}{crc:Pass}{filterMask:0x0}{rssi:-97}{lqi:197}{phy:6}{isAck:False}
    {syncWordId:0}{antenna:0}{channelHopIdx:254}{payload: 0x03 0x0c 0xde 0x00 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb
    0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24
    0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c
    0x3d 0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4a 0x4b 0x4c 0x4d 0x4e 0x4f 0x50 0x51 0x52 0x53 0x54
    0x55 0x56 0x57 0x58 0x59 0x5a 0x5b 0x5c 0x5d 0x5e 0x5f 0x60 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c
    0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7a 0x7b 0x7c 0x7d 0x7e 0x7f 0x80 0x81 0x82 0x83 0x84
    0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90 0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 0x99 0x9a 0x9b 0x9c
    0x9d 0x9e 0x9f 0xa0 0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf 0xb0 0xb1 0xb2 0xb3 0xb4
    0xb5 0xb6 0xb7 0xb8 0xb9 0xba 0xbb 0xbc 0xbd 0xbe 0xbf 0xc0 0xc1 0xc2 0xc3 0xc4 0xc5 0xc6 0xc7 0xc8 0xc9 0xca 0xcb 0xcc
    0xcd 0xce 0xcf 0xd0 0xd1 0xd2 0xd3 0xd4 0xd5 0xd6 0xd7 0xd8 0xd9 0xda 0xdb 0xdc 0xdd 0xde 0xdf 0xe0 0xe1 0xe2 0xe3 0xe4
    0xe5 0xe6 0xe7 0xe8 0xe9 0xea 0xeb 0xec 0xed 0xee 0xef 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5}}
```

###### Diagnostic Signals

With OFDM modulation configured, both stream mode (PN9) and CW signal generation are supported.

PN9 stream mode also requires setting up PHR (with the `set802154PHR` command) to select the MCS Level. It is also mandatory to configure the frame length field to 4 before the transmission, to set up the infinite stream needed for PN9.

As an example, the following CLI commands configure and enable the PN9 stream transmission mode on the radio in OFDM option 1 MCS4 at configindex 1.

```C
    > setconfigindex 1
    > rx 0
    > setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
    > setpower 140
    > rx 1
    > setTxLength 4
    > set802154Phr 2 4 0
    > setTxStream 1
```

Example:

```C
    > setconfigindex 1
      {{(setconfigindex)}{configIndex:1}{firstAvailableChannel:0}}
    > setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
      {{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE}{modeIndex:2}{voltage:3600}{rampTime:7}}
    > setpower 140
      {{(setpower)}{powerLevel:151}{power:140}}
    > setTxLength 4
      {{(setTxLength)}{TxLength:4}{TxLength Written:4}}
    > set802154Phr 2 4 0
      {{(set802154Phr)}{PhrSize:4}{PHR:0x400}}
      {{(set802154Phr)}{len:4}{payload: 0x00 0x04 0x00 0x00}}
    > setTxStream 1
    {{(setTxStream)}{Stream:Enabled}{None:Disabled}{StreamMode:PN9}{Time:1737513509}}
```

Use the following command to send a tone at the carrier frequency.

`> setTxTone 1`

Examples:

```C
    # To Start the tone
    > setTxTone 1
      {{(setTxTone)}{Stream:Enabled}{None:Disabled}{StreamMode:Tone}{Time:1293513244}}
    # To Stop the tone
    > setTxTone 0
    {{(setTxTone)}{None:Enabled}{Stream:Disabled}{Time:1298384979}}
```

It is equivalent to:

`> setTxStream 1 0`

##### IR Calibration Initialization for FSK or OFDM

For FSK or OFDM PHY (during initialization), after a setchannel on the corresponding PHY, a `rx 1` or `tx 1` is required to perform the calibration.

When using multiple PHYs including an OFDM PhyModeID, an IR calibration for OFDM must be performed. Silicon Labs strongly recommends loading one OFDM PHY (during initialization) using the setchannel on the corresponding OFDM channel and a `rx 1` RAILtest CLI command to perform the calibration. Once image rejection calibration has been performed with a Wi-SUN OFDM PHY, you do not need to do it with a Wi-SUN FSK PHY.

#### Known Issues with EFRFG25

##### Board-Specific Limitations

###### Board Support Limitations

When using the mainboard’s LCD, Silicon Labs recommends resetting the mainboard using either the reset button or the CLI reset command.

###### Missing CTune Calibration

Officially released Silicon Labs EFR32 radio boards equipped with HFXO (High-frequency Crystal Oscillator) are manufacturer-calibrated, and the calibrated CTune value is stored in the radio board's EEPROM memory. This value is then accessible (can be read and written) by Simplicity Commander.

However, the EFR32FG25 radio boards have no calibrated CTune value stored in the EEPROM memory.

The CTune value can be calibrated and retrieved at runtime by `setCTune` and `getCTune` RAILtest CLI commands respectively, or by using the `RAIL_SetTune()` and `RAIL_GetTune()` RAIL APIs. The calibration value can be stored using Simplicity Commander or through the Simplicity Studio Device Configuration menu.

###### Missing Notch on the Radio Board

Silicon Labs radio boards have little notches at the board connectors that prevent the user from connecting the radio board in a reversed orientation onto a WSTK.

For the correct orientation, see the following figure.

![Radio board on mainboard](/wisun-phy-quick-start/0.3/images/radio-board-orientation.png)

**Warning:** Incorrect placement of the radio board might cause serious damage on the mainboard. Make sure that the radio board is connected with the correct orientation before supplying power to the mainboard!

##### OFDM PA Limitations

OFDM modulation is designed to use a separate PA from that being used with different modulation types (2/4(G)FSK, MSK, OOK).

For all PA selected in a multi-PHY configuration, the PA initialization should be done. This is required only once, at initialization, and FSK must be done before OFDM:

- Set up the PA configuration
- Set the recommended PA level (check the max level depending on the radio board, 16 dBm for EFR32FG25)

##### Clocking

Switching PHYs while using the RFPLL as a clock source will incur a clock frequency shift.

##### DC/DC is On by Default

The sensitivity might be slightly degraded when the DC/DC is enabled. For best sensitivity, Silicon Labs recommends setting DC/DC to bypass mode. In the **Device Init: DC-DC** component, toggle **Enable DC/DC Converter** to off, and toggle **Set DC/DC Converter in Bypass Mode** to on, as shown in the following figures.

![Component configure control](/wisun-phy-quick-start/0.3/images/sld100-image9.png)

![Configuration settings](/wisun-phy-quick-start/0.3/images/sld100-image10.png)

##### Miscellaneous Issues

- RAIL timings are not accurate in comparison with on-air timing for Rx or TX frames. Manual tuning might be required.
- The 802.15.4 MAC address filtering with OFDM PHY for small frame size is not done correctly and then the frame is always received.

##### Other information

- Silicon Labs recommends using the BRD4270B, BRD4271A, or BRD4272A radio board for best performance:  
  - BRD4270B revA06 radio board RF matching network is tuned for 915 MHz and 920 MHz bands.  
  - BRD4271A revA06 radio board RF matching network is tuned for 868 MHz bands.  
  - BRD4272A revA03 radio board RF matching network is tuned for 470 MHz bands.
- Mode Switch mechanism is available and is documented separately in [Wi-SUN Mode Switch on EFR32FG25 with RAILtest](/wisun/2.12.0/wisun-phy-mode-switch-with-railtest).

### Wi-SUN PHY Mode Switch on EFR32FG25 with RAILtest

#### Wi-SUN PHY Mode Switch on EFR32FG25 with RAILtest

**NOTE: This section replaces _AN1403: Wi-SUN PHY Mode Switch on EFR32FG25 with RAILtest_. Further updates to this application note will be provided here.**

This application note is an introduction to the Wi-SUN PHY Mode Switch feature using the RAILtest example application. It describes:

- How to program EFR32FG25 devices to enable the Wi-SUN Mode Switch feature
- Known issues

_Proprietary is supported on all EFR32FG devices, although Mode Switch and OFDM modulation is available only on EFR32FG25 devices. In this document only the RAILtest example application is used._

#### Introduction

##### Mode Switch Definitions

The Wi-SUN FAN 1.1 specification describes the Modulation and Data Rate (MDR) Negotiation, with impacts at both the stack layer and the PHY mode switch.

This document only addresses the PHY mode switch as defined in on Wi-SUN PHY Technical Profile Specification 2V00 section 6.1.4, which describes Wi-SUN Mode Switch based on a specific Physical layer Protocol Data Unit (PPDU) frame using Mode Switch PHY header (PHR). This mechanism will be referred to as **Wi-SUN PHY mode switch** (for the function) or **mode switch PPDU** (for the specific PPDU name) to avoid ambiguity.

Note that Wi-SUN PHY Mode Switch is not compliant with the mode switch described in IEEE std 802.15.4-2020.

##### EFR32FG25 Support of Mode Switch and Deliveries

EFR32FG25 supports Wi-SUN PHY mode switch. The RAILtest application lets you test the Mode Switch PPDU with a specific radio configuration using RAILtest commands described in the following sections.

Wi-SUN PHY Mode Switch allows PHY switching from a Frequency Shift Keying(FSK) PHY to another FSK PHY, or from an FSK PHY to an Orthogonal frequency-division multiplexing (OFDM) PHY. The configuration is achieved through the Radio Configurator in Simplicity Studio. An example of _radio_settings.radioconf_ file for North America (NA), Japan (JP), and Europe (EU) is provided with the current document.

#### Set Up the Wi-SUN PHY Mode Switch Configuration

##### Mode Switch Configuration with the Radio Configurator

Once a new RAILtest project is created, the Radio Configurator opens automatically. You can then select the **Wi-SUN FAN 1.1 Profile**. The Radio Configurator provides a set of Wi-SUN FSK and OFDM PHYs as part of the Wi-SUN FAN 1.1 profile. The applicable Wi-SUN Regulatory Domain (for example NA, JP, EU, or BZ) according to Wi-SUN FAN 1.1 should be also selected.

To get a Mode Switch configuration between Wi-SUN PHYs, a channel-based multi-PHY configuration is required. More details on channel-based multi-PHY can be found in [https://community.silabs.com/s/article/rail-tutorial-multi-phy-usecases-and-examples?language=en_US](https://community.silabs.com/s/article/rail-tutorial-multi-phy-usecases-and-examples?language=en_US).

In the Radio Configurator, follow the steps below for an example for NA:

1. In the Protocol, select the **Wi-SUN FAN 1.1 Profile** and the **Wi-SUN Regulatory Domain**. In the following figure, the Wi-SUN **NA** Regulatory Domain is selected.  
   ![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image1.png)
2. Update the default channel configuration. To get a Mode Switch configuration, you can add the PhyModeID as the MSByte of the channel number, which is on 2 bytes. This way, RAIL can associate each PhyModeID with a different channel number, which will be useful in Rx.  
   For example, a PhyModeID = 2 (2FSK mode 1b 50 kbps mi=1) provides a channel number of 0x0200=512, as shown.  
   ![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image2.png)  
   > **Note**: The Wi-SUN Channel Plan ID list proposed depends on the Wi-SUN Regulatory Domain and on the selected Wi-SUN PHY Mode ID. The Wi-SUN Channel Plan ID selected supports automatically getting the base frequency and the channel spacing according to the Wi-SUN FAN 1.1 specification.
3. Add additional channel configurations for other PhyModeID using **Create new channel**:  
   ![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image3.png)
4. Enter a **Channel group name** and the parameters as shown in the following example.  
   ![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image4.png)
5. Add other channels and configure them as previously described for Mode Switch configuration. Use the following tables to compute the base channel number.

|FSK PHY Mode References|FEC Enabled|FSK PhyModeID|Channel Number (MSByte = PhyModeID and first channel=0)|
|---|---|---|---|
|#1a|no|1|0x0100 = 256|
|#1b|no|2|0X0200 = 512|
|#2a|no|3|0x0300 = 768|
|#2b|no|4|0x0400 = 1024|
|#3|no|5|0x0500 = 1280|
|#4a|no|6|0x0600 = 1536|
|#4b|no|7|0x0700 = 1792|
|#5|no|8|0x0800 = 2048|

|FSK PHY Mode References|FEC Enabled|FSK PhyModeID|Channel Number (MSByte = PhyModeID and first channel=0)|
|---|---|---|---|
|#1a|yes|17|0x1100 = 4352|
|#1b|yes|18|0X1200 = 4608|
|#2a|yes|19|0x1300 = 4864|
|#2b|yes|20|0x1400 = 5120|
|#3|yes|21|0x1500 = 5376|
|#4a|yes|22|0x1600 = 5632|
|#4b|yes|23|0x1700 = 5888|
|#5|yes|24|0x1800 = 6144|

**Notes**:

- **By default, the Mode Switch PPDU is always from an FSK to an FSK or an OFDM PhyModeID.** Therefore, after a switch to an OFDM PhyModeID, the application should use the `setchannel` RAILtest CLI command on both the Tx and Rx side to go back on an FSK PhyModeID. Alternatively, the RAILtest command `ModeSwitchLife 1` could be used (see [The trigModeSwitchTx RAILtest CLI Command](03-railtest-script-to-use-mode-switch#the-trigmodeswitchtx-railtest-cli-command)).
- Changing OFDM MCS within the same option does not require **Mode Switch PPDU but only to set the MCS using `set802154phr`.**
- The OFDM PHY in the _.radioconf_ file for Mode Switch only requires selecting the lowest MCS of the OFDM option available in the selected Wi-SUN Regulatory Domain as described below for the NA Regulatory Domain. Nevertheless, the MSByte of the channel number could use MCS0 PhyModeID.

|OFDM Options|PhyModeID for MC0|Channel Number (MSByte = PhyModeID and first channel=0)|PhyModeID with the lowest MCS for NA|
|---|---|---|---|
|Option 1|0x20 = 32|0x2000 = 8192|MCS2  0x22 = 34|
|Option 2|0x30 = 48|0x3000 = 12288|MCS3  0x33 = 51|
|Option 3|0x40 = 64|0x4000 = 16384|MCS4  0x44 = 68|
|Option 4|0x50 = 80|0x5000 = 20480|MCS4  0x54 = 84|

The `set802154phr` selects the MCS to be used and the PHYmodeID parameter in the `trigModeSwitchTx` selects the OFDM option, as described in [Script Example](03-railtest-script-to-use-mode-switch#script-example).

##### Mode Switch radio_settings.radioconf Example for NA, JP, EU

NA, JP, and EU Mode Switch _radio_settings.radioconf_ file is provided as an example with this document. This section provides details on the radio configuration settings.

###### NA Wi-SUN Regulatory d=Domain

For example, this Radio Configurator snapshot shows the Mode Switch Multi-PHY-based channel configuration for NA with Channel Plan ID 1, 2, 3, 4, and 5.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image5.png)

The Mode Switch configuration for the NA Regulatory Domain on `configindex 0` is summarized in the following table.

<table>
    <thead>
        <tr>
            <th>ChanPlanID</th>
            <th>Base Frequency (Hz)</th>
            <th>Channel Spacing (Hz)</th>
            <th>PhyModeID</th>
            <th>Channel Number (MSByte = PhyModeID and first channel=0)</th>
            <th>Last Channel Number</th>
            <th>PHY Modes References</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>902200000</td>
            <td>200000</td>
            <td>2</td>
            <td>0x0200 = 512</td>
            <td>640</td>
            <td>#1b</td>
        </tr>
        <tr>
            <td>1</td>
            <td>902200000</td>
            <td>200000</td>
            <td>18</td>
            <td>0x1200 = 4608</td>
            <td>4736</td>
            <td>#1b with FEC</td>
        </tr>
        <tr>
            <td>1</td>
            <td>902200000</td>
            <td>200000</td>
            <td>3</td>
            <td>0x0300 = 768</td>
            <td>896</td>
            <td>#2a</td>
        </tr>
        <tr>
            <td>1</td>
            <td>902200000</td>
            <td>200000</td>
            <td>19</td>
            <td>0x1300 = 4864</td>
            <td>4992</td>
            <td>#2a with FEC</td>
        </tr>
        <tr>
            <td>1</td>
            <td>902200000</td>
            <td>200000</td>
            <td>80</td>
            <td>0x5000 = 20480</td>
            <td>20608</td>
            <td>
                <p>OFDM Option 4 MCS set with set802154phr</p>
            </td>
        </tr>
        <tr>
            <td>2</td>
            <td>902400000</td>
            <td>400000</td>
            <td>5</td>
            <td>0x0500 = 1280</td>
            <td>1343</td>
            <td>#3</td>
        </tr>
        <tr>
            <td>2</td>
            <td>902400000</td>
            <td>400000</td>
            <td>21</td>
            <td>0x1500 = 5376</td>
            <td>5439</td>
            <td>#3 with FEC</td>
        </tr>
        <tr>
            <td>2</td>
            <td>902400000</td>
            <td>400000</td>
            <td>6</td>
            <td>0x0600 = 1536</td>
            <td>1599</td>
            <td>#4a</td>
        </tr>
        <tr>
            <td>2</td>
            <td>902400000</td>
            <td>400000</td>
            <td>22</td>
            <td>0x1600 = 5632</td>
            <td>5695</td>
            <td>#4a with FEC</td>
        </tr>
        <tr>
            <td>2</td>
            <td>902400000</td>
            <td>400000</td>
            <td>64</td>
            <td>0x4000 = 16384</td>
            <td>16447</td>
            <td>
                <p>OFDM Option 3 MCS set with set802154phr</p>
            </td>
        </tr>
        <tr>
            <td>3</td>
            <td>902600000</td>
            <td>600000</td>
            <td>8</td>
            <td>0x0800 = 2048</td>
            <td>2089</td>
            <td>#5</td>
        </tr>
        <tr>
            <td>3</td>
            <td>902600000</td>
            <td>600000</td>
            <td>24</td>
            <td>0x1800 = 6144</td>
            <td>6185</td>
            <td>#5 with FEC</td>
        </tr>
        <tr>
            <td>4</td>
            <td>902800000</td>
            <td>800000</td>
            <td>48</td>
            <td>0X3000 = 12288</td>
            <td>12319</td>
            <td>
                <p>OFDM Option 2 MCS set with set802154phr</p>
            </td>
        </tr>
        <tr>
            <td>5</td>
            <td>903200000</td>
            <td>1200000</td>
            <td>32</td>
            <td>0x2000 = 8192</td>
            <td>8212</td>
            <td>
                <p>OFDM Option 1 MCS set with set802154phr</p>
            </td>
        </tr>
    </tbody>
</table>

Mode switch can be enabled across all PHYs specified in the **PhyModeID** column.

###### JP Wi-SUN Regulatory Domain

This Radio Configurator snapshot shows the Mode Switch Multi-PHY-based channel configuration for JP with Channel Plan ID 21, 22, 23, and 24.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image6.png)

The Mode Switch configuration for the JP Regulatory Domain on `configindex 1` is summarized in the following table.

<table>
    <thead>
        <tr>
            <th>ChanPlanID</th>
            <th>Base Frequency (Hz)</th>
            <th>Channel Spacing (Hz)</th>
            <th>PhyModeID</th>
            <th>Channel Number (MSByte = PhyModeID and first channel=0)</th>
            <th>First Channel Number (not masked)</th>
            <th>Last Channel Number</th>
            <th>PHY Modes References</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>21</td>
            <td>920600000</td>
            <td>200000</td>
            <td>2</td>
            <td>0x0200 = 512</td>
            <td>521</td>
            <td>549</td>
            <td>#1b</td>
        </tr>
        <tr>
            <td>21</td>
            <td>920600000</td>
            <td>200000</td>
            <td>18</td>
            <td>0x1200 = 4608</td>
            <td>4617</td>
            <td>4645</td>
            <td>#1b with FEC</td>
        </tr>
        <tr>
            <td>21</td>
            <td>920600000</td>
            <td>200000</td>
            <td>80</td>
            <td>0x5000 = 20480</td>
            <td>20489</td>
            <td>20517</td>
            <td>OFDM Option 4 MCS set with set802154phr</td>
        </tr>
        <tr>
            <td>22</td>
            <td>920900000</td>
            <td>400000</td>
            <td>4</td>
            <td>0x0400 = 1024</td>
            <td>1028</td>
            <td>1041</td>
            <td>#2b</td>
        </tr>
        <tr>
            <td>22</td>
            <td>920900000</td>
            <td>400000</td>
            <td>20</td>
            <td>0x1400 = 5120</td>
            <td>5124</td>
            <td>5137</td>
            <td>#2b with FEC</td>
        </tr>
        <tr>
            <td>22</td>
            <td>920900000</td>
            <td>400000</td>
            <td>5</td>
            <td>0x0500 = 1280</td>
            <td>1284</td>
            <td>1297</td>
            <td>#3</td>
        </tr>
        <tr>
            <td>22</td>
            <td>920900000</td>
            <td>400000</td>
            <td>21</td>
            <td>0x1500 = 5376</td>
            <td>5380</td>
            <td>5393</td>
            <td>#3 with FEC</td>
        </tr>
        <tr>
            <td>22</td>
            <td>920900000</td>
            <td>400000</td>
            <td>64</td>
            <td>0x4000 = 16384</td>
            <td>16388</td>
            <td>16401</td>
            <td>OFDM Option 3 MCS set with set802154phr</td>
        </tr>
        <tr>
            <td>23</td>
            <td>920800000</td>
            <td>600000</td>
            <td>7</td>
            <td>0x0700 = 1792</td>
            <td>1795</td>
            <td>1803</td>
            <td>#4b</td>
        </tr>
        <tr>
            <td>23</td>
            <td>920800000</td>
            <td>600000</td>
            <td>23</td>
            <td>0x1700 = 5888</td>
            <td>5891</td>
            <td>5899</td>
            <td>#4b with FEC</td>
        </tr>
        <tr>
            <td>23</td>
            <td>920800000</td>
            <td>600000</td>
            <td>8</td>
            <td>0x0800 = 2048</td>
            <td>2051</td>
            <td>2059</td>
            <td>#5</td>
        </tr>
        <tr>
            <td>23</td>
            <td>920800000</td>
            <td>600000</td>
            <td>24</td>
            <td>0x1800 = 6144</td>
            <td>6147</td>
            <td>6155</td>
            <td>#5 with FEC</td>
        </tr>
        <tr>
            <td>24</td>
            <td>921100000</td>
            <td>800000</td>
            <td>48</td>
            <td>0X3000 = 12288</td>
            <td>12290</td>
            <td>12296</td>
            <td>OFDM Option 2 MCS set with set802154phr</td>
        </tr>
    </tbody>
</table>

Mode switch can be enabled across all PHYs specified in the **PhyModeID** column.

> **Note**: In Japan, a channel mask applies and forbids the use of the lower channels. The **First Channel number (not masked)** column indicates the first valid channel that can be used.

###### EU Wi-SUN Regulatory Domain Case 1

This Radio Configurator snapshot shows the Mode Switch Multi-PHY-based channel configuration for EU1. In this example, EU 1 includes both 863-870 MHz and 863-876 MHz bands, resulting in Channel Plan IDs 32, 33, 36, and 37, as shown.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image7.png)

Note the ChanPlanID32 and 36 have the same configuration except that ChanPlanID36 uses the maximum number of channels. The same is true for ChanPlanID33 and 37.

The mode switch configuration for the EU Regulatory Domain on `configindex 2` is summarized in the following table.

<table>
    <thead>
        <tr>
            <th>ChanPlanID</th>
            <th>Base Frequency (Hz)</th>
            <th>Channel Spacing (Hz)</th>
            <th>PhyModeID</th>
            <th>Channel Number (MSByte = PhyModeID and first channel=0)</th>
            <th>First Channel Number</th>
            <th>Last Channel Number</th>
            <th>PHY Modes References</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>32</td>
            <td>863100000</td>
            <td>100000</td>
            <td>1</td>
            <td>0x0100 = 256</td>
            <td>256</td>
            <td>324</td>
            <td>#1a</td>
        </tr>
        <tr>
            <td>32</td>
            <td>863100000</td>
            <td>100000</td>
            <td>17</td>
            <td>0x1100 = 4352</td>
            <td>4352</td>
            <td>4420</td>
            <td>#1a with FEC</td>
        </tr>
        <tr>
            <td>33</td>
            <td>863100000</td>
            <td>200000</td>
            <td>3</td>
            <td>0x0300 = 768</td>
            <td>768</td>
            <td>802</td>
            <td>#2a</td>
        </tr>
        <tr>
            <td>33</td>
            <td>863100000</td>
            <td>200000</td>
            <td>19</td>
            <td>0x1300 = 4864</td>
            <td>4864</td>
            <td>4898</td>
            <td>#2a with FEC</td>
        </tr>
        <tr>
            <td>33</td>
            <td>863100000</td>
            <td>200000</td>
            <td>5</td>
            <td>0x0500 = 1280</td>
            <td>1280</td>
            <td>1314</td>
            <td>#3</td>
        </tr>
        <tr>
            <td>33</td>
            <td>863100000</td>
            <td>200000</td>
            <td>21</td>
            <td>0x1500 = 5376</td>
            <td>5376</td>
            <td>5410</td>
            <td>#3 with FEC</td>
        </tr>
        <tr>
            <td>33</td>
            <td>863100000</td>
            <td>200000</td>
            <td>80</td>
            <td>0x5000 = 20480</td>
            <td>20480</td>
            <td>20514</td>
            <td>OFDM Option 4 MCS set with set802154phr</td>
        </tr>
        <tr>
            <td>36</td>
            <td>863100000</td>
            <td>100000</td>
            <td>1</td>
            <td>0x0100 = 256</td>
            <td>256</td>
            <td>380</td>
            <td>#1a</td>
        </tr>
        <tr>
            <td>36</td>
            <td>863100000</td>
            <td>100000</td>
            <td>17</td>
            <td>0x1100 = 4352</td>
            <td>4352</td>
            <td>4476</td>
            <td>#1a with FEC</td>
        </tr>
        <tr>
            <td>37</td>
            <td>863100000</td>
            <td>200000</td>
            <td>3</td>
            <td>0x0300 = 768</td>
            <td>768</td>
            <td>829</td>
            <td>#2a</td>
        </tr>
        <tr>
            <td>37</td>
            <td>863100000</td>
            <td>200000</td>
            <td>19</td>
            <td>0x1300 = 4864</td>
            <td>4864</td>
            <td>4925</td>
            <td>#2a with FEC</td>
        </tr>
        <tr>
            <td>37</td>
            <td>863100000</td>
            <td>200000</td>
            <td>5</td>
            <td>0x0500 = 1280</td>
            <td>1280</td>
            <td>1341</td>
            <td>#3</td>
        </tr>
        <tr>
            <td>37</td>
            <td>863100000</td>
            <td>200000</td>
            <td>21</td>
            <td>0x1500 = 5376</td>
            <td>5376</td>
            <td>5437</td>
            <td>#3 with FEC</td>
        </tr>
        <tr>
            <td>37</td>
            <td>863100000</td>
            <td>200000</td>
            <td>80</td>
            <td>0x5000 = 20480</td>
            <td>20480</td>
            <td>20541</td>
            <td>OFDM Option 4 MCS set with set802154phr</td>
        </tr>
    </tbody>
</table>

Mode switch can be enabled across all PHYs specified in the **PhyModeID** column.

> **Note**: In EU, a channel mask applies and forbids the use of some available channels in the middle and at the end of the RF band. The channel masking in the middle of the RF band is taken into account for Mode Switch thanks to a RAIL callback provided by the stack (see [RAIL_lib API Usage for Mode Switch PPDU](04-rail-lib-api-usage-for-mode-switch-ppdu)).

###### EU Wi-SUN Regulatory Domain Case 2

This Radio Configurator snapshot shows the Mode Switch Multi-PHY-based channel configuration for EU2 (870-876 MHz) with Channel Plan ID 34 and 35.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image8.png)

The Mode Switch configuration for the EU Regulatory Domain on `configindex 3` is summarized in the following table.

<table>
    <thead>
        <tr>
            <th>ChanPlanID</th>
            <th>Base frequency (Hz)</th>
            <th>Channel spacing (Hz)</th>
            <th>PhyModeID</th>
            <th>Channel number (MSByte = PhyModeID and first channel=0)</th>
            <th>First Channel number</th>
            <th>Last Channel number</th>
            <th>PHY modes References</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>34</td>
            <td>870100000</td>
            <td>100000</td>
            <td>1</td>
            <td>0x0100 = 256</td>
            <td>256</td>
            <td>310</td>
            <td>#1a</td>
        </tr>
        <tr>
            <td>34</td>
            <td>870100000</td>
            <td>100000</td>
            <td>17</td>
            <td>0x1100 = 4352</td>
            <td>4352</td>
            <td>4406</td>
            <td>#1a with FEC</td>
        </tr>
        <tr>
            <td>35</td>
            <td>870200000</td>
            <td>200000</td>
            <td>3</td>
            <td>0x0300 = 768</td>
            <td>768</td>
            <td>794</td>
            <td>#2a</td>
        </tr>
        <tr>
            <td>35</td>
            <td>870200000</td>
            <td>200000</td>
            <td>19</td>
            <td>0x1300 = 4864</td>
            <td>4864</td>
            <td>4890</td>
            <td>#2a with FEC</td>
        </tr>
        <tr>
            <td>35</td>
            <td>870200000</td>
            <td>200000</td>
            <td>5</td>
            <td>0x0500 = 1280</td>
            <td>1280</td>
            <td>1306</td>
            <td>#3</td>
        </tr>
        <tr>
            <td>35</td>
            <td>870200000</td>
            <td>200000</td>
            <td>21</td>
            <td>0x1500 = 5376</td>
            <td>5376</td>
            <td>5402</td>
            <td>#3 with FEC</td>
        </tr>
        <tr>
            <td>35</td>
            <td>870200000</td>
            <td>200000</td>
            <td>80</td>
            <td>0x5000 = 20480</td>
            <td>20480</td>
            <td>20506</td>
            <td>OFDM Option 4 MCS set with set802154phr</td>
        </tr>
    </tbody>
</table>

Mode switch can be enabled across all PHYs specified in the **PhyModeID** column.

> **Note**: In EU, a channel mask applies and forbids the use of some available channels in the middle and at the end of the RF band. The channel masking in the middle of the RF band is taken into account for Mode Switch thanks to a RAIL callback provided by the stack (see [RAIL_lib API Usage for Mode Switch PPDU](04-rail-lib-api-usage-for-mode-switch-ppdu)).

#### RAILtest Script to Use Mode Switch

Before using the Mode Switch PPDU, reading _Getting Started with Wi-SUN PHY Configuration_ is recommended. This is available on the Wi-SUN site in [https://docs.silabs.com/](https://docs.silabs.com/).

##### The trigModeSwitchTx RAILtest CLI Command

The SiSDK provides a new RAILtest CLI command, `trigModeSwitchTx`, to manage the Mode switch PPDU in Tx. After some RAIL initialization, this command sends the Mode Switch PPDU with the specified PHR to inform the Rx nodes to switch to the new PhyModeID.

```sh
> help trigModeSwitchTx

trigModeSwitchTx    Transmit a Mode Switch packet then transmit packets on the new PHY with current
                    TX options. Depending on modeSwitchLife configuration, after all iterations are
                    done, it either stays on the new PHY or returns to the base PHY.
                    [uint8] new PhyModeId, i.e. ID of the PHYMode we are switching to
                    [uint8] number of packets transmitted on the new PHY
                    [uint32opt] number of times the sequence mode switch packet followed by data
                    packets is repeated, default is 1 if argument is absent
                    [uint32opt] delayMilliseconds before switching back to base PHY after all packets
                    have been transmitted on the new PHY, default is 0 if argument is absent.
                    Multitimer is used for delay greater than 0.
> help modeSwitchLife
modeSwitchLife      Return to the base PHY after all data packets transmitted for TX or after
                    MODE_SWITCH_START event and multitimer expiration after first data packet
                    reception on new phy for RX.
                    [uint8] 0=stay on new PHY (normal Wi-SUN FAN behaviour)
                            1=return to base PHY (special test mode)
```

With `trigModeSwitchTx`, the CCA checking after the Mode switch PPDU is not implemented. To add it, call `setlbtmode csma` and `setlbtparams 0 0 1 -80 0 160 0` before calling `trigModeSwitchTx`. After the Mode Switch PPDU, the data frame must be transmitted within a maximum delay of 1.5 ms, as per the specification.

> **Notes**: The two last optional fields in `trigModeSwitchTx` and the `modeSwitchLife` command are only useful for test purposes.
> 
> The Mode Switch PPDU is transmitted in broadcast manner. Therefore, there is no MAC address filtering, and all receivers are impacted.

##### Mode Switch PPDU Snapshot in Zero Span Spectrum

The following shows a Mode Switch example from FSK to another FSK PhyModeID with CSMA-CA enabled, and illustrates the timing of frames during PhyModeID switch:

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image9.png)

The following illustrates a Mode Switch from FSK to OFDM PhyModeID with CSMA-CA enabled.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image10.png)

> **Note**: After the Mode Switch PPDU, the data frame might use another carrier frequency. The resolution bandwidth (RBW) of the spectrum analyzer should be set according to this new frequency, so that zero span can detect the data frame transmitted.

##### FSK and OFDM Channel-Based Multi-PHY: IR Calibration Initialization

For FSK or OFDM PHY (during initialization), after a `setchannel` on the corresponding PHY, an `rx 1` or `tx 1` command is required to perform the calibration. When using multiple PHYs including an OFDM PhyModeID, an IR calibration for OFDM must be performed. Silicon Labs strongly recommends loading one OFDM PHY (during initialization) using the RAILtest CLI commands `setchannel` on the corresponding OFDM channel and `rx 1` to perform the calibration. Once image rejection calibration has been performed with a Wi-SUN OFDM PHY, you do not need to do it with a Wi-SUN FSK PHY.

##### Script Example

This section presents a complete example showing how to configure and send the Mode Switch with the EFR32FG25 radio using the RAILtest application. It assumes the EFR32FG25 is flashed with an image with a Wi-SUN Mode Switch configuration.

The following steps are required:

- For all PA selected in the channel-based multi-PHY, the initialization should be done (only required once at initialization with FSK PA configuration before the OFDM PA configuration).  
  - Set up the PA configuration.  
  - Set the recommended PA level (check the maximum level depending on the radio board, 16 dBm for EFR32FG25).
- If IR calibration is enabled including an OFDM PhyModeID, then call `setchannel OFDM_base_channel` for IR calibration (see previous section).
- Mode Switch RAIL initialization must be done in Tx and Rx:  
  - `Enable802154 rx 110 192 672 0`: Enable RAIL 802.15.4 management (needed to get Mode Switch enabled in RAIL). Note the timing parameters provided are for ACK management. This is not used in mode switch PPDU. Before calling this command, radio should be in idle mode.  
  - `setRxOptions 4`: Enable DUALSYNC in Tx and Rx in case of FSK FEC usage in the channel-based multi-PHY.  
  - `set802154g 7`: Enable Mode Switch and dynamic FEC, which are required for Mode Switch. Before calling this command, a FSK PHY should be selected.  
  - `setPromiscuousMode 1`: Avoid MAC filtering on packet received.  
  - `setTxdelay 10`: Set 10 ms between data frames.  
  - `setTxLength 63`: Set the data frame length. This could be another frame length value. Remember to call `set802154Phr` after a new `setTxLength`. Note that FSK frame length corresponds to setTxLength value -2 and that OFDM frame length corresponds to setTxLength value -4.  
  - `resetCounters`: Reset the status counters.
- `setEventConfig 0x0 0x0 24576 24576` and `printEvents 0x0 24576`: In Rx, Mode Switch events are enabled and printed. The RAIL_EVENT_IEEE802154_MODESWITCH_START event occurs on Mode Switch PPDU reception. The RAIL_EVENT_IEEE802154_MODESWITCH_END event occurs in the following cases:  
  - A timeout when no data packet is received after the mode switch packet (or if the packet is received too late)  
  - A CRC error  
  - A bad MAC address on the data packet received after the mode switch packet. With `setPromiscuousMode 1`, there is no MAC address filtering.
- `Set802154phr`: Uses different parameters between FSK and OFDM frame, as described in [QSG181: Silicon Labs Wi-SUN Quick-Start Guide](https://www.silabs.com/documents/public/quick-start-guides/qsg181-wi-sun-sdk-quick-start-guide.pdf). To switch on OFDM PHY, `Set802154phr` should be set with the selected MCS. The new PhyModeID set in `trigModeSwitchTx` selects only the OFDM option.
- `trigModeSwitchTx`: set the new PhyModeID and the number of data frames to transmit.

These steps result in the following script:

```sh
#### PA configuration/init (to do only one time to switch with correct PA from FSK to OFDM)
#### and IR calibration using OFDM option and channel common to all regions (20489)
#### and selection of FSK PHY channel (512) before calling set802154g
> rx 0
> setchannel 512
> rx 1
> rx 0
> setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
> setpower 140
> setchannel 512
> rx 1
> rx 0
> setchannel 20489
> rx 1
> rx 0
> setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
> setpower 140
> setchannel 20489
> rx 1
> setchannel 512
> rx 1

#### Mode Switch RAIL initialization for Mode Switch
> rx 0
> enable802154 rx 110 192 672 0
> setRxOptions 4
> set802154g 7
> rx 1
> setPromiscuousMode 1
> setTxDelay 10
> setTxLength 63
> resetCounters

#### Only on Rx side: enable Mode Switch events:
#### RAIL_EVENT_IEEE802154_MODESWITCH_START and RAIL_EVENT_IEEE802154_MODESWITCH_END
> setEventConfig 0x0 0x0 24576 24576
> printEvents 0x0 24576

#### Only on Tx side to switch to FSK PHY: FSK PHR + trigModeSwitchTx
#### with one packet sent with FSK PhyModId=3
> Set802154phr 1 0 1
> trigModeSwitchTx 3 1

#### Only in Tx side to switch to OFDM PHY: one packet sent with OFDM PHR MCS4 and OFDM PhyModeID 80
> Set802154phr 2 4 0
> trigModeSwitchTx 80 1

#### After Mode Switch step we should come back to FSK base channel in Tx and Rx side with:
> setchannel 512
```

> **Note**: More details on RAILtest commands can be found in [UG409: RAILtest User's Guide](https://www.silabs.com/documents/public/user-guides/ug409-railtest-users-guide.pdf).

##### A Complete FSK-to-FSK Mode Switch Example in NA region

```sh
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1516549207}}
>> setchannel 512
  {{(setchannel)}{channel:512}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1516862048}}
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1517030918}}
> setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
  {{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE}{modeIndex:0}{voltage:3600}{rampTime:7}}
> setpower 140
  {{(setpower)}{powerLevel:70}{power:140}}
> setchannel 512
  {{(setchannel)}{channel:512}}> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1517474858}}
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1519142526}}
> enable802154 rx 110 192 672 0
  {{(enable802154)}{802.15.4:Enabled}{rxDefaultState:Rx}{txDefaultState:Rx}{idleTiming:110}
  {turnaroundTime:192}{ackTimeout:672}{defaultFramePending:False}}
> setRxOptions 4
  {{(setRxOptions)}{storeCrc:False}{ignoreCrcErrors:False}{enableDualSync:True}{trackAborted:False}
  {removeAppendedInfo:False}{rxAntenna:Any}{frameDet:On}}
> set802154g 7
  {{(set802154g)}{15.4G_GB868:True}{15.4G_DynamicFEC:True}{Wi-SUN_ModeSwitch:True}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1519819463}}
> setPromiscuousMode 1
  {{(setPromiscuousMode)}{PromiscuousMode:Enabled}}
> setTxDelay 10
  {{(setTxDelay)}{txDelay:10}}
> setTxLength 63
  {{(setTxLength)}{TxLength:63}{TxLength Written:63}}
> resetCounters
  {{(resetCounters)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}
{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}
{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}
{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:512}
{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}
{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:0}{TxChannelBusy:0}{TxClear:0}
{TxCca:0}{TxRetry:0}{UserTxStarted:0}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}
{rxRawSourceBytes:0x000000000}}
```

Note that after a `setchannel`, it is recommended to do “`rx 1`” to get the PHY loaded.

The Mode Switch Rx events configuration:

```sh
> setEventConfig 0x0 0x0 24576 24576
  {{(setEventConfig)}{Mask:0x600000000000}{Values:0x600000000000}}
> printEvents 0x0 24576
  {{(printEvents)}{enablePrintEvents:0x600000000000}}
```

On the Tx side, the `set802154phr` and `trigModeSwitchTx` FSK usage to switch from mode 1b to mode 2a:

```sh
> Set802154phr 1 0 1
{{(Set802154phr)}{PhrSize:2}{PHR:0x8210}}
{{(Set802154phr)}{len:63}{payload: 0x10 0x82 0xb8 0x01 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e}}
> trigModeSwitchTx 3 1
{{(txModeSwitch)}{PacketTx:Enabled}{None:Disabled}{Time:1522467866}}
{{(modeSwitchChangeChannel)}{channel:768}}
{{(appMode)}{None:Enabled}{PacketTx:Disabled}{Time:1522482020}}
{{(txEnd)}{txStatus:Complete}{transmitted:1}{lastTxTime:1522481935}{timePos:6}{lastTxStart:1522475758}{ccaSuccess:2}{failed:0}{lastTxStatus:0x000000000}{txRemain:0}{isAck:False}}
> status
{{(status)}{UserTxCount:2}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}
{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}
{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}
{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:768}
{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}
{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:0}{TxChannelBusy:0}{TxClear:2}{TxCca:2}
{TxRetry:0}{UserTxStarted:2}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}
{rxRawSourceBytes:0x000000000}}
```

On the Rx side, the expected event and the Rx frame are returned:

```sh
{{(event)}{timestamp:2942451808}{eventName:RAIL_EVENT_IEEE802154_MODESWITCH_START}}
{{(rxPacket)}{len:63}{timeUs:2942453545}{timePos:5}{crc:Pass}{filterMask:0x0}{rssi:-8}{lqi:255}
{phy:0}{isAck:False}{syncWordId:0}{antenna:0}{channelHopIdx:254}{channel:768}{ed154:255}
{lqi154:255}{payload: 0x10 0x82 0xb8 0x01 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e}}
> status
{{(status)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}
{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:1}{RxCrcErrDrop:0}{SyncDetect:2}
{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:768}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:1}{TxChannelBusy:0}{TxClear:0}
{TxCca:0}{TxRetry:0}{UserTxStarted:1}{PaProtect:0}{SubPhy0:9}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}
{rxRawSourceBytes:0x000000000}}
```

**Notes:**

1. In Rx status, there are two SyncDetect frames corresponding to Mode Switch PPDU plus the data frame using the new PhyModeID. There is only one Rxcount frame corresponding to the data frame received. The channel is also changed to 768, which is expected.
2. After a Mode Switch PPDU, RAIL does not come back automatically to the FSK base PHY. In the example above, `setchannel 512` must be used to return to the base FSK, before a potential switch to another PHY.

##### A Complete FSK-to-OFDM Mode Switch Example in NA Region

This example shows the initialization of the two PAs and the Mode Switch in RAIL with returned console messages:

```sh
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1516549207}}
>> setchannel 512
  {{(setchannel)}{channel:512}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1516862048}}
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1517030918}}
> setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10  {{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE}{modeIndex:0}{voltage:3600}{rampTime:7}}
> setpower 140
  {{(setpower)}{powerLevel:70}{power:140}}
>> setchannel 512
  {{(setchannel)}{channel:512}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1517474858}}
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1517611032}}
> setchannel 20489
  {{(setchannel)}{channel:20489}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1517885057}}
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1518019524}}
> setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10  {{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE}{modeIndex:2}{voltage:3600}{rampTime:7}}
> setpower 140
  {{(setpower)}{powerLevel:118}{power:135}}
> setchannel 20489
  {{(setchannel)}{channel:20489}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1518471563}}
> setchannel 512
  {{(setchannel)}{channel:512}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1518776089}}
> rx 0
  {{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:1519142526}}
> enable802154 rx 110 192 672 0
  {{(enable802154)}{802.15.4:Enabled}{rxDefaultState:Rx}{txDefaultState:Rx}{idleTiming:110}
  {turnaroundTime:192}{ackTimeout:672}{defaultFramePending:False}}
> setRxOptions 4
  {{(setRxOptions)}{storeCrc:False}{ignoreCrcErrors:False}{enableDualSync:True}{trackAborted:False}
  {removeAppendedInfo:False}{rxAntenna:Any}{frameDet:On}}
> set802154g 7
  {{(set802154g)}{15.4G_GB868:True}{15.4G_DynamicFEC:True}{Wi-SUN_ModeSwitch:True}}
> rx 1
  {{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:1519819463}}
> setPromiscuousMode 1
  {{(setPromiscuousMode)}{PromiscuousMode:Enabled}}
> setTxDelay 10
  {{(setTxDelay)}{txDelay:10}}
> setTxLength 63
  {{(setTxLength)}{TxLength:63}{TxLength Written:63}}
> resetCounters
  {{(resetCounters)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}
{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}
{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}
{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:512}
{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}
{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:0}{TxChannelBusy:0}{TxClear:0}
{TxCca:0}{TxRetry:0}{UserTxStarted:0}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}{rxRawSourceBytes:0x000000000}}
```

Note that after a `setchannel` it is recommended to do “`rx 1`” to get the PHY loaded.

The Mode Switch Rx events configuration:

```sh
> setEventConfig 0x0 0x0 24576 24576
  {{(setEventConfig)}{Mask:0x600000000000}{Values:0x600000000000}}
> printEvents 0x0 24576
  {{(printEvents)}{enablePrintEvents:0x600000000000}}
```

On the Tx side, the `set802154phr` OFDM and `trigModeSwitchTx` from FSK to OFDM to switch from mode #1b to OFDM option 4 MCS4:

```sh
> Set802154phr 2 4 0
  {{(Set802154phr)}{PhrSize:4}{PHR:0x1b80400}}
  {{(Set802154phr)}{len:63}{payload: 0x00 0x04 0xb8 0x01 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e}}
> trigModeSwitchTx 80 1
  {{(txModeSwitch)}{PacketTx:Enabled}{None:Disabled}{Time:3925975352}}
  {{(modeSwitchChangeChannel)}{channel:20480}}
  {{(appMode)}{None:Enabled}{PacketTx:Disabled}{Time:3925988859}}
  {{(txEnd)}{txStatus:Complete}{transmitted:1}{lastTxTime:3925988787}{timePos:6}
  {lastTxStart:3925984019}{ccaSuccess:2}{failed:0}{lastTxStatus:0x000000000}{txRemain:0}
  {isAck:False}}
> status
  {{(status)}{UserTxCount:2}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}
  {AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}
  {NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}
  {ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}
  {Channel:20480}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}
  {RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:0}{TxChannelBusy:0}
  {TxClear:2}{TxCca:2}{TxRetry:0}{UserTxStarted:2}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}
  {SubPhy3:0}{rxRawSourceBytes:0x000000000}}
```

On the Rx side, the expected event and the Rx frame are returned {phy:4} for MCS4:

```sh
{{(event)}{timestamp:4285050697}{eventName:RAIL_EVENT_IEEE802154_MODESWITCH_START}}
{{(rxPacket)}{len:59}{timeUs:4285055046}{timePos:5}{crc:Pass}{filterMask:0x0}{rssi:-6}{lqi:203}{phy:4}{isAck:False}{syncWordId:0}{antenna:0}{channelHopIdx:254}{channel:20480}
{ed154:255}{lqi154:255}{payload: 0x03 0x04 0xb8 0x01 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a}}
status
{{(status)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}
{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:1}{RxCrcErrDrop:0}{SyncDetect:2}
{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}
{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}
{Channel:20480}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}
{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:0}{TxChannelBusy:0}
{TxClear:0}{TxCca:0}{TxRetry:0}{UserTxStarted:0}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}
{SubPhy3:0}{rxRawSourceBytes:0x000000000}}
```

**Notes:**

1. In Rx status, there are two SyncDetect frames corresponding to Mode Switch PPDU plus the data frame using the new PhyModeID. There is only one Rxcount frame corresponding to the data frame received. The channel is also changed to 20480, which is expected with {phy:4} for MCS4.
2. After a Mode Switch PPDU, RAIL does not come back automatically to the FSK base PHY. In the example above, `setchannel 512` must be used to return to the base FSK, before a potential switch to another PHY.

#### RAIL_lib API Usage for Mode Switch PPDU

The following figure provides details about how the RAIL_lib API is used by RAILtest to send/receive a mode switch PPDU followed by a data packet on the new channel. For each RAILtest command taken from the example script in section [Script Example](03-railtest-script-to-use-mode-switch#script-example), RAILtest behavior and especially the calls to the RAIL_lib API are explained. It also clarifies the most significant actions performed by RAIL_lib for the mode switch.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image11.png)

Notes:

- RAIL checks the first bit of the PHR to know if it is Mode Switch PPDU. If Mode Switch is not enabled through `ieee802154Enable()` function, then the Mode Switch PPDU is deleted and not processed.
- The channel mask defined in Wi-SUN FAN 1.1 is managed at the stack level through the callback used by `RAIL RAILCb_IEEE802154_isModeSwitchNewChannelValid()` as shown above.

RAIL_lib structures used for mode switch:

- RAIL_IEEE802154_Config_t: This configuration structure is used to initialize IEEE802.15.4 features, which is required to use mode switch. It is defined in the _rail_ieee802154.h_ file and an example of initialization by RAILtest can be found in _railtest/app_ci/154_rx_ci.c_ file in the `ieee802154Enable()` function.
- RAIL_IEEE802154_ModeSwitchPhr_t: This structure contains a PHYModeID and the corresponding mode switch PHR. It is defined in the _rail_ieee802154.h_ file.

The _rail_config.c_ file contains a RAIL_IEEE802154_ModeSwitchPhr_t table (wisun_modeSwitchPhrs) which is used to format a mode switch packet by writing the mode switch PHR corresponding to the new channel PHYModeId. An example of mode switch packet formatting can be found in _railtest/app_ci/154_rx_ci.c_ file in the `trigModeSwitchTx()` function. The mode switch PHR is described in on Wi-SUN PHY Technical Profile Specification 2V00.

When a Mode switch configuration is saved in _radio_settings.radioconf_, then the generated _rail_config.c_ should contain a constant table `RAIL_IEEE802154_ModeSwitchPhr_t wisun_modeSwitchPhrs` with the selected PhyModeID, as shown in the following example.

![image](/wisun-phy-mode-switch-with-railtest/0.1/images/sld777-image12.png)

#### Known Issues

This section lists only the known issues related to Mode Switch. Other known issues can be found in [Getting Started with Wi-SUN PHY Configuration](/wisun/2.12.0/wisun-phy-quick-start).

- WSTK's LCD and LEDs status are not correctly updated in Rx after `trigModeSwitchTx`.
- When CSMA-CA is enabled, the Mode Switch from PhyModeID 18 to OFDM is not successful and the event _RAIL_EVENT_IEEE802154_MODESWITCH_END_ is raised.

### Getting Started with Concurrent Mode on EFR32FG25 using RAILtest

#### Getting Started with Concurrent Mode on EFR32FG25 using RAILtest

**NOTE: This section replaces _AN1410: Getting Started with Concurrent Mode on EFR32FG25 using RAILtest_. Further updates to this application note will be provided here.**

This document is a quick start guide for Wi-SUN concurrent mode using RAILtest. It describes:

- The Wi-SUN concurrent detection mode provided with EFR32FG25
- How to configure a concurrent PHY with Simplicity Studio
- How to configure and use the concurrent mode through RAILtest
- Known issues

_Proprietary is supported on all EFR32FG devices, although OFDM modulation and concurrent mode are available only on EFR32FG25 devices. In this document, only the RAILtest example application is used._

#### Concurrent Detection Mode Description

Concurrent mode is a dual detection of Wi-SUN FSK and Wi-SUN OFDM frames at the receiver side.

This feature can be considered as an advanced mode switch case without signaling, which improves network performance. This feature requires that the receiver listens to both FSK and OFDM frames simultaneously. The first detected preamble selects the demodulator used for frame reception, FSK or OFDM. As such, only one frame can be received (no concurrent reception).

Given concurrent detection is an extension of mode switch, it is based on Wi-SUN PHY Technical Profile Specification 2V00 and uses all its definitions, in particular:

- The base PHY is the FSK PHY
- The alternate PHY is the OFDM PHY

Concurrent mode could be used by the stack as the Wi-SUN FAN 1.1 mode switch. The channel numbering re-uses the same rules as for Wi-SUN FAN 1.1 as listed below:

- The channel of the new operating mode must be a valid channel as specified by the ChanPlanID and the respective ChanMask in Wi-SUN PHY Technical Profile Specification 2V00.
- The channel of the new mode must be the one with a center frequency closest to that of the original channel used in base mode. If two channels are equally distant from the original channel, the higher channel must be used.

Note that Wi-SUN mode switch and thus the channel selection scheme differ from the one defined in IEEE802.15.4-2020.

The same RF signal is used to do the dual detection. The base (FSK PHY) channel number automatically selects the alternate (OFDM PHY) channel number as shown below for FSK mode XX and OFDM option XX.

![image](/wisun-concurrent-mode-with-railtest/0.1/images/sld778-image1.png)

- Base channel number 0 up to 7 selects alternate channel number 0.
- Base channel number 8 up to 13 selects alternate channel number 1.

Depending on the selected base channel number the Intermediate Frequency (IF) in the receiver is dynamically computed for the base and the alternate PHY. Therefore, the user cannot modify the IF in concurrent mode.

#### Concurrent Mode Radio Configuration

##### Set Up Wi-SUN Concurrent Mode

The concurrent mode configurations available are as shown below:

|Regulatory Domain|Concurrent Base PHY|Concurrent Alternate PHY|
|---|---|---|
|NA|FSK_50kbps_1b FAN1.1 Profile|OFDM option 1 FAN1.1 Profile|
|JP|FSK_100kbps_2b ECHONET Profile|OFDM option 3 FAN1.1 Profile|
|EU|FSK_50kbps_1a FAN1.1 Profile|OFDM option 4 FAN1.1 Profile|

Note: Depending on customer requests, other concurrent modes could be added in the future.

##### Concurrent Mode Configuration using the Simplicity Studio Radio Configurator

![image](/wisun-concurrent-mode-with-railtest/0.1/images/sld778-image2.png)

With the last SiSDK, the Radio Configurator GUI allows you to select a concurrent PHY based on the previous table when selecting a radio profile **Wi-SUN FAN 1.1 Profile** in **Protocol Configuration** as shown below for the NA regulatory domain:

In the **Channel Group**, the base FSK PHY through the Wi-SUN PHY Operating Mode ID could be selected. Then selecting the **Customized** option, it could be possible depending on the FSK base PHY to select an alternate OFDM PHY for concurrent mode detection.

For example, the Wi-SUN FAN 1.1 with NA regulatory domain, the FSK 1b with 50kbps could be a base PHY providing **Concurrent OFDM Option** selection set by default to **NONE** as shown below:

![image](/wisun-concurrent-mode-with-railtest/0.1/images/sld778-image3.png)

![image](/wisun-concurrent-mode-with-railtest/0.1/images/sld778-image4.png)

In the previous snapshot with **Concurrent OFDM Option** set to **NONE**, it is an FSK mode 1b providing 50kbps with PHY Operating Mode ID=2. In the **Concurrent OFDM Option** list, the OFDM option can be selected to get a concurrent PHY with FSK plus OFDM as shown below:

The **Alternate Base Channel Frequency**, the **Alternate Channel Spacing**, and the **Alternate Number of Channels** are provided by default. These fields values are compliant as specified by the ChanPlanID in Wi-SUN PHY Technical Profile Specification 2V00. It is possible to modify these values nevertheless note the FSK channel plan should be compatible with the OFDM channel plan as described in section 1.

Notes:

- For Regulatory domain JP, the PHY FSK_100kbps_2b uses the ECHONET Profile in place of FAN1.1 Profile with a preamble length of 15 bytes and an FCS length with 2 bytes CRC.
- For Regulatory domain EU, a channel mask applies and forbids the use of some available channels in the middle and at the end of the RF band. The channel masking in the middle of the RF band is taken into account thanks to a RAIL callback provided by the stack (see [RAIL_lib API Usage for Mode Switch PPDU](/wisun/2.12.0/wisun-phy-mode-switch-with-railtest/04-rail-lib-api-usage-for-mode-switch-ppdu)).

#### Concurrent Mode with RAILtest

This section assumes the EFR32FG25 is flashed with a RAILtest application image with a Wi-SUN concurrent PHY as described in the previous section.

##### Concurrent Mode Usage at the Rx Side

With a concurrent PHY, the following steps are required at the receiver side:

- All PA selected in the channel-based multi-PHY must be initialized (only required once at initialization, FSK PA first then OFDM PA).
- Set up the PA configuration.
- Set the recommended PA level (check the max level depending on the radio board, 16 dBm for EFR32FG25).
- For IR calibration for OFDM PHY, call `setchannel` followed by “`rx 1`” for IR calibration.

The following is an example for NA concurrent mode using `configindex 0` and `setchannel 0` with the rail_config.c described in previous section:

```sh
rx 0
setconfigindex 0
setchannel 0
rx 1
#### FSK and OFDM PA configuration + Calibration
rx 0
setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
setpower 100
setchannel 0
rx 1
rx 0
setchannel 0
rx 1
rx 0
setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
setpower 100
setchannel 0
rx 1
```

##### Concurrent Mode Usage at the Tx Side

With a concurrent PHY, use the same initialization at the transmitter side as at the receiver side, with some additional configurations for Tx.

The following additional steps are required:

- `setTxdelay 10`: Set 10 ms between data frames.
- `setTxLength 63`: Set the data frame length. This could be another frame length value. Remember to call `set802154Phr` after a new `setTxLength`. Note that FSK frame length corresponds to `setTxLength` value -2 and that OFDM frame length corresponds to `setTxLength` value -4.
- `configTxOptions`: Provides a way to select the base PHY or the alternate PHY in Tx through the `concurrentPhyId` field. Set to 0 to select the base PHY or 512 to select the alternate PHY.
- `set802154Phr`: Uses different parameters between FSK and OFDM frame, as described in [Getting Started with Wi-SUN PHY](/wisun/2.12.0/wisun-phy-quick-start/). For OFDM PHY, `set802154Phr` should be set with the selected MCS and the new PhyModeID.

The following is an example for NA using `configindex 0`:

```sh
rx 0
setconfigindex 0
setchannel 0
rx 1
rx 0
setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
setpower 160
setchannel 0
rx 1
rx 0
setchannel 0
rx 1
rx 0
setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
setpower 160
setchannel 0
rx 1
setTxDelay 10
setTxLength 63
#### CCA : enable CSMA-CA
setLbtMode csma
setLbtParams 0 0 1 -80 0 160 0

#to Tx FSK frames
rx 0
configTxOptions 0
rx 1
set802154Phr 1 0 1
tx 1

#to Tx OFDM frames using MCS4
rx 0
configTxOptions 512
rx 1
set802154Phr 2 4 0
tx 1
```

Notes:

- this previous script also allows receiving either FSK or OFDM frames.
- For FSK 2b ECHONET Profile, the set802154Phr parameters are as shown below:  
  ```sh  
  set802154Phr 1 1 1  
  ```

##### A Complete Example

This section provides a complete Tx and Rx example, along with illustrations of diagnostic signals.

###### A Complete Tx and Rx Example

This complete example shows how to transmit FSK and OFDM modulated packets with the EFR32FG25 radio using the RAILtest application on the concurrent PHY.

```sh
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:79293671}}
> setconfigindex 0
{{(setconfigindex)}{configIndex:0}{firstAvailableChannel:0}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:79693550}}
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:79824401}}
> setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
{{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE }{modeIndex:0}{voltage:3600}{rampTime:7}}
> setpower 160
{{(setpower)}{powerLevel:255}{power:160}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:80369403}}
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:80503536}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:80764283}}
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:80901650}}
> setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
{{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE }{modeIndex:2}{voltage:3600}{rampTime:7}}
> setpower 160
{{(setpower)}{powerLevel:255}{power:160}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:81440368}}
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:81440855}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:81442897}}
> status
{{(status)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:0}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:1}{TxChannelBusy:0}{TxClear:0}{TxCca:0}{TxRetry:0}{UserTxStarted:1}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}{rxRawSourceBytes:0x000000000}}
> setTxDelay 10
{{(setTxDelay)}{txDelay:10}}
> setTxLength 63
{{(setTxLength)}{TxLength:63}{TxLength Written:63}}

#### CCA : enable CSMA-CA
> setLbtMode csma
{{(setLbtMode)}{LbtMode:CSMA}}
> setLbtParams 0 0 1 -80 0 160 0
{{(setLbtParams)}{MinBo:0}{MaxBo:0}{Tries:1}{Threshold:-80}{Backoff:0}{Duration:160}{Timeout:0}}

#### Tx FSK frame
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:82890344}}
> configTxOptions 0
{{(configTxOptions)}{waitForAck:False}{removeCrc:False}{syncWordId:0}{txAntenna:Any}{altPreambleLen:False}{ccaPeakRssi:False}{ccaOnly:False}{resend:False}{concurrentPhyId:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:83181435}}
> set802154Phr 1 0 1
{{(set802154Phr)}{PhrSize:2}{PHR:0x8210}}
{{(set802154Phr)}{len:63}{payload: 0x10 0x82 0x11 0x22 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e}}
> tx 1
{{(tx)}{PacketTx:Enabled}{None:Disabled}{Time:83480564}}
{{(appMode)}{None:Enabled}{PacketTx:Disabled}{Time:83507884}}
{{(txEnd)}{txStatus:Complete}{transmitted:1}{lastTxTime:83507848}{timePos:6}{lastTxStart:83484458}{ccaSuccess:1}{failed:0}{lastTxStatus:0x000000000}{txRemain:0}{isAck:False}}
> status
{{(status)}{UserTxCount:1}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:0}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:1}{TxChannelBusy:0}{TxClear:1}{TxCca:1}{TxRetry:0}{UserTxStarted:2}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}{rxRawSourceBytes:0x000000000}}

#### Tx OFDM frame using MCS4
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:83933827}}
> configTxOptions 512
{{(configTxOptions)}{waitForAck:False}{removeCrc:False}{syncWordId:0}{txAntenna:Any}{altPreambleLen:False}{ccaPeakRssi:False}{ccaOnly:False}{resend:False}{concurrentPhyId:1}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:84214833}}
> set802154Phr 2 4 0
{{(set802154Phr)}{PhrSize:4}{PHR:0x1b80400}}
{{(set802154Phr)}{len:63}{payload: 0x00 0x04 0xb8 0x01 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e}}
> tx 1
{{(tx)}{PacketTx:Enabled}{None:Disabled}{Time:84518189}}
{{(appMode)}{None:Enabled}{PacketTx:Disabled}{Time:84523714}}
{{(txEnd)}{txStatus:Complete}{transmitted:1}{lastTxTime:84523676}{timePos:6}{lastTxStart:84522105}{ccaSuccess:1}{failed:0}{lastTxStatus:0x000000000}{txRemain:0}{isAck:False}}
> status
{{(status)}{UserTxCount:2}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:0}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:1}{TxChannelBusy:0}{TxClear:2}{TxCca:2}{TxRetry:0}{UserTxStarted:4}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}{rxRawSourceBytes:0x000000000}}
```

The following example displays the reception of previous Tx FSK and OFDM modulated packets with the EFR32FG25 radio using the RAILtest application on the concurrent PHY:

```sh
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:82699471}}
> setconfigindex 0
{{(setconfigindex)}{configIndex:0}{firstAvailableChannel:0}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:83088638}}

#### FSK and OFDM PA configuration + Calibration
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:83346793}}
> setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE 3600 10
{{(setpowerconfig)}{sucess:true}{mode:RAIL_TX_POWER_MODE_SUBGIG_POWERSETTING_TABLE}{modeIndex:0} {voltage:3600} {rampTime:7}}
> setpower 160
{{(setpower)}{powerLevel:255}{power:160}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:83892640}}
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:84020488}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:84278019}}
> rx 0
{{(rx)}{Rx:Disabled}{Idle:Enabled}{Time:84408265}}
> setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
{{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE} {modeIndex:2}{voltage:3600}{rampTime:7}}
> setpower 160
{{(setpower)}{powerLevel:255}{power:160}}
> setchannel 0
{{(setchannel)}{channel:0}}
> rx 1
{{(rx)}{Rx:Enabled}{Idle:Disabled}{Time:84929530}}

> status
{{(status)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:0}{RxCrcErrDrop:0}{SyncDetect:0}{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:0}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:1}{TxChannelBusy:0}{TxClear:0}{TxCca:0}{TxRetry:0}{UserTxStarted:1}{PaProtect:0}{SubPhy0:0}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}{rxRawSourceBytes:0x000000000}}

#### **Rx event of one FSK frame** (with incorrect RSSI level see known issues)
{{(**rxPacket**)}{len:63}{timeUs:110705035}{timePos:5}{crc:Pass}{filterMask:0x0}{rssi:-86}{lqi:255}{phy:0}{isAck:False}{syncWordId:0}{antenna:0}{channelHopIdx:254}{channel:0}{payload: 0x10 0x82 0x11 0x22 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e}}

#### **Rx event of one OFDM frame**
{{(**rxPacket**)}{len:59}{timeUs:111720745}{timePos:5}{crc:Pass}{filterMask:0x0}{rssi:-47}{lqi:235}{phy:4}{isAck:False}{syncWordId:0}{antenna:0}{channelHopIdx:254}{channel:0}{payload: 0x03 0x04 0xb8 0x01 0x33 0x44 0x55 0x0f 0x77 0x88 0x99 0xaa 0xbb 0xcc 0xdd 0xee 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26 0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e 0x2f 0x30 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x3a }}
> status
{{(status)}{UserTxCount:0}{AckTxCount:0}{UserTxAborted:0}{AckTxAborted:0}{UserTxBlocked:0}{AckTxBlocked:0}{UserTxUnderflow:0}{AckTxUnderflow:0}{RxCount:2}{RxCrcErrDrop:0}{SyncDetect:2}{NoRxBuffer:0}{TxRemainErrs:0}{RfSensed:0}{ackTimeout:0}{ackTxFpSet:0}{ackTxFpFail:0}{ackTxFpAddrFail:0}{RfState:Rx}{RAIL_state_active:0}{RAIL_state_rx:1}{RAIL_state_tx:0}{Channel:0}{AppMode:None}{TimingLost:0}{TimingDetect:0}{FrameErrors:0}{RxFifoFull:0}{RxOverflow:0}{AddrFilt:0}{Aborted:0}{RxBeams:0}{DataRequests:0}{Calibrations:1}{TxChannelBusy:0}{TxClear:0}{TxCca:0}{TxRetry:0}{UserTxStarted:1}{PaProtect:0}{SubPhy0:1}{SubPhy1:0}{SubPhy2:0}{SubPhy3:0}{rxRawSourceBytes:0x000000000}}
```

##### Diagnostic Signals

With concurrent PHY, both stream mode (PN9) and CW signal generation are supported. The selection between FSK or OFDM Tx path is done using `configTxOptions` with value 0 for FSK and 512 for OFDM.

As an example, the following CLI commands configure and enable the PN9 stream transmission mode on the radio using the Base FSK PHY using `configindex 0`.

```sh
> setconfigindex 0
> rx 0
> setpowerconfig RAIL_TX_POWER_MODE_SUBGIG_PA_POWERSETTING_TABLE 3600 10
> setpower 140
> rx 1
> configTxOptions 0
> set802154Phr 1 0 1
> setTxStream 1
```

Note with the FSK, the `setTxStream` is not running correctly so it is recommended to use the FSK PHY without the concurrent mode using OFDM (see the known issues in section 4).

For OFDM path, PN9 stream mode also requires setting up PHR (with the `set802154PHR` command) to select MCS Level. Before this it is also mandatory to configure the frame length field to 4 before the transmission, to set up the infinite stream needed for PN9.

As an example, the following CLI commands configure and enable the PN9 stream transmission mode on the radio in OFDM option 1 MCS4 at `configindex 1`.

```sh
> setconfigindex 1
> rx 0
> setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
> setpower 140
> rx 1
> configTxOptions 512
> setTxLength 4
> set802154Phr 2 4 0
> setTxStream 1
```

Example:

```sh
> setconfigindex 1
{{(setconfigindex)}{configIndex:1}{firstAvailableChannel:0}}
> setpowerconfig RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE 3600 10
{{(setpowerconfig)}{success:true}{mode:RAIL_TX_POWER_MODE_OFDM_PA_POWERSETTING_TABLE }{modeIndex:2}{voltage:3600}{rampTime:7}}
> setpower 140
{{(setpower)}{powerLevel:255}{power:140}}
> configTxOptions 512
{{(configTxOptions)}{waitForAck:False}{removeCrc:False}{syncWordId:0}{txAntenna:Any}
{altPreambleLen:False}{ccaPeakRssi:False}{ccaOnly:False}{resend:False}{concurrentPhyId:1}}
> setTxLength 4
{{(setTxLength)}{TxLength:4}{TxLength Written:4}}
> set802154Phr 2 4 0
{{(set802154Phr)}{PhrSize:4}{PHR:0x400}}
{{(set802154Phr)}{len:4}{payload: 0x00 0x04 0x00 0x00}}
> setTxStream 1
{{(setTxStream)}{Stream:Enabled}{None:Disabled}{StreamMode:PN9}{Time:1737513509}}
```

To send a tone at the carrier frequency, the following CLI command can be used:

```sh
> setTxTone 1
```

Examples:

```sh
#### To Start the tone
> setTxTone 1
{{(setTxTone)}{Stream:Enabled}{None:Disabled}{StreamMode:Tone}{Time:1293513244}}
#### To Stop the tone
> setTxTone 0
{{(setTxTone)}{None:Enabled}{Stream:Disabled}{Time:1298384979}}
```

It is equivalent to:

```sh
> setTxStream 1 0
```

#### Known Issues

In this section, only the known issues related to concurrent mode are listed. Other known issues can be found in [Getting Started with Wi-SUN PHY](/wisun/2.12.0/wisun-phy-quick-start) and for Wi-SUN Mode Switch in [Wi-SUN PHY Mode Switch on EFR32FG25 with RAILtest](/wisun/2.12.0/wisun-phy-mode-switch-with-railtest).

##### Known Issues

- Diagnostic signals for concurrent PHY selecting FSK are not running correctly. So, it is recommended to use the FSK PHY in place of the concurrent PHY.
- The RSSI provided with FSK Rx frame could be with an offset in comparison with the RSSI provided with OFDM Rx frame.

## API Reference

### Wi-SUN Stack Changelog

### Release 2.12

(release date TBC)

#### New Features and Improvements

- added support for LLVM Clang
- added SoC direct connect client
- introduced [sl_wisun_set_dhcpv6_vendor_data()](sl-wisun-api#sl-wisun-set-dhcpv6-vendor-data) to set custom vendor data in DHCPv6 Solicit messages
- improved key rotation reliability by retrying to fetch the new key(s) indefinitely during the rotation window
- LFN adapts its listening strategy to measured drift of its parent
- improved recovery of LFN after parent reboot
- improved asynchronous frames TX fairness between nodes
- expanded wisun_rf_test component with tx and rx modes
- persist RPL DODAG ID in NVM to reset RPL DAO sequence on DODAG ID change
- persist RPL DAO sequence in NVM in both linear and circular region to prevent DAO packet drop by BR
- introduced wisun_alloc plugin to reserve a separate heap dedicated to critical Wi-SUN features
- select a free PRS channel for RAIL RTCC sync to avoid conflicts with FEM and RF switch PRS channels
- introduce PAN-wide channel mask for explicit channel plan
- add mandatory AZ/NZ phys in default radio configuration
- deprecated Border Router parameter 'dhcp_address_lifetime_s'
- reduced useless RPL traffic and potential ICMPv6 "destination unreachable" errors by dropping DAO-ACKs to outdated DAOs
- allow up to 8 LFN multicast group enrollment
- enabled SL_WISUN_MSG_ERROR_IND_ID to indicate allocation failures
- introduced new sl_wisun_set_last_gasp API to enter/leave Last Gasp mode
- introduced new sl_wisun_set_first_breath API
- Broadcast Slot Number is always 0 in fixed channel (FAN TPS change)
- introduced sl_wisun_set_option API
- introduced sl_wisun_reset_parameters API
- introduced sl_wisun_set_ffn_advanced_parameters API
- introduced sl_wisun_set_lfn_advanced_parameters API
- introduced sl_wisun_br_set_advanced_parameters API
- introduced a default "automatic" mode to remove the need for manual connection parameter configuration. See sl_wisun_set_option documentation for details.
- introduced SL_WISUN_OPTION_JOIN_NODE_COUNT to override the PAN size used for automatic parameter adjustment. See documentation for details.
- deprecated the legacy sl_wisun_br_set_network_size API
- deprecated temp_link_min_timeout_s field from [sl_wisun_params_misc_s](sl-wisun-params-misc-s) and [sl_wisun_br_params_misc_s](sl-wisun-br-params-misc-s)
- read POM-IE from EAPOL frames
- allow setting SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MS at any time.
- introduced [sl_wisun_lfn_params_t](sl-wisun-lfn-params-t) v5, added lpas_interval_s
- LPAS frames may be triggered with API [sl_wisun_trigger_frame()](sl-wisun-api#sl-wisun-trigger-frame)
- POSIX-aligned the socket-related headers under `stack/inc/posix/` (`sys/socket.h`, `sys/select.h`, `arpa/inet.h`, `netinet/in.h`, `netinet/ip6.h`); the legacy `socket/socket.h` and `socket/select.h` umbrella headers remain as compatibility aggregators so existing application code keeps building unchanged

##### RCP API

- 2.20.1  
  - Give high priority to LPA frames in REQ_DATA_TX compared to LFN unicast.
- 2.20.0  
  - Support disabling LFN broadcast with SET_FHSS_LFN_BC.  
  - Start LFN broadcast on REQ_RADIO_ENABLE instead of first LPA REQ_DATA_TX.
- 2.19.1  
  - Fix CNF_DATA_TX returning ambiguous status codes.
- 2.19.0  
  - Add status COUNTER_EXHAUSTED to CNF_DATA_TX.
- 2.18.0  
  - When initiating EDFE with REQ_DATA_TX, put data in the initial frame.
- 2.17.0  
  - Support absolute offset in LTO-IE with REQ_DATA_TX.
- Add SoC direct connect client
- replaced internal event task by the usage of sl_event_system
- added a component that reads sl_event_system and calls sl_wisun_on_event
- moved sl_statistics timer to lower priority ns_event_loop

#### Bug Fixes

- ignore incorrectly sized excluded channel mask in US-IE, BS-IE and LCP-IE
- fixed potential additional authentication traffic when changing PAN
- fixed impossibility to clear MAC address table when table is full
- fixed authentication not skipped on reboot with valid credentials in NVM
- fixed incorrect TX abort handling during CCA causing TX inability until fallback to join state 1
- fixed dropping loopback traffic
- fixed IPv6 connectivity issue with Wi-Fi backhaul
- fixed [sl_wisun_get_join_state()](sl-wisun-api#sl-wisun-get-join-state) returning an error during transition from JS 5 to JS 1
- fixed LPA frame timeout: use 300s as intended instead of LFN unicast timeout
- fixed lowpan fragment reassembly timeout
- fixed dropped frames without source address when MAC filtering is enabled
- fixed unwanted decrement of hop limit when forwarding multicast packets to LFNs
- fixed new neighbor entries not inheriting the configured default rate algorithm
- fixed potential memory corruption on error during 6LoWPAN fragmentation
- fixed nodes getting stuck in JS4 when deleting a MAC neighbor that was being probed for ETX
- fixed OFDM channel number inconsistent with Simplicity Studio tools
- fixed LCP-IE verification on LFN. Frame containing invalid LCP-IE are now discarded.
- fixed LFNs sometimes taking longer than expected to notice their parent is disconnected.
- fixed LFNs mistakenly sending GTKL KDE in Key Requests
- fixed KDE ordering in Key Requests
- fixed Transmit Flow Control calculation in mode switch
- fixed not unregistering a node's GUA to its former secondary parent
- fixed LFN multicast group not completely removed when registration fails
- fixed [sl_wisun_get_network_info()](sl-wisun-api#sl-wisun-get-network-info) reporting wrong PAN ID when disconnected
- fixed LFN multicast group registration not refreshed on LFN reconnection
- fixed closing Direct Connect session on frame counter error
- fixed initiating MPL forwarding for raw Wi-SUN multicast packets received that do not originate from a LFN child
- fixed handling of channel busy rail event on rf test
- fixed insertion of NR KDE in EAPOL Key Requests while configured for FAN 1.0
- fixed abnormally long timeouts in MAC for frames with an LFN destination

### Release 2.10

(release date TBC)

#### New Features and Improvements

- made FreeRTOS the default RTOS in all sample applications
- added handling of LTO-IE with 0 ms Adjusted Listening Interval
- added DAO transmission parameters
- added DODAG version number and DTSN to the SoC BR's NVM. Added a DTSN increase in case of unexpected SoC BR's reboot
- made the BR SoC send a PCS on reboot to retrieve the broadcast timings quicker
- update sl_wisun_set_pom_ie to remove POM-IE when phy_mode_id_count = 0
- improved the reliability of transmissions towards LFN
- removed associated EARO routes when the BR SoC receives a DAO without itself in the transits
- added [sl_wisun_br_revoke_pairwise_keys()](sl-wisun-br-api#sl-wisun-br-revoke-pairwise-keys) and [sl_wisun_br_revoke_gtks()](sl-wisun-br-api#sl-wisun-br-revoke-gtks)
- LFNs maintain TID across power cyclings
- reworked the BR SoC routing, now always takes the nodes' RPL prefered parent advertised in DAOs to route packets
- improved protection against key reinstallation
- added MAC parameters
- added [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters). Deprecate sl_wisun_set_regulation API.
- added [sl_wisun_set_eap_identity()](sl-wisun-api#sl-wisun-set-eap-identity)
- improved DIS transmission strategy in order to not overload the device in crowded networks
- added EAPOL, traffic and MAC to LFN parameters
- set routing cost to 0xffff when neighbor table is full
- RCP requires FreeRTOS
- RCP recommends CPC but requires it with Ocelot
- always send the packets to the BR through the preferred parent
- added concurrent detection statistics (global and by neighbor)
- reduced the amount of unnecessary address registration
- introduced an LFN lib supporting efr32xg23 parts
- drop wisun_rb_detection component
- improved LFN LPCS retry policy
- added [sl_wisun_br_get_routing_table_from_index()](sl-wisun-br-api#sl-wisun-br-get-routing-table-from-index)
- ncp application is production level
- ROVR set to 0 in multicast NA
- reject unsupported FFN-managed LFN Window Style
- added api to log events
- improve handling of frame counter rollover
- added [sl_wisun_set_rx_fifo_size()](sl-wisun-api#sl-wisun-set-rx-fifo-size)
- release libraries are LTO-enabled
- improved default eapol key-request parameters
- added [sl_wisun_set_fan_tps_version()](sl-wisun-api#sl-wisun-set-fan-tps-version)
- improved network responsiveness to RPL metric updates to better ensure connection continuity
- improved connection stability by staying connected the primary parent's rank goes over the rank limit
- improved MAC security neighbor table management
- added blocking mode support for the tcp connect request
- duty cycle level indications are more reactive
- added api sli_wisun_clear_event_filters to clear all event logger filters
- added MRHOF hysteresis to backup parents selection
- limited the size of the RPL parent set to 4 parents max
- removed the RSL threshold applied over radio sensitivity that prevented accepting in-range RPL candidates
- removed limitation on parent and rank change in join state 5 and above to better reflect RPL metric updates
- set rpl_dio_redundancy_constant to 0 in the border router's connection parameters in all network sizes
- fixed EDFE frame format in FAN 1.0 mode
- added DHCP solicit transmission parameters
- added dao_max_delay_s to RPL parameter set
- LFN listen interval must be included in NR-IE
- removed explicit PTI enable from Wi-SUN stack initialization, the default state can be set in sl_rail_util_pti configuration
- always insert an IPv6 tunnel header when routing to a LFN parent
- prioritize LFN transmission on FFN BC dwell interval
- ignored A flag in DAO-ACK status
- accept tunneled IPv6 packets without any RPL hop-by-hop option nor Source Routing Header
- removed Random Early Detection congestion algorithm
- handle multicast originated by LFN
- replaced NS-ARO zero lifetime with a 60s lifetime
- persist RPL DAO sequence in NVM until DAO-ACK RX with a DAO sequence in the circular portion
- improved MAC retry strategy
- refuse registering DAO routes creating source routing loop at the border router
- reduced delay before transmission. Improved maximum throughput
- added all mandatory phys in default radio configuration
- added CCA busy log with channel in MAC
- improved LFN parenting features and dropped LFN_PAN_TIMEOUT as required by FAN-TPS 1.1v11
- updated Singapore Channel Plan Id according to Phy TPS 2v04
- Updated Brazil Channel mask according to Phy TPS 2v04

##### RCP API

- 2.16.0  
  - Add SET_LOG command.
- 2.15.1  
  - Configure BC fixed channel with SET_FHSS_FFN_BC.
- 2.15.0  
  - Add SET_DATA_EDFE command.
- 2.14.0  
  - Support changing UC channel function while being in fixed channel in SET_FHSS_UC.  
  - FATAL when using 0 dwell interval in SET_FHSS_UC.
- 2.13.0  
  - Add SET_RADIO_APC command.
- 2.12.0  
  - Add SET_RADIO_CSMA command.
- 2.11.0  
  - SET_RADIO_REGULATION always resets regulation data when called.  
  - Add flag in REQ_DATA_TX to enable reporting of TX duration over the last hour in CNF_DATA_TX.  
  - Add REQ_RADIO_TX_DURATION_RESET command.

#### Bug Fixes

- fixed authenticator dropping supplicant retries with high congestion
- fixed socket TX buffer full in case of routing or memory error
- fixed timeout management on asynchronous packets
- fixed async fragment could be split with DFE/EDFE frames
- fixed segmentation fault when unexpected EDFE final frame is received
- fixed a fault when an LFN fails to complete multiple handshakes in join state 5
- fixed node failing to connect after obtaining an inactive GTK first
- fixed not decrementing hop limit when forwarding multicast packets to LFNs
- fixed authenticator vulnerability to installation of predictable keys
- fixed CCA threshold value used for O-QPSK PHYs
- fixed memory corruption when returning to join state 1 while proxying RPL for LFNs
- fixed MAC tx confirmation overwriting previous one in case of consecutive failures
- fixed memory corruption when processing RPL source routing header with size increase
- fixed memory leak when authenticator sends eapol key packets
- fixed assert when memory allocation fails
- fixed supplicant not responding to 4WH-Msg3 retries
- fixed segmentation fault if [sl_wisun_reset_statistics()](sl-wisun-api#sl-wisun-reset-statistics) is called before connection
- fixed missing Frame Counter increment on reboot during initial connection
- fixed unhandled allocation issue leading to NULL pointer exception
- fixed Frame Counter reset when using eapol.allow_skip=false parameter
- fixed initial_key_max_s overflowing when set above 65
- fixed LFN directly connected to the BR not appearing in the routing table
- fixed NS zero lifetime being sent before receiving a DAO-ACK
- fixed radio being disabled after mode switch PHR RX on LFN, which could block further TX/RX
- fixed stopping DHCP and EAPOL relays when falling back to JS 4.1
- fixed connectivity loss between BR and direct children when RPL Transits are not in RPL PC order in DAO
- fixed MAC security neighbor table growing beyond configured maximum
- fixed invalid security neighbor table entry allocation on unsecured frame RX
- fixed segmentation fault if aborting during transmission of a ack/response frame or mode switch
- fixed empty SRH handling
- fixed potential segmentation fault on malformed SRH
- fixed congestion caused by queued MPL frames that were not aborted despite heard trickle consistency
- fixed LFN supplicant crash after many authentication failures
- fixed RPL parents not being removed when they try to register with an NS(ARO)
- fixed invalid parent selection behavior on parent DagRank increase preventing secondary parent usage
- fixed multicast DIO not being sent instantly on DagRank increase
- fixed looped-back multicast packets being forwarded twice more than expected to registered LFNs
- fixed MAC FSM and RAIL RX timeout using slowest PHY
- fixed DAO sequence incremented on every retry
- fixed LFN proxy DAOs not being sent when a DAO is already in transit
- fixed possible memory corruption when number of hop is too high
- fixed do not remove neighbor used for EAPOL relay or DHCP relay
- fixed use after free in EDFE
- fixed calculation of UIO on LFN timing change
- fixed a crash during initialization on OFDM-only PHY configuration
- fixed a rare crash caused by fallback to join state 1 resetting current call stack used variables
- fixed possible lock in MAC during mode switch
- fixed null pointer dereference in RPL proxy when receiving NS(EARO) from LFN while disconnected
- configure BC fixed channel on BT-IE received from trusted nodes in RCP
- fixed handling of POM-IE in LPA frames
- fixed LFN maintain route to parent after lost connection
- fixed packets dropped in lowpan_down never confirmed to upper layer (e.g. socket)
- fixed handling of LTO-IE in LPA, LPC and EAPOL frames (both TX and RX)
- fixed latest L/GTK lifetime on revocation
- fixed LFN parent imprecisely targetting the LFN slot start
- fixed RCP not writing LBT-IE in ACKs to LFNs
- fixed handling of masked channel plans
- fixed assert in IRQ triggering exception
- fixed MAC could send packet out of order
- fixed memory leak when relaying EAPoL-Relay packets to targeted FFN
- fixed encrypted frames being processed from join state 1 when reconnecting
- fixed unexpected PAN ID on roam from join state 2
- fixed SRH handling in LFNs
- fixed mode-switch configuration failure while stack is already started

### Release 2.6

(release date 2025-06-04)

#### New Features and Improvements

- removed data available traces on BR SoC CLI for the dhcpv6 socket
- added MAC statistics to track the time spent in idle and TX states
- introduced [sl_wisun_connection_params_t](sl-wisun-connection-params-t) v6
- added MPL statistics
- introduced [sl_wisun_lfn_params_t](sl-wisun-lfn-params-t) v3, added eapol_unicast_interval_ms
- added [sl_wisun_set_preferred_pan()](sl-wisun-api#sl-wisun-set-preferred-pan) API
- wisun_fan_certification component uses stack's default FAN TPS Version (FAN 1.1)
- limit the number of children a router can accept
- deny temporarily a router unable to parent
- updated BZ and SG channel plans according to PHY TPS 2v03
- FFN and LFN now have storage for Frame Counters of up to 15 different PAN
- ETSI Adaptive Power Control available for EU PHYs
- add sl_wisun_config_neighbor_table_size API. Deprecate sl_wisun_set_neighbor_table_size API.
- add new security neighbor table
- ACK timeout now measured to start of response frame. It allows being back to RX channels right after Tack if no response is received.
- added debug MAC traces by default in RCP
- chan_params_table ownership is transfered to application
- FC-IE transmit flow control now corresponds to the estimated frame duration
- WH-IEs from duplicate frames are now processed.
- extended [sl_wisun_statistics_heap_t](sl-wisun-statistics-heap-t) to output highest used, currently used, free and total heap space.
- added concurrent detection support and [sl_wisun_config_concurrent_detection()](sl-wisun-api#sl-wisun-config-concurrent-detection) API
- exposed the node's estimated hop count to the BR in [sl_wisun_network_info_t](sl-wisun-network-info-t). Added the SL_WISUN_NETWORK_UPDATE_FLAGS_HOP_COUNT event
- added GlobalSign and Wisekey device credentials in Wi-SUN SoC CLI
- added Wisekey device credentials in Wi-SUN SoC Border Router CLI
- added multi fragments EDFE support in SOC
- removed automatic global repair that was done every 12 hours
- added [sl_wisun_br_trigger_global_repair()](sl-wisun-br-api#sl-wisun-br-trigger-global-repair) to manually trigger a global repair
- Node Role IE includes LBATS Implemented field
- do not send unicast DIS to denied neighbors
- delay initial DIS so it doesn't overlap with PC sequence
- add DMP support
- introduced Wi-SUN NVM versioning
- removed OQPSK SFM configuration in sample applications
- add more meaningful status codes for SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID indication
- introduced [sl_wisun_br_get_routing_table_entry_count()](sl-wisun-br-api#sl-wisun-br-get-routing-table-entry-count) and [sl_wisun_br_get_routing_table()](sl-wisun-br-api#sl-wisun-br-get-routing-table) for the SoC Border router
- added an event on BR routing table updates (the type of update is differentiated)
- improved LFN strategy after authentication failure
- added Vendor Payload IE to advertise the node's concurrent detection capabilities

##### RCP API

- 2.10.0  
  - Support concurrent detection in transmission.  
  - Add alternate PHYs to REQ_RADIO_LIST command.
- 2.9.0  
  - add command to update LFN unicast schedule for TX
- 2.8.0  
  - Use Source PAN ID specified in 15.4 header when relevant. Previously, the PAN ID set with SET_FILTER_PANID was always used, which lacked flexibility. An error would occur if the Source PAN ID in the 15.4 header differed from the one set.
- 2.7.0  
  - fix tx-abort command
- 2.6.0  
  - handle channel masks for mode-switch

#### Bug Fixes

- fixed mode switch feature from router / border router to LFN
- fixed PSA crypto key leak preventing authentication after multiple attempts over the device's lifetime
- Border Router parameters can only be set while stopped
- drop security handshake frames from a previous connection
- fixed issue preventing LFN from sending LPAS correctly
- LFN unregister from multicast group when the corresponding socket is closed
- fixed RCP reset triggered when MAC would purge LFN frames upon LFN PAN Advertisement transmission
- seeded MPL messages are now sent the same number of times as their trickle's parameter TimerExpirations
- fixed buffer read overflow in [sl_wisun_br_set_ipv6_prefix()](sl-wisun-br-api#sl-wisun-br-set-ipv6-prefix)
- fixed use-after-free in case of DHCPv6 failure
- fixed dhcp preferred lifetime when address lifetime is infinite
- fixed wrong error message in wisun_soc_cli when reconnecting during an ongoing disconnection
- fixed tasks' priority in SoC BR
- fixed unregistering when changing parent (send NS(ARO) with no lifetime)
- fixed RPL GLobal Repair, no DAO was transmitted if the same preferred parent was selected
- fixed a memory corruption causing authentication failures on Secure Vault Mid devices
- fixed Neighbor Cache Refresh
- fixed issue blocking an LFN in reception state for the duration of a broadcast interval
- fixed aborted frames generating no confirmation
- fixed Source Addressing Mode of EDFE Response Frames in wisun_rcp
- fixed LFN PAN Advertisements sometimes stuck until timeout
- fixed sl_wisun_br_dhcpv6_set_vendor_data API
- fixed EDFE retries not done with a CCA backoff
- fixed an FHSS synchronization issue due to incorrect UFSI values
- fixed radio configuration file error with SG phys
- advertise border router address/prefix lifetime as infinite instead of 0 in DIO packets
- fixed nodes roaming back and forth with PAN Defect and Preferred PAN enabled
- fixed missing timeout for LFN broadcast packet
- analyze inner IPv6 headers to refresh neighbor address registrations
- fixed node stuck in Join State 3 when it cannot decrypt a PC from its previous PAN
- fixed handling of SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID on BR CLI
- prevent dao path sequence counter from resetting when going to join state 1 and 3
- fixed rescheduling issue with LFN frames that would make a node completely unable to operate
- fixed invalid duplicated frame detection from LFN neighbors as an FFN
- fixed invalid duplicated frame detection from FFN parent as an LFN
- fixed cleaning of LFN neighbors in MAC neighbor table
- fixed return option value of [getsockopt()](sl-wisun-socket-api#getsockopt) for SO_SNDLOWAT option
- Path Lifetime in DAO is rounded up
- fixed LFN issue when multiple frames advertise an updated LUS-IE
- handle invalid 4WH message 3 and GKH message 1
- fix send/sendto setting wrong errno when sendq is fulland socket is not in blocking mode
- fix send/sendto not returning the correct number of sent bytes in the case of a partial packet send
- fixed synchronization to broadcast schedule after LFN parent selection
- router now deletes earo route when receiving ns aro lifetime 0
- fixed wrong timeout for LFN
- fixed incorrect backoff slot duration with SUN OFDM
- fixed LFN failing in Join State 3 when it fails to decrypt an FFN-specific packet
- enable 15.4 acceleration in RAIL only if 15.4g is supported
- fixed PAN Defect IE relayed twice by FFNs
- fixed ETSI Adaptive Power Control with FAN TPS version 1.0
- fixed setting correct errno values for socket API
- fixed dependencies for set_dhcp_vendor_data command on BR SoC CLI
- fixed wrong default k trickle parameter
- fixed FFN unable to send DAO until PAN timeout
- fixed Preferred PAN and PAN Defect generating too much traffic
- fixed CCA delay over 1000µs due to inaccurate TX timing reported by RAIL
- fixed LFN unicast schedule resync on LBT-IE receptions from parent

### Release 2.3

(release date 2024-12-16)

#### New Features and Improvements

- added [sl_wisun_set_leaf()](sl-wisun-api#sl-wisun-set-leaf) API to make an FFN act as RPL leaf.
- added [sl_wisun_set_tx_power_ddbm()](sl-wisun-api#sl-wisun-set-tx-power-ddbm) API to set the Tx power with a 0.1 dB resolution
- added [sl_wisun_br_set_ipv6_up_handler()](sl-wisun-br-api#sl-wisun-br-set-ipv6-up-handler) API to register a callback function to handle IPv6 packets received from Wi-SUN network
- added [sl_wisun_br_ipv6_down()](sl-wisun-br-api#sl-wisun-br-ipv6-down) API to forward IPv6 packets to Wi-SUN network from backhaul point-of-view
- added [sl_wisun_trace_debug()](sl-wisun-trace-api#sl-wisun-trace-debug), [sl_wisun_trace_info()](sl-wisun-trace-api#sl-wisun-trace-info), [sl_wisun_trace_warn()](sl-wisun-trace-api#sl-wisun-trace-warn) and [sl_wisun_trace_error()](sl-wisun-trace-api#sl-wisun-trace-error) to trace events in the stack journal.
- added [sl_wisun_set_phy_sensitivity()](sl-wisun-api#sl-wisun-set-phy-sensitivity) API to set the RX sensitivity for a chosen PHY
- added lfn_na_wait_duration_m in FFN connection params to configure how often an FFN retransmits DAO on behalf of a registered LFN.
- introduced Direct Connect
- introduced PAN Defect
- added Wi-SUN border router libraries. They were previously kept private.
- added Wi-SUN border router public APIs headers. They were previously kept private.
- added support for Wi-Fi connectivity based on Silicon LABS SiWx917 and WiSeConnect v3.4.0
- added support for an external DHCPv6 Server
- added DAO No-Path transmission to de-register a router prior to leaving the network
- updated the RX sensitivities with updated values.
- updated Registration Refresh Request as mandated by FAN TPS 1.1v09.
- updated NA channel plans 4 and 5 as mandated by PHY TPS amendment 1VA12
- improved retransmission mechanism
- improved handling of parent changes/losses
- reduced weight given to the ETX first measure in the ETX EWMA
- reduced weight given to the RSL first measure in the RSL EWMA
- reworked MAC, FFN and LFN bootstrap state machines
- raised TCP maximum segment size (mss)
- dropped deprecated definitions related to socket options

##### RCP API

- 2.5.0  
  - Allow using security key with index 8.
- 2.4.1  
  - Fix the start of the LFN broadcast schedule.  
  - FATAL when failing to start the LFN broadcast schedule.  
  - FATAL when trying to send an LFN broadcast frame without having the LFN broadcast schedule running.
- 2.4.0  
  - Add phy sensitivity to REQ_RADIO_LIST command.
- 2.3.0  
  - Add timing info, parent address and parent frame counters to SET_FHSS_FFN_BC command.

#### Bug Fixes

- fixed incorrect EAP packet filtering when the EAP packet ID would rollover
- fixed PAN Cost calculation
- fixed memory leak when a node is disconnected and has neighbors with registered POM-IE info
- fixed IPV6_RECVTCLASS, IPV6_UNICAST_HOPS, IPV6_MULTICAST_HOPS and SO_EDFE_MODE socket options
- fixed SO_NONBLOCK socket option not being handled correctly
- fixed POM-IE when only 1 other PhyModeId is available
- fixed FFN multicast packet transmission timeout when LFN multicast packet also pending for transmission
- fixed MPL Buffer Message set containing messages with a sequence inferior to min sequence
- fixed MPL messages not being deleted on expiration when trickle timer was inhibited
- fixed multicast entry management in LFN parenting
- fixed RPL candidate parent set, reject neighbors with low RSL
- fixed hop limit field in IPv6 tunneling
- changed parent unregistration to include all parents, preventing bad DAO route on reconnection
- fixed missing probe to a new neighbor in join state 5
- RPL parents from the previous connection are not loaded from NVM if discovery.allow_skip is false
- changed BSI / broadcast schedule update to be only when receiving a PC with a new PAN version
- fixed parent selection causing frequent parent switches or invalid infinite rank advertised
- fixed segmentation fault when candidate parent timeout and no preferred parent is selected
- fixed an issue causing the radio to stay in IDLE state until the next TX after an RX timeout

### Release 2.0

(release date 2024-06-05)

#### New Features and Improvements

- dropped the support of our previous socket API.
- added a random delay before starting an LFN join sequence.
- added support for [select()](sl-wisun-select-api#select), [sendmsg()](sl-wisun-socket-api#sendmsg), [recvmsg()](sl-wisun-socket-api#recvmsg), [getpeername()](sl-wisun-socket-api#getpeername) and [getsockname()](sl-wisun-socket-api#getsockname).
- extended the list of supported socket options.
- split the stack into smaller software modules offering more granularity and helping reduce the memory footprint.

#### Bug Fixes

- fixed an issue causing the radio to be stuck in RX. The cause has been identified as a race in the lower layers of the radio driver.
- fixed an invalid memory access in the timer and event lists.
- fixed multiple invalid counter and timer updates during state transitions and RPL parent updates. They were causing abusive router disconnections.
- fixed an invalid use of a link-local as a source address in the DAO.
- fixed the condition upon which the MAC reset the CCA failures counter.
- fixed an invalid PAN ID filter configuration that was preventing routers from connecting to a new border router after a PAN timeout.

### Release 1.10

(release date 2023-04-10)

#### New Features and Improvements

- added a new API [sl_wisun_set_neighbor_table_size()](sl-wisun-api#sl-wisun-set-neighbor-table-size)that set the neighbor table size.

#### Bug Fixes

- fixed an invalid initialization causing the number of retries sent by Wi-SUN RCP to be inconsistent.
- fixed an error that, in some rare occasions, could cause the IPv6 source routing header corruption.
- fixed an error that was causing significant transmissions delays when a multicast packet reception occurred during the transmission of asynchronous packets.
- fixed LFN clock drift compensation. It sometimes skipped and caused the LFN to disconnect.
- improved the resiliance of 4-way handshake to errors. After a missing packet the joining node and the authenticator ended with a different status.

### Release 1.9

(release date 2023-02-14)

#### New Features and Improvements

- major update of the RCP. Must be used in pair with wsbrd v1.9 and more recent. It significantly reduces the memory footprint. The memory required to run the application no longer depends on the number of routers connected to the border router.
- dropped the high-reliability transmission mechanism. Its use was not recommended and it was causing a significant increase of all communications latency.
- added support for ETSI Adaptive Power Control.
- improved LFNs clock drift compensation. It reduces the power consumption and the connection stability.

#### Bug Fixes

- fixed an error causing UDP sockets to be closed when receiving packets with an empty payload.
- fixed an error causing the frequency hopping to be blocked on rare occasions.
- fixed an error causing LLC messaging allocation to fail. It was caused by an invalid logic in the mac tx queue.
- fixed an error causing LFNs to use an invalid broadcast schedule after a reconnection.
- fixed an error causing LFNs reconnection to a router to fail.
- fixed an error preventing LFNs to send NS(EARO) and thus to reconnect after a given number of non-consequentive unsuccessful connection attempts.
- fixed an error causing an invalid memory access in dense topologies.
- LUS-IE were sent in all LFN data frames, even when the Listen Interval did not change.

### Release 1.8

(release date 2023-12-13)

#### New Features and Improvements

- added a new API [sl_wisun_get_stack_version()](sl-wisun-api#sl-wisun-get-stack-version) that returns the stack version.
- updated [sl_wisun_join()](sl-wisun-api#sl-wisun-join) to support the customization of PHY configurations. Extended sl_wisun_phy_config_type_t and [sl_wisun_phy_config_t](sl-wisun-phy-config-t) to allow the customization of OFDM, FSK and O-QPSK entries.
- added support for LFN Timing Offset (LTO). Avoid LFN broadcast and unicast overlaps.
- added support for LFN multicast reception.
- added support for SUN DSSS-OQPSK.
- added support for blocking sockets.
- added support for the new Indian PHY configurations.

#### Bug Fixes

- fixed an error causing an assert when a device connects to network and then later re-join with a different device type.
- fixed an error causing an LFN parent to hard fault on an LFN disconnection.
- fixed an invalid variable initialization that could cause a device frame counter to be set to 0 when using IAR.
- fixed an invalid configuration preventing LFN to connect when using the Balanced or Eco modes.
- fixed an invalid initialization in MPL that was causing a multicast packet to be considered as old after a router re-connection.
- fixed an invalid time synchronization between an LFN and his FFN parent. It was causing significant drifts making downstream communications instable after a while.
- the Join Metric IE was not forwarded when the join state 1 was skipped.
- fixed an error causing a LFN to be out-of-sync when no packet is exchanged for more than 1h10 (uint32 max us)
- fixed an error causing MAC retries to be skipped on rare occasions.
- fixed an error causing routers to stay on the wrong channel after performing asynchronous transmissions.
- LFN are now send a Neighbor Solicitation with an EARO with a zero lifetime when disconnecting.
- Wi-SUN OUI was coded with the wrong byte ordering.
- maintained and restored the DHCP Identity Association ID (IAID) across reboots.
- that stack performed a CSMA/CA on asynchronous frame transmissions. This behavior is specifically forbidden in the FAN TPS.
- the stack occasionally tried to send a Neighbor Advertisement (NA) as a reply to a received Neighbor Solicitation (NS) used for Neighbor Unreachability Detection (NUD). This behavior is specifically forbidden in the FAN TPS.

### Release 1.7.1

(release date 2023-10-10)

#### Bug Fixes

- fixed an issue causing LFN LGTK and frame counter recovery from NVM after a reboot to be skipped.
- fixed an invalid memory access when receiving a multicast packet with a full neighbor table.
- fixed LFN parent timeout. It was still partially relying on the FFN timeout mechanism.
- fixed LFN address renewal.
- fixed an invalid memory access in the RCP. It could either trigger an assert “ref_counter <= 0" or call free() on an invalid memory section.
- fixed an issue causing a mis-calculation of the ETX.
- fixed an issue causing an invalid memory access when starting the SoC border router with an invalid PHY configuration
- fixed an interoperability issue when using JP regulatory domain.
- fixed a race between FHSS and ND causing an invalid memory access when disconnecting itself or an LFN child.
- fixed FFN LGTK acquisition. FFN were performing a full 4-way handshake instead of a shorter 2-way handshake.
- fixed an issue causing DHCP lease renewal to happen too often.
- fixed an issue causing an invalid memory access when starting the stack without any certificate.
- added missing Node Role KDE. Routers not supporting LFN parenting were missing the information element and were considered as FAN1.0 devices by Silicon Labs border routers.

### Release 1.7

(release date 2023-06-07)

#### New Features and Improvements

- LFN devices are now able to enter in Energy Mode 2 (EM2) if the application allows it.
- added support for PAN-Wide IE.
- adapted EDFE support for FAN 1.1.
- adapted MPL support for FAN 1.1.
- major refactoring of the stack internal timekeeping.

#### Bug Fixes

- frame counters were not increased on retries.
- fixed an issue causing UDP packets to be silently dropped. This was caused by an inappropriate management of fragmented packets.
- fixed an issue causing a suitable neighbor to be refused as a potential parent. Data packets missing a US-IE were refused while they should have been accepted. The stack was not keeping track of the US-IE received during the authentication process. This was causing interoperability issues with Nissin System routers.
- fixed an improper stack initialization when used outside of a project generated with SLC.
- fixed an issue causing a memory corruption when disconnecting an LFN.

### Release 1.6

(release date 2023-06-07) 

#### New Features and Improvements

- added a new API [sl_wisun_set_lfn_parameters()](sl-wisun-api#sl-wisun-set-lfn-parameters) that configures all the LFN-specific settings.
- added a new API [sl_wisun_set_lfn_support()](sl-wisun-api#sl-wisun-set-lfn-support) that sets the maximum number of LFNs that can be connected to a single FFN.
- added a new API [sl_wisun_set_mode_switch()](sl-wisun-api#sl-wisun-set-mode-switch) that supersedes [sl_wisun_set_mode_switch()](sl-wisun-api#sl-wisun-set-mode-switch).The old API is still availa-ble but it is recommended to move to the more recent one.
- added a new API [sl_wisun_set_pti_state()](sl-wisun-api#sl-wisun-set-pti-state) that enable the Packet Trace Interface (PTI). For more information about the PTI in the context of Wi-SUN, refer to Wi-SUN’s Getting Started section on docs.silabs.com.
- implemented LFN LGTK rotation
- added support for a non-standard OFDM 64QAM PHY.
- added support for EFR32FG28
- optimized the reconnection of routers to an existing network: if configured to do so, the routers will now try to skip the scanning and authenticated step of the joining procedure.

#### Bug Fixes

- fixed an issue that could cause acknowlges to be sent to the wrong channel.
- fixed several issues that could cause an assert after a call to [sl_wisun_disconnect()](sl-wisun-api#sl-wisun-disconnect).
- fixed an issue that could cause a mutex to be kept for an undefined period of time. It was causing devices to be indefinitely stalled.

### Release 1.5.2

(release date 2023-04-19)

- fixed an RNG error that could happen on EFR32xG12.
- fixed an error causing LPA to be missed on PHY configurations using a lot of channels.
- fixed an error causing a segmentation fault on congested networks.

### Release 1.5.1

(release date 2023-03-08)

- reduced the NS(EARO) retry period during the first connection. It reduces the time to connect in case of retransmission and improves the process’s reliability.
- unencrypted LPC are not accepted by LFN anymore.
- fixed FEC support in Linux Border Router RCP.

### Release 1.5.0

(release date 2023-02-01)

- added a new SL_WISUN_SOCKET_OPTION_SEND_BUFFER_LIMIT socket option to configure the transmission buffer length.
- added a new SL_WISUN_PHY_CONFIG_IDS option in [sl_wisun_join()](sl-wisun-api#sl-wisun-join). It allows the selection of a specific entry in the radio configuration.
- added LFN parent synchronization and time-out detection.
- added LFN EAPOL accelerated listening schedule.

#### Bug Fixes

- fixed a regression in the connection time.

### Release 1.4.0

(release date 2022-12-14)

#### New Features and Improvements

- added minimal support for FAN1.1 LFN (Limited Functional Node). LFN devices are able to connect and communicate but are not using any of the EFR32 energy management mode. As such, they are not optimized for battery powered devices and should only be used for evaluation and experimentation.  
  - added a new API [sl_wisun_set_device_type()](sl-wisun-api#sl-wisun-set-device-type)that configures the role of device. It can be either a router (FFN – Full Functional Node) or an end node (LFN)  
  - added a new set of libraries supporting both LFN and FFN device types. Those libraries are used when the new “Stack LFN Support” plugin is installed.
- added support for FAN 1.1 PHY mode switch.  
  - added a new API [sl_wisun_set_mode_switch()](sl-wisun-api#sl-wisun-set-mode-switch) that indicates if the device can mode switch with a given neighbor.  
  - added new APIs [sl_wisun_set_pom_ie()](sl-wisun-api#sl-wisun-set-pom-ie)and [sl_wisun_get_pom_ie()](sl-wisun-api#sl-wisun-get-pom-ie) that write or read the content of the POM-IE (PHY Operating Mode Information Element). It contains the list of the PHY operating mode a node is willing to use for communication.
- added a new API [sl_wisun_join()](sl-wisun-api#sl-wisun-join) that triggers a new connection. It can be used either with the old (1V08 – regulatory domain, operating class, operating mode) or the new (1VA8 – regulatory domain, channel plan id, PHY mode if) nomenclature. That new API is meant to replace sl_wisun_connect().
- added a new API [sl_wisun_set_connection_parameters()](sl-wisun-api#sl-wisun-set-connection-parameters) that extends the set of the configuration parameters. Used in pair with [sl_wisun_join()](sl-wisun-api#sl-wisun-join), it replaces sl_wisun_connect() network size parameter.
- added support for FSK FEC. FEC can be enable either by setting fec field of [sl_wisun_phy_config_t](sl-wisun-phy-config-t) structure or by using a PHY mode id that explicity enables FEC.
- added support of EFR32FG25. It supports all FAN1.1 OFDM modulation schemes and all FAN1.0 FSK configurations.
- added support of EFF01

#### Deprecated Items

- sl_wisun_connect() is replaced by [sl_wisun_join()](sl-wisun-api#sl-wisun-join).
- sl_wisun_set_channel_plan() is replaced by [sl_wisun_join()](sl-wisun-api#sl-wisun-join).
- sl_wisun_set_network_size() is replaced by [sl_wisun_set_connection_parameters()](sl-wisun-api#sl-wisun-set-connection-parameters)

### Release 1.3.2

(release date 2022-28-09)

#### Bug Fixes

- fixed an invalid Path Control field configuration in RPL DAO packet.

### Release 1.3.1

(release date 2022-06-08)

#### Net Features and Improvements

- when ARIB radio regulation is selected, the stack refuses all EDFE initialization requests sending an EDFE final frame.

#### Bug Fixes

- fixed PAN Advert and PAN Config Trickle timer configuration. Inconsistent transmissions were not correctly managed. It could lead to suboptimal behavior in dense areas of a network.
- fixed a performance issue that was causing Linux Border Router RCP to become unreachable when running throughput tests with high-speed data rates. That issue was fixed by using DMA to collect UART data.
- fixed an initialization issue that was causing PAN Advert and PAN Config asynchronous transmission requests to be dropped. That issue was most likely to happen with TEST and SMALL network size configuration and could cause connection durations to be significantly longer.

### Release 1.3.0

(release date 2022-06-08)

#### New Features and Improvements

- most of the stack crypto operations are now made through ARM PSA Crypo API.
- added a new API [sl_wisun_set_device_private_key_id()](sl-wisun-api#sl-wisun-set-device-private-key-id) that indicates which PSA Crypto key handler contains the device private key and has to be used by the stack. It is the application responsibility to create the key.
- added a new API [sl_wisun_set_regulation()](sl-wisun-api#sl-wisun-set-regulation) that configures the regional regulation the stack must comply to. Refer to UG495 for more information about regional regulation in Wi-SUN Stack.
- added a new event SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID that is fired when the transmission budget is cross-ing one of the transmission budget threshold. The transmission budget is defined by the regional regulation. Refer to UG495 for more information about regional regulation in Wi-SUN Stack.
- added a new API [sl_wisun_set_regulation_tx_thresholds()](sl-wisun-api#sl-wisun-set-regulation-tx-thresholds) that configures the threshold used to fire SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID event.
- added a new API [sl_wisun_set_advert_fragment_duration()](sl-wisun-api#sl-wisun-set-advert-fragment-duration) that configures the asynchronous transmission frag-ment duration. It can be used to reduce the impact on the latency of long advertisement periods.
- added a new API sl_wisun_set_unicast_tx_mode() that enables a high-reliability transmission mechanism for unicast communication. It trades off unicast communication reliability for latency.
- [sl_wisun_set_channel_mask()](sl-wisun-api#sl-wisun-set-channel-mask) channel filter is now applied to asynchronous transmissions and unicast listening schedule. The function was renamed [sl_wisun_set_allowed_channel_mask()](sl-wisun-api#sl-wisun-set-allowed-channel-mask) to make it more self-explanatory.

#### Bug Fixes

- Fixed an error that was causing radio calibrations to be skipped during Wi-SUN Stack initialization.

### Release 1.2.3

(release date 2022-03-09)

#### Bug Fixes

- Applied the PA configuration set in the application. It was previously ignored and the same configuration was always used.

### Release 1.2.2

(release date 2022-02-21)

#### Bug Fixes

- Fixed a recurrence of the error that could cause the stack to assert on a RAIL_StartCcaCsmaTx when trying to connect to a network that cannot be reached.

### Release 1.2.1

(release date 2022-01-26)

#### Bug Fixes

- Fixed an error that could cause the stack to assert on a RAIL_StartCcaCsmaTx when trying to connect to a network that cannot be reached.

### Release 1.2

(release date 2021-10-13)

#### New Features and Improvements

- added release quality libraries. They provide the same Wi-SUN features but are not logging anything.
- added a new API sl_wisun_reset_statistics that resets all the counters read by calling sl_wisun_get_statistics.
- added new APIs [sl_wisun_get_neighbor_count()](sl-wisun-api#sl-wisun-get-neighbor-count) and [sl_wisun_get_neighbors()](sl-wisun-api#sl-wisun-get-neighbors) that indicate the neighbor count (parents and children) and their MAC address.
- added a new API [sl_wisun_get_neighbor_info()](sl-wisun-api#sl-wisun-get-neighbor-info) that returns information about a neighbor.
- added a new API [sl_wisun_set_unicast_settings()](sl-wisun-api#sl-wisun-set-unicast-settings) that configures the frequency hopping unicast dwell interval.
- added a new API [sl_wisun_set_trace_level()](sl-wisun-trace-api#sl-wisun-set-trace-level) and [sl_wisun_set_trace_filter()](sl-wisun-trace-api#sl-wisun-set-trace-filter) that configure the stack traces.
- added support for mbedtls v3.0.
- stack flash footprint reduction.
- reworked Wi-SUN stack tasks priorities.
- fixed the unicast channel filtering.
- fixed an error causing the authentication waiting list to be broken.

### Release 1.1.2

(release date 2021-10-13)

#### New Features and Improvements

- fixed an issue causing a hard-fault during a parent information update.

### Release 1.1.1

(release date 2021-09-08)

#### New Features and Improvements

- fixed a drift in the frequency hopping mechanism that could lead to disconnections in quiet networks.

### Release 1.1.0

(release date 2021-07-21)

#### New Features and Improvements

- fixed an issue causing the event SL_WISUN_MSG_CONNECTED_IND_ID to be fired although no new connection was established. It was fired after each network update.
- fixed an issue causing connections to fail after an operating class update.
- fixed an issue causing US-IE configuration to be invalid when excluding channels.

### Release 1.0.1

(release date 2021-06-16)

#### New Features and Improvements

- fixed an issue causing a parent to lose track of its child frequency hopping sequence. The child router was sending an incorrect IFSU misleading the parent router and forcing it to be one frequency hop interval late.

### Release 1.0.0

(release date 2021-04-21)

#### New Features and Improvements

- fixed memory leaks during the disconnection and reset processes.
- added a new disconnected join state to sl_wisun_get_join_state API.
- miscellaneous API minor updates

### Release 0.2.2

(release date 2021-04-21)

#### New Features and Improvements

- fixed a bug causing connection with network_size 'Test' to be slower than it used to be.
- added border router support for custom PHYs
- added a new API for clearing credential cache
- added a new API for MAC address management

### Release 0.2.1

(release date 2021-04-07)

#### New Features and Improvements

- fixed a bug causing unicasts to be sent on the wrong channel
- updated a configuration that prevented multicast to be forwarded

### Release 0.2.0

(release date 2021-01-25)

#### New Features and Improvements

- added support for CMSIS RTOS API2
- fixed UDP sockets corner cases.

### Release 0.1.0

(release date 2020-12-10)

#### New Features and Improvements

- added support for Gecko SDK v3.1
- added support for operating mode 2a (100kbps) and 3 (150kbps)
- added new APIs [sl_wisun_allow_mac_address()](sl-wisun-api#sl-wisun-allow-mac-address) and [sl_wisun_deny_mac_address()](sl-wisun-api#sl-wisun-deny-mac-address) that enable MAC filtering.

### Wi-SUN NCP Application

### Overview

The Wi-SUN NCP (Network Co-Processor) application provides a production-ready implementation for handling Wi-SUN stack communication through a message-based interface. The NCP acts as a bridge between a host processor and the Wi-SUN stack.

### Message Flow

#### Requests

```c
Host Application → Transport/driver → NCP Task → Wi-SUN Stack

```

#### Confirmations/Indications

```c
Wi-SUN Stack → NCP Task → Transport/driver → Host application

```

 The NCP receives complete messages from the transport layer, validates them, forwards to the Wi-SUN stack, and returns confirmations and asynchronous indications.

### Buffer Format Requirements

#### Message Structure

All messages sent to the NCP transport layer must follow this format:

```c
┌─────────────────┬─────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────┐
│   Header (8B)   │ Message Body (varies according to the request/confirmation) │ Variable Data (varies according to trailing data size)   │
└─────────────────┴─────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────

```

#### Header Format

```c
typedef struct {
  uint16_t length;
  uint8_t id;
  uint8_t info;
} sl_wisun_msg_header_t;

```

**Critical Requirements:**

- `header.length` must equal the total message size
- `header.id` must be a valid Wi-SUN message ID
- Message must be complete

#### Buffer Size Configuration

Configure `SL_WSNCP_BUFFER_SIZE` in your `.slcp` file: 

```c
- name: "SL_WSNCP_BUFFER_SIZE" 
  value: "1500"

```

### Usage Examples

#### 1. Basic Request

```c
// Example: Get IP address
sl_wisun_msg_get_ip_address_req_t req = {0};

// Initialize request
req.header.id = SL_WISUN_MSG_GET_IP_ADDRESS_REQ_ID;
req.header.length = sizeof(req);  // Must match actual size
req.body.address_type = SL_WISUN_IP_ADDRESS_TYPE_GLOBAL;

// Send to the ncp host

```

#### 2. Socket Operations

```c
// Example: Open UDP socket
sl_wisun_msg_open_socket_req_t open_req = {0};

open_req.header.id = SL_WISUN_MSG_OPEN_SOCKET_REQ_ID;
open_req.header.length = sizeof(open_req);
open_req.body.domain = AF_INET6;
open_req.body.type = SOCK_DGRAM;
open_req.body.protocol = IPPROTO_UDP;

// send to the ncp host

```

#### 3. Variable Data Messages

```c
// Example: Send data to socket
uint16_t data_length = 100;  // Example payload size
uint8_t *sendto_buffer = malloc(sizeof(sl_wisun_msg_sendto_on_socket_req_t) + data_length);
sl_wisun_msg_sendto_on_socket_req_t *sendto_req = (sl_wisun_msg_sendto_on_socket_req_t *)sendto_buffer;

// Initialize request
sendto_req->header.id = SL_WISUN_MSG_SENDTO_ON_SOCKET_REQ_ID;
sendto_req->header.length = sizeof(sl_wisun_msg_sendto_on_socket_req_t) + data_length;
sendto_req->body.socket_id = socket_id;
sendto_req->body.remote_address = remote_ipv6_address;
sendto_req->body.remote_port = remote_port;
sendto_req->body.data_length = data_length;

// Copy data after the fixed structure
memcpy(sendto_req->body.data, payload_data, data_length);

// send to the ncp host

```

### Confirmation Handling

#### What You Need to Do:

- **Configure `SL_WSNCP_BUFFER_SIZE` in your `.slcp`** to sufficiently hold all you intended confirmations plus any trailing data.

**Minimum confirmation buffer size**: `sizeof(sl_wisun_msg_header_t) + sizeof(uint32_t)` (12 bytes) for status field.

#### Confirmation Reception

```c
// Handle confirmation from transport layer
void handle_confirmation(uint16_t len, const uint8_t *data) {
    if (len < sizeof(sl_wisun_msg_header_t) + sizeof(uint32_t)) {
        printf("Confirmation too small\n");
        return;
    }
    
    const sl_wisun_msg_header_t *header = (const sl_wisun_msg_header_t *)data;
    const uint32_t *status = (const uint32_t *)(data + sizeo(sl_wisun_msg_header_t));
    
    if (*status == SL_STATUS_OK) {
        // Process successful confirmation
        printf("Request ID:0x%02X successful\n", header->id);
        // Access confirmation data based on message type
    } else {
        // Handle error
        printf("Request ID:0x%02X failed with status: 0x%08X\n", *status);
    }
}

```

### Validation and Error Handling

#### Buffer Validation

The NCP performs these checks:

1. **Size Check**:  
   - Message must fit in configured buffer size  
   - For request messages, message length should be the size of the request (hdr + body + trailing data if any)  
   - For confirmation messages, length should be sufficient to hold the confirmation (hdr + body + trailing data if any)
2. **Header Validation**: Valid message ID and length consistency
3. **Completeness Check**: Message must be complete (no fragmentation)

#### Error Responses

```c
// Handle common errors
if (status == SL_STATUS_WOULD_OVERFLOW) {
    // Message too large - increase buffer size
    printf("Message too large for buffer\n");
}

if (status == SL_STATUS_INVALID_PARAMETER) {
    // Invalid message format - check header.length
    printf("Invalid message format\n");
}

```

### Best Practices

1. **Always set `header.length` correctly** - must match total message size
2. **Use appropriate buffer sizes** for your message types
3. **Send complete messages** - no fragmentation
4. **Allocate sufficient confirmation buffers** - account for variable data

### Common Issues

1. **Buffer Overflow**: Increase `SL_WSNCP_BUFFER_SIZE`
2. **Header Length Mismatch**: Ensure `header.length` equals actual message size
3. **Invalid Message ID**: Use correct Wi-SUN message IDs
4. **Incomplete Messages**: Send complete messages in single transmission
5. **Confirmation Buffer Too Small**: Allocate sufficient space for confirmation + variable data

### Wi-SUN Sockets

 Wi-SUN sockets are based on the well-known BSD socket API, also known as the POSIX socket API. Each socket represents a handle for the local endpoint of a communication circuit.

> Earlier Silicon Labs socket API was deprecated in release 1.8 and removed in release 2.0.

### API Overview

While Wi-SUN sockets follow the BSD socket API conventions, there are some limitations and omissions in the implementation as described below.

- Wi-SUN FAN supports only IPv6, so none of the IPv4-specific socket functionality is available
- Socket handles are specific to Wi-SUN sockets and cannot be used as file descriptors in C library function calls or other APIs
- POSIX signals are not supported, socket signaling uses Wi-SUN API events instead

Functions supported:

- [socket()](sl-wisun-socket-api#socket)
- [close()](sl-wisun-socket-api#close)
- [bind()](sl-wisun-socket-api#bind)
- [send()](sl-wisun-socket-api#send)
- [sendto()](sl-wisun-socket-api#sendto)
- [sendmsg()](sl-wisun-socket-api#sendmsg)
- [recvfrom()](sl-wisun-socket-api#recvfrom)
- [recv()](sl-wisun-socket-api#recv)
- [recvmsg()](sl-wisun-socket-api#recvmsg)
- [accept()](sl-wisun-socket-api#accept)
- [connect()](sl-wisun-socket-api#connect)
- [listen()](sl-wisun-socket-api#listen)
- [setsockopt()](sl-wisun-socket-api#setsockopt)
- [getsockopt()](sl-wisun-socket-api#getsockopt)
- [getsockname()](sl-wisun-socket-api#getsockname)
- [getpeername()](sl-wisun-socket-api#getpeername)
- [select()](sl-wisun-select-api#select) (requires a separate application component)

Following functions are not supported:

- gethostbyname()
- gethostbyaddr()
- poll()

### Migration to BSD Socket API

The following table details the mapping between the BSD socket API and the former Silicon Labs socket API.

|Former Silicon Labs Socket API Function|BSD Function|
|---|---|
|sl_wisun_open_socket()|[socket()](sl-wisun-socket-api#socket)|
|sl_wisun_bind_socket()|[bind()](sl-wisun-socket-api#bind)|
|sl_wisun_listen_on_socket()|[listen()](sl-wisun-socket-api#listen)|
|sl_wisun_connect_socket()|[connect()](sl-wisun-socket-api#connect)|
|sl_wisun_accept_on_socket()|[accept()](sl-wisun-socket-api#accept)|
|sl_wisun_send_on_socket()|[send()](sl-wisun-socket-api#send)|
|sl_wisun_sendto_on_socket()|[sendto()](sl-wisun-socket-api#sendto)|
|sl_wisun_receive_on_socket()|[recv()](sl-wisun-socket-api#recv)|
|sl_wisun_close_socket()|[close()](sl-wisun-socket-api#close)|
|sl_wisun_get_socket_option()|[getsockopt()](sl-wisun-socket-api#getsockopt)|
|sl_wisun_set_socket_option()|[setsockopt()](sl-wisun-socket-api#setsockopt)|

### Socket Life Cycle

In general, a socket is created by explicitly calling [socket()](sl-wisun-socket-api#socket) and must be explicitly closed by calling [close()](sl-wisun-socket-api#close). This both closes the communication circuit and frees any resources allocated to the socket.

In certain protocols, the communication circuit may be closed by the remote peer. This is indicated with a [SL_WISUN_MSG_SOCKET_CLOSING_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-closing-ind-id) event. Although the socket connection is closed, the system resources will not be freed until the application calls [close()](sl-wisun-socket-api#close).

### Exchanging Data

Certain protocols require a socket in a connected state, meaning the underlying protocol must first establish a session with the remote peer before data can be exchanged. It is also optionally possible on certain connectionless protocols. In either case, connecting a socket creates a direct communication link with a remote peer, allowing the socket to be used only with that particular peer.

To switch a socket into connected state, use [connect()](sl-wisun-socket-api#connect). See the table below for protocol details.

|Protocol|Unconnected|Connected|
|---|---|---|
|[IPPROTO_UDP](sl-wisun-socket-api#ipproto-udp)|MAY|MAY|
|[IPPROTO_TCP](sl-wisun-socket-api#ipproto-tcp)|MUST NOT|MUST|
|[IPPROTO_ICMP](sl-wisun-socket-api#ipproto-icmp)|MUST|MUST NOT|

#### Transmit

When a socket is in unconnected state, [sendto()](sl-wisun-socket-api#sendto) is used to transmit data. The function requires the application to specify the remote peer address and port number on each call. When a socket is connected, [send()](sl-wisun-socket-api#send) is used instead. Because the socket is "locked" into a single remote peer, address and port number are not needed.

A successful return code indicates the socket has buffered the provided data and the application may free the data resources. The application receives a [SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-sent-ind-id) event when a part or all buffered data has been sent, depending on the used protocol.

#### Receive

To manage received socket data, the socket can be either in indication mode or in polling mode. All sockets default to polling mode.

In polling mode, the application will receive a [SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-available-ind-id) event on data reception. The received data is stored in the socket buffer until the application reads it using [recv()](sl-wisun-socket-api#recv) or [recvfrom()](sl-wisun-socket-api#recvfrom). A socket that generated a [SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-available-ind-id) will never block.

In indication mode, the received data is sent as a [SL_WISUN_MSG_SOCKET_DATA_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-ind-id) event as soon as it is received. The application must either handle the data immediately or store it for later processing. Either way, the socket will not keep the data once the event handler returns.

### Blocking operations

By default, socket operations are blocking, i.e. the calling RTOS task is suspended until the socket operation completes. Sockets can be configured as non-blocking either by or'ing [SOCK_NONBLOCK](sl-wisun-socket-api#sock-nonblock) flag to the type parameter of [socket()](sl-wisun-socket-api#socket), or using the socket option [SO_NONBLOCK](sl-wisun-socket-api#so-nonblock). Only a single blocking operation per socket is allowed.

### Client

#### TCP Example

1. Open a TCP socket using `socket(AFINET_6, SOCK_STREAM, IPPROTO_TCP)`.
2. Initiate connection to the remote server using `connect()`.
3. Wait for [SL_WISUN_MSG_SOCKET_CONNECTED_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-connected-ind-id) event.
4. ... Exchange data with the remote server ...
5. Close the socket using `close()`.

#### UDP Example

1. Open an UDP socket using `socket(AFINET_6, SOCK_DGRAM, IPPROTO_UDP)`.
2. ... Exchange data with the remote server ...
3. Close the socket using `close()`.

### Server

#### TCP Example

1. Open a TCP socket using `socket(AFINET_6, SOCK_STREAM, IPPROTO_TCP)`.
2. Set the server socket port number using `bind()`.
3. Set the server socket into listening state using `listen()`.
4. Wait for [SL_WISUN_MSG_SOCKET_CONNECTION_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-connection-available-ind-id) event.
5. Accept the client connection using `accept()` on the server socket.
6. ... Exchange data with the remote client using the newly created client socket ...
7. Close the client socket using `close()`.
8. Go to 4.

#### UDP Example

1. Open an UDP socket using `socket(AFINET_6, SOCK_DGRAM, IPPROTO_UDP)`.
2. Set the socket port number using `bind()`.
3. ... Exchange data with the remote client ...

### Deprecated List

- Global [sl_wisun_app_status_get_remote_address](sl-wisun-app-status#sl-wisun-app-status-get-remote-address)  (void) SL_DEPRECATED_API_SDK_2025_6  
  This function is not thread-safe, use sl_wisun_app_status_get_remote_addr instead.
- Global [sl_wisun_br_set_network_size](sl-wisun-br-api#sl-wisun-br-set-network-size)  (sl_wisun_network_size_t size) SL_DEPRECATED_API_SDK_2026_6  
  This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_br_set_connection_parameters()](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) instead.
- Global [sl_wisun_coap_free](sl-wisun-coap-api#sl-wisun-coap-free)  (void *addr) SL_DEPRECATED_API_SDK_2025_6  
  Replace this function by sl_free.
- Global [sl_wisun_coap_malloc](sl-wisun-coap-api#sl-wisun-coap-malloc)  (uint16_t size) SL_DEPRECATED_API_SDK_2025_6  
  Replace this function by sl_malloc.
- Global [sl_wisun_set_channel_mask](sl-wisun-api#sl-wisun-set-channel-mask)  (const [sl_wisun_channel_mask_t](sl-wisun-channel-mask-t) *channel_mask)  
  This function is an alias for [sl_wisun_set_allowed_channel_mask()](sl-wisun-api#sl-wisun-set-allowed-channel-mask). It is maintained for backward compatibility.
- Global [sl_wisun_set_neighbor_table_size](sl-wisun-api#sl-wisun-set-neighbor-table-size)  (uint8_t size) SL_DEPRECATED_API_SDK_2025_6  
  This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_config_neighbor_table()](sl-wisun-api#sl-wisun-config-neighbor-table) instead.
- Global [sl_wisun_set_regulation](sl-wisun-api#sl-wisun-set-regulation)  (sl_wisun_regulation_t regulation) SL_DEPRECATED_API_SDK_2025_12  
  This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters) instead.
- Global [sl_wisun_set_tx_power](sl-wisun-api#sl-wisun-set-tx-power)  (int8_t tx_power) SL_DEPRECATED_API_SDK_2024_6  
  This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_set_tx_power_ddbm()](sl-wisun-api#sl-wisun-set-tx-power-ddbm) instead.
- Global [sl_wisun_util_connect](sl-wisun-util#sl-wisun-util-connect)  (const uint8_t *network_name) SL_DEPRECATED_API_SDK_2024_6  
  This function will be removed in the future versions of the Wi-SUN stack.
- Global [sl_wisun_util_get_phy_config](sl-wisun-util#sl-wisun-util-get-phy-config)  ([sl_wisun_phy_config_t](sl-wisun-phy-config-t) *phy_config) SL_DEPRECATED_API_SDK_2024_6  
  This function will be removed in the future versions of the Wi-SUN stack.

### Wi-SUN Overview

### Wi-SUN Stack

The Wi-SUN stack API is the primary Application Programming Interface (API) for applications running on Silicon Labs EFR32 Wireless Gecko SoCs to interact with the Silicon Labs Wi-SUN FAN wireless stack. It allows the application to manage the connection to a Wi-SUN FAN network as well as to communicate with other devices in the network using a socket-based communication interface.

See the [Wi-SUN Stack API](sl-wisun-api) for more details.

### Stack Plugins

Wi-SUN stack plugin components are software modules tightly linked to the stack that provide means to customize it: debug, manufacturing or Wi-SUN specific optional features. They can have significant impact on key capabilities and footprint.

- [RF Test](sl-wisun-rf-test) provides low-level APIs to produce an RF tone or a modulated packet and calibrate the radio.
- [Stack Trace and Debug](sl-wisun-trace-api) provides extended trace capabilities to the stack and stack plugin components.
- [Dedicated allocator for Wi-SUN critical features](sl-wisun-alloc) provides a separate heap in which crypto-related allocations are made.

### Service Components

The following software components are provided to help and accelerate Wi-SUN application developments by offering common functionalities. They can easily be added to an existing Wi-SUN application through Simplicity Studio graphical interface. The components are shared in source code in the Gecko SDK.

- [Application Core](sl-wisun-app-core-api) provides a set of high-level helper APIs designed to ease the application development.
- [Application Settings](sl-wisun-app-setting) provides an interface for Application Setting
- [Util Functions](sl-wisun-util) provides utility functions.
- [CoAP](sl-wisun-coap-api) provides a CoAP (Constrained Application Protocol) implementation running on top of the Wi-SUN stack.
- [Ping](sl-wisun-ping-api) provides a ping implementation based on the ICMPv6 protocol.
- [iPerf](sl-iperf) provides an iPerf2 implementation to test the throughput over UDP.
- [Over-The-Air Device Firmware Upgrade (Alpha)](sl-wisun-ota-dfu-api) provides an Over-The-Air Device Firmware Upgrade solution for Wi-SUN devices.
- [Trivial File Transfer Protocol (TFTP) Client (Alpha)](sl-tftp-clnt-1) Trivial File Transfer Protocol (TFTP) Client API
- [Application Memory Statistic (Alpha)](app-os-stat) provides solution for gathering application memory statistic
- [Application Status over CoAP (Alpha)](sl-wisun-app-status) provides solution to send application status notifications over CoAP
- [Silicon Labs socket API (deprecated)](sl-wisun-sl-socket-compat) provides a compatibility with Silicon Labs former socket API.
- [Keychain](sl-wisun-keychain) provides simplified certificate/private key handling.

### Versioning

Silicon Labs Wi-SUN solution follows the Semantic Versioning guidelines for release cycle transparency and to maintain backward compatibility.

### Wi-SUN Services

The Wi-SUN service software components are provided to help and accelerate Wi-SUN application developments by offering common functionalities. They can easily be added to an existing Wi-SUN application through Simplicity Studio graphical interface. The components are shared in source code in the Gecko SDK.

The service components are especially useful to build upon the Wi-SUN - SoC Empty project and start as close as possible to a final application targeted by a developer.

The following diagram shows the software components available for users to leverage in their Wi-SUN application. Moreover, it highlights each component dependencies to other software components. ![User Component Overview](/wisun-stack-api/2.12.0/images/component-hierarchy.png)

#### Modules

[Util Functions](sl-wisun-util)

[Application Core](sl-wisun-app-core-api)

[Application Settings](sl-wisun-app-setting)

[CoAP](sl-wisun-coap-api)

[Ping](sl-wisun-ping-api)

[iPerf](sl-iperf)

[Over-The-Air Device Firmware Upgrade (Alpha)](sl-wisun-ota-dfu-api)

[Trivial File Transfer Protocol (TFTP) Client (Alpha)](sl-tftp-clnt-1)

[Application Memory Statistic (Alpha)](app-os-stat)

[Application Status over CoAP (Alpha)](sl-wisun-app-status)

[Silicon Labs socket API (deprecated)](sl-wisun-sl-socket-compat)

[Keychain](sl-wisun-keychain)

#### Util Functions

The Util Functions component provides helper functions to inform the application about the Wi-SUN PHY configured in the RAIL configuration file. 

##### Functions

###### sl_wisun_util_connect

`sl_status_t sl_wisun_util_connect(const uint8_t *network_name) SL_DEPRECATED_API_SDK_2024_6`

**Description:** Connect to a Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|network_name|Name of the Wi-SUN network as a zero-terminated string|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise
- One of the following:  
  - SL_STATUS_OK if successful  
  - SL_STATUS_INVALID_CONFIGURATION if a configuration that cannot be managed by the plugin is used  
  - SL_STATUS_FAIL if an other error occured

Since Wi-SUN frequency band settings are deduced from first RAIL configuration listed in RAIL's channelConfigs array, using this function is not recommended if more than one RAIL configuration is described.

**Deprecated**This function will be removed in the future versions of the Wi-SUN stack.

###### sl_wisun_util_get_phy_config

`sl_status_t sl_wisun_util_get_phy_config(sl_wisun_phy_config_t *phy_config) SL_DEPRECATED_API_SDK_2024_6`

**Description:** Get PHY settings of the first RAIL configuration listed in RAIL's channelConfigs array.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_phy_config_t](sl-wisun-phy-config-t) *|[out]|phy_config|Pointer to PHY configuration|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise
- One of the following:  
  - SL_STATUS_OK if successful  
  - SL_STATUS_INVALID_CONFIGURATION if a configuration that cannot be managed by the plugin is used  
  - SL_STATUS_FAIL if an other error occured

**Warnings**

- Do not call this function while the Wi-SUN stack is started.

**Deprecated**This function will be removed in the future versions of the Wi-SUN stack.

#### Application Settings

The Application Settings component provides the fundamental API for getting and setting Wi-SUN related settings within the application code. After initializing with the [app_wisun_setting_init()](sl-wisun-app-setting#app-wisun-setting-init) function, the setters and getters can be used in the application to interface with runtime settings such as network name, network size, TX power, and PHY configuration.

A notification mechanism is implemented and is triggered by the appropriate settings changes.

The following code snippet demonstrates the API usage: 

```c
#include "sl_wisun_api.h"
#include "sl_wisun_app_setting.h"
#include "sl_wisun_app_core_util.h"

static void change_settings(void) {
  app_setting_wisun_t setting = { 0 };
  sl_status_t status = SL_STATUS_FAIL;

  // Disconnect before setting new values
  sl_wisun_disconnect();

  // Get all the settings
  status = app_wisun_setting_get(&setting);
  if (status != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Increasing TX power
  setting.tx_power += 10;

  status = app_wisun_setting_set_tx_power(&setting.tx_power);
  if (status != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Connect with the new settings
  sl_wisun_app_core_util_connect_and_wait();
}

```

##### Functions

###### app_wisun_setting_get

`sl_status_t app_wisun_setting_get(app_setting_wisun_t *const wisun_setting)`

**Description:** Get the Wi-SUN settings.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|app_setting_wisun_t *const|[out]|wisun_setting|is the obtained Wi-SUN setting|

**Returns**

- sl_status_t if the getting is successful it returns SL_STATUS_OK, otherwise error code.

###### app_wisun_setting_get_network_name

`sl_status_t app_wisun_setting_get_network_name(char *const name, uint8_t size)`

**Description:** Get the Wi-SUN network name.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *const|[out]|name|pointer where the name is copied onto|
|uint8_t|[in]|size|is the size of the name buffer|

**Returns**

- sl_status_t it is successful if it returns SL_STATUS_OK otherwise it is not.

###### app_wisun_setting_get_network_size

`sl_status_t app_wisun_setting_get_network_size(uint8_t *const size)`

**Description:** Get the Wi-SUN network size.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *const|[out]|size|pointer where the network size is copied onto|

**Returns**

- sl_status_t it is successful if it returns SL_STATUS_OK otherwise it is not.

###### app_wisun_setting_get_phy

`sl_status_t app_wisun_setting_get_phy(sl_wisun_phy_config_t *const phy)`

**Description:** Get the Wi-SUN PHY.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_phy_config_t](sl-wisun-phy-config-t) *const|[out]|phy|pointer where the PHY is copied onto|

**Returns**

- sl_status_t it is successful if it returns SL_STATUS_OK otherwise it is not.

###### app_wisun_setting_get_tx_power

`sl_status_t app_wisun_setting_get_tx_power(int16_t *const tx_power)`

**Description:** Get the Wi-SUN TX power.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int16_t *const|[out]|tx_power|pointer where the TX power is copied onto|

**Returns**

- sl_status_t it is successful if it returns SL_STATUS_OK otherwise it is not.

###### app_wisun_setting_init

`void app_wisun_setting_init(void)`

**Description:** Initialize Wi-SUN setting.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

###### app_wisun_setting_init_phy_cfg

`sl_status_t app_wisun_setting_init_phy_cfg(void)`

**Description:** Init internal PHY settings.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Full radio config: data initialized with default HPY for appropriate board Simple PHY: get first element of PHY list by 'sl_wisun_util_get_rf_settings' **Returns**

- sl_status_t it is successful if it returns SL_STATUS_OK otherwise it is not.

###### app_wisun_setting_set_network_name

`sl_status_t app_wisun_setting_set_network_name(const char *const name)`

**Description:** Set the Wi-SUN network name.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *const|[out]|name|is the network name that will be set.|

**Returns**

- sl_status_t if the set is successful it returns SL_STATUS_OK, otherwise error code.

###### app_wisun_setting_set_network_size

`sl_status_t app_wisun_setting_set_network_size(const uint8_t *const size)`

**Description:** Set the Wi-SUN network size.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *const|[in]|size|is the pointer to network size that will be set.|

**Returns**

- sl_status_t if the set is successful it returns SL_STATUS_OK, otherwise error code.

###### app_wisun_setting_set_phy

`sl_status_t app_wisun_setting_set_phy(const sl_wisun_phy_config_t *const phy)`

**Description:** Set the Wi-SUN PHY.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_phy_config_t](sl-wisun-phy-config-t) *const|[out]|phy|is the PHY that will be set.|

**Returns**

- sl_status_t if the set is successful it returns SL_STATUS_OK, otherwise error code.

###### app_wisun_setting_set_tx_power

`sl_status_t app_wisun_setting_set_tx_power(const int16_t *const tx_power)`

**Description:** Set the Wi-SUN TX power.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const int16_t *const|[out]|tx_power|is the pointer to TX power that will be set.|

**Returns**

- sl_status_t if the set is successful it returns SL_STATUS_OK, otherwise error code.

#### Silicon Labs socket API (deprecated)

Silicon Labs socket API is deprecated. This component is provided as a temporary solution to maintain a compatility with v1.7 and older.

#### Application Core

The Application Core component is designed to offer utilities commonly used in Wi-SUN applications with the following features:

- **The [sl_wisun_app_core_util_connect_and_wait()](sl-wisun-app-core-api#sl-wisun-app-core-util-connect-and-wait) function** configures the network size setting, the TX output power, the certificates and keys. The function is waiting for the connected state. Its final action is to initiate the Wi-SUN connection process. The [sl_wisun_app_core_network_connect()](sl-wisun-app-core-api#sl-wisun-app-core-network-connect) and [sl_wisun_app_core_util_network_is_connected()](sl-wisun-app-core-api#sl-wisun-app-core-util-network-is-connected) functions also provide an easy way to establish a connection and wait for it to be ready.
- **Event handlers for basic Wi-SUN network events** include the basic event handler implementations.
- **Available addresses**. The [sl_wisun_app_core_get_current_addresses()](sl-wisun-app-core-api#sl-wisun-app-core-get-current-addresses) function retrieves known IPv6 addresses.
- **Status Getter**. Use [sl_wisun_app_core_get_state()](sl-wisun-app-core-api#sl-wisun-app-core-get-state) function to get the status of the Stack API calls. The [sl_wisun_app_core_get_time_stat()](sl-wisun-app-core-api#sl-wisun-app-core-get-time-stat) function retrives the connection time, disconnection time stamps and total elapsed time in those states.
- **Limited Function Node (LFN) device support**. Use [sl_wisun_app_core_get_device_type()](sl-wisun-app-core-api#sl-wisun-app-core-get-device-type) to get the selected device type for the project. The device type can be changed in the Wi-SUN configurator interface. [sl_wisun_app_core_get_lfn_profile()](sl-wisun-app-core-api#sl-wisun-app-core-get-lfn-profile) and [sl_wisun_app_core_get_lfn_params()](sl-wisun-app-core-api#sl-wisun-app-core-get-lfn-params) provide an interface to access the selected LFN profile and its parameters.

The following code snippet shows how the connection can be performed in an application thread:

```c
#include "sl_wisun_app_core.h"
#include "sl_wisun_app_core_util.h"

/*App task function*/
void app_task(void *args)
{
  (void) args;

  // Connect to the wisun network.
  sl_wisun_app_core_util_connect_and_wait();

  while (1) {

    // Put your application code here.
    osDelay(1);
  }
}

```

##### Modules

[Configurations](sl-wisun-app-core-config)

[Type definitions](sl-wisun-app-core-api-types)

##### undefined

###### sl_wisun_app_core_util_project_info_init

`void sl_wisun_app_core_util_project_info_init(const char *app_name)`

**Description:** Initialize Wi-SUN project information.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|app_name|Application name|

Init internal instance 

###### sl_wisun_app_core_util_project_info_print

`void sl_wisun_app_core_util_project_info_print(const bool json_format)`

**Description:** Print Wi-SUN project information.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const bool|[in]|json_format|Json format required indicator|

Print project info in pretty or json format. 

###### sl_wisun_app_core_util_project_info_get

`const app_project_info_t * sl_wisun_app_core_util_project_info_get(void)`

**Description:** Get Wi-SUN Project info.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get a constant instance of internal Wi-SUN project info **Returns**

- app_project_info_t * Project info

###### sl_wisun_app_core_util_wait_for_connection

`void sl_wisun_app_core_util_wait_for_connection(void)`

**Description:** Wait for the connection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function doesn't call the [sl_wisun_app_core_network_connect()](sl-wisun-app-core-api#sl-wisun-app-core-network-connect) function. The function provides a delay loop with optional heart beat printing till the connection state has not been changed. 

###### sl_wisun_app_core_util_connect_and_wait

`void sl_wisun_app_core_util_connect_and_wait(void)`

**Description:** Connect and wait for connection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

The function calls [sl_wisun_app_core_network_connect()](sl-wisun-app-core-api#sl-wisun-app-core-network-connect) function and [sl_wisun_app_core_util_wait_for_connection()](sl-wisun-app-core-api#sl-wisun-app-core-util-wait-for-connection) function. It can be useful at the beginning of application thread. 

###### sl_wisun_app_core_util_network_is_connected

`bool sl_wisun_app_core_util_network_is_connected(void)`

**Description:** The network is connected.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Wrapper function of join state getter **Returns**

- true Connected
- false Not connected

###### sl_wisun_app_core_util_dispatch_thread

`void sl_wisun_app_core_util_dispatch_thread(void)`

**Description:** Thread dispatch function.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

For low power LFN mode, the delay value is 'SL_WISUN_APP_CORE_THREAD_LP_DISPATCH_MS', for FFN mode, the delay is 1ms 

##### Functions

###### sl_wisun_app_core_get_current_addresses

`void sl_wisun_app_core_get_current_addresses(sl_wisun_app_core_current_addr_t *const dest_addresses)`

**Description:** Get the current addresses.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_app_core_current_addr_t](sl-wisun-app-core-api-types#sl-wisun-app-core-current-addr-t) *const|[out]|dest_addresses|Destination|

Copy cached addresses into destination. 

###### sl_wisun_app_core_get_device_type

`sl_wisun_device_type_t sl_wisun_app_core_get_device_type(void)`

**Description:** Get Wi-SUN device type.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Getter to get device type. Device type can be SL_WISUN_LFN or SL_WISUN_ROUTER (FFN) **Returns**

- l_wisun_device_type_t Device type.

###### sl_wisun_app_core_get_join_state

`sl_wisun_join_state_t sl_wisun_app_core_get_join_state(void)`

**Description:** Get Wi-SUN join state.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Thread-safe getter to get connection state. Join state is stored in appropriate event callback. **Returns**

- sl_wisun_join_state_t Join state value.

###### sl_wisun_app_core_get_lfn_params

`const sl_wisun_lfn_params_t * sl_wisun_app_core_get_lfn_params(void)`

**Description:** Get LFN parameters.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- [sl_wisun_lfn_params_t](sl-wisun-lfn-params-t) pointer to the set profile parameters of LFN.

###### sl_wisun_app_core_get_lfn_profile

`sl_wisun_lfn_profile_t sl_wisun_app_core_get_lfn_profile(void)`

**Description:** Get Wi-SUN LFN profile.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Getter to get LFN profile. Device type can be SL_WISUN_LFN_PROFILE_TEST, SL_WISUN_LFN_PROFILE_BALANCED or SL_WISUN_LFN_PROFILE_ECO **Returns**

- sl_wisun_lfn_profile_t LFN profile.

###### sl_wisun_app_core_get_regulation_active

`bool sl_wisun_app_core_get_regulation_active(void)`

**Description:** Return the state of the regional regulation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function tells the caller if a regulation is currently active. **Returns**

- Boolean indicating if a regional regulation is currently active.

###### sl_wisun_app_core_get_regulation_thresholds

`sl_status_t sl_wisun_app_core_get_regulation_thresholds(sl_wisun_app_core_reg_thresholds_t *thresholds_out)`

**Description:** Get the warning and alert levels for approaching/exceeded the TX budget.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_app_core_reg_thresholds_t](sl-wisun-app-core-api-types#sl-wisun-app-core-reg-thresholds-t) *|[out]|thresholds_out|pointer to the struct to hold the thresholds|

Values representing percentages of the allowed transmission quota in ms are returned for the warning and alert levels, respectively. **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_app_core_get_remaining_tx_budget

`sl_status_t sl_wisun_app_core_get_remaining_tx_budget(uint32_t *const budget_out)`

**Description:** Get the remaining budget from the transmission quota.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *const|[out]|budget_out|pointer to return the remaining budget to.|

Returns the state of the regional regulation and the remaining budget in ms if applicable, or zero budget if exceeded or not regulated. **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_app_core_get_state

`sl_status_t sl_wisun_app_core_get_state(uint32_t *const state)`

**Description:** Get application core state.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t *const|[out]|state|is the indicator of the error|

The function retrieves the application core state value (32 bits) **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_app_core_get_time_stat

`void sl_wisun_app_core_get_time_stat(sl_wisun_app_core_time_stat_t *const tstat)`

**Description:** Get time statistic.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_app_core_time_stat_t](sl-wisun-app-core-api-types#sl-wisun-app-core-time-stat-t) *const|[out]|tstat|Time statistic structure|

Create a copy of time statistic storage with up-to-date values 

###### sl_wisun_app_core_init

`void sl_wisun_app_core_init(void)`

**Description:** Initialize Wi-SUN application core.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializing mutex, socket handler and set Wi-SUN settings. 

###### sl_wisun_app_core_network_connect

`void sl_wisun_app_core_network_connect(void)`

**Description:** Connect to the Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Network initialization and connection. The function initializes the network with parameters (Network name, TX Power, Network size, etc.) by the stored settings in NVM if the settings component is added to the project, otherwise with the default settings. 

###### sl_wisun_app_core_set_regulation_active

`void sl_wisun_app_core_set_regulation_active(bool enabled)`

**Description:** Set the regional regulation to active or passive.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|enabled|(true = active, false = not active)|

After a stack API call for regional regulation, this function can be used to store the status of the regulation (active or not). 

###### sl_wisun_app_core_set_regulation_thresholds

`void sl_wisun_app_core_set_regulation_thresholds(const int8_t warning_level, const int8_t alert_level)`

**Description:** Set up warning and alert thresholds for the regional regulation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const int8_t|[in]|warning_level|new percentage for the warning threshold|
|const int8_t|[in]|alert_level|new percentage for the alert threshold|

Sets up the percentages of warnings and alerts where the regulation indicate that the transmission quota is approached/exceeded. 

###### sl_wisun_app_core_wait_state

`sl_status_t sl_wisun_app_core_wait_state(const uint32_t state, const uint32_t timeout)`

**Description:** Waiting for application core state flags.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint32_t|[in]|state|state variable which includes the expected flags|
|const uint32_t|[in]|timeout|timeout for waiting|

The function waits for application core states described in the state variable. Multiple state flags can be set. The function waits for all flags. Flags are not cleared in this function. **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

##### Configurations

###### Macros

`#define SL_WISUN_APP_CORE_DEFAULT_REGULATION_ALERT_THRESHOLD 95U`

**Description**: Transmission duration level alert threshold.

`#define SL_WISUN_APP_CORE_DEFAULT_REGULATION_WARNING_THRESHOLD 85U`

**Description**: Transmission duration level warning threshold.

`#define SL_WISUN_APP_CORE_MAIN_STACK_SIZE_WORD 256UL`

**Description**: Recommended Application thread stack size.

`#define SL_WISUN_APP_CORE_REGULATION SL_WISUN_APP_CORE_REGULATION_NONE`

**Description**: Regulation.

`#define SL_WISUN_APP_CORE_REGULATION_ARIB 1U`

**Description**: Regulation ARIB.

`#define SL_WISUN_APP_CORE_REGULATION_NONE 0U`

**Description**: Regulation None.

`#define SL_WISUN_APP_CORE_REGULATION_WPC 2U`

**Description**: Regulation WPC.

`#define SL_WISUN_APP_CORE_THREAD_LP_DISPATCH_MS 1000UL`

**Description**: Thread dispatch delay for low power mode.

`#define SL_WISUN_APP_CORE_TX_BUDGET 720000UL`

**Description**: Wi-SUN regulation transmission budget.

##### Type definitions

###### Modules

[sl_wisun_app_core_current_addr](sl-wisun-app-core-current-addr)

[sl_wisun_app_core_reg_thresholds](sl-wisun-app-core-reg-thresholds)

[sl_wisun_app_core_time_stat](sl-wisun-app-core-time-stat)

###### Enumerations

###### sl_wisun_app_core_state (heading level 7)

```
enum sl_wisun_app_core_state {
    SL_WISUN_APP_CORE_STATE_NETWORK_CONNECTED = 0
    SL_WISUN_APP_CORE_STATE_NETWORK_DISCONNECTED
    SL_WISUN_APP_CORE_STATE_NETWORK_CONNECTION_LOST
    SL_WISUN_APP_CORE_STATE_SETTING_ERROR
    SL_WISUN_APP_CORE_STATE_CONNECTION_ERROR
    SL_WISUN_APP_CORE_STATE_SET_NETWORK_SIZE_ERROR
    SL_WISUN_APP_CORE_STATE_SET_TX_POWER_ERROR
    SL_WISUN_APP_CORE_STATE_SET_DWELL_INTERVAL_ERROR
    SL_WISUN_APP_CORE_STATE_SET_MAC_ADDR_ERROR
    SL_WISUN_APP_CORE_STATE_SET_ALLOW_MAC_ADDR_ERROR
    SL_WISUN_APP_CORE_STATE_SET_DENY_MAC_ADDR_ERROR
    SL_WISUN_APP_CORE_STATE_SET_TRUSTED_CERTIFICATE_ERROR
    SL_WISUN_APP_CORE_STATE_SET_DEVICE_CERTIFICATE_ERROR
    SL_WISUN_APP_CORE_STATE_SET_DEVICE_PRIVATE_KEY_ERROR
    SL_WISUN_APP_CORE_STATE_GET_RF_SETTINGS_ERROR
}
```

**Description:**

Error flag bits enum type definition.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_APP_CORE_STATE_NETWORK_CONNECTED|Network connected.|
|SL_WISUN_APP_CORE_STATE_NETWORK_DISCONNECTED|Network disconnected.|
|SL_WISUN_APP_CORE_STATE_NETWORK_CONNECTION_LOST|Network connection lost.|
|SL_WISUN_APP_CORE_STATE_SETTING_ERROR|Setting Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_CONNECTION_ERROR|Connection Failed Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_NETWORK_SIZE_ERROR|Network Size Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_TX_POWER_ERROR|TX Power Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_DWELL_INTERVAL_ERROR|Dwel interval Error flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_MAC_ADDR_ERROR|Setting MAC address Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_ALLOW_MAC_ADDR_ERROR|setting Allow mac address Error Flag bit|
|SL_WISUN_APP_CORE_STATE_SET_DENY_MAC_ADDR_ERROR|setting Deny mac address Error Flag bit|
|SL_WISUN_APP_CORE_STATE_SET_TRUSTED_CERTIFICATE_ERROR|Trusted Certificate Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_DEVICE_CERTIFICATE_ERROR|Device Certificate Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_SET_DEVICE_PRIVATE_KEY_ERROR|Device Private Key Error Flag bit.|
|SL_WISUN_APP_CORE_STATE_GET_RF_SETTINGS_ERROR|Get RF Setting Error Flag bit.|

###### Typedefs

###### sl_wisun_app_core_current_addr_t (heading level 7)

`typedef struct sl_wisun_app_core_current_addr sl_wisun_app_core_current_addr_t`

**Description:**

Current address storage structure definition.

###### sl_wisun_app_core_reg_thresholds_t (heading level 7)

`typedef struct sl_wisun_app_core_reg_thresholds sl_wisun_app_core_reg_thresholds_t`

**Description:**

Regulation thresholds.

###### sl_wisun_app_core_state_t (heading level 7)

`typedef enum sl_wisun_app_core_state sl_wisun_app_core_state_t`

**Description:**

Error flag bits enum type definition.

###### sl_wisun_app_core_time_stat_t (heading level 7)

`typedef struct sl_wisun_app_core_time_stat sl_wisun_app_core_time_stat_t`

**Description:**

Application time statistic.

Current address storage structure definition. 

###### Public Attributes (heading level 7)

###### border_router (heading level 8)

```
in6_addr_t sl_wisun_app_core_current_addr::border_router
```

**Description:** Border Router address.

###### global (heading level 8)

```
in6_addr_t sl_wisun_app_core_current_addr::global
```

**Description:** Global address.

###### link_local (heading level 8)

```
in6_addr_t sl_wisun_app_core_current_addr::link_local
```

**Description:** Link local address.

###### primary_parent (heading level 8)

```
in6_addr_t sl_wisun_app_core_current_addr::primary_parent
```

**Description:** Primary Parent address.

###### secondary_parent (heading level 8)

```
in6_addr_t sl_wisun_app_core_current_addr::secondary_parent
```

**Description:** Secondary Parent address.

Regulation thresholds. 

###### Public Attributes (heading level 7)

###### alert_threshold (heading level 8)

```
int8_t sl_wisun_app_core_reg_thresholds::alert_threshold
```

**Description:** Alert thresholds.

###### warning_threshold (heading level 8)

```
int8_t sl_wisun_app_core_reg_thresholds::warning_threshold
```

**Description:** Warning thresholds.

Application time statistic. 

###### Public Attributes (heading level 7)

###### conn_cnt (heading level 8)

```
uint32_t sl_wisun_app_core_time_stat::conn_cnt
```

**Description:** Connection counter.

###### connected_ms (heading level 8)

```
uint64_t sl_wisun_app_core_time_stat::connected_ms
```

**Description:** Last connected ms.

###### curr_ms (heading level 8)

```
uint64_t sl_wisun_app_core_time_stat::curr_ms
```

**Description:** Current ms.

###### disconnected_ms (heading level 8)

```
uint64_t sl_wisun_app_core_time_stat::disconnected_ms
```

**Description:** Last disconnected ms.

###### tot_connected_ms (heading level 8)

```
uint64_t sl_wisun_app_core_time_stat::tot_connected_ms
```

**Description:** Total connected ms.

###### tot_disconnected_ms (heading level 8)

```
uint64_t sl_wisun_app_core_time_stat::tot_disconnected_ms
```

**Description:** Total disconnected ms.

#### CoAP

The Wi-SUN CoAP component offers an application layer implementation built on top of the Wi-SUN stack and its socket API. The CoAP protocol is specifically designed as an Internet Application Protocol for constrained devices operating in lossy networks (as defined in [RFC 7252](https://datatracker.ietf.org/doc/html/rfc7252)). Wi-SUN FAN networks precisely fit this definition.

The CoAP implementation relies on the UDP transport layer for sending and receiving packets. Within the component, you'll find a set of helper functions that assist in building CoAP payloads, parsing CoAP packets, and freeing CoAP packets. Additionally, the CoAP Resource Handler service manages registered resources.

For resource discovery, the Resource Discovery request provides an interface to retrieve information about available resources. These resources have additional attributes beyond the URI (Uniform Resource Identifier) path, which can be selectively filtered using specific Resource Discovery requests.

Furthermore, the CoAP Notification service allows the creation and schedule of notifications for the remote host. The schedule time and send conditions can be customized based on the application requirements. To incorporate the CoAP component into the application, simply add it to the project and initialize it using [sl_wisun_coap_init()](sl-wisun-coap-api#sl-wisun-coap-init).

The CoAP component is compatible with third-party implementations, such as the [libcoap](https://libcoap.net) server and client binaries.

The following block diagram shows the architecture of CoAP component: ![coap](/wisun-stack-api/2.12.0/images/coap.png)

The following example shows the CoAP resource and notification initialization:

```c
#include <string.h>
#include "sl_wisun_coap.h"
#include "sl_wisun_coap_rhnd.h"
#include "sl_wisun_coap_notify.h"

#define NOTIFY_URI_PATH "notify/temperature"

// CoAP Resource Handler callback
static sl_wisun_coap_packet_t *
callback_to_handle_requests(const sl_wisun_coap_packet_t * const req_packet) {
  sl_wisun_coap_packet_t *resp_packet = NULL;

  // Build pre-initialized CoAP packet with content response message code
  resp_packet = sl_wisun_coap_build_response(req_packet, COAP_MSG_CODE_RESPONSE_CONTENT);
  if (resp_packet == NULL) {
    return NULL;
  }

  // Build your CoAP payload (resp_packet->payload_ptr)
  // and set the payload length (resp_packet->payload_len)

  return resp_packet;
}

static bool condition_callback(const sl_wisun_coap_notify_t * notify) {
  // Build your notification condition and return the check result
  (void) notify;
  return true;
}

static sl_wisun_coap_packet_t *
callback_to_build_packet(const sl_wisun_coap_notify_t *notify) {
  // Initialize a CoAP Packet
  static sl_wisun_coap_packet_t pkt = {
    .msg_code = COAP_MSG_CODE_REQUEST_PUT, // Message Code: PUT request
    .msg_id = 1234, // Message ID
    .msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE, // Message type
    .content_format = COAP_CT_TEXT_PLAIN, // Content format
    .uri_path_ptr = NULL, // URI Path pointer
    .uri_path_len = 0, // URI Path length
    .payload_ptr = NULL, // Payload pointer
    .payload_len = 0, // Payload length
    .token_ptr = NULL, // Token pointer
    .token_len = 0, // Token length
    .options_list_ptr = NULL // Option list pointer
  };

  (void) notify;

  // Set the URI path
  pkt.uri_path_ptr = (uint8_t *)NOTIFY_URI_PATH;
  pkt.uri_path_len = strlen(NOTIFY_URI_PATH);

  // Set your notification payload content
  // pkt.payload_ptr = your_prebuilt_buf;
  // pkt.payload_len = your_payload_length;

  // Return with the notification packet
  return &pkt;
}

static void init_resource_and_notification(void) {
  // Return value
  int32_t ret = 0;

  // Resource descriptor allocation
  sl_wisun_coap_rhnd_resource_t coap_resource = { 0 };

  // Notification handler allocation
  sl_wisun_coap_notify_t notify = { 0 };

  // Prepare resource with default content
  sl_wisun_coap_rhnd_resource_init(&coap_resource);

  // Resource URI path
  coap_resource.data.uri_path = "/sensor/temperature";

  // Resource type
  coap_resource.data.resource_type = "temp";

  // Interface
  coap_resource.data.interface = "i2c-sensor";

  // Function pointer to handle requests, like temperature measurement and response packet build.
  // Pointer type is sl_wisun_coap_packet_t * (*)(const sl_wisun_coap_packet_t * const req_packet)
  coap_resource.auto_response = callback_to_handle_requests;

  // You can initialize an extended callback instead of the standard callback type.
  // The extended callback receives the source address of the requests.
  // The function pointer type is
  // sl_wisun_coap_packet_t * (*)(const sockaddr_in6_t * const src_addr, const sl_wisun_coap_packet_t * const req_packet)
  // coap_resource.auto_response_ext = extended_callback_to_handle_requests;

  // Redirect response
  // The callback performs a response redirection. You can build your new destination address
  // and retrieve the new_addr argument
  // Pointer type is
  // void (*)(sockaddr_in6_t * const new_addr,const sl_wisun_coap_packet_t * const req_packet)
  // coap_resource.redirect_response = NULL;

  // Resource is discoverable. You can get information with resource discovery request
  // GET /.well-known/core
  coap_resource.discoverable = true;

  // Add resource to the resource list
  assert(sl_wisun_coap_rhnd_resource_add(&coap_resource) == SL_STATUS_OK);

  // Set the notification ID
  notify.id = "my-notification";

  // Set the destination address of notification
  ret = inet_pton(AF_INET6,
                  "2001:db8::1",
                  &notify.remote_addr.sin6_addr);
  assert(ret == 1);
  notify.remote_addr.sin6_port = htons(5683);

  // Set the schedule time of the notification, 1s is in the example
  notify.schedule_time_ms = 1000;

  // Initialize the condition callback.
  // The callback checks the condition whether the created CoAP packet should be sent
  // The function pointer type is bool (*)(const sl_wisun_coap_notify_t * notify)
  notify.condition_cb = condition_callback;

  // Initialize the notification handler that builds the CoAP packet
  // The function pointer type is
  // sl_wisun_coap_packet_t * (*)(const sl_wisun_coap_notify_t * notify)
  notify.hnd_cb = callback_to_build_packet;

  // Add the notification to the notification list
  assert(sl_wisun_coap_notify_add(&notify) == SL_STATUS_OK);
}

```

##### Modules

[Configurations](sl-wisun-coap-config)

[Type definitions](sl-wisun-coap-types)

[CoAP Resource Handler API](sl-wisun-coap-rhnd-api)

[CoAP Notification API](sl-wisun-coap-notify-api)

##### Functions

###### sl_wisun_coap_build_response

`sl_wisun_coap_packet_t * sl_wisun_coap_build_response(const sl_wisun_coap_packet_t *req, sl_wisun_coap_message_code_t msg_code)`

**Description:** Build generic response for request wrapper function.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *|[in]|req|request|
|[sl_wisun_coap_message_code_t](sl-wisun-coap-types#sl-wisun-coap-message-code-t)|[in]|msg_code|message code to build|

Used sn_coap_build_response. **Returns**

- sl_wisun_coap_header_t* built packet ptr on the heap

###### sl_wisun_coap_builder

`int16_t sl_wisun_coap_builder(uint8_t *dest_buff, const sl_wisun_coap_packet_t *message)`

**Description:** CoAP message builder Wi-SUN.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|dest_buff|destination buffer for raw message|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *|[in]|message|message structure|

Used sl_wisun_coap_builder. **Returns**

- int16_t On success bytes of built message, on failure -1 if CoAP header structure is wrong -2 if NULL ptr set as argument

###### sl_wisun_coap_builder_calc_size

`uint16_t sl_wisun_coap_builder_calc_size(const sl_wisun_coap_packet_t *message)`

**Description:** CoAP packet calc size wrapper.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *|[in]|message|message ptr|

Used sn_coap_builder_calc_needed_packet_data_size. **Returns**

- uint16_t size

###### sl_wisun_coap_destroy_packet

`void sl_wisun_coap_destroy_packet(sl_wisun_coap_packet_t *packet)`

**Description:** Destroy packet.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *|N/A|packet|packet|

It must be used to avoid memory leaks! Free the all of allocated buffer for packet 

###### sl_wisun_coap_destroy_payload_str

`__STATIC_INLINE void sl_wisun_coap_destroy_payload_str(char *str)`

**Description:** Destroy payload string.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *|[in]|str|String|

'\0' terminated string in the heap, it must be freed 

###### sl_wisun_coap_destroy_uri_path_str

`__STATIC_INLINE void sl_wisun_coap_destroy_uri_path_str(const char *uri_str)`

**Description:** Destroy URI path string.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|uri_str|URI string ptr|

Call free on allocated pointer 

###### sl_wisun_coap_free

`void sl_wisun_coap_free(void *addr) SL_DEPRECATED_API_SDK_2025_6`

**Description:** Free Wi-SUN CoAP.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void *|N/A|addr|address ptr|

OS-dependent thread-safe implementation. 

**Deprecated**Replace this function by sl_free.

###### sl_wisun_coap_get_lib_handler

`const sl_wisun_coap_handle_t * sl_wisun_coap_get_lib_handler(void)`

**Description:** Get the library handler pointer from the internal handler structure.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Not thread safe! It is needed only to use Pelion mbed-coap library functions **Returns**

- const sl_wisun_coap_handle_t* pointer to the lib handler

###### sl_wisun_coap_get_payload_str

`char * sl_wisun_coap_get_payload_str(const sl_wisun_coap_packet_t *const packet)`

**Description:** Prepare payload string.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *const|[in]|packet|Packet|

'\0' terminated string in the heap, it must be freed **Returns**

- char* payload string, NULL on error

###### sl_wisun_coap_get_uri_path_str

`char * sl_wisun_coap_get_uri_path_str(const sl_wisun_coap_packet_t *const packet)`

**Description:** Prepare URI path string.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *const|[in]|packet|Packet|

'\0' terminated string in the heap, it must be freed **Returns**

- char* URI path string, NULL on error

###### sl_wisun_coap_init

`void sl_wisun_coap_init(const sl_wisun_coap_tx_callback tx_callback, const sl_wisun_coap_rx_callback rx_callback, const sl_wisun_coap_version_t version)`

**Description:** Initialize Wi-SUN CoAP.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_tx_callback](sl-wisun-coap-types#sl-wisun-coap-tx-callback)|[in]|tx_callback|TX callback, if it's NULL, the default callback is applied|
|const [sl_wisun_coap_rx_callback](sl-wisun-coap-types#sl-wisun-coap-rx-callback)|[in]|rx_callback|RX callback, if it's NULL, the default callback is applied|
|const [sl_wisun_coap_version_t](sl-wisun-coap-types#sl-wisun-coap-version-t)|[in]|version|CoAP version|

Set the Wi-SUN CoAP internal descriptor. 

**Referenced by:** [sl_wisun_coap_init_default](sl-wisun-coap-api#sl-wisun-coap-init-default)

###### sl_wisun_coap_init_default

`__STATIC_INLINE void sl_wisun_coap_init_default(void)`

**Description:** Initialize Wi-SUN CoAP default.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initializes the internal descriptor with default values. 

**References:** [sl_wisun_coap_init](sl-wisun-coap-api#sl-wisun-coap-init)

###### sl_wisun_coap_malloc

`void * sl_wisun_coap_malloc(uint16_t size) SL_DEPRECATED_API_SDK_2025_6`

**Description:** Implement malloc.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|N/A|size|size for malloc|

OS-dependent thread-safe implementation. **Returns**

- void* the memory pointer

**Deprecated**Replace this function by sl_malloc.

###### sl_wisun_coap_parser

`sl_wisun_coap_packet_t * sl_wisun_coap_parser(uint16_t packet_data_len, uint8_t *packet_data)`

**Description:** CoAP parser wrapper function.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|packet_data_len|packet data size|
|uint8_t *|[in]|packet_data|packet data ptr|

Used sn_coap_parser **Returns**

- sl_wisun_coap_packet_t* Parsed packet pointer

###### sl_wisun_coap_print_packet

`void sl_wisun_coap_print_packet(const sl_wisun_coap_packet_t *packet, const bool hex_format)`

**Description:** Print CoAP packets and all of attached buffer, payload, token, uri_path.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *|[in]|packet|packet to print|
|const bool|[in]|hex_format|hex format bool to decide buffer print format|

Pretty printer function, with hex format option for buffers 

##### Macros

`#define SL_COAP_SERVICE_LOOP ()`

**Description**: CoAP Service loop.

##### Configurations

###### Macros

`#define SL_WISUN_COAP_EASY_CLNT_SRV_INSTANCE_ENABLE 0U`

**Description**: Enable easy CoAP client and CoAP server instances.

`#define SL_WISUN_COAP_MEM_USE_STATIC_MEMORY_POOL 0U`

**Description**: Enable Static Memory Pool usage.

`#define SL_WISUN_COAP_NOTIFY_DEFAULT_REMOTE_ADDR "2001:db8::1"`

**Description**: Default remote address to notify.

`#define SL_WISUN_COAP_NOTIFY_DEFAULT_REMOTE_PORT 5683U`

**Description**: Default port of the remote host to notify.

`#define SL_WISUN_COAP_NOTIFY_MAX_NOTIFICATION 10U`

**Description**: Maximum capacity of the CoAP Notification Table.

`#define SL_WISUN_COAP_NOTIFY_MAX_RETRANSMIT 5U`

**Description**: Number of retries for confirmable messages.

`#define SL_WISUN_COAP_NOTIFY_SERVICE_ENABLE 1U`

**Description**: Enable Notification service.

`#define SL_WISUN_COAP_NOTIFY_SOCK_BUFF_SIZE 1024UL`

**Description**: Notification service socket communication buffer size.

`#define SL_WISUN_COAP_NOTIFY_STACK_SIZE_WORD 224UL`

**Description**: Notification service stack size in CPU word.

`#define SL_WISUN_COAP_RESOURCE_HND_MAX_RESOURCES 10U`

**Description**: Maximum capacity of the CoAP Resource Table.

`#define SL_WISUN_COAP_RESOURCE_HND_SERVICE_ENABLE 1U`

**Description**: Enable Resource Handler service.

`#define SL_WISUN_COAP_RESOURCE_HND_SERVICE_PORT 5683U`

**Description**: Resource handler service listener port.

`#define SL_WISUN_COAP_RESOURCE_HND_SOCK_BUFF_SIZE 1024UL`

**Description**: Resource handler service socket communication buffer size.

`#define SL_WISUN_COAP_RESOURCE_HND_STACK_SIZE_WORD 240UL`

**Description**: Resource handler service stack size in CPU word.

`#define SL_WISUN_COAP_RESOURCE_HND_VERBOSE_MODE_ENABLE 0U`

**Description**: Enable Resource Handler verbose mode.

##### Type definitions

###### Modules

[sl_wisun_coap](sl-wisun-coap)

###### Typedefs

###### sl_wisun_coap_free_t (heading level 7)

`typedef void(* sl_wisun_coap_free_t) (void *mem)`

**Description:**

Wi-SUN CoAP free function pointer typedef.

###### sl_wisun_coap_handle_t (heading level 7)

`typedef struct coap_s sl_wisun_coap_handle_t`

**Description:**

Wi-SUN CoAP handler for Wi-SUN component.

###### sl_wisun_coap_malloc_t (heading level 7)

`typedef void *(* sl_wisun_coap_malloc_t) (uint16_t size)`

**Description:**

Wi-SUN CoAP malloc function pointer typedef.

###### sl_wisun_coap_message_code_t (heading level 7)

`typedef sn_coap_msg_code_e sl_wisun_coap_message_code_t`

**Description:**

Wi-SUN CoAP message code typedef.

###### sl_wisun_coap_message_type_t (heading level 7)

`typedef sn_coap_msg_type_e sl_wisun_coap_message_type_t`

**Description:**

Wi-SUN CoAP message type typedef.

###### sl_wisun_coap_option_list_t (heading level 7)

`typedef sn_coap_options_list_s sl_wisun_coap_option_list_t`

**Description:**

Wi-SUN CoAP option list typedef.

###### sl_wisun_coap_option_num_t (heading level 7)

`typedef sn_coap_option_numbers_e sl_wisun_coap_option_num_t`

**Description:**

Wi-SUN CoAP option number typedef.

###### sl_wisun_coap_packet_t (heading level 7)

`typedef sn_coap_hdr_s sl_wisun_coap_packet_t`

**Description:**

Wi-SUN CoAP message typedef.

###### sl_wisun_coap_rx_callback (heading level 7)

`typedef int8_t(* sl_wisun_coap_rx_callback) (sn_coap_hdr_s *header, sn_nsdl_addr_s *addr, void *param)`

**Description:**

Wi-SUN CoAP RX callback function pointer typedef.

###### sl_wisun_coap_t (heading level 7)

`typedef struct sl_wisun_coap sl_wisun_coap_t`

**Description:**

Wi-SUN CoAP descriptor structure.

###### sl_wisun_coap_tx_callback (heading level 7)

`typedef uint8_t(* sl_wisun_coap_tx_callback) (uint8_t *packet_data, uint16_t packet_data_size, sn_nsdl_addr_s *addr, void *param)`

**Description:**

Wi-SUN CoAP TX callback function pointer typedef.

###### sl_wisun_coap_version_t (heading level 7)

`typedef coap_version_e sl_wisun_coap_version_t`

**Description:**

Wi-SUN CoAP version typedef.

###### Macros

`#define SL_WISUN_COAP_URI_PATH_MAX_SIZE (128U)`

**Description**: Maximum size of the URI path string.

Wi-SUN CoAP descriptor structure. 

###### Public Attributes (heading level 7)

###### free (heading level 8)

```
sl_wisun_coap_free_t sl_wisun_coap::free
```

**Description:** free function

###### handler (heading level 8)

```
sl_wisun_coap_handle_t* sl_wisun_coap::handler
```

**Description:** lib handler

###### malloc (heading level 8)

```
sl_wisun_coap_malloc_t sl_wisun_coap::malloc
```

**Description:** malloc function

###### rx_callback (heading level 8)

```
sl_wisun_coap_rx_callback sl_wisun_coap::rx_callback
```

**Description:** RX callback.

###### tx_callback (heading level 8)

```
sl_wisun_coap_tx_callback sl_wisun_coap::tx_callback
```

**Description:** TX callback.

###### version (heading level 8)

```
sl_wisun_coap_version_t sl_wisun_coap::version
```

**Description:** CoAP version.

##### CoAP Resource Handler API

###### Modules

[Type definitions](sl-wisun-coap-rhnd-types)

###### Functions

###### sl_wisun_coap_rhnd_get_resources (heading level 7)

`const sl_wisun_coap_rhnd_resource_t * sl_wisun_coap_rhnd_get_resources(void)`

**Description:** Get resources.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Getting linked list of resources **Returns**

- const sl_wisun_coap_rhnd_resource_t* Resource list, on error is NULL ptr

###### sl_wisun_coap_rhnd_init (heading level 7)

`void sl_wisun_coap_rhnd_init(void)`

**Description:** Initialization of the CoAP Resource Discovery internals.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

###### sl_wisun_coap_rhnd_is_request_packet (heading level 7)

`bool sl_wisun_coap_rhnd_is_request_packet(const sl_wisun_coap_packet_t *const packet)`

**Description:** Is request packet?

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_packet_t](sl-wisun-coap-types#sl-wisun-coap-packet-t) *const|[in]|packet|Packet|

helper function **Returns**

- true Request packet
- false Response or Empty packet

###### sl_wisun_coap_rhnd_print_resources (heading level 7)

`void sl_wisun_coap_rhnd_print_resources(void)`

**Description:** Print resources.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Print resource URI paths 

###### sl_wisun_coap_rhnd_reset_auto_response (heading level 7)

`sl_status_t sl_wisun_coap_rhnd_reset_auto_response(const char *uri_path)`

**Description:** Reset auto-response callback.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|uri_path|URI path|

Set callback ptr to NULL in resource descriptor **Returns**

- sl_status_t SL_STATUS_OK on success, SL_STATUS_FAIL on error

###### sl_wisun_coap_rhnd_resource_add (heading level 7)

`sl_status_t sl_wisun_coap_rhnd_resource_add(const sl_wisun_coap_rhnd_resource_t *const src_resource)`

**Description:** Register a new resource into the CoAP Resource table.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_rhnd_resource_t](sl-wisun-coap-rhnd-types#sl-wisun-coap-rhnd-resource-t) *const|[in]|src_resource|the new resource's descriptor|

**Returns**

- True if the registration is successful

###### sl_wisun_coap_rhnd_resource_init (heading level 7)

`__STATIC_INLINE void sl_wisun_coap_rhnd_resource_init(sl_wisun_coap_rhnd_resource_t *const src_resource)`

**Description:** Initialise empty resource.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_coap_rhnd_resource_t](sl-wisun-coap-rhnd-types#sl-wisun-coap-rhnd-resource-t) *const|[in]|src_resource|Resource descriptor|

Set pointers to NULL and flags to false 

**References:** [sl_wisun_coap_rhnd_resource::auto_response](sl-wisun-coap-rhnd-resource#auto-response), [sl_wisun_coap_rhnd_resource::auto_response_ext](sl-wisun-coap-rhnd-resource#auto-response-ext), [sl_wisun_coap_rhnd_resource::data](sl-wisun-coap-rhnd-resource#data), [sl_wisun_coap_rhnd_resource::discoverable](sl-wisun-coap-rhnd-resource#discoverable), [sl_wisun_coap_rhnd_resource_data::interface](sl-wisun-coap-rhnd-resource-data#interface), [sl_wisun_coap_rhnd_resource::next](sl-wisun-coap-rhnd-resource#next), [sl_wisun_coap_rhnd_resource::redirect_response](sl-wisun-coap-rhnd-resource#redirect-response), [sl_wisun_coap_rhnd_resource_data::resource_type](sl-wisun-coap-rhnd-resource-data#resource-type) and [sl_wisun_coap_rhnd_resource_data::uri_path](sl-wisun-coap-rhnd-resource-data#uri-path)

###### sl_wisun_coap_rhnd_resource_remove_by_uri (heading level 7)

`sl_status_t sl_wisun_coap_rhnd_resource_remove_by_uri(const char *uri_path)`

**Description:** Remove a resource from the CoAP Resource table referenced by name.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|uri_path|URI path of the resource to be removed|

**Returns**

- True if removal is successful

###### sl_wisun_coap_rhnd_set_auto_response (heading level 7)

`sl_status_t sl_wisun_coap_rhnd_set_auto_response(const char *uri_path, sl_wisun_coap_rhnd_auto_resp_t response)`

**Description:** Set auto-response callback.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|uri_path|URI path|
|[sl_wisun_coap_rhnd_auto_resp_t](sl-wisun-coap-rhnd-types#sl-wisun-coap-rhnd-auto-resp-t)|[in]|response|Response callback|

Set callback for resource **Returns**

- sl_status_t SL_STATUS_OK on success, SL_STATUS_FAIL on error

###### Type definitions

###### Modules (heading level 7)

[sl_wisun_coap_rhnd_resource](sl-wisun-coap-rhnd-resource)

[sl_wisun_coap_rhnd_resource_data](sl-wisun-coap-rhnd-resource-data)

###### Typedefs (heading level 7)

###### sl_wisun_coap_rhnd_auto_resp_ext_t (heading level 8)

`typedef sl_wisun_coap_packet_t *(* sl_wisun_coap_rhnd_auto_resp_ext_t) (const sockaddr_in6_t *const src_addr, const sl_wisun_coap_packet_t *const req_packet)`

**Description:**

Extended auto response callback for resources.

###### sl_wisun_coap_rhnd_auto_resp_t (heading level 8)

`typedef sl_wisun_coap_packet_t *(* sl_wisun_coap_rhnd_auto_resp_t) (const sl_wisun_coap_packet_t *const req_packet)`

**Description:**

Auto-Response callback for resources.

###### sl_wisun_coap_rhnd_redirect_resp_t (heading level 8)

`typedef void(* sl_wisun_coap_rhnd_redirect_resp_t) (sockaddr_in6_t *const new_addr, const sl_wisun_coap_packet_t *const req_packet)`

**Description:**

Redirect response callback type to create new destination socket address.

###### sl_wisun_coap_rhnd_resource_data_t (heading level 8)

`typedef struct sl_wisun_coap_rhnd_resource_data sl_wisun_coap_rhnd_resource_data_t`

**Description:**

Resource table data.

###### sl_wisun_coap_rhnd_resource_t (heading level 8)

`typedef struct sl_wisun_coap_rhnd_resource sl_wisun_coap_rhnd_resource_t`

**Description:**

Resource table entry.

Resource table entry. 

###### Public Attributes (heading level 8)

###### auto_response (heading level 9)

```
sl_wisun_coap_rhnd_auto_resp_t sl_wisun_coap_rhnd_resource::auto_response
```

**Description:** Auto response.

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### auto_response_ext (heading level 9)

```
sl_wisun_coap_rhnd_auto_resp_ext_t sl_wisun_coap_rhnd_resource::auto_response_ext
```

**Description:** Auto response extended If it's registered in the resource descriptor, it will be called instead of auto_response.

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### data (heading level 9)

```
sl_wisun_coap_rhnd_resource_data_t sl_wisun_coap_rhnd_resource::data
```

**Description:** Resource data.

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### discoverable (heading level 9)

```
bool sl_wisun_coap_rhnd_resource::discoverable
```

**Description:** Resource discoverable.

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### next (heading level 9)

```
struct sl_wisun_coap_rhnd_resource* sl_wisun_coap_rhnd_resource::next
```

**Description:** Next pointer.

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### redirect_response (heading level 9)

```
sl_wisun_coap_rhnd_redirect_resp_t sl_wisun_coap_rhnd_resource::redirect_response
```

**Description:** Redirect response callback.

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

Resource table data. 

###### Public Attributes (heading level 8)

###### interface (heading level 9)

```
const char* sl_wisun_coap_rhnd_resource_data::interface
```

**Description:** inteface type string

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### resource_type (heading level 9)

```
const char* sl_wisun_coap_rhnd_resource_data::resource_type
```

**Description:** resource type string

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

###### uri_path (heading level 9)

```
const char* sl_wisun_coap_rhnd_resource_data::uri_path
```

**Description:** resource URI path string

**Referenced by:** [sl_wisun_coap_rhnd_resource_init](sl-wisun-coap-rhnd-api#sl-wisun-coap-rhnd-resource-init)

##### CoAP Notification API

###### Modules

[Type definitions](sl-wisun-coap-notify-types)

###### Functions

###### sl_wisun_coap_notify_add (heading level 7)

`sl_status_t sl_wisun_coap_notify_add(const sl_wisun_coap_notify_t *const src_notify)`

**Description:** Register a new notification.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_notify_t](sl-wisun-coap-notify-types#sl-wisun-coap-notify-t) *const|[in]|src_notify|the new notification's descriptor to add|

Notification is added to the internal storage. **Returns**

- sl_status_t SL_STATUS_OK if the notification is added successfully, otherwise SL_STATUS_FAIL

###### sl_wisun_coap_notify_get_by_id (heading level 7)

`const sl_wisun_coap_notify_t * sl_wisun_coap_notify_get_by_id(const char *id)`

**Description:** Get notification by ID.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|id|unique ID of the notification (custom string)|

Get pointer to the notification instance in the storage. **Returns**

- sl_wisun_coap_notify_t * pointer to notify instance if succeeded, otherwise NULL ptr

###### sl_wisun_coap_notify_init (heading level 7)

`void sl_wisun_coap_notify_init(void)`

**Description:** Initialization of the CoAP notification service.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

If the service is enabled, the notification thread is initialized also. 

###### sl_wisun_coap_notify_init_default_inst (heading level 7)

`sl_status_t sl_wisun_coap_notify_init_default_inst(sl_wisun_coap_notify_t *const notify, const char *id)`

**Description:** Init default notification instance.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_coap_notify_t](sl-wisun-coap-notify-types#sl-wisun-coap-notify-t) *const|[in]|notify|notify descriptor for init|
|const char *|[in]|id|unique ID of the notification (custom string)|

Default remote address and port are defined in the config file. **Returns**

- sl_status_t SL_STATUS_OK if the initialization is succeeded, otherwise SL_STATUS_FAIL

###### sl_wisun_coap_notify_print_notifications (heading level 7)

`void sl_wisun_coap_notify_print_notifications(void)`

**Description:** Print notifications.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Print content of the internal storage.

Print resource URI paths 

###### sl_wisun_coap_notify_remove_by_id (heading level 7)

`sl_status_t sl_wisun_coap_notify_remove_by_id(const char *id)`

**Description:** Remove notification from the CoAP notification table referenced by name.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|id|Notification ID|

Remove notification from the internal storage. **Returns**

- sl_status_t SL_STATUS_OK if the notification is removed successfully, otherwise SL_STATUS_FAIL

###### sl_wisun_coap_notify_send_notification (heading level 7)

`sl_status_t sl_wisun_coap_notify_send_notification(const sl_wisun_coap_notify_t *const notify)`

**Description:** Send notification.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_notify_t](sl-wisun-coap-notify-types#sl-wisun-coap-notify-t) *const|[in]|notify|Notification instance. It includes all the necessary information about destination.|

Notification should be initialised properly before sending. **Returns**

- sl_status_t SL_STATUS_OK if the notification is sent successfully, otherwise SL_STATUS_FAIL

###### Type definitions

###### Modules (heading level 7)

[sl_wisun_coap_notify](sl-wisun-coap-notify)

###### Typedefs (heading level 7)

###### sl_wisun_coap_notify_t (heading level 8)

`typedef struct sl_wisun_coap_notify sl_wisun_coap_notify_t`

**Description:**

CoAP Notify type definition.

CoAP Notify type definition. 

###### Public Attributes (heading level 8)

###### condition_cb (heading level 9)

```
bool(* sl_wisun_coap_notify::condition_cb) (const struct sl_wisun_coap_notify *notify)
```

**Description:** Condition check callback, it returns with the result of send condition (true: send, false: not send)

###### hnd_cb (heading level 9)

```
sl_wisun_coap_packet_t *(* sl_wisun_coap_notify::hnd_cb) (const struct sl_wisun_coap_notify *notify)
```

**Description:** Packet handler callback, it returns with the built CoAP packet.

###### id (heading level 9)

```
const char* sl_wisun_coap_notify::id
```

**Description:** ID string.

###### remote_addr (heading level 9)

```
sockaddr_in6_t sl_wisun_coap_notify::remote_addr
```

**Description:** Remote address.

###### schedule_time_ms (heading level 9)

```
uint32_t sl_wisun_coap_notify::schedule_time_ms
```

**Description:** Schedule time (ms)

###### tick_ms (heading level 9)

```
uint32_t sl_wisun_coap_notify::tick_ms
```

**Description:** Tick counter (ms)

#### Ping

The Ping component implements a ping service using the ICMPv6 protocol. It can send ICMPv6 Echo Request, receive corresponding responses, and calculate round-trip latency.

Applications can emit a single ping packet using the [sl_wisun_ping_request()](sl-wisun-ping-api#sl-wisun-ping-request) API. To receive the pong response, the [sl_wisun_ping_response()](sl-wisun-ping-api#sl-wisun-ping-response) API is called. The [sl_wisun_ping()](sl-wisun-ping-api#sl-wisun-ping) function offers a straightforward solution for periodic ping packet transmission and reception. To halt the process, use the [sl_wisun_ping_stop()](sl-wisun-ping-api#sl-wisun-ping-stop) function.

Ping test parameters such as size, number of pings sent, and timeout for response absence are configurable. Initialization of the component is done by calling the [sl_wisun_ping_init()](sl-wisun-ping-api#sl-wisun-ping-init) function.

The following example demonstrates how the ping request can be called:

```c
#include "sl_wisun_ping.h"

static void ping_remote(void) {
  int32_t ret = 0;
  sockaddr_in6_t remote_addr = { 0 };
  sl_status_t status = SL_STATUS_FAIL;

  // Create address structure from ping
  ret = inet_pton(AF_INET6,
                  "2001:db8::1",
                  &remote_addr.sin6_addr);

  if (ret != 1) {
    // Error handling
    return;
  }

  // Send and receive ping requests and responses
  status = sl_wisun_ping(&remote_addr, // Ping remote_addr IPv6 address
                         10, // with 10 packets
                         512, // packet length is 512 bytes
                         NULL, // Custom statitistic handler is not required
                         NULL); // Request/Response handler is not required
  if (status != SL_STATUS_OK) {
    // Error handling
    return;
  }
}

```

##### Modules

[Configurations](sl-wisun-ping-config)

[Type definitions](sl-wisun-ping-api-types)

##### Functions

###### sl_wisun_ping

`sl_status_t sl_wisun_ping(const sockaddr_in6_t *const remote_addr, const uint16_t packet_count, const uint16_t packet_length, sl_wisun_ping_stat_hnd_t stat_hnd, sl_wisun_ping_req_resp_done_hnd_t req_resp_sent_hnd)`

**Description:** Provide a high level ping API.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sockaddr_in6_t](sl-wisun-socket-api#sockaddr-in6-t) *const|[in]|remote_addr|Remote destination address|
|const uint16_t|[in]|packet_count|Count of packets|
|const uint16_t|[in]|packet_length|ICMPv6 packet length including header|
|[sl_wisun_ping_stat_hnd_t](sl-wisun-ping-api-types#sl-wisun-ping-stat-hnd-t)|[in]|stat_hnd|Custom statistic handler function|
|[sl_wisun_ping_req_resp_done_hnd_t](sl-wisun-ping-api-types#sl-wisun-ping-req-resp-done-hnd-t)|[in]|req_resp_sent_hnd|Request/Response sent handler function|

The function provides an interface for periodically sending and receiving ping ICMPv6 packets, and collecting statistic data. **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL or SL_STATUS_ABORT

###### sl_wisun_ping_init

`void sl_wisun_ping_init(void)`

**Description:** Initialize the ping service module.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function initializes the service thread, mutex, and message queues. 

###### sl_wisun_ping_request

`void sl_wisun_ping_request(const sl_wisun_ping_info_t *const ping_request)`

**Description:** Send a ping request.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_ping_info_t](sl-wisun-ping-api-types#sl-wisun-ping-info-t) *const|[in]|ping_request|Ping Request Information|

The function sends a single ICMPv6 request. 

###### sl_wisun_ping_response

`void sl_wisun_ping_response(sl_wisun_ping_info_t *const ping_response)`

**Description:** Retrieve a ping response.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_ping_info_t](sl-wisun-ping-api-types#sl-wisun-ping-info-t) *const|[out]|ping_response|Ping Response Information|

The function retrieves a ping response information. 

###### sl_wisun_ping_stop

`void sl_wisun_ping_stop(void)`

**Description:** Stop the current ping process.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Reset request and response queues and send a special ping request with interrupt ping status. 

##### Macros

`#define SL_WISUN_PING_CODE_ECHO_REQUEST (0U)`

**Description**: Ping echo request code field value.

`#define SL_WISUN_PING_CODE_ECHO_RESPONSE (0U)`

**Description**: Ping echo response code field value.

`#define SL_WISUN_PING_ICMP_PORT (0U)`

**Description**: Dedicated port for ICMPv6 echo messages.

`#define SL_WISUN_PING_MAX_PACKET_LENGTH (SL_WISUN_PING_MIN_PACKET_LENGTH - 1 + SL_WISUN_PING_MAX_PAYLOAD_LENGTH)`

**Description**: Max packet length.

`#define SL_WISUN_PING_MAX_REQUEST_RESPONSE (128U)`

**Description**: Maximum count of ping request/response for message queues.

`#define SL_WISUN_PING_MIN_PACKET_LENGTH (9U)`

**Description**: Minimum packet length with 1 byte payload.

`#define SL_WISUN_PING_TYPE_ECHO_REQUEST (128U)`

**Description**: Ping echo request type field value.

`#define SL_WISUN_PING_TYPE_ECHO_RESPONSE (129U)`

**Description**: Ping echo response type field value.

##### Configurations

###### Macros

`#define SL_WISUN_PING_MAX_PAYLOAD_LENGTH 144U`

**Description**: Maximum length of payload.

`#define SL_WISUN_PING_PACKET_COUNT 4U`

**Description**: Default packet count for ping.

`#define SL_WISUN_PING_PACKET_INTERVAL 1000U`

**Description**: Packet Interval.

`#define SL_WISUN_PING_PACKET_SIZE 40U`

**Description**: Default packet size for ping.

`#define SL_WISUN_PING_STACK_SIZE_WORD 192U`

**Description**: Ping thread stack size in word.

`#define SL_WISUN_PING_TIMEOUT_MS 10000U`

**Description**: Ping timeout.

##### Type definitions

###### Modules

[sl_wisun_ping_echo_request](sl-wisun-ping-echo-request)

[sl_wisun_ping_info](sl-wisun-ping-info)

[sl_wisun_ping_stat](sl-wisun-ping-stat)

###### Typedefs

###### sl_wisun_ping_echo_request_t (heading level 7)

`typedef struct sl_wisun_ping_echo_request sl_wisun_ping_echo_request_t`

**Description:**

Ping echo request packed structure type definitions.

###### sl_wisun_ping_echo_response_t (heading level 7)

`typedef sl_wisun_ping_echo_request_t sl_wisun_ping_echo_response_t`

**Description:**

Ping response type definition.

###### sl_wisun_ping_info_t (heading level 7)

`typedef struct sl_wisun_ping_info sl_wisun_ping_info_t`

**Description:**

Ping info structure type definition.

###### sl_wisun_ping_req_resp_done_hnd_t (heading level 7)

`typedef void(* sl_wisun_ping_req_resp_done_hnd_t) (sl_wisun_ping_info_t *req, sl_wisun_ping_info_t *resp)`

**Description:**

Ping request/response sent handler.

###### sl_wisun_ping_stat_hnd_t (heading level 7)

`typedef void(* sl_wisun_ping_stat_hnd_t) (sl_wisun_ping_stat_t *stat)`

**Description:**

Ping statistic typedef.

###### sl_wisun_ping_stat_t (heading level 7)

`typedef struct sl_wisun_ping_stat sl_wisun_ping_stat_t`

**Description:**

Statistic ping type definition.

Ping echo request packed structure type definitions. 

###### Public Attributes (heading level 7)

###### checksum (heading level 8)

```
uint16_t sl_wisun_ping_echo_request::checksum
```

**Description:** Checksum.

###### code (heading level 8)

```
uint8_t sl_wisun_ping_echo_request::code
```

**Description:** Code.

###### identifier (heading level 8)

```
uint16_t sl_wisun_ping_echo_request::identifier
```

**Description:** Identifier.

###### payload (heading level 8)

```
uint8_t sl_wisun_ping_echo_request::payload[SL_WISUN_PING_MAX_PAYLOAD_LENGTH]
```

**Description:** Payload array.

###### sequence_number (heading level 8)

```
uint16_t sl_wisun_ping_echo_request::sequence_number
```

**Description:** Sequence number.

###### type (heading level 8)

```
uint8_t sl_wisun_ping_echo_request::type
```

**Description:** type

Ping info structure type definition. 

###### Public Attributes (heading level 7)

###### identifier (heading level 8)

```
uint16_t sl_wisun_ping_info::identifier
```

**Description:** Identifier.

###### lost (heading level 8)

```
bool sl_wisun_ping_info::lost
```

**Description:** Lost packet flag.

###### packet_length (heading level 8)

```
uint16_t sl_wisun_ping_info::packet_length
```

**Description:** ICMPv6 packet length including header.

###### remote_addr (heading level 8)

```
sockaddr_in6_t sl_wisun_ping_info::remote_addr
```

**Description:** Wi-SUN remote address.

###### response_time_ms (heading level 8)

```
uint32_t sl_wisun_ping_info::response_time_ms
```

**Description:** Response time millisecond.

###### sequence_number (heading level 8)

```
uint16_t sl_wisun_ping_info::sequence_number
```

**Description:** Sequence number.

###### start_time_stamp (heading level 8)

```
uint32_t sl_wisun_ping_info::start_time_stamp
```

**Description:** Start time stamp.

###### stop_time_stamp (heading level 8)

```
uint32_t sl_wisun_ping_info::stop_time_stamp
```

**Description:** Stop time stamp.

Statistic ping type definition. 

###### Public Attributes (heading level 7)

###### avg_time_ms (heading level 8)

```
uint32_t sl_wisun_ping_stat::avg_time_ms
```

**Description:** Average echo time millisecond.

###### lost (heading level 8)

```
uint16_t sl_wisun_ping_stat::lost
```

**Description:** Lost packet count.

###### max_time_ms (heading level 8)

```
uint32_t sl_wisun_ping_stat::max_time_ms
```

**Description:** Maximum echo time millisecond.

###### min_time_ms (heading level 8)

```
uint32_t sl_wisun_ping_stat::min_time_ms
```

**Description:** Minimum echo time millisecond.

###### packet_count (heading level 8)

```
uint16_t sl_wisun_ping_stat::packet_count
```

**Description:** Packet count.

###### packet_length (heading level 8)

```
uint16_t sl_wisun_ping_stat::packet_length
```

**Description:** Packet length.

###### remote_addr (heading level 8)

```
sockaddr_in6_t sl_wisun_ping_stat::remote_addr
```

**Description:** Wi-SUN remote address.

#### iPerf

The iPerf component offers a solution compatible with [iPerf2](https://sourceforge.net/projects/iperf2/) for measuring UDP throughput. It provides comprehensive UDP support and implements both server and client modes, enabling the exchange of packets to assess bandwidth performance, inter-arrival jitter, and packet loss. The component relies on various functions, to configure and execute your iPerf test. Parameters such as the server and client ports, preferred bandwidth, packet count, and remote peer address can be customized. Upon completion of each iPerf test, an iPerf report is generated.

To integrate the iPerf component into the application, simply add it to the project and initialize it using [sl_iperf_service_init()](sl-iperf#sl-iperf-service-init).

The following examples show how you can initialize a iPerf server and then an iPerf client

```c
#include <string.h>
#include "cmsis_os2.h"
#include "sl_iperf.h"
#include "sl_iperf_util.h"

static void exec_iperf_server(void) {
  sl_iperf_test_t srv_test = { 0 };

  // Initialize Server test
  sl_iperf_test_init(&srv_test, SL_IPERF_MODE_SERVER, SL_IPERF_IPROTOV6_UDP);

  // Set minimum time duration for the test
  srv_test.opt.duration_ms = 10000;

  // Add the test to the execution queue
  if (sl_iperf_test_add(&srv_test) == false) {
    // Error handling
    return;
  }

  // Waiting for the test result
  if (sl_iperf_test_get(&srv_test, osWaitForever) == false) {
    // Error handling
    return;
  }

  // Print the result in JSON format
  sl_iperf_print_test_log_json(&srv_test);
}

```

```c
static void exec_iperf_client(void)
{
  sl_iperf_test_t clnt_test = { 0 };

  // Initialize Client test
  sl_iperf_test_init(&clnt_test, SL_IPERF_MODE_CLIENT, SL_IPERF_IPROTOV6_UDP);

  // Configure test parameters
  // Set the remote server address
  strncpy(clnt_test.opt.remote_addr, "2001:db8::1", SL_IPERF_IP_STR_BUFF_LEN);

  // Set the bandwidth to 10 kBit/s
  clnt_test.opt.bandwidth = 10000;

  // Add the test to the execution queue
  if (sl_iperf_test_add(&clnt_test) == false) {
    // Error handling
    return;
  }

  // Waiting for the test result
  if (sl_iperf_test_get(&clnt_test, osWaitForever) == false) {
    // Error handling
    return;
  }

  // Print the result in JSON format
  sl_iperf_print_test_log_json(&clnt_test);
}

```

##### Modules

[Configurations](sl-iperf-config)

[Type definitions](sl-iperf-types)

[Portable interface](sl-iperf-network-interface-api)

##### Functions

###### sl_iperf_service_init

`void sl_iperf_service_init(void)`

**Description:** Initialize the iPerf service.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Init OS objects and default contents 

###### sl_iperf_test_add

`bool sl_iperf_test_add(sl_iperf_test_t *const test)`

**Description:** Add the iPerf test to the execution queue.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *const|[in]|test|Test descriptor|

Add test to the input messagequeue. **Returns**

- true On Success
- false On Failure

###### sl_iperf_test_get

`bool sl_iperf_test_get(sl_iperf_test_t *const test, const uint32_t timeout_ms)`

**Description:** Get the iPerf test from the result queue.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *const|[out]|test|Destination test descriptor|
|const uint32_t|[in]|timeout_ms|Timeout for getting test from messagequeue|

Get the test from the output messagequeue. **Returns**

- true On Success
- false On Failure

###### sl_iperf_test_init

`void sl_iperf_test_init(sl_iperf_test_t *const test, sl_iperf_mode_t mode, sl_iperf_protocol_t protocol)`

**Description:** Initialize the iPerf test.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *const|[inout]|test|Test descriptor|
|[sl_iperf_mode_t](sl-iperf-types#sl-iperf-mode-t)|[in]|mode|Mode|
|[sl_iperf_protocol_t](sl-iperf-network-interface-api#sl-iperf-protocol-t)|[in]|protocol|Protocol|

Initialize a test descriptor with default content 

###### sl_iperf_test_set_default_buff

`void sl_iperf_test_set_default_buff(sl_iperf_test_t *const test)`

**Description:** Set the default internal test buffer.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *const|[out]|test|Test descriptor|

Helper function 

###### sl_iperf_test_set_default_logger

`void sl_iperf_test_set_default_logger(sl_iperf_test_t *const test)`

**Description:** Set the default internal logger for the test descriptor.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *const|[out]|test|Test descriptor|

Helper function 

###### sl_iperf_test_udp_client

`void sl_iperf_test_udp_client(sl_iperf_test_t *test)`

**Description:** Execute the iPerf UDP client test.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *|[inout]|test|Test descriptor|

iPerf UDP client test. 

###### sl_iperf_test_udp_server

`void sl_iperf_test_udp_server(sl_iperf_test_t *test)`

**Description:** Execute the iPerf UDP server test.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_test_t](sl-iperf-types#sl-iperf-test-t) *|[inout]|test|Test descriptor|

iPerf UDP server test. 

##### Macros

`#define SL_IPERF_HEADER_EPOCH_START (0x00001000UL)`

**Description**: iPerf header epoch start mask

`#define SL_IPERF_HEADER_EXTEND (0x40000000UL)`

**Description**: iPerf header extended mask

`#define SL_IPERF_HEADER_SEQNO64B (0x08000000UL)`

**Description**: iPerf header seqno 64bit mask

`#define SL_IPERF_HEADER_TIME_MODE (0x80000000UL)`

**Description**: iPerf header time mode mask

`#define SL_IPERF_HEADER_TRIPTIME (0x00000010UL)`

**Description**: iPerf header triptime mask

`#define SL_IPERF_HEADER_UDPTEST (0x20000000UL)`

**Description**: iPerf header UDP test mask

`#define SL_IPERF_HEADER_VERSION1 (0x80000000UL)`

**Description**: iPerf header version1 mask

`#define SL_IPERF_HEADER_VERSION2 (0x04000000UL)`

**Description**: iPerf header version2 mask

`#define SL_IPERF_SERVER_UDP_TX_FINACK_COUNT (10U)`

**Description**: iPerf Server TX FINACK max count to retry

`#define SL_IPERF_UDP_SERVER_FIN_ACK_SIZE (128U)`

**Description**: iPerf UDP server final ack size

##### Configurations

###### Macros

`#define SL_IPERF_BUFFER_SIZE 1232U`

**Description**: Server receiver buffer size.

`#define SL_IPERF_CLIENT_DEFAULT_BANDWIDTH_BPS 20000U`

**Description**: Default bandwidth in bits/sec.

`#define SL_IPERF_CLIENT_DEFAULT_SEND_TIME_MS 10000U`

**Description**: Default sending time in millisec.

`#define SL_IPERF_DEFAULT_INTERVAL_MS 1000U`

**Description**: Default statistic update interval.

`#define SL_IPERF_LOG_JSON_INDENT 2U`

**Description**: Set json formatted log indent in space count.

`#define SL_IPERF_MAX_TEST_TIMEOUT_MS 2000U`

**Description**: Maximum possible additional test timeout after duration time.

`#define SL_IPERF_MESSAGE_QUEUE_SIZE 16U`

**Description**: Set test message queue size.

`#define SL_IPERF_SERVER_DEFAULT_PORT 5001U`

**Description**: Default Server port.

`#define SL_IPERF_SOCKET_ADDR_LEN 32U`

**Description**: Set the address length buffer size.

`#define SL_IPERF_STACK_SIZE_WORD 256U`

**Description**: Set test thread stack size in word depth.

`#define SL_IPERF_VERBOSE_MODE 0U`

**Description**: Enable verbose prints.

##### Type definitions

###### Modules

[sl_iperf_clnt_hdr_ext](sl-iperf-clnt-hdr-ext)

[sl_iperf_clnt_hdr_ext_isoch_settings](sl-iperf-clnt-hdr-ext-isoch-settings)

[sl_iperf_clnt_hdr_ext_starttime_fq](sl-iperf-clnt-hdr-ext-starttime-fq)

[sl_iperf_clnt_hdr_isoch_payload](sl-iperf-clnt-hdr-isoch-payload)

[sl_iperf_conn](sl-iperf-conn)

[sl_iperf_log](sl-iperf-log)

[sl_iperf_log_str_buff](sl-iperf-log-str-buff)

[sl_iperf_opt](sl-iperf-opt)

[sl_iperf_stats](sl-iperf-stats)

[sl_iperf_test](sl-iperf-test)

[sl_iperf_udp_clnt_hdr](sl-iperf-udp-clnt-hdr)

[sl_iperf_udp_clnt_hdr_v1](sl-iperf-udp-clnt-hdr-v1)

[sl_iperf_udp_datagram](sl-iperf-udp-datagram)

[sl_iperf_udp_srv_hdr](sl-iperf-udp-srv-hdr)

###### Enumerations

###### sl_iperf_err (heading level 7)

```
enum sl_iperf_err {
    SL_IPERF_ERR_NONE
    SL_IPERF_ERR_NETWORK_CONNECTION
    SL_IPERF_ERR_SERVER_SOCK_BIND
    SL_IPERF_ERR_SERVER_SOCK_OPEN
    SL_IPERF_ERR_SERVER_SOCK_CLOSE
    SL_IPERF_ERR_SERVER_SOCK_LISTEN
    SL_IPERF_ERR_SERVER_SOCK_ACCEPT
    SL_IPERF_ERR_SERVER_SOCK_RX
    SL_IPERF_ERR_SERVER_SOCK_WIN_SIZE
    SL_IPERF_ERR_CLIENT_SOCK_OPEN
    SL_IPERF_ERR_CLIENT_SOCK_BIND
    SL_IPERF_ERR_CLIENT_SOCK_CONN
    SL_IPERF_ERR_CLIENT_SOCK_TX
    SL_IPERF_ERR_CLIENT_SOCK_TX_INV_ARG
    SL_IPERF_ERR_CLIENT_SOCK_CLOSE
}
```

**Description:**

iPerf error enumeration type definition

**Enumerator:**

|   |   |
|---|---|
|SL_IPERF_ERR_NONE|No error.|
|SL_IPERF_ERR_NETWORK_CONNECTION|Network connection error.|
|SL_IPERF_ERR_SERVER_SOCK_BIND|Server socket bind error.|
|SL_IPERF_ERR_SERVER_SOCK_OPEN|Server socket open error.|
|SL_IPERF_ERR_SERVER_SOCK_CLOSE|Server socket close error.|
|SL_IPERF_ERR_SERVER_SOCK_LISTEN|Server socket listen error.|
|SL_IPERF_ERR_SERVER_SOCK_ACCEPT|Server socket accept error.|
|SL_IPERF_ERR_SERVER_SOCK_RX|Server socket RX error.|
|SL_IPERF_ERR_SERVER_SOCK_WIN_SIZE|Server socket windows size error.|
|SL_IPERF_ERR_CLIENT_SOCK_OPEN|Client socket open error.|
|SL_IPERF_ERR_CLIENT_SOCK_BIND|Client socket bind error.|
|SL_IPERF_ERR_CLIENT_SOCK_CONN|Client socket connect error.|
|SL_IPERF_ERR_CLIENT_SOCK_TX|Client socket TX error.|
|SL_IPERF_ERR_CLIENT_SOCK_TX_INV_ARG|Client socket TX invalid argument error.|
|SL_IPERF_ERR_CLIENT_SOCK_CLOSE|Client socket socket close error.|

###### sl_iperf_mode (heading level 7)

```
enum sl_iperf_mode {
    SL_IPERF_MODE_SERVER
    SL_IPERF_MODE_CLIENT
}
```

**Description:**

iPerf mode

**Enumerator:**

|   |   |
|---|---|
|SL_IPERF_MODE_SERVER|Server mode.|
|SL_IPERF_MODE_CLIENT|Client mode.|

###### sl_iperf_opt_bw_format (heading level 7)

```
enum sl_iperf_opt_bw_format {
    SL_IPERF_OPT_BW_FORMAT_BITS_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_KBITS_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_MBITS_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_GBITS_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_BYTES_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_KBYTES_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_MBYTES_PER_SEC
    SL_IPERF_OPT_BW_FORMAT_GBYTES_PER_SEC
}
```

**Description:**

Bandwidth format enumeration type definition.

**Enumerator:**

|   |   |
|---|---|
|SL_IPERF_OPT_BW_FORMAT_BITS_PER_SEC|Bits/sec format.|
|SL_IPERF_OPT_BW_FORMAT_KBITS_PER_SEC|KBits/sec format.|
|SL_IPERF_OPT_BW_FORMAT_MBITS_PER_SEC|MBits/sec format.|
|SL_IPERF_OPT_BW_FORMAT_GBITS_PER_SEC|GBits/sec format.|
|SL_IPERF_OPT_BW_FORMAT_BYTES_PER_SEC|Bytes/sec format.|
|SL_IPERF_OPT_BW_FORMAT_KBYTES_PER_SEC|KBytes/sec format.|
|SL_IPERF_OPT_BW_FORMAT_MBYTES_PER_SEC|MBytes/sec format.|
|SL_IPERF_OPT_BW_FORMAT_GBYTES_PER_SEC|GBytes/sec format.|

###### sl_iperf_status (heading level 7)

```
enum sl_iperf_status {
    SL_IPERF_TEST_STATUS_FREE
    SL_IPERF_TEST_STATUS_QUEUED
    SL_IPERF_TEST_STATUS_RUNNING
    SL_IPERF_TEST_STATUS_DONE
    SL_IPERF_TEST_STATUS_ERR
}
```

**Description:**

Test status type definition.

**Enumerator:**

|   |   |
|---|---|
|SL_IPERF_TEST_STATUS_FREE|Test unused.|
|SL_IPERF_TEST_STATUS_QUEUED|Test queued.|
|SL_IPERF_TEST_STATUS_RUNNING|Test running.|
|SL_IPERF_TEST_STATUS_DONE|Test done with no error.|
|SL_IPERF_TEST_STATUS_ERR|Test done with error.|

###### Typedefs

###### sl_iperf_clnt_hdr_ext_isoch_settings_t (heading level 7)

`typedef struct sl_iperf_clnt_hdr_ext_isoch_settings sl_iperf_clnt_hdr_ext_isoch_settings_t`

**Description:**

iPerf Client Isochronous settings

###### sl_iperf_clnt_hdr_ext_starttime_fq_t (heading level 7)

`typedef struct sl_iperf_clnt_hdr_ext_starttime_fq sl_iperf_clnt_hdr_ext_starttime_fq_t`

**Description:**

iPerf Client header extended FQ start time

###### sl_iperf_clnt_hdr_ext_t (heading level 7)

`typedef struct sl_iperf_clnt_hdr_ext sl_iperf_clnt_hdr_ext_t`

**Description:**

iPerf Client Header extended

###### sl_iperf_clnt_hdr_isoch_payload_t (heading level 7)

`typedef struct sl_iperf_clnt_hdr_isoch_payload sl_iperf_clnt_hdr_isoch_payload_t`

**Description:**

iPerf Client Isochronous payload

###### sl_iperf_clnt_hdr_v1_t (heading level 7)

`typedef struct sl_iperf_udp_clnt_hdr_v1 sl_iperf_clnt_hdr_v1_t`

**Description:**

iPerf CLient Header v1

###### sl_iperf_conn_t (heading level 7)

`typedef struct sl_iperf_conn sl_iperf_conn_t`

**Description:**

iPerf connection descriptor type definition

###### sl_iperf_error_t (heading level 7)

`typedef enum sl_iperf_err sl_iperf_error_t`

**Description:**

iPerf error enumeration type definition

###### sl_iperf_log_print_t (heading level 7)

`typedef int32_t(* sl_iperf_log_print_t) (sl_iperf_log_t *const log, const char *format,...)`

**Description:**

Printer function type definition.

###### sl_iperf_log_str_buff_t (heading level 7)

`typedef struct sl_iperf_log_str_buff sl_iperf_log_str_buff_t`

**Description:**

Log string buffer type definition.

###### sl_iperf_log_t (heading level 7)

`typedef struct sl_iperf_log sl_iperf_log_t`

**Description:**

iPerf log type definition

###### sl_iperf_mode_t (heading level 7)

`typedef enum sl_iperf_mode sl_iperf_mode_t`

**Description:**

iPerf mode

###### sl_iperf_opt_bw_format (heading level 7)

`typedef enum sl_iperf_opt_bw_format sl_iperf_opt_bw_format`

**Description:**

Bandwidth format enumeration type definition.

###### sl_iperf_opt_t (heading level 7)

`typedef struct sl_iperf_opt sl_iperf_opt_t`

**Description:**

iPerf test option type definition

###### sl_iperf_stats_t (heading level 7)

`typedef struct sl_iperf_stats sl_iperf_stats_t`

**Description:**

iPerf statistic data type definition

###### sl_iperf_status_t (heading level 7)

`typedef enum sl_iperf_status sl_iperf_status_t`

**Description:**

Test status type definition.

###### sl_iperf_test_callback_t (heading level 7)

`typedef void(* sl_iperf_test_callback_t) (sl_iperf_test_t *)`

**Description:**

iPerf Test callback type definition

###### sl_iperf_test_id_t (heading level 7)

`typedef uint16_t sl_iperf_test_id_t`

**Description:**

Test ID type definition.

###### sl_iperf_test_t (heading level 7)

`typedef struct sl_iperf_test sl_iperf_test_t`

**Description:**

iPerf test descriptor

###### sl_iperf_udp_clnt_hdr_t (heading level 7)

`typedef struct sl_iperf_udp_clnt_hdr sl_iperf_udp_clnt_hdr_t`

**Description:**

iPerf Client UDP header

###### sl_iperf_udp_datagram_t (heading level 7)

`typedef struct sl_iperf_udp_datagram sl_iperf_udp_datagram_t`

**Description:**

iPerf UDP datagram structure type definition

###### sl_iperf_udp_srv_hdr_t (heading level 7)

`typedef struct sl_iperf_udp_srv_hdr sl_iperf_udp_srv_hdr_t`

**Description:**

iPerf server header

###### Macros

`#define SL_IPERF_IP_STR_BUFF_LEN (40U)`

**Description**: iPerf ip address string max length definition

iPerf Client Header extended 

###### Public Attributes (heading level 7)

###### l_flags (heading level 8)

```
int16_t sl_iperf_clnt_hdr_ext::l_flags
```

**Description:** Lower flags.

###### l_rate (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext::l_rate
```

**Description:** Lower rate.

###### l_version (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext::l_version
```

**Description:** Lower version.

###### length (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext::length
```

**Description:** Length.

###### reserved (heading level 8)

```
uint16_t sl_iperf_clnt_hdr_ext::reserved
```

**Description:** Reserved.

###### tcp_write_prefetch (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext::tcp_write_prefetch
```

**Description:** TCP write prefetch.

###### tos (heading level 8)

```
uint16_t sl_iperf_clnt_hdr_ext::tos
```

**Description:** Tos.

###### type (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext::type
```

**Description:** Type.

###### u_flags (heading level 8)

```
int16_t sl_iperf_clnt_hdr_ext::u_flags
```

**Description:** Upper flags.

###### u_rate (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext::u_rate
```

**Description:** Upper rate.

###### u_version (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext::u_version
```

**Description:** Upper version.

iPerf Client Isochronous settings 

###### Public Attributes (heading level 7)

###### l_burst_ipg (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::l_burst_ipg
```

**Description:** Lower Burst IPG.

###### l_fps (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::l_fps
```

**Description:** Lower FPS.

###### l_mean (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::l_mean
```

**Description:** Lower Mean.

###### l_variance (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::l_variance
```

**Description:** Lower Variance.

###### u_burst_ipg (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::u_burst_ipg
```

**Description:** Upper Burst IPG.

###### u_fps (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::u_fps
```

**Description:** Upper FPS.

###### u_mean (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::u_mean
```

**Description:** Upper Mean.

###### u_variance (heading level 8)

```
int32_t sl_iperf_clnt_hdr_ext_isoch_settings::u_variance
```

**Description:** Upper Variance.

iPerf Client header extended FQ start time 

###### Public Attributes (heading level 7)

###### l_fq_rate (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext_starttime_fq::l_fq_rate
```

**Description:** Lower FQ rate.

###### reserved (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext_starttime_fq::reserved
```

**Description:** Reserved.

###### start_tv_sec (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext_starttime_fq::start_tv_sec
```

**Description:** Start sec.

###### start_tv_usec (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext_starttime_fq::start_tv_usec
```

**Description:** Start usec.

###### u_fq_rate (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_ext_starttime_fq::u_fq_rate
```

**Description:** Upper FQ rate.

iPerf Client Isochronous payload 

###### Public Attributes (heading level 7)

###### burst_period (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::burst_period
```

**Description:** period units microseconds

###### burst_size (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::burst_size
```

**Description:** Burst size.

###### frame_id (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::frame_id
```

**Description:** Frame ID.

###### prev_frameid (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::prev_frameid
```

**Description:** Previous frame ID.

###### remaining (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::remaining
```

**Description:** Remaining.

###### reserved (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::reserved
```

**Description:** Reserved.

###### start_tv_sec (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::start_tv_sec
```

**Description:** Start sec.

###### start_tv_usec (heading level 8)

```
uint32_t sl_iperf_clnt_hdr_isoch_payload::start_tv_usec
```

**Description:** Start usec.

iPerf connection descriptor type definition 

###### Public Attributes (heading level 7)

###### buff (heading level 8)

```
uint8_t* sl_iperf_conn::buff
```

**Description:** Buffer ptr to receive/transmit.

###### buff_size (heading level 8)

```
size_t sl_iperf_conn::buff_size
```

**Description:** RX/TX buffer transmit.

###### clnt_addr (heading level 8)

```
sl_iperf_socket_addr_t sl_iperf_conn::clnt_addr
```

**Description:** Client sock addr IP.

###### run (heading level 8)

```
bool sl_iperf_conn::run
```

**Description:** Server (rx'd) or client (tx'd) started.

###### socket_id (heading level 8)

```
int32_t sl_iperf_conn::socket_id
```

**Description:** local socket id

###### socket_id_clnt (heading level 8)

```
int32_t sl_iperf_conn::socket_id_clnt
```

**Description:** Accepted sock used by TCP server to rx.

###### srv_addr (heading level 8)

```
sl_iperf_socket_addr_t sl_iperf_conn::srv_addr
```

**Description:** Server sock addr IP.

iPerf log type definition 

###### Public Attributes (heading level 7)

###### buff (heading level 8)

```
sl_iperf_log_str_buff_t sl_iperf_log::buff
```

**Description:** Buff string instance.

###### buffered (heading level 8)

```
bool sl_iperf_log::buffered
```

**Description:** Buffered.

###### colored (heading level 8)

```
bool sl_iperf_log::colored
```

**Description:** Colored.

###### last_res (heading level 8)

```
int32_t sl_iperf_log::last_res
```

**Description:** Last result.

###### print (heading level 8)

```
int32_t(* sl_iperf_log::print) (struct sl_iperf_log *const log, const char *format,...)
```

**Description:** Stdout and buffer printer.

Log string buffer type definition. 

###### Public Attributes (heading level 7)

###### buff (heading level 8)

```
char* sl_iperf_log_str_buff::buff
```

**Description:** Buff ptr.

###### pos (heading level 8)

```
char* sl_iperf_log_str_buff::pos
```

**Description:** Position ptr.

###### size (heading level 8)

```
size_t sl_iperf_log_str_buff::size
```

**Description:** Size.

iPerf test option type definition 

###### Public Attributes (heading level 7)

###### bandwidth (heading level 8)

```
uint32_t sl_iperf_opt::bandwidth
```

**Description:** expected bandwidth in bits/sec

###### buf_len (heading level 8)

```
uint16_t sl_iperf_opt::buf_len
```

**Description:** Buf len to tx or rx.

###### bw_format (heading level 8)

```
sl_iperf_opt_bw_format sl_iperf_opt::bw_format
```

**Description:** Bandwidth format.

###### duration_ms (heading level 8)

```
uint16_t sl_iperf_opt::duration_ms
```

**Description:** Time in sec to tx.

###### interval_ms (heading level 8)

```
uint16_t sl_iperf_opt::interval_ms
```

**Description:** Interval (ms) between bandwidth update.

###### mode (heading level 8)

```
sl_iperf_mode_t sl_iperf_opt::mode
```

**Description:** Server or client mode.

###### multicast (heading level 8)

```
bool sl_iperf_opt::multicast
```

**Description:** Join multicast group (address is stored in 'remote_addr')

###### packet_nbr (heading level 8)

```
uint16_t sl_iperf_opt::packet_nbr
```

**Description:** Nbr of packets to tx.

###### persistent (heading level 8)

```
bool sl_iperf_opt::persistent
```

**Description:** Server in persistent mode.

###### port (heading level 8)

```
uint16_t sl_iperf_opt::port
```

**Description:** Server or client port.

###### protocol (heading level 8)

```
sl_iperf_protocol_t sl_iperf_opt::protocol
```

**Description:** UDP or TCP protocol.

###### remote_addr (heading level 8)

```
char sl_iperf_opt::remote_addr[SL_IPERF_IP_STR_BUFF_LEN]
```

**Description:** Remote address for TX.

###### win_size (heading level 8)

```
uint16_t sl_iperf_opt::win_size
```

**Description:** Win size to tx or rx.

iPerf statistic data type definition 

###### Public Attributes (heading level 7)

###### bandwidth (heading level 8)

```
uint32_t sl_iperf_stats::bandwidth
```

**Description:** Rx or Tx cur bandwidth in bits/s.

###### bytes (heading level 8)

```
uint32_t sl_iperf_stats::bytes
```

**Description:** Nbr of bytes rx'd or tx'd on net.

###### end_err (heading level 8)

```
bool sl_iperf_stats::end_err
```

**Description:** Err with UDP FIN or FINACK.

###### errs (heading level 8)

```
uint32_t sl_iperf_stats::errs
```

**Description:** Nbr of rx or tx errs.

###### finack_bw (heading level 8)

```
uint32_t sl_iperf_stats::finack_bw
```

**Description:** Bandwidth in Final ACK in bits/s (calculated from FinACK tot length and FinACK duration ms)

###### finack_duration_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::finack_duration_ms
```

**Description:** Time duration in Final ACK.

###### finack_pkt (heading level 8)

```
uint32_t sl_iperf_stats::finack_pkt
```

**Description:** Packet count in Final ACK.

###### finack_tot_len (heading level 8)

```
uint32_t sl_iperf_stats::finack_tot_len
```

**Description:** Total length of received bytes in Final ACK.

###### last_recv_pkt_cnt (heading level 8)

```
uint32_t sl_iperf_stats::last_recv_pkt_cnt
```

**Description:** Last received packets (for update)

###### nbr_calls (heading level 8)

```
uint32_t sl_iperf_stats::nbr_calls
```

**Description:** Nbr of I/O sys calls.

###### nbr_rcv_snt_packets (heading level 8)

```
uint32_t sl_iperf_stats::nbr_rcv_snt_packets
```

**Description:** Nbr of rx'd or tx'd packets.

###### tot_packets (heading level 8)

```
uint32_t sl_iperf_stats::tot_packets
```

**Description:** Nbr of rx'd or tx'd and lost packets.

###### transitory_error_cnts (heading level 8)

```
uint32_t sl_iperf_stats::transitory_error_cnts
```

**Description:** Nbr of transitory err.

###### ts_curr_recv_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::ts_curr_recv_ms
```

**Description:** Current received packet timestamp.

###### ts_curr_sent_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::ts_curr_sent_ms
```

**Description:** Current sent packet timestamp.

###### ts_end_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::ts_end_ms
```

**Description:** End timestamp (ms).

###### ts_prev_recv_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::ts_prev_recv_ms
```

**Description:** Previous received packet timestamp.

###### ts_prev_sent_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::ts_prev_sent_ms
```

**Description:** Previous sent packet timestamp.

###### ts_start_ms (heading level 8)

```
sl_iperf_ts_ms_t sl_iperf_stats::ts_start_ms
```

**Description:** Start timestamp (ms).

###### udp_async_error (heading level 8)

```
bool sl_iperf_stats::udp_async_error
```

**Description:** First UDP pkt rx'd.

###### udp_dup_pkt (heading level 8)

```
uint32_t sl_iperf_stats::udp_dup_pkt
```

**Description:** Nbr of pkt ID rx'd more than once.

###### udp_jitter (heading level 8)

```
int64_t sl_iperf_stats::udp_jitter
```

**Description:** UDP jitter.

###### udp_lost_pkt (heading level 8)

```
uint32_t sl_iperf_stats::udp_lost_pkt
```

**Description:** Nbr of UDP pkt lost.

###### udp_out_of_order (heading level 8)

```
uint32_t sl_iperf_stats::udp_out_of_order
```

**Description:** Nbr of pkt rx'd out of order.

###### udp_rx_last_pkt (heading level 8)

```
int32_t sl_iperf_stats::udp_rx_last_pkt
```

**Description:** Prev pkt ID rx'd.

iPerf test descriptor 

###### Public Attributes (heading level 7)

###### cb (heading level 8)

```
void(* sl_iperf_test::cb) (struct sl_iperf_test *)
```

**Description:** Callback.

###### conn (heading level 8)

```
sl_iperf_conn_t sl_iperf_test::conn
```

**Description:** Connection.

###### err (heading level 8)

```
sl_iperf_error_t sl_iperf_test::err
```

**Description:** Error.

###### id (heading level 8)

```
sl_iperf_test_id_t sl_iperf_test::id
```

**Description:** Test ID.

###### log (heading level 8)

```
sl_iperf_log_t* sl_iperf_test::log
```

**Description:** Log object ptr.

###### opt (heading level 8)

```
sl_iperf_opt_t sl_iperf_test::opt
```

**Description:** Options.

###### statistic (heading level 8)

```
sl_iperf_stats_t sl_iperf_test::statistic
```

**Description:** Statistics.

###### status (heading level 8)

```
sl_iperf_status_t sl_iperf_test::status
```

**Description:** Status.

iPerf Client UDP header 

###### Public Attributes (heading level 7)

###### base (heading level 8)

```
sl_iperf_clnt_hdr_v1_t sl_iperf_udp_clnt_hdr::base
```

**Description:** Base v1 header.

###### dtg (heading level 8)

```
sl_iperf_udp_datagram_t sl_iperf_udp_clnt_hdr::dtg
```

**Description:** Datagram.

###### extend (heading level 8)

```
sl_iperf_clnt_hdr_ext_t sl_iperf_udp_clnt_hdr::extend
```

**Description:** Extended header.

###### isoch (heading level 8)

```
sl_iperf_clnt_hdr_isoch_payload_t sl_iperf_udp_clnt_hdr::isoch
```

**Description:** Isochronous payload.

###### isoch_settings (heading level 8)

```
sl_iperf_clnt_hdr_ext_isoch_settings_t sl_iperf_udp_clnt_hdr::isoch_settings
```

**Description:** Isochronous settings.

###### start_fq (heading level 8)

```
sl_iperf_clnt_hdr_ext_starttime_fq_t sl_iperf_udp_clnt_hdr::start_fq
```

**Description:** Extended start FQ.

iPerf CLient Header v1 

###### Public Attributes (heading level 7)

###### amount (heading level 8)

```
int32_t sl_iperf_udp_clnt_hdr_v1::amount
```

**Description:** Amount.

###### buf_len (heading level 8)

```
int32_t sl_iperf_udp_clnt_hdr_v1::buf_len
```

**Description:** Buffer Length.

###### flags (heading level 8)

```
int32_t sl_iperf_udp_clnt_hdr_v1::flags
```

**Description:** Flags.

###### num_threads (heading level 8)

```
int32_t sl_iperf_udp_clnt_hdr_v1::num_threads
```

**Description:** Number of threads.

###### port (heading level 8)

```
int32_t sl_iperf_udp_clnt_hdr_v1::port
```

**Description:** Port.

###### win_band (heading level 8)

```
int32_t sl_iperf_udp_clnt_hdr_v1::win_band
```

**Description:** Win band.

iPerf UDP datagram structure type definition 

###### Public Attributes (heading level 7)

###### id (heading level 8)

```
int32_t sl_iperf_udp_datagram::id
```

**Description:** Packet id.

###### id2 (heading level 8)

```
int32_t sl_iperf_udp_datagram::id2
```

**Description:** Packet id.

###### time_var_sec (heading level 8)

```
uint32_t sl_iperf_udp_datagram::time_var_sec
```

**Description:** Time variable for sec.

###### time_var_usec (heading level 8)

```
uint32_t sl_iperf_udp_datagram::time_var_usec
```

**Description:** Time variable for usec.

iPerf server header 

###### Public Attributes (heading level 7)

###### dtg (heading level 8)

```
sl_iperf_udp_datagram_t sl_iperf_udp_srv_hdr::dtg
```

**Description:** Udp datagram.

###### flags (heading level 8)

```
int32_t sl_iperf_udp_srv_hdr::flags
```

**Description:** Server flag.

###### jitter_sec (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::jitter_sec
```

**Description:** Jitter hi.

###### jitter_usec (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::jitter_usec
```

**Description:** Jitter low.

###### lost_pkt_cnt (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::lost_pkt_cnt
```

**Description:** Lost pkt cnt.

###### out_of_order_cnt (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::out_of_order_cnt
```

**Description:** Rx pkt out of order cnt.

###### packet_cnt (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::packet_cnt
```

**Description:** Packet count.

###### stop_sec (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::stop_sec
```

**Description:** Stop time in sec.

###### stop_usec (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::stop_usec
```

**Description:** Stop time in usec.

###### tot_len_l (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::tot_len_l
```

**Description:** Tot bytes rx'd low part.

###### tot_len_u (heading level 8)

```
uint32_t sl_iperf_udp_srv_hdr::tot_len_u
```

**Description:** Tot bytes rx'd hi part.

##### Portable interface

###### Modules

[sl_iperf_socket_addr](sl-iperf-socket-addr)

[sl_iperf_socket_in6addr](sl-iperf-socket-in6addr)

[sl_iperf_time](sl-iperf-time)

###### Enumerations

###### sl_iperf_protocol (heading level 7)

```
enum sl_iperf_protocol {
    SL_IPERF_IPROTOV6_UDP = 0
    SL_IPERF_IPROTOV6_TCP
    SL_IPERF_IPROTOV4_UDP
    SL_IPERF_IPROTOV4_TCP
}
```

**Description:**

iPerf socket IP protocol type definition enum

**Enumerator:**

|   |   |
|---|---|
|SL_IPERF_IPROTOV6_UDP|UDP IPv6 protocol.|
|SL_IPERF_IPROTOV6_TCP|TCP IPv6 protocol.|
|SL_IPERF_IPROTOV4_UDP|UDP IPv4 protocol.|
|SL_IPERF_IPROTOV4_TCP|TCP IPv4 protocol.|

###### Typedefs

###### sl_iperf_protocol_t (heading level 7)

`typedef enum sl_iperf_protocol sl_iperf_protocol_t`

**Description:**

iPerf socket IP protocol type definition enum

###### sl_iperf_socket_addr_t (heading level 7)

`typedef struct sl_iperf_socket_addr sl_iperf_socket_addr_t`

**Description:**

Socket address type definition wrapper.

###### sl_iperf_socket_in6addr_t (heading level 7)

`typedef struct sl_iperf_socket_in6addr sl_iperf_socket_in6addr_t`

**Description:**

Raw ip address byes.

###### sl_iperf_time_t (heading level 7)

`typedef struct sl_iperf_time sl_iperf_time_t`

**Description:**

iPerf time data type definition

###### sl_iperf_ts_ms_t (heading level 7)

`typedef uint64_t sl_iperf_ts_ms_t`

**Description:**

iPerf timestamp millisecond data type definition

###### Variables

###### sl_iperf_socket_inaddr_any (heading level 7)

```
const sl_iperf_socket_in6addr_t sl_iperf_socket_inaddr_any
```

**Description:** Anyaddress constant.

###### Functions

###### sl_iperf_delay_ms (heading level 7)

`void sl_iperf_delay_ms(const uint32_t ms)`

**Description:** iPerf millisec delay

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint32_t|[in]|ms|Millisec value|

Customizable delay function 

###### sl_iperf_get_socket_addr (heading level 7)

`__STATIC_INLINE void sl_iperf_get_socket_addr(const sl_iperf_socket_addr_t *const src_addr, void *const dest_addr)`

**Description:** Get socket address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[in]|src_addr|Source address (iPerf type)|
|void *const|[inout]|dest_addr|Destination address (custom type)|

Create a full copy from iperf source address into the custom destination address. 

###### sl_iperf_get_socket_addr_ip (heading level 7)

`void sl_iperf_get_socket_addr_ip(const sl_iperf_socket_addr_t *const addr, void *const ip)`

**Description:** Get IP address bytes from iPerf address structure.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[in]|addr|iPerf address|
|void *const|[out]|ip|IP address destination buffer|

Getter function of IP address 

###### sl_iperf_get_socket_addr_port (heading level 7)

`uint16_t sl_iperf_get_socket_addr_port(const sl_iperf_socket_addr_t *const addr)`

**Description:** Get port number of iperf address structure.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[in]|addr|iPerf address|

Getter function of port property **Returns**

- uint16_t Port number

###### sl_iperf_get_timestamp_ms (heading level 7)

`sl_iperf_ts_ms_t sl_iperf_get_timestamp_ms(void)`

**Description:** Get millisec timestamp.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Get CPU tick convert to millisec **Returns**

- sl_iperf_ts_ms_t Timestamp in millisec

###### sl_iperf_inet_ntop (heading level 7)

`const char * sl_iperf_inet_ntop(const sl_iperf_socket_addr_t *const src_addr, char *const dst_str, const size_t size)`

**Description:** Convert IPv4 and IPv6 addresses from binary to text form.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[in]|src_addr|Source address in byte form|
|char *const|[out]|dst_str|Destination buffer ptr|
|const size_t|[in]|size|Size of the destination buffer.|

Converts the network address structure src in the af address family into a character string. **Returns**

- It returns a non-null pointer to dst. NULL is returned if there was an error

###### sl_iperf_inet_pton (heading level 7)

`int32_t sl_iperf_inet_pton(const char *src_str, sl_iperf_socket_addr_t *const dst_addr)`

**Description:** Convert addresses from text to binary form.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|src_str|Source string|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[out]|dst_addr|Destination address pointer|

It converts the character string src into a network address structure. **Returns**

- 1 on success, -1 on error (POSIX described the 0 value too)

###### sl_iperf_join_multicast_group (heading level 7)

`int32_t sl_iperf_join_multicast_group(const int32_t sockid, const sl_iperf_socket_addr_t *const multicast_addr)`

**Description:** Join multicast group.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const int32_t|[in]|sockid|Socket ID to join|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[in]|multicast_addr|Multicast group address|

Join socket to multicast group to get packets on group address **Returns**

- int32_t

###### sl_iperf_leave_multicast_group (heading level 7)

`int32_t sl_iperf_leave_multicast_group(const int32_t sockid, const sl_iperf_socket_addr_t *const multicast_addr)`

**Description:** Leave multicast group.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const int32_t|[in]|sockid|Socket ID to join|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[in]|multicast_addr|Multicast group address|

Remove socket from multicast group **Returns**

- int32_t

###### sl_iperf_network_htonl (heading level 7)

`uint32_t sl_iperf_network_htonl(uint32_t val)`

**Description:** iPerf host to network long

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|val|Value|

htonl implementation for iPerf **Returns**

- uint32_t Converted value

###### sl_iperf_network_htons (heading level 7)

`uint16_t sl_iperf_network_htons(uint16_t val)`

**Description:** iPerf host to network short

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|val|Value|

htons implementation for iPerf **Returns**

- uint16_t Converted value

###### sl_iperf_network_is_connected (heading level 7)

`bool sl_iperf_network_is_connected(void)`

**Description:** Check network connection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Checking the connection status. **Returns**

- true Network is connected
- false Network is NOT connected

###### sl_iperf_network_ntohl (heading level 7)

`uint32_t sl_iperf_network_ntohl(uint32_t val)`

**Description:** iPerf network to host long

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|val|Value|

ntohl implementation for iPerf **Returns**

- uint32_t Converted value

###### sl_iperf_network_ntohs (heading level 7)

`uint16_t sl_iperf_network_ntohs(uint16_t val)`

**Description:** iPerf network to host short

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|val|Value|

ntohs implementation for iPerf **Returns**

- uint16_t Converted value

###### sl_iperf_network_wait_for_connection (heading level 7)

`void sl_iperf_network_wait_for_connection(void)`

**Description:** Wait for network connection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Waiting for the network connected status. 

###### sl_iperf_nw_interface_init (heading level 7)

`void sl_iperf_nw_interface_init(void)`

**Description:** Init iPerf Network Interface.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize network interface 

###### sl_iperf_set_socket_addr (heading level 7)

`__STATIC_INLINE void sl_iperf_set_socket_addr(sl_iperf_socket_addr_t *const dest_addr, const void *const src_addr)`

**Description:** Set iPerf socket address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[inout]|dest_addr|Destination address (custom type)|
|const void *const|[in]|src_addr|Source address (iPerf type)|

Cerate a full copy of custom source address to the destination iperf address. 

###### sl_iperf_set_socket_addr_family (heading level 7)

`void sl_iperf_set_socket_addr_family(sl_iperf_socket_addr_t *const addr)`

**Description:** Set iPerf socket address family.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[out]|addr|Socket address structure|

Set address family in socket address structure 

###### sl_iperf_set_socket_addr_ip (heading level 7)

`void sl_iperf_set_socket_addr_ip(sl_iperf_socket_addr_t *const addr, const void *const ip)`

**Description:** Set IP address bytes in iPerf address structure.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[inout]|addr|iPerf address|
|const void *const|[in]|ip|IP address source buffer|

Setter function of IP address 

###### sl_iperf_set_socket_addr_port (heading level 7)

`void sl_iperf_set_socket_addr_port(sl_iperf_socket_addr_t *const addr, const uint16_t port)`

**Description:** Set port in iperf address structure.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *const|[inout]|addr|iPerf address|
|const uint16_t|[out]|port|Port number|

Setter function of port property 

###### sl_iperf_socket_accept (heading level 7)

`int32_t sl_iperf_socket_accept(int32_t sockid, sl_iperf_socket_addr_t *addr)`

**Description:** Accept a connection on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *|[inout]|addr|Is filled in with the address of the peer (remote) socket In Wi-SUN case, it shouldn't be NULL ptr, but for external sockets should be.|

It is used with connection-based socket types (TCP). It extracts the first connection request on the queue of pending connections for the listening socket. **Returns**

- On success, return with the socket id for accepted socket, on error -1 is returned.

###### sl_iperf_socket_bind (heading level 7)

`int32_t sl_iperf_socket_bind(int32_t sockid, const sl_iperf_socket_addr_t *addr)`

**Description:** Bind a name to an iPerf socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *|[in]|addr|address structure ptr|

Assigns the address specified by addr to the socket referred to by the socket id. It is normally necessary to assign a local address using [bind()](sl-wisun-socket-api#bind) before a SOCK_STREAM socket may receive connections **Returns**

- On success, zero is returned. On error, -1 is returned

###### sl_iperf_socket_close (heading level 7)

`int32_t sl_iperf_socket_close(int32_t sockid)`

**Description:** Close socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|

Close socket and remove from the socket handler storage **Returns**

- if any error occurred, return with -1, otherwise return with the socket id

###### sl_iperf_socket_connect (heading level 7)

`int32_t sl_iperf_socket_connect(int32_t sockid, const sl_iperf_socket_addr_t *addr)`

**Description:** Initiate a connection on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *|[in]|addr|If the socket sockid is of type SOCK_DGRAM, then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received. If the socket is of type SOCK_STREAM, this call attempts to make a connection to the socket that is bound to the address specified by addr.|

Connects the socket referred to by the socketid to the address specified by addr. **Returns**

- If the connection or binding succeeds, zero is returned. On error, -1 is returned.

###### sl_iperf_socket_create (heading level 7)

`int32_t sl_iperf_socket_create(sl_iperf_protocol_t protocol)`

**Description:** Create iPerf socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_iperf_protocol_t](sl-iperf-network-interface-api#sl-iperf-protocol-t)|[in]|protocol|Protocol|

Create a socket by selected protocol and return with the socket ID **Returns**

- int32_t Socket ID

###### sl_iperf_socket_getsockopt (heading level 7)

`int32_t sl_iperf_socket_getsockopt(int32_t sockid, int32_t level, int32_t optname, void *optval, size_t *optlen)`

**Description:** Get socket option.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|int32_t|[in]|level|Not used in Wi-SUN domain.|
|int32_t|[in]|optname|Option name.|
|void *|[out]|optval|Destination option value pointer|
|size_t *|[in]|optlen|Must be the size of [sl_wisun_socket_option_data_t](sl-wisun-socket-option-data-t) union|

The function gets socket option by optname, and copy option data to optval ptr **Returns**

- Return 0 on success, other wise -1

###### sl_iperf_socket_listen (heading level 7)

`int32_t sl_iperf_socket_listen(int32_t sockid, int32_t backlog)`

**Description:** Listen for connections on an iPerf socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|int32_t|[in]|backlog|Argument defines the maximum length to which the queue of pending connections for sockid may grow. Not implemented for Wi-SUN, the connection queue size is always 1|

Marks the socket referred to by sockid as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept **Returns**

- On success, zero is returned. On error, -1 is returned

###### sl_iperf_socket_recv (heading level 7)

`int32_t sl_iperf_socket_recv(int32_t sockid, void *buff, size_t len)`

**Description:** Receive a message from a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|void *|[out]|buff|destination buffer ptr|
|size_t|[in]|len|length of data to read|

It should be used for connection-oriented protocol (TCP) **Returns**

- return the number of bytes received, or -1 if an error occurred

###### sl_iperf_socket_recvfrom (heading level 7)

`int32_t sl_iperf_socket_recvfrom(int32_t sockid, void *buf, uint32_t len, sl_iperf_socket_addr_t *src_addr)`

**Description:** Receive messages from a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|void *|[out]|buf|destination buffer ptr|
|uint32_t|[in]|len|length of data to read|
|[sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *|[in]|src_addr|Source address|

It can be used to receive data on a socket whether or not it is connection-oriented. **Returns**

- return the number of bytes received, or -1 if an error occurred

###### sl_iperf_socket_send (heading level 7)

`int32_t sl_iperf_socket_send(int32_t sockid, const void *buff, size_t len)`

**Description:** Send a message on a socket,.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|const void *|[in]|buff|buffer pointer to send|
|size_t|[in]|len|length of buffer to send|

It is preferred with connection-oriented sockets (TCP). **Returns**

- On success, these calls return the number of bytes sent. On error, -1 is returned

###### sl_iperf_socket_sendto (heading level 7)

`int32_t sl_iperf_socket_sendto(int32_t sockid, const void *buff, uint32_t len, const sl_iperf_socket_addr_t *dest_addr)`

**Description:** Send a message on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|const void *|[in]|buff|buffer pointer to send|
|uint32_t|[in]|len|length of buffer to send|
|const [sl_iperf_socket_addr_t](sl-iperf-network-interface-api#sl-iperf-socket-addr-t) *|[in]|dest_addr|destination address ptr, the structure must be prepared for UDP sockets|

It is preferred in datagram mode (UDP). **Returns**

- On success, these calls return the number of bytes sent. On error, -1 is returned

###### sl_iperf_socket_setsockopt (heading level 7)

`int32_t sl_iperf_socket_setsockopt(int32_t sockid, int32_t level, int32_t optname, const void *optval, size_t optlen)`

**Description:** Set socket option.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|int32_t|[in]|level|Not used in Wi-SUN domain.|
|int32_t|[in]|optname|Option name.|
|const void *|[in]|optval|Option value structure pointer. For Wi-SUN it is casted to sl_wisun_socket_option_t|
|size_t|[in]|optlen|Must be the size of [sl_wisun_socket_option_data_t](sl-wisun-socket-option-data-t) union|

This function can set socket properties. There are some limitation in Wi-SUN domain: optlen and level args are not used. optname and optval are casted to the corresponding Wi-SUN types: sl_wisun_socket_option_t and [sl_wisun_socket_option_data_t](sl-wisun-socket-option-data-t). [sl_wisun_socket_option_data_t](sl-wisun-socket-option-data-t) is a union type to include all of implemented Wi-SUN socket options **Returns**

- Return 0 on success, other wise -1

###### Macros

`#define sl_iperf_assert_sock_addr_len (__type)`

**Description**: Assert socket address length macro function.

`#define SL_IPERF_IN6ADDR_SIZE (16U)`

**Description**: Size definition of IPv6 address.

`#define SL_IPERF_NW_API_ERROR (-1)`

**Description**: Define network api ERROR value.

Socket address type definition wrapper. 

###### Public Attributes (heading level 7)

###### addr (heading level 8)

```
uint8_t sl_iperf_socket_addr::addr[SL_IPERF_SOCKET_ADDR_LEN]
```

**Description:** Addres structure bytes.

Raw ip address byes. 

###### Public Attributes (heading level 7)

###### ip (heading level 8)

```
uint8_t sl_iperf_socket_in6addr::ip[SL_IPERF_IN6ADDR_SIZE]
```

**Description:** IP address bytes.

iPerf time data type definition 

###### Public Attributes (heading level 7)

###### sec (heading level 8)

```
uint32_t sl_iperf_time::sec
```

**Description:** Seconds.

###### usec (heading level 8)

```
uint32_t sl_iperf_time::usec
```

**Description:** Microseconds.

#### Over-The-Air Device Firmware Upgrade (Alpha)

The Wi-SUN Over-The-Air Device Firmware Upgrade (OTA DFU) service is implemented to facilitate the updating of Wi-SUN device firmware. This component requires the Gecko Bootloader API to execute firmware writing, verification, and bootload operations.

To obtain a new Gecko Bootloader File (GBL) from a remote host Over-The-Air, a Trivial File Transfer Protocol (TFTP) client is employed, leveraging the Wi-SUN network. The entire firmware upgrade session is manageable over CoAP, with the service offering remote host connection settings, firmware file selection, notification, and status request capabilities. Configuration of the connection to the TFTP remote host can be accomplished within the component configuration file. To use this component, a bootloader must be flashed onto the device. The component relies on functions that reside within the bootloader. To choose the appropriate bootloader, consider factors such as flash location (internal or external) and size. To save on download time, we recommend applying compression on both the bootloader and device projects.

The following diagram shows the component architecture: ![ota-dfu-component](/wisun-stack-api/2.12.0/images/ota-dfu.png)

The example below shows how OTA DFU can be performed in any project.

```c
#include <stdio.h>
#include "cmsis_os2.h"
#include "sl_wisun_ota_dfu.h"

static void start_ota_dfu(void) {
  sl_status_t api_status = SL_STATUS_FAIL;
  uint32_t fw_update_status = 0;

  // Set remote host that stores the firmware image.
  // TFTP protocol is used to download the firmware.
  // 69 is the default TFTP Port
  api_status = sl_wisun_ota_dfu_set_host_addr("2001:db8::1", 69);
  if (api_status != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Set GBL file path
  // The path is relative to the preconfigured TFTP shared directory
  api_status = sl_wisun_ota_dfu_set_gbl_path("my_new_firmware.gbl");
  if (api_status != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Start firmware update
  api_status = sl_wisun_ota_dfu_start_fw_update();
  if (api_status != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Waiting for the firmware download to finish.
  while(1) {
    fw_update_status = sl_wisun_ota_dfu_get_fw_update_status();
    if (fw_update_status & (1 << SL_WISUN_OTA_DFU_STATUS_FW_DOWNLOADED)) {
      printf("Firmware downloaded. Preparing to bootload\n");
      break;
    } else if (fw_update_status & (1 << SL_WISUN_OTA_DFU_STATUS_FW_DOWNLOAD_ERROR)) {
      printf("Firmware download failed\n");
      break;
    }
    osDelay(1);
  }
}

```

The CoAP remote settings can be configured as follows:

```c
coap-client -m get -N -B 3 -t text coap://[$WISUN_NODE_IPV6_ADDR]:5683/ota/dfu -e "help"

Commands:

[P: POST (set), G: GET (get)]
[G] help
[G] (empty payload) status
[P] start
[P] stop
[P] install
[G|P] host_address <ipv6> <port>
[G|P] gbl <path>
[G|P] uri <path>
[G|P] notify_host_address <ipv6> <port>
[G|P] notify_uri <path>
[G|P] notify_chunk_cnt <count>

```

##### Modules

[Type definitions](sl-wisun-ota-dfu-types)

[Configurations](sl-wisun-ota-dfu-config)

##### Functions

###### sl_wisun_ota_dfu_error_hnd

`void sl_wisun_ota_dfu_error_hnd(const sl_wisun_ota_dfu_error_code_t error_code, sl_wisun_ota_dfu_error_ctx_t *const ctx)`

**Description:** OTA DFU error handler (weak implementation)

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_ota_dfu_error_code_t](sl-wisun-ota-dfu-types#sl-wisun-ota-dfu-error-code-t)|[in]|error_code|Error code|
|[sl_wisun_ota_dfu_error_ctx_t](sl-wisun-ota-dfu-types#sl-wisun-ota-dfu-error-ctx-t) *const|[in]|ctx|Error context with error details|

Catch error in different stages of boot load. 

###### sl_wisun_ota_dfu_free_fw_update_status_json_str

`void sl_wisun_ota_dfu_free_fw_update_status_json_str(const char *str)`

**Description:** Free the status string buffer.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|str|String ptr|

Call CoAP free to release allocated memory 

###### sl_wisun_ota_dfu_get_fw_update_statistics

`sl_status_t sl_wisun_ota_dfu_get_fw_update_statistics(sl_wisun_ota_dfu_statistics_t *const stats)`

**Description:** Get firmware update statistics.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_ota_dfu_statistics_t](sl-wisun-ota-dfu-types#sl-wisun-ota-dfu-statistics-t) *const|[out]|stats|Pointer to statistics structure|

Get firmware update statistics **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise failure

###### sl_wisun_ota_dfu_get_fw_update_status

`uint32_t sl_wisun_ota_dfu_get_fw_update_status(void)`

**Description:** Get the status value.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Returning the value of event flags **Returns**

- uint32_t Status

###### sl_wisun_ota_dfu_get_fw_update_status_flag

`bool sl_wisun_ota_dfu_get_fw_update_status_flag(const sl_wisun_ota_dfu_status_t status_flag)`

**Description:** Get the status flag value.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_ota_dfu_status_t](sl-wisun-ota-dfu-types#sl-wisun-ota-dfu-status-t)|[in]|status_flag|Status flag enum|

Bool representation of status variable bit value **Returns**

- bool true if the flag is set, otherwise false

###### sl_wisun_ota_dfu_get_fw_update_status_json_str

`const char * sl_wisun_ota_dfu_get_fw_update_status_json_str(void)`

**Description:** Get the status string in JSON format.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

String buffer is allocated in heap by CoAP allocator **Returns**

- const char * Allocated string pointer on success, otherwise NULL

###### sl_wisun_ota_dfu_get_gbl_path

`sl_status_t sl_wisun_ota_dfu_get_gbl_path(char *const dst_gbl_path, const uint16_t dst_gbl_path_size)`

**Description:** Get GBL file path.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *const|[out]|dst_gbl_path|GBL file path|
|const uint16_t|[in]|dst_gbl_path_size|GBL path size|

Get GBL file path **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_get_host_addr

`sl_status_t sl_wisun_ota_dfu_get_host_addr(char *const dst_host, const uint16_t dst_host_size, uint16_t *dst_port)`

**Description:** Get host addres and port.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *const|[out]|dst_host|Host address|
|const uint16_t|[in]|dst_host_size|Host address size|
|uint16_t *|[out]|dst_port|Host port|

Get host address and port **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_get_host_uri

`sl_status_t sl_wisun_ota_dfu_get_host_uri(char *const dst_uri, const uint16_t dst_uri_size)`

**Description:** Get host uri path.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|char *const|[out]|dst_uri|Uri path|
|const uint16_t|[in]|dst_uri_size|Uri path size|

Get host uri path **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_init

`void sl_wisun_ota_dfu_init(void)`

**Description:** Initialize the device firmware upgrade service.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize Wi-SUN OTA Device Firmware Upgrade service. 

###### sl_wisun_ota_dfu_reboot_and_install

`sl_status_t sl_wisun_ota_dfu_reboot_and_install(void)`

**Description:** Reboot device.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Reboot device with calling corresponding gecko bootloader 'bootloader_rebootAndInstall' API This functions is available if auto-reboot mode is disabled. **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_set_gbl_path

`sl_status_t sl_wisun_ota_dfu_set_gbl_path(const char *gbl_path)`

**Description:** Set GBL file path.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|gbl_path|GBL file path|

Set GBL file path **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_set_host_addr

`sl_status_t sl_wisun_ota_dfu_set_host_addr(const char *host, const uint16_t port)`

**Description:** Set host address and port.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|host|Host address|
|const uint16_t|[in]|port|Host port|

Set host address and port **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_set_host_uri

`sl_status_t sl_wisun_ota_dfu_set_host_uri(const char *uri)`

**Description:** Set host uri path.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|uri|Uri path|

Set host uri path **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_start_fw_update

`sl_status_t sl_wisun_ota_dfu_start_fw_update(void)`

**Description:** Start firmware update.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Start firmware update by setting SL_WISUN_OTA_DFU_STATUS_FW_UPDATE_STARTED flag **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_wisun_ota_dfu_stop_fw_update

`sl_status_t sl_wisun_ota_dfu_stop_fw_update(void)`

**Description:** Stop firmware update.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Stop firmware update by setting SL_WISUN_OTA_DFU_STATUS_FW_UPDATE_STOPPED flag **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

##### Macros

`#define SL_WISUN_OTA_DFU_COAP_URI_PATH_STR_BUF_LEN 128U`

**Description**: OTA DFU CoAP URI Path string buffer length.

`#define SL_WISUN_OTA_DFU_GBL_PATH_STR_BUF_LEN 256U`

**Description**: OTA DFU GBL File name string buffer length.

`#define SL_WISUN_OTA_DFU_IPV6_STR_BUF_LEN 40U`

**Description**: OTA DFU IPV6 string buffer length.

`#define SL_WISUN_OTA_DFU_SERVICE_LOOP ()`

**Description**: OTA DFU Service loop.

##### Configurations

###### Macros

`#define SL_WISUN_OTA_DFU_AUTO_INSTALL_ENABLED 1U`

**Description**: Enable auto reboot and install.

`#define SL_WISUN_OTA_DFU_GBL_FILE "wisun_firmware.gbl"`

**Description**: Firmware image (gbl) file name.

`#define SL_WISUN_OTA_DFU_HOST_ADDR "2001:db8::1"`

**Description**: TFTP service listening address.

`#define SL_WISUN_OTA_DFU_HOST_NOTIFY_ENABLED 1U`

**Description**: Enable host notification.

`#define SL_WISUN_OTA_DFU_NOTIFY_DOWNLOAD_CHUNK_CNT 10U`

**Description**: Count of received chunk to notify in download task.

`#define SL_WISUN_OTA_DFU_NOTIFY_HOST_ADDR "2001:db8::1"`

**Description**: OTA DFU notification server address.

`#define SL_WISUN_OTA_DFU_NOTIFY_PORT 5683U`

**Description**: OTA DFU Host notification listener port.

`#define SL_WISUN_OTA_DFU_NOTIFY_URI_PATH "/ota/dfu_notify"`

**Description**: OTA DFU notification resource URI path.

`#define SL_WISUN_OTA_DFU_STACK_SIZE_WORD 360UL`

**Description**: OTA DFU service stack size in CPU word.

`#define SL_WISUN_OTA_DFU_STORAGE_SLOT_ID 0U`

**Description**: Storage slot ID.

`#define SL_WISUN_OTA_DFU_TFTP_DATA_BLOCK_SIZE 1228U`

**Description**: TFTP data block size.

`#define SL_WISUN_OTA_DFU_TFTP_PORT 69U`

**Description**: TFTP service listener port.

`#define SL_WISUN_OTA_DFU_TFTP_TIMEOUT_SEC 8U`

**Description**: TFTP server retransmission timeout in seconds.

`#define SL_WISUN_OTA_DFU_URI_PATH "/ota/dfu"`

**Description**: OTA DFU resource URI path.

`#define SL_WISUN_OTA_DFU_VERBOSE_MODE_ENABLED 0U`

**Description**: Enable verbose mode.

##### Type definitions

###### Modules

[sl_wisun_ota_dfu_error_ctx](sl-wisun-ota-dfu-error-ctx)

[sl_wisun_ota_dfu_error_ctx_btl_fw_set](sl-wisun-ota-dfu-error-ctx-btl-fw-set)

[sl_wisun_ota_dfu_error_ctx_btl_fw_verify](sl-wisun-ota-dfu-error-ctx-btl-fw-verify)

[sl_wisun_ota_dfu_error_ctx_fw_download](sl-wisun-ota-dfu-error-ctx-fw-download)

[sl_wisun_ota_dfu_settings](sl-wisun-ota-dfu-settings)

[sl_wisun_ota_dfu_statistics](sl-wisun-ota-dfu-statistics)

###### Enumerations

###### sl_wisun_ota_dfu_error_code (heading level 7)

```
enum sl_wisun_ota_dfu_error_code {
    SL_WISUN_OTA_DFU_ERROR_FW_DOWNLOAD = 1001UL
    SL_WISUN_OTA_DFU_ERROR_FW_VERIFY
    SL_WISUN_OTA_DFU_ERROR_FW_SET
}
```

**Description:**

Wi-SUN OTA DFU error code enumeration.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_OTA_DFU_ERROR_FW_DOWNLOAD|Firmware downloaded error code.|
|SL_WISUN_OTA_DFU_ERROR_FW_VERIFY|Firmware verify error code.|
|SL_WISUN_OTA_DFU_ERROR_FW_SET|Firmware set error code.|

###### sl_wisun_ota_dfu_status (heading level 7)

```
enum sl_wisun_ota_dfu_status {
    SL_WISUN_OTA_DFU_STATUS_FW_UPDATE_STARTED = 0
    SL_WISUN_OTA_DFU_STATUS_FW_DOWNLOADED
    SL_WISUN_OTA_DFU_STATUS_FW_VERIFIED
    SL_WISUN_OTA_DFU_STATUS_FW_SET
    SL_WISUN_OTA_DFU_STATUS_FW_UPDATE_STOPPED
    SL_WISUN_OTA_DFU_STATUS_FW_DOWNLOAD_ERROR
    SL_WISUN_OTA_DFU_STATUS_FW_VERIFY_ERROR
    SL_WISUN_OTA_DFU_STATUS_FW_SET_ERROR
}
```

**Description:**

Wi-SUN OTA DFU Status enumeration.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_OTA_DFU_STATUS_FW_UPDATE_STARTED|Firmware update started.|
|SL_WISUN_OTA_DFU_STATUS_FW_DOWNLOADED|Firmware downloaded.|
|SL_WISUN_OTA_DFU_STATUS_FW_VERIFIED|Firmware verified.|
|SL_WISUN_OTA_DFU_STATUS_FW_SET|Firmware set.|
|SL_WISUN_OTA_DFU_STATUS_FW_UPDATE_STOPPED||
|SL_WISUN_OTA_DFU_STATUS_FW_DOWNLOAD_ERROR|Firmware Download error.|
|SL_WISUN_OTA_DFU_STATUS_FW_VERIFY_ERROR|Firmware Verify error.|
|SL_WISUN_OTA_DFU_STATUS_FW_SET_ERROR|Firmware Set error.|

###### Typedefs

###### sl_wisun_ota_dfu_error_code_t (heading level 7)

`typedef enum sl_wisun_ota_dfu_error_code sl_wisun_ota_dfu_error_code_t`

**Description:**

Wi-SUN OTA DFU error code enumeration.

###### sl_wisun_ota_dfu_error_ctx_btl_fw_set_t (heading level 7)

`typedef struct sl_wisun_ota_dfu_error_ctx_btl_fw_set sl_wisun_ota_dfu_error_ctx_btl_fw_set_t`

**Description:**

Wi-SUN OTA DFU set error context definition.

###### sl_wisun_ota_dfu_error_ctx_btl_fw_verify_t (heading level 7)

`typedef struct sl_wisun_ota_dfu_error_ctx_btl_fw_verify sl_wisun_ota_dfu_error_ctx_btl_fw_verify_t`

**Description:**

Wi-SUN OTA DFU verify error context definition.

###### sl_wisun_ota_dfu_error_ctx_fw_download_t (heading level 7)

`typedef struct sl_wisun_ota_dfu_error_ctx_fw_download sl_wisun_ota_dfu_error_ctx_fw_download_t`

**Description:**

Wi-SUN OTA DFU download error context definition.

###### sl_wisun_ota_dfu_error_ctx_t (heading level 7)

`typedef union sl_wisun_ota_dfu_error_ctx sl_wisun_ota_dfu_error_ctx_t`

**Description:**

Wi-SUN OTA DFU error context definition.

###### sl_wisun_ota_dfu_settings_t (heading level 7)

`typedef struct sl_wisun_ota_dfu_settings sl_wisun_ota_dfu_settings_t`

**Description:**

Wi-SUN OTA DFU settings typedef.

###### sl_wisun_ota_dfu_statistics_t (heading level 7)

`typedef struct sl_wisun_ota_dfu_statistics sl_wisun_ota_dfu_statistics_t`

**Description:**

Wi-SUN OTA DFU statistics typedef.

###### sl_wisun_ota_dfu_status_t (heading level 7)

`typedef enum sl_wisun_ota_dfu_status sl_wisun_ota_dfu_status_t`

**Description:**

Wi-SUN OTA DFU Status enumeration.

Wi-SUN OTA DFU error context definition. 

###### Public Attributes (heading level 7)

###### download (heading level 8)

```
sl_wisun_ota_dfu_error_ctx_fw_download_t sl_wisun_ota_dfu_error_ctx::download
```

**Description:** Download error context.

###### set (heading level 8)

```
sl_wisun_ota_dfu_error_ctx_btl_fw_set_t sl_wisun_ota_dfu_error_ctx::set
```

**Description:** Set error context.

###### verify (heading level 8)

```
sl_wisun_ota_dfu_error_ctx_btl_fw_verify_t sl_wisun_ota_dfu_error_ctx::verify
```

**Description:** Verify error context.

Wi-SUN OTA DFU set error context definition. 

###### Public Attributes (heading level 7)

###### ret_val (heading level 8)

```
int32_t sl_wisun_ota_dfu_error_ctx_btl_fw_set::ret_val
```

**Description:** Return value of API call.

Wi-SUN OTA DFU verify error context definition. 

###### Public Attributes (heading level 7)

###### ret_val (heading level 8)

```
int32_t sl_wisun_ota_dfu_error_ctx_btl_fw_verify::ret_val
```

**Description:** Return value of API call.

Wi-SUN OTA DFU download error context definition. 

###### Public Attributes (heading level 7)

###### data_size (heading level 8)

```
uint16_t sl_wisun_ota_dfu_error_ctx_fw_download::data_size
```

**Description:** Data size.

###### offset (heading level 8)

```
uint32_t sl_wisun_ota_dfu_error_ctx_fw_download::offset
```

**Description:** Offset of GBL file.

###### ret_val (heading level 8)

```
int32_t sl_wisun_ota_dfu_error_ctx_fw_download::ret_val
```

**Description:** Return value of API call.

Wi-SUN OTA DFU settings typedef. 

###### Public Attributes (heading level 7)

###### coap_uri_path (heading level 8)

```
char sl_wisun_ota_dfu_settings::coap_uri_path[SL_WISUN_OTA_DFU_COAP_URI_PATH_STR_BUF_LEN]
```

**Description:** CoAP URI path.

###### gbl_path_str (heading level 8)

```
char sl_wisun_ota_dfu_settings::gbl_path_str[SL_WISUN_OTA_DFU_GBL_PATH_STR_BUF_LEN]
```

**Description:** GBL file path.

###### host_addr_str (heading level 8)

```
char sl_wisun_ota_dfu_settings::host_addr_str[SL_WISUN_OTA_DFU_IPV6_STR_BUF_LEN]
```

**Description:** Host address string buffer.

###### host_port (heading level 8)

```
uint16_t sl_wisun_ota_dfu_settings::host_port
```

**Description:** Host port.

Wi-SUN OTA DFU statistics typedef. 

###### Public Attributes (heading level 7)

###### downl_bytes (heading level 8)

```
uint32_t sl_wisun_ota_dfu_statistics::downl_bytes
```

**Description:** Downloaded bytes.

###### elapsed_time_since_rst (heading level 8)

```
sl_sleeptimer_date_t sl_wisun_ota_dfu_statistics::elapsed_time_since_rst
```

**Description:** Elapsed time since reset.

###### fw_downl_time (heading level 8)

```
sl_sleeptimer_date_t sl_wisun_ota_dfu_statistics::fw_downl_time
```

**Description:** Firmware download time.

###### fw_update_time (heading level 8)

```
sl_sleeptimer_date_t sl_wisun_ota_dfu_statistics::fw_update_time
```

**Description:** Firmware update time.

###### global_ip_str (heading level 8)

```
const char* sl_wisun_ota_dfu_statistics::global_ip_str
```

**Description:** Global IP String.

###### received_cnt (heading level 8)

```
uint32_t sl_wisun_ota_dfu_statistics::received_cnt
```

**Description:** Received packet count.

###### resent_cnt (heading level 8)

```
uint32_t sl_wisun_ota_dfu_statistics::resent_cnt
```

**Description:** Resent packet count.

###### start_time (heading level 8)

```
sl_sleeptimer_timestamp_t sl_wisun_ota_dfu_statistics::start_time
```

**Description:** Start time reference in seconds.

#### Trivial File Transfer Protocol (TFTP) Client (Alpha)

The TFTP Client facilitates file exchange between a client and any remote host over UDP. This component provides an easy-to-use solution for downloading and uploading files from a remote host. The TFTP client can be initialized with [sl_tftp_clnt_init()](sl-tftp-clnt-1#sl-tftp-clnt-init), and the functions [sl_tftp_clnt_get()](sl-tftp-clnt-1#sl-tftp-clnt-get) and [sl_tftp_clnt_put()](sl-tftp-clnt-1#sl-tftp-clnt-put) can be used to download and upload files, respectively. Additionally, the block size and timeout options can be configured to negotiate between the server and the client, optimizing the transmission. The component implements the TFTP protocol as specified in [RFC 1350](https://datatracker.ietf.org/doc/html/rfc1350).

To ensure proper functionality, a TFTP server, such as tftpd-hpa, must be prepared on the remote host.

The following code example shows how to download a file with TFTP Client:

```c
#include "sl_tftp_clnt.h"

// TFTP data callback
// In this callback you can implement storing data chunks to flash, heap or any other memory.
static void tftp_data_hnd(sl_tftp_clnt_t * const clnt,
                          const uint8_t * const data_ptr,
                          const uint16_t data_size) {
  (void)data_ptr;
  (void)data_size;
  printf("Data received chunk %u (%u bytes)\n",
         clnt->packet.content.data.block_num,
         clnt->packet.content.data.data_size);
}

// TFTP error callback
// You can implement error handling in this callback.
static void tftp_error_hnd(sl_tftp_clnt_t * const clnt,
                           const uint16_t error_code,
                           const char *error_msg) {
  (void)clnt;
  printf("Error (%u): %s\n", error_code, error_msg);
}

static void tftp_get_file(void) {
  static sl_tftp_clnt_t tftp_clnt = { 0 };

  // Initialize Client instance
  if (sl_tftp_clnt_init(&tftp_clnt,
                        "2001:db8::1",
                        SL_TFTP_DEFAULT_HOST_PORT,
                        tftp_data_hnd,
                        tftp_error_hnd) != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Set blocksize option
  if (sl_tftp_clnt_set_option(&tftp_clnt,
                              SL_TFTP_OPT_EXT_BLOCKSIZE,
                              1228) != SL_STATUS_OK) {
    // Error handling
    return;
  }

  // Start to download a file
  if (sl_tftp_clnt_get(&tftp_clnt,
                       "test.txt") != SL_STATUS_OK) {
    // Error handling
    return;
  }

  while (1) {
    if (sl_tftp_clnt_is_op_finished(&tftp_clnt)) {
      printf("File download finished\n");
      break;
    }
    osDelay(1);
  }
}

```

##### Modules

[Configurations](sl-ftp-config)

[Type definitions](sl-tftp-clnt-defs)

[Portable interface](sl-ftp-portable-interface)

##### Typedefs

###### sl_tftp_clnt_data_hnd_t

`typedef void(* sl_tftp_clnt_data_hnd_t) (sl_tftp_clnt_t *const clnt, const uint8_t *const data_ptr, const uint16_t data_size)`

**Description:**

Data handler callback definition.

###### sl_tftp_clnt_error_hnd_t

`typedef void(* sl_tftp_clnt_error_hnd_t) (sl_tftp_clnt_t *const clnt, const uint16_t error_code, const char *error_msg)`

**Description:**

Error handler callback defintion.

##### Functions

###### sl_tftp_clnt_default_init

`__STATIC_INLINE sl_status_t sl_tftp_clnt_default_init(sl_tftp_clnt_t *const clnt)`

**Description:** Init TFTP Client default.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client to initialize|

Initialize Client with default values from config file parameters: host: SL_TFTP_CLNT_DEFAULT_HOST port: SL_TFTP_DEFAULT_HOST_PORT data_hnd: simple hex dump callback error_hnd: error code and message printer **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

**References:** [SL_TFTP_CLNT_DEFAULT_HOST](sl-ftp-config#sl-tftp-clnt-default-host), [sl_tftp_clnt_init](sl-tftp-clnt-1#sl-tftp-clnt-init) and [SL_TFTP_DEFAULT_HOST_PORT](sl-tftp-clnt-1#sl-tftp-default-host-port)

###### sl_tftp_clnt_get

`__STATIC_INLINE sl_status_t sl_tftp_clnt_get(sl_tftp_clnt_t *const clnt, const char *file)`

**Description:** TFT Client Get.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client|
|const char *|[in]|file|File name|

Get file from server in octet mode **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

**References:** [sl_tftp_clnt_request](sl-tftp-clnt-1#sl-tftp-clnt-request), [SL_TFTP_MODE_OCTET_STR](sl-tftp-clnt-1#sl-tftp-mode-octet-str) and [SL_TFTP_OPCODE_RRQ](sl-tftp-clnt-1#sl-tftp-opcode-rrq)

###### sl_tftp_clnt_init

`sl_status_t sl_tftp_clnt_init(sl_tftp_clnt_t *const clnt, const char *host, const uint16_t port, sl_tftp_clnt_data_hnd_t data_hnd, sl_tftp_clnt_error_hnd_t error_hnd)`

**Description:** Init TFTP Client.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client to initialize|
|const char *|[in]|host|Host address string|
|const uint16_t|[in]|port|Port number|
|[sl_tftp_clnt_data_hnd_t](sl-tftp-clnt-1#sl-tftp-clnt-data-hnd-t)|[in]|data_hnd|Data handler callback|
|[sl_tftp_clnt_error_hnd_t](sl-tftp-clnt-1#sl-tftp-clnt-error-hnd-t)|[in]|error_hnd|Error handler callback|

Initialize TFTP Client context **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

**Referenced by:** [sl_tftp_clnt_default_init](sl-tftp-clnt-1#sl-tftp-clnt-default-init)

###### sl_tftp_clnt_is_op_finished

`bool sl_tftp_clnt_is_op_finished(const sl_tftp_clnt_t *const clnt)`

**Description:** TFTP Client is finished operation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[in]|clnt|Client|

Check read or write operations whether is in progress **Returns**

- true Is finished
- false Is in progress

###### sl_tftp_clnt_is_op_get

`bool sl_tftp_clnt_is_op_get(const sl_tftp_clnt_t *const clnt)`

**Description:** TFTP Client is Get operation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[in]|clnt|Client|

Check Read operation is in progress **Returns**

- true Is in progress otherwise false

###### sl_tftp_clnt_is_op_put

`bool sl_tftp_clnt_is_op_put(const sl_tftp_clnt_t *const clnt)`

**Description:** TFTP Client is Put operation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[in]|clnt|Client|

Check Write operation is in progress **Returns**

- true Is in progress otherwise false

###### sl_tftp_clnt_is_op_rrq_wrq_failed

`bool sl_tftp_clnt_is_op_rrq_wrq_failed(const sl_tftp_clnt_t *const clnt)`

**Description:** TFTP Client is RRQ or WRQ failed.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[in]|clnt|Client|

Check Read or Write Request operation is failed **Returns**

- true Is failed otherwise false

###### sl_tftp_clnt_print_pkt

`void sl_tftp_clnt_print_pkt(const sl_tftp_pkt_t *const pkt)`

**Description:** Print packet.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_tftp_pkt_t](sl-tftp-clnt-defs#sl-tftp-pkt-t) *const|[in]|pkt|Packet to print|

Print packet info in json format 

###### sl_tftp_clnt_put

`__STATIC_INLINE sl_status_t sl_tftp_clnt_put(sl_tftp_clnt_t *const clnt, const char *file)`

**Description:** TFT Client Put.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client|
|const char *|[in]|file|File name to store data|

Send buffer content to file on remote server **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

**References:** [sl_tftp_clnt_request](sl-tftp-clnt-1#sl-tftp-clnt-request), [SL_TFTP_MODE_OCTET_STR](sl-tftp-clnt-1#sl-tftp-mode-octet-str) and [SL_TFTP_OPCODE_WRQ](sl-tftp-clnt-1#sl-tftp-opcode-wrq)

###### sl_tftp_clnt_request

`sl_status_t sl_tftp_clnt_request(sl_tftp_clnt_t *const clnt, const uint16_t opcode, const char *file, const char *mode)`

**Description:** TFTP Client request.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client|
|const uint16_t|[in]|opcode|Operation code: SL_TFTP_OPCODE_RRQ or SL_TFTP_OPCODE_WRQ|
|const char *|[in]|file|File name to put or get|
|const char *|[in]|mode|Mode string|

Send request for Server (RRQ or WRQ) **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

**Referenced by:** [sl_tftp_clnt_get](sl-tftp-clnt-1#sl-tftp-clnt-get) and [sl_tftp_clnt_put](sl-tftp-clnt-1#sl-tftp-clnt-put)

###### sl_tftp_clnt_service_init

`void sl_tftp_clnt_service_init(void)`

**Description:** Init TFTP Client service.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize TFTP client OS objects 

###### sl_tftp_clnt_set_option

`sl_status_t sl_tftp_clnt_set_option(sl_tftp_clnt_t *const clnt, const char *opt, const uint32_t value)`

**Description:** Set TFTP Client option.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client|
|const char *|[in]|opt|Option string|
|const uint32_t|[in]|value|Option value|

Set TFTP Client option in the TFTP client instance. The supported options are:

- SL_TFTP_OPT_EXT_BLOCKSIZE: Blocksize option (8 - 1228 for Wi-SUN)
- SL_TFTP_OPT_EXT_TIMEOUT_INTERVAL: Timeout interval option (1 - 255) **Returns**  
  - sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_tftp_clnt_terminate_session

`sl_status_t sl_tftp_clnt_terminate_session(sl_tftp_clnt_t *const clnt)`

**Description:** TFTP Client terminate session.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[inout]|clnt|Client|

Terminate TFTP session **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

###### sl_tftp_clnt_wait_op_finished

`sl_status_t sl_tftp_clnt_wait_op_finished(const sl_tftp_clnt_t *const clnt)`

**Description:** TFTP Client wait operation finished.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_tftp_clnt_t](sl-tftp-clnt-defs#sl-tftp-clnt-t) *const|[in]|clnt|Client|

Wait for operation to finish **Returns**

- sl_status_t SL_STATUS_OK on success, otherwise SL_STATUS_FAIL

##### Macros

`#define SL_TFTP_DEFAULT_DATA_BLOCK_SIZE 512U`

**Description**: TFTP Default data block size.

`#define SL_TFTP_DEFAULT_HOST_PORT 69U`

**Description**: Default TFTP host port.

`#define SL_TFTP_DEFAULT_SRV_RET_TIMEOUT_SEC 1U`

**Description**: TFTP Default server retransmit timeout interval in seconds.

`#define SL_TFTP_ERRORCODE_ACCVIOL 2U`

**Description**: Access violation.

`#define SL_TFTP_ERRORCODE_DISKFULL 3U`

**Description**: Disk full or allocation exceeded.

`#define SL_TFTP_ERRORCODE_FEXIST 6U`

**Description**: File already exists.

`#define SL_TFTP_ERRORCODE_FNOTFOUND 1U`

**Description**: File not found.

`#define SL_TFTP_ERRORCODE_ILLEGALOP 4U`

**Description**: Illegal TFTP operation.

`#define SL_TFTP_ERRORCODE_NOTDEF 0U`

**Description**: Not defined, see error message (if any).

`#define SL_TFTP_ERRORCODE_NOUSR 7U`

**Description**: No such user.

`#define SL_TFTP_ERRORCODE_OPTNEGOTFAIL 8U`

**Description**: Terminate transfer due to option negotiation.

`#define SL_TFTP_ERRORCODE_UNKNTID 5U`

**Description**: Unknown transfer ID.

`#define SL_TFTP_MODE_NETASCII_STR "netascii"`

**Description**: Netascii mode string.

`#define SL_TFTP_MODE_NETASCII_STR_LEN 8U`

**Description**: Netascii mode string length.

`#define SL_TFTP_MODE_OCTET_STR "octet"`

**Description**: Octet mode string.

`#define SL_TFTP_MODE_OCTET_STR_LEN 5U`

**Description**: Octet mode string length.

`#define SL_TFTP_OPCODE_ACK 4U`

**Description**: TFTP Acknowledgement operation code.

`#define SL_TFTP_OPCODE_DATA 3U`

**Description**: TFTP Data operation code.

`#define SL_TFTP_OPCODE_ERROR 5U`

**Description**: TFTP Error operation code.

`#define SL_TFTP_OPCODE_OACK 6U`

**Description**: TFTP Option Acknowledgement operation code.

`#define SL_TFTP_OPCODE_RRQ 1U`

**Description**: TFTP Read Request operation code.

`#define SL_TFTP_OPCODE_WRQ 2U`

**Description**: TFTP Write Request operation code.

`#define SL_TFTP_OPT_EXT_BLOCKSIZE "blksize"`

**Description**: TFTP Blocksize Option.

`#define SL_TFTP_OPT_EXT_BLOCKSIZE_LEN 7U`

**Description**: TFTP Blocksize Option length.

`#define SL_TFTP_OPT_EXT_MULTICAST "multicast"`

**Description**: TFTP Multicast Option.

`#define SL_TFTP_OPT_EXT_MULTICAST_LEN 9U`

**Description**: TFTP Multicast Option length.

`#define SL_TFTP_OPT_EXT_TIMEOUT_INTERVAL "timeout"`

**Description**: TFTP Timeout Interval Option.

`#define SL_TFTP_OPT_EXT_TIMEOUT_INTERVAL_LEN 7U`

**Description**: TFTP Timeout Interval Option length.

`#define SL_TFTP_OPT_EXT_TRANSFER_SIZE "tsize"`

**Description**: TFTP Transfer Size Option.

`#define SL_TFTP_OPT_EXT_TRANSFER_SIZE_LEN 5U`

**Description**: TFTP Transfer Size Option length.

`#define SL_TFTP_OPT_EXT_WINDOWSIZE "windowsize"`

**Description**: TFTP Windowsize Option.

`#define SL_TFTP_OPT_EXT_WINDOWSIZE_LEN 10U`

**Description**: TFTP Windowsize Option length.

`#define SL_TFTP_SERVICE_LOOP while (1)`

**Description**: TFTP Service loop definition.

`#define SL_TFTP_STR_MAX_LEN 256UL`

**Description**: TFTP string max length (filename, mode)

##### Configurations

###### Macros

`#define SL_FTP_ENABLE_FTP_PROTOCOL 0U`

**Description**: Enable FTP TCP based protocol.

`#define SL_FTP_ENABLE_TFTP_PROTOCOL 1U`

**Description**: Enable TFTP UDP based protocol.

`#define SL_TFTP_CLNT_DEFAULT_HOST "aabb:ccdd::eeff:0011:2233:4455"`

**Description**: TFTP Default remote host address string.

`#define SL_TFTP_CLNT_RECV_TIMEOUT_MS 300000UL`

**Description**: TFTP default receive timeout (ms)

`#define SL_TFTP_CLNT_STACK_SIZE_WORD 256UL`

**Description**: TFTP Client service stack size in word.

`#define SL_TFTP_DEBUG 0U`

**Description**: Enable TFTP debug prints.

##### Portable interface

###### Functions

###### sl_ftp_delay_ms (heading level 7)

`void sl_ftp_delay_ms(const uint32_t delay_ms)`

**Description:** Delay ms.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint32_t|N/A|delay_ms|Milliseconds|

Portable function 

**Referenced by:** [sl_tftp_delay_ms](sl-ftp-portable-interface#sl-tftp-delay-ms)

###### sl_ftp_dump_buff (heading level 7)

`void sl_ftp_dump_buff(const uint8_t *const data_ptr, const uint16_t data_size)`

**Description:** Dump buffer.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *const|[in]|data_ptr|Data ptr|
|const uint16_t|[in]|data_size|Data size|

Util function to dump buffer in hex format 

**Referenced by:** [sl_tftp_dump_buff](sl-ftp-portable-interface#sl-tftp-dump-buff)

###### sl_ftp_get_global_addr (heading level 7)

`const char * sl_ftp_get_global_addr(void)`

**Description:** FTP get global IP address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Portable function **Returns**

- Global address string representation

**Referenced by:** [sl_tftp_get_global_addr](sl-ftp-portable-interface#sl-tftp-get-global-addr)

###### sl_ftp_init (heading level 7)

`void sl_ftp_init(void)`

**Description:** FTP Init.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Initialize FTP service 

###### sl_ftp_is_network_connected (heading level 7)

`bool sl_ftp_is_network_connected(void)`

**Description:** FTP network is connected.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Portable function **Returns**

- true if network is connected, otherwise false

**Referenced by:** [sl_tftp_is_network_connected](sl-ftp-portable-interface#sl-tftp-is-network-connected)

###### sl_ftp_socket_close (heading level 7)

`int32_t sl_ftp_socket_close(int32_t sockid)`

**Description:** FTP Close.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|N/A|sockid|Socket ID|

Portable function **Returns**

- int32_t Closed socket ID on success, -1 on error

**Referenced by:** [sl_tftp_socket_close](sl-ftp-portable-interface#sl-tftp-socket-close)

###### sl_ftp_wait_for_connection (heading level 7)

`void sl_ftp_wait_for_connection(void)`

**Description:** FTP wait for network connection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Portable function 

**Referenced by:** [sl_tftp_wait_for_connection](sl-ftp-portable-interface#sl-tftp-wait-for-connection)

###### sl_tftp_delay_ms (heading level 7)

`__STATIC_INLINE void sl_tftp_delay_ms(const uint32_t delay_ms)`

**Description:** TFTP Delay ms.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint32_t|N/A|delay_ms|Milliseconds|

Alias function 

**References:** [sl_ftp_delay_ms](sl-ftp-portable-interface#sl-ftp-delay-ms)

###### sl_tftp_dump_buff (heading level 7)

`__STATIC_INLINE void sl_tftp_dump_buff(const uint8_t *const data_ptr, const uint16_t data_size)`

**Description:** Define SL_TFTP_DEBUG.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *const|[in]|data_ptr|Data ptr|
|const uint16_t|[in]|data_size|Data size|

TFTP Dump buffer

Alias function

**References:** [sl_ftp_dump_buff](sl-ftp-portable-interface#sl-ftp-dump-buff)

###### sl_tftp_get_global_addr (heading level 7)

`__STATIC_INLINE const char * sl_tftp_get_global_addr(void)`

**Description:** TFTP get global IP address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Portable function **Returns**

- Global address string representation

**References:** [sl_ftp_get_global_addr](sl-ftp-portable-interface#sl-ftp-get-global-addr)

###### sl_tftp_is_network_connected (heading level 7)

`__STATIC_INLINE bool sl_tftp_is_network_connected(void)`

**Description:** TFTP network is connected.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Alias function **Returns**

- true if network is connected, otherwise false

**References:** [sl_ftp_is_network_connected](sl-ftp-portable-interface#sl-ftp-is-network-connected)

###### sl_tftp_socket_close (heading level 7)

`__STATIC_INLINE int32_t sl_tftp_socket_close(int32_t sockid)`

**Description:** TFTP Close.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|N/A|sockid|Socket ID|

Alias function **Returns**

- int32_t Closed socket ID on success, -1 on error

**References:** [sl_ftp_socket_close](sl-ftp-portable-interface#sl-ftp-socket-close)

###### sl_tftp_udp_free_addr (heading level 7)

`void sl_tftp_udp_free_addr(void *addr)`

**Description:** Free address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void *|[in]|addr|Address structure|

Release the allocated address structure 

###### sl_tftp_udp_get_addr (heading level 7)

`void * sl_tftp_udp_get_addr(const char *host, uint16_t port)`

**Description:** Get UDP address structure.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|host|Host string|
|uint16_t|[in]|port|Port|

Allocate address structure and set host address and port **Returns**

- void * Address structure

###### sl_tftp_udp_recvfrom (heading level 7)

`int32_t sl_tftp_udp_recvfrom(int32_t sockid, void *buff, uint32_t len, void *src_addr)`

**Description:** TFTP Receive messages on a UDP socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket id|
|void *|[out]|buff|destination buffer ptr|
|uint32_t|[in]|len|length of data to read|
|void *|[out]|src_addr|Source address|

Receives data on a socket whether or not it is connection-oriented. **Returns**

- return the number of bytes received, or -1 if an error occurred

###### sl_tftp_udp_sendto (heading level 7)

`int32_t sl_tftp_udp_sendto(int32_t sockid, const void *buff, uint32_t len, const void *dest_addr)`

**Description:** TFTP Send a message on a UDP socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int32_t|[in]|sockid|socket ID|
|const void *|[in]|buff|buffer pointer to send|
|uint32_t|[in]|len|length of data to send|
|const void *|[in]|dest_addr|destination address ptr, the structure must be prepared for UDP sockets|

Preferred in datagram mode (UDP). **Returns**

- On success, these calls return the number of bytes sent. On error, -1 is returned

###### sl_tftp_udp_socket_create (heading level 7)

`int32_t sl_tftp_udp_socket_create(void)`

**Description:** TFTP udp socket create.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Portable function **Returns**

- int32_t Socket ID

###### sl_tftp_wait_for_connection (heading level 7)

`__STATIC_INLINE void sl_tftp_wait_for_connection(void)`

**Description:** TFTP wait for network connection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Alias function 

**References:** [sl_ftp_wait_for_connection](sl-ftp-portable-interface#sl-ftp-wait-for-connection)

###### Macros

`#define sl_ftp_debug (format, ...)`

**Description**: FTP debug macro function.

`#define SL_FTP_ERROR SL_FTP_INVALID_SOCKID`

**Description**: FTP error value.

`#define SL_FTP_INVALID_SOCKID (-1)`

**Description**: FTP invalid socket ID.

`#define SL_FTP_LOCAL_HOST_STR "::"`

**Description**: FTP Localhost string.

`#define SL_TFTP_ERROR SL_FTP_ERROR`

**Description**: TFTP error value (alias)

`#define SL_TFTP_INVALID_SOCKID SL_FTP_INVALID_SOCKID`

**Description**: TFTP invalid socket ID (alias)

`#define SL_TFTP_LOCAL_HOST_STR SL_FTP_LOCAL_HOST_STR`

**Description**: TFTP Localhost string (alias)

##### Type definitions

###### Modules

[sl_tftp_ack_pkt](sl-tftp-ack-pkt)

[sl_tftp_clnt](sl-tftp-clnt)

[sl_tftp_clnt_opt](sl-tftp-clnt-opt)

[sl_tftp_data_pkt](sl-tftp-data-pkt)

[sl_tftp_error_pkt](sl-tftp-error-pkt)

[sl_tftp_oack_pkt](sl-tftp-oack-pkt)

[sl_tftp_pkt](sl-tftp-pkt)

[sl_tftp_pkt_content](sl-tftp-pkt-content)

[sl_tftp_req_pkt](sl-tftp-req-pkt)

###### Typedefs

###### sl_tftp_ack_pkt_t (heading level 7)

`typedef struct sl_tftp_ack_pkt sl_tftp_ack_pkt_t`

**Description:**

TFTP ACK packet.

###### sl_tftp_clnt_opt_t (heading level 7)

`typedef struct sl_tftp_clnt_opt sl_tftp_clnt_opt_t`

**Description:**

TFTP Client options The definition doesn't include the unsupported options.

###### sl_tftp_clnt_t (heading level 7)

`typedef struct sl_tftp_clnt sl_tftp_clnt_t`

**Description:**

TFTP Client.

###### sl_tftp_data_pkt_t (heading level 7)

`typedef struct sl_tftp_data_pkt sl_tftp_data_pkt_t`

**Description:**

TFTP data packet.

###### sl_tftp_error_pkt_t (heading level 7)

`typedef struct sl_tftp_error_pkt sl_tftp_error_pkt_t`

**Description:**

TFTP error packet.

###### sl_tftp_oack_pkt_t (heading level 7)

`typedef struct sl_tftp_oack_pkt sl_tftp_oack_pkt_t`

**Description:**

TFTP OACK packet.

###### sl_tftp_pkt_content_t (heading level 7)

`typedef union sl_tftp_pkt_content sl_tftp_pkt_content_t`

**Description:**

TFTP Packet content union.

###### sl_tftp_pkt_t (heading level 7)

`typedef struct sl_tftp_pkt sl_tftp_pkt_t`

**Description:**

TFTP packet handler.

###### sl_tftp_req_pkt_t (heading level 7)

`typedef struct sl_tftp_req_pkt sl_tftp_req_pkt_t`

**Description:**

TFTP request packet.

TFTP ACK packet. 

###### Public Attributes (heading level 7)

###### block_num (heading level 8)

```
uint16_t sl_tftp_ack_pkt::block_num
```

**Description:** Block number.

TFTP Client. 

###### Public Attributes (heading level 7)

###### data_hnd (heading level 8)

```
void(* sl_tftp_clnt::data_hnd) (struct sl_tftp_clnt *const clnt, const uint8_t *const data_ptr, const uint16_t data_size)
```

**Description:** Data handler callback.

###### error_hnd (heading level 8)

```
void(* sl_tftp_clnt::error_hnd) (struct sl_tftp_clnt *const clnt, const uint16_t error_code, const char *error_msg)
```

**Description:** Error handler callback.

###### evt_flags (heading level 8)

```
osEventFlagsId_t sl_tftp_clnt::evt_flags
```

**Description:** Event flags.

###### ext_data (heading level 8)

```
const uint8_t* sl_tftp_clnt::ext_data
```

**Description:** External data pointer to WRQ.

###### ext_data_size (heading level 8)

```
uint32_t sl_tftp_clnt::ext_data_size
```

**Description:** External data size.

###### host (heading level 8)

```
const char* sl_tftp_clnt::host
```

**Description:** Host address string.

###### options (heading level 8)

```
sl_tftp_clnt_opt_t sl_tftp_clnt::options
```

**Description:** Options.

###### packet (heading level 8)

```
sl_tftp_pkt_t sl_tftp_clnt::packet
```

**Description:** Packet.

###### port (heading level 8)

```
uint16_t sl_tftp_clnt::port
```

**Description:** Port.

TFTP Client options The definition doesn't include the unsupported options. 

###### Public Attributes (heading level 7)

###### blksize (heading level 8)

```
uint32_t sl_tftp_clnt_opt::blksize
```

**Description:** Blocksize option.

###### timeout_sec (heading level 8)

```
uint32_t sl_tftp_clnt_opt::timeout_sec
```

**Description:** Timeout interval option.

TFTP data packet. 

###### Public Attributes (heading level 7)

###### block_num (heading level 8)

```
uint16_t sl_tftp_data_pkt::block_num
```

**Description:** Block number.

###### data (heading level 8)

```
uint8_t* sl_tftp_data_pkt::data
```

**Description:** Data ptr.

###### data_size (heading level 8)

```
uint16_t sl_tftp_data_pkt::data_size
```

**Description:** Data size.

TFTP error packet. 

###### Public Attributes (heading level 7)

###### errcode (heading level 8)

```
uint16_t sl_tftp_error_pkt::errcode
```

**Description:** Error code.

###### errmsg (heading level 8)

```
const char* sl_tftp_error_pkt::errmsg
```

**Description:** Error message.

TFTP OACK packet. 

###### Public Attributes (heading level 7)

###### opt_list (heading level 8)

```
const char* sl_tftp_oack_pkt::opt_list
```

**Description:** Option list start ptr.

###### size (heading level 8)

```
uint16_t sl_tftp_oack_pkt::size
```

**Description:** Total size of option list.

TFTP packet handler. 

###### Public Attributes (heading level 7)

###### content (heading level 8)

```
sl_tftp_pkt_content_t sl_tftp_pkt::content
```

**Description:** Content.

###### opcode (heading level 8)

```
uint16_t sl_tftp_pkt::opcode
```

**Description:** Operation code.

TFTP Packet content union. 

###### Public Attributes (heading level 7)

###### ack (heading level 8)

```
sl_tftp_ack_pkt_t sl_tftp_pkt_content::ack
```

**Description:** ACK.

###### data (heading level 8)

```
sl_tftp_data_pkt_t sl_tftp_pkt_content::data
```

**Description:** Data.

###### error (heading level 8)

```
sl_tftp_error_pkt_t sl_tftp_pkt_content::error
```

**Description:** Error.

###### oack (heading level 8)

```
sl_tftp_oack_pkt_t sl_tftp_pkt_content::oack
```

**Description:** OACK.

###### request (heading level 8)

```
sl_tftp_req_pkt_t sl_tftp_pkt_content::request
```

**Description:** Request.

TFTP request packet. 

###### Public Attributes (heading level 7)

###### filename (heading level 8)

```
const char* sl_tftp_req_pkt::filename
```

**Description:** File name.

###### mode (heading level 8)

```
const char* sl_tftp_req_pkt::mode
```

**Description:** Mode.

#### Application Memory Statistic (Alpha)

The service systematically collects heap and stack usage data from active threads across various configurations involving FreeRTOS, MicriumOS, and different toolchains such as GCC and IAR. This critical information is then relayed to the Real-Time Transfer (RTT) console. To ensure accurate reporting, proper RTT setup is essential. The component includes a warning mechanism that provides hints about missing or incorrect configurations.

Within the component configuration, you can set the service thread parameters, the update period time, the maximum count of trackable threads, and enable heap usage statistics. A common scenario involves increasing the measurable thread stack size and the application heap size before beginning testing.

Based on the measurement results, adjustments can be made to the appropriate thread's stack and the application heap size. Stack size is calculated using the highest watermarks, and the last result always displays the maximum values.

The following RTT log demonstrates the component's operation:

```c
[APP_OS_STAT][AppMain] Used/Tot: 584/1024 (58%)
[APP_OS_STAT][Ping] Used/Tot: 232/1024 (23%)
[APP_OS_STAT][WisunLedTask] Used/Tot: 192/320 (64%)
[APP_OS_STAT][AppOsStatThread] Used/Tot: 728/1024 (72%)
[APP_OS_STAT][Wi-SUN Event Task] Used/Tot: 500/2000 (25%)
[APP_OS_STAT][Wi-SUN Task] Used/Tot: 1164/2000 (58%)
[APP_OS_STAT][CoAP-Notification-Service] Used/Tot: 208/1024 (20%)
[APP_OS_STAT][CoAP-RHND-Service] Used/Tot: 240/1024 (24%)
[APP_OS_STAT][CLI instance vcom] Used/Tot: 340/1600 (21%)
[APP_OS_STAT][Kernel's Stat Task] Used/Tot: 188/1024 (18%)
[APP_OS_STAT][heap]  addr 0x2000BF80   Used/Tot: 65560/475264 (13%)

```

##### Modules

[Configurations](app-os-stat-config)

##### undefined

###### app_os_stat_init

`void app_os_stat_init(void)`

**Description:** Initialize App OS statistic service.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Init thread and statistic storage 

###### app_os_stat_register_thread

`sl_status_t app_os_stat_register_thread(const osThreadId_t thr_id)`

**Description:** Register thread to track.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const osThreadId_t|[in]|thr_id|Thread ID|

Thread stack usage is tracked **Returns**

- sl_status_t SL_STATUS_OK on success, SL_STATUS_FAIL on error

###### app_os_stat_remove_thread

`sl_status_t app_os_stat_remove_thread(const osThreadId_t thr_id)`

**Description:** Remove thread from list.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const osThreadId_t|[in]|thr_id|Thread ID|

Remove thread from tracked thread list **Returns**

- sl_status_t SL_STATUS_OK on success, SL_STATUS_FAIL on error

##### Configurations

###### Macros

`#define APP_OS_STAT_ASYNC_MODE_ENABLED 0U`

**Description**: Enable async mode.

`#define APP_OS_STAT_HEAP_ENABLED 1U`

**Description**: Enable heap usage statistic.

`#define APP_OS_STAT_MANUAL_REGISTER_THREADS 0U`

**Description**: Enable manual thread registering.

`#define APP_OS_STAT_MAX_THREAD_CNT 20U`

**Description**: Maximum registerable thread count.

`#define APP_OS_STAT_RTT_LOG_CHANNEL 0U`

**Description**: RTT Log channel for app os statistics.

`#define APP_OS_STAT_STACK_SIZE_WORD 256U`

**Description**: App OS statistic thread stack size in word.

`#define APP_OS_STAT_THREAD_PRIO osPriorityHigh`

**Description**: App OS statistic thread priority.

`#define APP_OS_STAT_THREAD_STACK_ENABLED 1U`

**Description**: Enable thread stack usage statistic.

`#define APP_OS_STAT_UPDATE_PERIOD_TIME_MS 1000U`

**Description**: App OS statistic update period time.

`#define APP_OS_STAT_VERBOSE_MODE_ENABLED 0U`

**Description**: Enable verbose mode.

#### Application Status over CoAP (Alpha)

The component implements status notifications and resources over CoAP. The component can be used in any application to gather runtime information about devices. The component should be initialized with the [sl_wisun_app_status_init()](sl-wisun-app-status#sl-wisun-app-status-init) function. Conditional sending can be customized by implementing the [sl_wisun_app_status_condition_cb()](sl-wisun-app-status#sl-wisun-app-status-condition-cb) function. Server and notification parameters can be configured in the [sl_wisun_app_status_config.h](sl-wisun-app-status-config-8h-source#sl-wisun-app-status-config-8h-source) file or at runtime using the appropriate setters/getters.

When the application starts, the component is initialized automatically with the default values from the configuration header. The configuration interface provides options to enable or disable the expected statistics data from the nodes, such as device information, execution time statistics, and neighbor information.

Notifications can be received on any CoAP server, such as the [libcoap](https://libcoap.net) server application. Over the prebuilt binaries, any custom library can be used to implement a CoAP server that receives the notifications from the Wi-SUN node.

CoAP resources can be accessed using the CoAP client, such as the [libcoap](https://libcoap.net) client application to provide a solution for handling CoAP requests sent directly to the node. The application status resource is configurable through the configuration header file and can be optionally enabled or disabled at compile time.

The following JSON shows the payload of the status notification/resource:

```c
{
"dev_info": {
  "hw": "BRD4270B A06 EFR32FG25B222F1920IM56",
  "sw": "Wi-SUN Ping Application v2.0.0 (stack: v2.3.0 FFN)",
  "mac": "60:A4:23:FF:FE:37:A7:57",
  "ip": "fd12:3456::62a4:23ff:fe37:a757"
},
"stat": {
  "run": "000-02:47:37",
  "conn_cnt": 2,
  "conn": "000-00:30:35",
  "tot_conn": "000-02:43:23",
  "disconn": "000-00:26:26",
  "tot_disconn": "000-00:04:26",
  "available": "97.35%"
},
"nb_info": {
  "ip":["t","lt","txc","txf","txms","txmsf","rpl","etx","rslo","rsli"],
  "fd12:3456::62a4:23ff:fe37:aed9":[0,2191,1352,0,0,0,128,134,133,143],
  "fd12:3456::32fb:10ff:feed:414e":[2,2080,29,0,0,0,65535,141,119,132],
  "fd12:3456::62a4:23ff:fe37:aee3":[2,545,14,0,0,0,65535,160,101,114]
}
}

```

##### Modules

[Configurations](sl-wisun-app-status-config)

##### Functions

###### sl_wisun_app_status_condition_cb

`bool sl_wisun_app_status_condition_cb(const sl_wisun_coap_notify_t *notify)`

**Description:** Application Status notification callback.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_coap_notify_t](sl-wisun-coap-notify-types#sl-wisun-coap-notify-t) *|N/A|notify|Notification context.|

The function provides an implementable callback to create custom condition check to send notification. It's a weak implementation, by default it returns true always. **Returns**

- bool The result of the condition check.

###### sl_wisun_app_status_get_remote_addr

`sl_status_t sl_wisun_app_status_get_remote_addr(sockaddr_in6_t *const addr)`

**Description:** Application Status notification remote address and port getter.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sockaddr_in6_t](sl-wisun-socket-api#sockaddr-in6-t) *const|N/A|addr|Pointer to sockaddr_in6_t structure to fill with remote address|

The function provides a getter function for the address and port parameters that are static for the file **Returns**

- sl_status_t SL_STATUS_OK if getting remote addr was success, otherwise error

###### sl_wisun_app_status_get_remote_address

`sockaddr_in6_t * sl_wisun_app_status_get_remote_address(void) SL_DEPRECATED_API_SDK_2025_6`

**Description:** Application Status notification remote address and port getter.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

The function provides a getter function for the address and port parameters that are static for the file **Returns**

- sockaddr_in6_t The pointer to the address setting structure

**Deprecated**This function is not thread-safe, use sl_wisun_app_status_get_remote_addr instead.

###### sl_wisun_app_status_get_schedule_time_ms

`uint32_t sl_wisun_app_status_get_schedule_time_ms(void)`

**Description:** Application Status notification schedule time getter.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

The function provides a getter function for the schedule time parameters that are static for the file **Returns**

- uint32_t The schedule time in ms

###### sl_wisun_app_status_init

`void sl_wisun_app_status_init(void)`

**Description:** Init Application Status notification content.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Init notification content and callbacks. 

###### sl_wisun_app_status_set_remote_address

`sl_status_t sl_wisun_app_status_set_remote_address(const char *remote_address, const uint16_t port)`

**Description:** Application Status notification remote address and port setter.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|N/A|remote_address|remote address to be selected|
|const uint16_t|N/A|port|remote port to be selected|

The function provides a setter function for the address and port parameters that are static for the file **Returns**

- sl_status_t SL_STATUS_OK if setting was success or the proper sl_status enum of the error

###### sl_wisun_app_status_set_schedule_time_ms

`void sl_wisun_app_status_set_schedule_time_ms(const uint32_t new_schedule_time_ms)`

**Description:** Application Status notification schedule time setter.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint32_t|N/A|new_schedule_time_ms|The schedule time in ms|

The function provides a setter function for the schedule time parameters that are static for the file

##### Configurations

###### Macros

`#define SL_WISUN_APP_STATUS_COAP_RESOURCE_ENABLE 1U`

**Description**: Enable CoAP resource.

`#define SL_WISUN_APP_STATUS_DEFAULT_NOTIFICATION_ID "app-status"`

**Description**: Default notification ID string.

`#define SL_WISUN_APP_STATUS_DEFAULT_REMOTE_ADDR "2001:db8::1"`

**Description**: Default remote address to send status report.

`#define SL_WISUN_APP_STATUS_DEFAULT_REMOTE_PORT 5683U`

**Description**: Default port of the remote host to send status report.

`#define SL_WISUN_APP_STATUS_DEFAULT_SCHEDULE_TIME_MS 10000UL`

**Description**: Default schedule time to send status report.

`#define SL_WISUN_APP_STATUS_DEFAULT_URI_PATH "/app/status"`

**Description**: Default URI Path to use in status report packet.

`#define SL_WISUN_APP_STATUS_DEVICE_INFO_ENABLE 1U`

**Description**: Enable execution time.

`#define SL_WISUN_APP_STATUS_EXECUTION_TIME_ENABLE 1U`

**Description**: Enable execution time.

`#define SL_WISUN_APP_STATUS_NEIGHBOR_INFO_ENABLE 1U`

**Description**: Enable Neighbor info.

#### Keychain

Wi-SUN Keychain API is an interface for retrieving device credentials and trusted CA certificates from a set of keychains.

Supported keychain types:

- **built-in** Built-in keychain is created during compilation time and cannot be changed. The application may add its own credentials via template contributions using Silicon Labs Configurator. Device private keys are stored unencrypted.
- **NVM** NVM keychain is dynamically provisioned either during device production or while on the field. Device private keys are stored in PSA ITS, device certificates and trusted CA certificates are stored in NVM3. Depending on the device capabilities, PSA ITS may be encrypted.

```c
#include "sl_memory_manager.h"
#include "sl_wisun_api.h"
#include "sl_wisun_keychain.h"

uint8_t trustedca_count;
sl_wisun_keychain_entry_t *trustedca;
sl_wisun_keychain_credential_t *credential;
uint16_t certificate_options;

// Retrieve a device credential
credential = sl_wisun_keychain_get_credential(SL_WISUN_KEYCHAIN_AUTOMATIC, 0);

// Configure the device certificate
sl_wisun_set_device_certificate(SL_WISUN_CERTIFICATE_OPTION_NONE,
                                credential->certificate.data_length,
                                credential->certificate.data);

// Configure the device private key
if (credential->pk.type == SL_WISUN_KEYCHAIN_KEY_TYPE_PLAINTEXT) {
  sl_wisun_set_device_private_key(SL_WISUN_PRIVATE_KEY_OPTION_NONE,
                                  credential->pk.u.plaintext.data_length,
                                  credential->pk.u.plaintext.data);
} else {
  sl_wisun_set_device_private_key_id(credential->pk.u.key_id);
}

// Free the device credential, ownership was transferred
sl_free(credential);

// Enumerate the trusted CA certificates
trustedca_count = sl_wisun_keychain_get_trustedca_count();

// Loop through available trusted CA certificates
certificate_options = SL_WISUN_CERTIFICATE_OPTION_NONE;
for (uint8_t idx = 0; idx < trustedca_count; ++idx) {
  // Retrieve a trusted CA certificate
  trustedca = sl_wisun_keychain_get_trustedca(idx);

  // Configure the trusted CA certificate
  sl_wisun_set_trusted_certificate(certificate_options,
                                   trustedca->data_length,
                                   trustedca->data);

  // Free the trusted CA certificate, ownership was transferred
  sl_free(trustedca);

  // The trusted CA certificates after the first one must be
  // configured with SL_WISUN_CERTIFICATE_OPTION_APPEND.
  certificate_options |= SL_WISUN_CERTIFICATE_OPTION_APPEND;
}

```

It's possible to utilize Silicon Labs Configurator to add credentials/trusted CAs to the built-in keychain during compile time through template contributions.

- wisun_keychain_include::path is the name of the header file that contains the uint8_t array declarations or definitions.
- wisun_keychain_trustedca::certificate is the name of the uint8_t array for a trusted CA certificate. This variable can be defined multiple times.
- wisun_keychain_credential::certificate is the name of the uint8_t array for the device certificate.
- wisun_keychain_credential::key is the name of the uint8_t array for the device private key.

```c
template_contribution:
  - name: wisun_keychain_include
    value:
      path: certificate_example.h
  - name: wisun_keychain_trustedca
    value:
      certificate: EXAMPLE_ROOT_CERT
  - name: wisun_keychain_trustedca
    value:
      certificate: EXAMPLE_MCA_CERT
  - name: wisun_keychain_trustedca
    value:
      certificate: EXAMPLE_MICA_CERT
  - name: wisun_keychain_credential
    value:
      certificate: EXAMPLE_DEVICE_CERT
      key: EXAMPLE_DEVICE_KEY

```

In certificate_example.h 

```c
const uint8_t EXAMPLE_ROOT_CERT[] = {
  ...
};
const uint8_t EXAMPLE_MCA_CERT[] = {
  ...
};
const uint8_t EXAMPLE_MICA_CERT[] = {
  ...
};
const uint8_t EXAMPLE_DEVICE_CERT[] = {
  ...
};
const uint8_t EXAMPLE_DEVICE_KEY[] = {
  ...
};

```

##### Modules

[sl_wisun_keychain_credential_t](sl-wisun-keychain-credential-t)

[sl_wisun_keychain_entry_t](sl-wisun-keychain-entry-t)

[sl_wisun_keychain_key_t](sl-wisun-keychain-key-t)

##### Enumerations

###### sl_wisun_keychain_key_type_t

```
enum sl_wisun_keychain_key_type_t {
    SL_WISUN_KEYCHAIN_KEY_TYPE_PLAINTEXT
    SL_WISUN_KEYCHAIN_KEY_TYPE_ID
}
```

**Description:**

Enumeration for private key type.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_KEYCHAIN_KEY_TYPE_PLAINTEXT|Private key is stored in plaintext.|
|SL_WISUN_KEYCHAIN_KEY_TYPE_ID|Private key is stored in PSA ITS.|

###### sl_wisun_keychain_t

```
enum sl_wisun_keychain_t {
    SL_WISUN_KEYCHAIN_AUTOMATIC
    SL_WISUN_KEYCHAIN_BUILTIN
    SL_WISUN_KEYCHAIN_NVM
}
```

**Description:**

Enumeration for keychain.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_KEYCHAIN_AUTOMATIC|Automatic keychain selection.|
|SL_WISUN_KEYCHAIN_BUILTIN|Built-in keychain.|
|SL_WISUN_KEYCHAIN_NVM|NVM keychain.|

##### Functions

###### sl_wisun_keychain_get_credential

`sl_wisun_keychain_credential_t * sl_wisun_keychain_get_credential(sl_wisun_keychain_t keychain, uint8_t index)`

**Description:** Retrieve a device credential.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_keychain_t](sl-wisun-keychain#sl-wisun-keychain-t)|[in]|keychain|Keychain to use<br/><br/>- [SL_WISUN_KEYCHAIN_AUTOMATIC](sl-wisun-keychain#sl-wisun-keychain-automatic): Use NVM keychain if available, built-in otherwise<br/>- [SL_WISUN_KEYCHAIN_BUILTIN](sl-wisun-keychain#sl-wisun-keychain-builtin): Use built-in keychain<br/>- [SL_WISUN_KEYCHAIN_NVM](sl-wisun-keychain#sl-wisun-keychain-nvm): Use NVM keychain|
|uint8_t|[in]|index|Built-in credential index (0...max)|

**Returns**

- Pointer to the device credential on success, NULL otherwise.

This function retrieves a device credential from the given keychain. Calling function is responsible for freeing the returned entry. 

###### sl_wisun_keychain_get_trustedca

`sl_wisun_keychain_entry_t * sl_wisun_keychain_get_trustedca(uint8_t index)`

**Description:** Retrieve a trusted CA certificate.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|index|Trusted CA certificate index to retrieve (0...max)|

**Returns**

- Pointer to the trusted CA certificate on success, NULL otherwise.

This function retrieves a trusted CA certificate from one of the keychains. The index must be below the value returned by [sl_wisun_keychain_get_trustedca_count()](sl-wisun-keychain#sl-wisun-keychain-get-trustedca-count). Calling function is responsible for freeing the returned entry. 

###### sl_wisun_keychain_get_trustedca_count

`uint8_t sl_wisun_keychain_get_trustedca_count()`

**Description:** Retrieve the number of trusted CA certificates.

**Returns**

- Number of trusted CA certificates, 0 if none.

This function returns the number of trusted CA certificates in all available keychains.

Data structure for a device credential. 

###### Public Attributes

###### certificate (heading level 7)

```
sl_wisun_keychain_entry_t sl_wisun_keychain_credential_t::certificate
```

**Description:** Device certificate.

###### pk (heading level 7)

```
sl_wisun_keychain_key_t sl_wisun_keychain_credential_t::pk
```

**Description:** Device private key.

Data structure for a keychain entry. 

###### Public Attributes

###### data (heading level 7)

```
const void* sl_wisun_keychain_entry_t::data
```

**Description:** Pointer to data.

**Details:** When freeing a keychain entry, this pointer must not be freed.

###### data_length (heading level 7)

```
size_t sl_wisun_keychain_entry_t::data_length
```

**Description:** Amount of data in bytes.

###### keychain (heading level 7)

```
sl_wisun_keychain_t sl_wisun_keychain_entry_t::keychain
```

**Description:** Keychain were the entry is stored.

Data structure for a device private key. 

###### Public Attributes

###### key_id (heading level 7)

```
uint32_t sl_wisun_keychain_key_t::key_id
```

**Description:** Private key when type is SL_WISUN_KEYCHAIN_KEY_TYPE_ID.

###### keychain (heading level 7)

```
sl_wisun_keychain_t sl_wisun_keychain_key_t::keychain
```

**Description:** Keychain were the private keý is stored.

###### plaintext (heading level 7)

```
sl_wisun_keychain_entry_t sl_wisun_keychain_key_t::plaintext
```

**Description:** Private key when type is SL_WISUN_KEYCHAIN_KEY_TYPE_PLAINTEXT.

###### type (heading level 7)

```
sl_wisun_keychain_key_type_t sl_wisun_keychain_key_t::type
```

**Description:** Type of the private key.

###### u (heading level 7)

```
union sl_wisun_keychain_key_t::@7 sl_wisun_keychain_key_t::u
```

**Description:** Private key.

### Wi-SUN Stack Plugin

The Wi-SUN stack plugin components are software modules tightly linked to the stack that provide means to customize it: debug, manufacturing, or Wi-SUN-specific optional features. They can have significant impact on key capabilities and memory footprint. 

#### Modules

[Stack Trace and Debug](sl-wisun-trace-api)

[RF Test](sl-wisun-rf-test)

[Dedicated allocator for Wi-SUN critical features](sl-wisun-alloc)

#### Stack Trace and Debug

The Trace and Debug component adds tracing capabilities to the stack and stack plugin components. The component provides APIs to configure or filter out the debug traces output. 

##### Functions

###### sl_wisun_set_trace_filter

`sl_status_t sl_wisun_set_trace_filter(const uint8_t filter[SL_WISUN_FILTER_BITFIELD_SIZE])`

**Description:** Set the trace filter.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t|[in]|filter|Bit mask of trace group IDs. First byte of the array represents IDs 0 - 7, with bit 0 being ID 0. Second byte represents IDs 8 - 15 and so forth. If a bit is set, the corresponding trace group ID is selected for tracing. 0 means the particular trace group ID is disabled. Bit enumeration is defined in [sl_wisun_trace_group_t](sl-wisun-types#sl-wisun-trace-group-t).|

Indicate which trace group will be displayed.

**Returns**

- One of the following:  
  - SL_STATUS_NOT_AVAILABLE if the [Stack Trace and Debug](sl-wisun-trace-api) component is not installed  
  - SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_set_trace_level

`sl_status_t sl_wisun_set_trace_level(uint8_t group_count, const sl_wisun_trace_group_config_t *trace_config)`

**Description:** Set the trace level.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|group_count|Number of groups to configure. If 0, enable all levels for all groups. Maximum [SL_WISUN_TRACE_GROUP_COUNT](sl-wisun-types#sl-wisun-trace-group-count).|
|const [sl_wisun_trace_group_config_t](sl-wisun-trace-group-config-t) *|[in]|trace_config|Table with group_count element filled. It indicates the trace level to be displayed for each group.|

**Returns**

- One of the following:  
  - SL_STATUS_NOT_AVAILABLE if the [Stack Trace and Debug](sl-wisun-trace-api) component is not installed  
  - SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_trace_debug

`sl_status_t sl_wisun_trace_debug(const char *fmt,...)`

**Description:** Generate application logs using Wi-SUN stack trace mechanism with DEBUG level.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|fmt|Format string (same syntax as printf)|
|...|[in]|undefined|Variable arguments related to fmt|

**Returns**

- SL_STATUS_NOT_AVAILABLE if using the release library, SL_STATUS_OK otherwise

###### sl_wisun_trace_error

`sl_status_t sl_wisun_trace_error(const char *fmt,...)`

**Description:** Generate application logs using Wi-SUN stack trace mechanism with ERROR level.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|fmt|Format string (same syntax as printf)|
|...|[in]|undefined|Variable arguments related to fmt|

**Returns**

- SL_STATUS_NOT_AVAILABLE if using the release library, SL_STATUS_OK otherwise

###### sl_wisun_trace_info

`sl_status_t sl_wisun_trace_info(const char *fmt,...)`

**Description:** Generate application logs using Wi-SUN stack trace mechanism with INFO level.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|fmt|Format string (same syntax as printf)|
|...|[in]|undefined|Variable arguments related to fmt|

**Returns**

- SL_STATUS_NOT_AVAILABLE if using the release library, SL_STATUS_OK otherwise

###### sl_wisun_trace_warn

`sl_status_t sl_wisun_trace_warn(const char *fmt,...)`

**Description:** Generate application logs using Wi-SUN stack trace mechanism with WARN level.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const char *|[in]|fmt|Format string (same syntax as printf)|
|...|[in]|undefined|Variable arguments related to fmt|

**Returns**

- SL_STATUS_NOT_AVAILABLE if using the release library, SL_STATUS_OK otherwise

#### RF Test

The RF Test component provides low-level APIs to produce an RF tone or a modulated packet. The RF Test component cannot run simultaneously with the Wi-SUN stack and is only meant for production calibration. 

##### Functions

###### sl_wisun_is_running_rf_test

`bool sl_wisun_is_running_rf_test()`

**Description:** Return the current status of the RF test plugin.

**Returns**

- One of the following:  
  - True if a test is running.  
  - False otherwise.

###### sl_wisun_rf_test_event_callback

`void sl_wisun_rf_test_event_callback(uint64_t events, int8_t rssi)`

**Description:** Handles RF events generated during RF tests.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint64_t|[in]|events|RAIL event mask associated with the RF test event|
|int8_t|[in]|rssi|RSSI in dBm; valid when SL_RAIL_EVENT_RX_PACKET_RECEIVED is set in events, otherwise SL_WISUN_RF_TEST_RSSI_NOT_AVAILABLE|

This callback updates the RF test state based on the RAIL event and should be called when an event of type SL_WISUN_LOGGER_EVENT_TYPE_RF_TEST is received by the application.

###### sl_wisun_rf_test_rx_stop

`sl_status_t sl_wisun_rf_test_rx_stop(void)`

**Description:** Stop RF test RX reception.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This API ends an active RF test RX session started with [sl_wisun_rf_test_start_rx()](sl-wisun-rf-test#sl-wisun-rf-test-start-rx).

**Returns**

- One of the following:  
  - SL_STATUS_OK if the RX test stopped successfully.  
  - SL_STATUS_INVALID_STATE if not currently receiving.  
  - SL_STATUS_NOT_SUPPORTED if the feature is not implemented.

###### sl_wisun_rf_test_set_phy_config

`sl_status_t sl_wisun_rf_test_set_phy_config(sl_wisun_phy_config_t *phy_config)`

**Description:** Must be called before [sl_wisun_rf_test_start_tx()](sl-wisun-rf-test#sl-wisun-rf-test-start-tx), [sl_wisun_rf_test_start_rx()](sl-wisun-rf-test#sl-wisun-rf-test-start-rx), [sl_wisun_start_stream()](sl-wisun-rf-test#sl-wisun-start-stream) and [sl_wisun_start_tone()](sl-wisun-rf-test#sl-wisun-start-tone).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_phy_config_t](sl-wisun-phy-config-t) *|[in]|phy_config|Pointer to PHY configuration structure|

Sets the phy configuration for the subsequent RF test operations.

**Returns**

- One of the following:  
  - SL_STATUS_OK if the PHY configuration was set successfully.  
  - SL_STATUS_NOT_READY if called before the stack initialization.  
  - SL_STATUS_BUSY if a test is already running.  
  - SL_STATUS_NETWORK_UP if a connection is already established or in progress.  
  - SL_STATUS_NOT_FOUND if the PHY configuration was not found.

###### sl_wisun_rf_test_start_rx

`sl_status_t sl_wisun_rf_test_start_rx(uint16_t channel, uint32_t duration)`

**Description:** Start RF test RX reception on a fixed channel.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|channel|Index of the physical channel to transmit on|
|uint32_t|[in]|duration|Duration in milliseconds (0 = run until stopped)|

This API puts the radio into continuous RX on the given channel for the requested duration. If duration is 0, RX continues until explicitly stopped.

**Returns**

- One of the following:  
  - SL_STATUS_OK if the RX test started successfully.  
  - SL_STATUS_NOT_READY if called before the stack initialization.  
  - SL_STATUS_BUSY if a test is already running.  
  - SL_STATUS_NETWORK_UP if a connection is already established or in progress.  
  - SL_STATUS_INVALID_PARAMETER if an invalid parameter is provided.  
  - SL_STATUS_NOT_SUPPORTED if the feature is not implemented.

###### sl_wisun_rf_test_start_tx

`sl_status_t sl_wisun_rf_test_start_tx(uint16_t channel, uint16_t count, uint16_t data_length, uint8_t *data, uint32_t interval, bool cca_enabled)`

**Description:** Start an RF test packet transmission sequence.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|channel|Index of the physical channel to transmit on|
|uint16_t|[in]|count|Number of packets to transmit (must be greater than 0)|
|uint16_t|[in]|data_length|Length of data in each packet (must be between 1 and 2047 - CRC length, typically 2045 for FSK, 2043 for OFDM or OQPSK)|
|uint8_t *|[in]|data|Pointer to data to transmit; if NULL a default ramp pattern is used|
|uint32_t|[in]|interval|Interval between transmissions in milliseconds (must be greater than 0)|
|bool|[in]|cca_enabled|Set true to perform a single CCA check before the initial transmit|

This API schedules repeated packet transmissions on a fixed channel using the currently configured RF test PHY (see [sl_wisun_rf_test_set_phy_config()](sl-wisun-rf-test#sl-wisun-rf-test-set-phy-config)). The packets are sent at a constant interval until the total number of transmissions is reached. If `cca_enabled` is true, a single CCA check is performed before the initial transmit using the default single-CCA CSMA settings. To receive the packets, another application can use [sl_wisun_rf_test_start_rx()](sl-wisun-rf-test#sl-wisun-rf-test-start-rx) on the same channel.

**Returns**

- One of the following:  
  - SL_STATUS_OK if the transmission started successfully.  
  - SL_STATUS_NOT_READY if called before the stack initialization.  
  - SL_STATUS_BUSY if a test is already running.  
  - SL_STATUS_NETWORK_UP if a connection is already established or in progress.  
  - SL_STATUS_INVALID_PARAMETER if an invalid parameter is provided.  
  - SL_STATUS_NOT_SUPPORTED if the feature is not implemented.

###### sl_wisun_set_test_tx_power

`sl_status_t sl_wisun_set_test_tx_power(int8_t tx_power)`

**Description:** Set transmit power.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int8_t|[in]|tx_power|Transmit power in units of dBm, can be negative.|

**Returns**

- always SL_STATUS_OK

###### sl_wisun_start_stream

`sl_status_t sl_wisun_start_stream(uint16_t channel)`

**Description:** Start transmitting a random stream of characters to enable the measurement of radio modulation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|channel|Index of the physical channel to transmit on|

**Returns**

- One of the following:  
  - SL_STATUS_OK if the stream transmission started successfully.  
  - SL_STATUS_NOT_READY if called before the stack initialization.  
  - SL_STATUS_BUSY if a test is already running.  
  - SL_STATUS_NETWORK_UP if a connection is already established or in progress.  
  - SL_STATUS_INVALID_PARAMETER if an invalid channel is configured.

Transmit a PN9 bytes sequence. See sl_rail_start_tx_stream() for more information. 

###### sl_wisun_start_tone

`sl_status_t sl_wisun_start_tone(uint16_t channel)`

**Description:** Start transmitting an unmodulated tone.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|channel|Index of the physical channel to transmit on|

**Returns**

- One of the following:  
  - SL_STATUS_OK if the stream transmission started successfully.  
  - SL_STATUS_NOT_READY if called before the stack initialization.  
  - SL_STATUS_BUSY if a test is already running.  
  - SL_STATUS_NETWORK_UP if a connection is already established or in progress.  
  - SL_STATUS_INVALID_PARAMETER if an invalid channel is configured.

Transmit a PN9 bytes sequence. See sl_rail_start_tx_stream() for more information. 

###### sl_wisun_stop_stream

`sl_status_t sl_wisun_stop_stream()`

**Description:** Stop a previously started stream of characters.

**Returns**

- One of the following:  
  - SL_STATUS_OK if the stream transmission stopped successfully.  
  - SL_STATUS_INVALID_STATE if while not transmitting a stream.

See sl_rail_stop_tx_stream() for more information. 

###### sl_wisun_stop_tone

`sl_status_t sl_wisun_stop_tone()`

**Description:** Stop a previously started tone.

**Returns**

- One of the following:  
  - SL_STATUS_OK if the tone stopped successfully.  
  - SL_STATUS_INVALID_STATE if while not transmitting a tone.

See sl_rail_stop_tx_stream() for more information.

#### Dedicated allocator for Wi-SUN critical features

The Wi-SUN alloc component provides a separate heap dedicated to critical Wi-SUN features, including cryptographic operations. It redirects MbedTLS calloc and free functions to a custom allocator working with a static array of configurable size (defaults to 16kB). The purpose of this heap is to make the Wi-SUN stack more reliable under heavy heap usage by reserving enough space to always be able to maintain connectivity. In the event that the heap runs out of memory, the custom allocator defaults back to standard functions as a best effort strategy. Note: all cryptographic operations may allocate on this heap; if the application requires more operations than those needed by Wi-SUN, the heap should be dimensioned accordingly. Use sl_wisun_heap_get_stats() to help track heap usage if need be.

### Wi-SUN Stack API

Wi-SUN Stack API provides functions for managing and configuring the Wi-SUN protocol stack. 

The API allows applications to initiate and manage network connections, set security credentials, configure PHY and MAC parameters, and retrieve network statistics and information. It's based on requests from the application to the stack and events from the stack to the application. Requests are made using function calls, where a function call either performs the required action immediately or initiates an internal operation within the stack, which terminates with an event. All events contain a status code, indicating the result of the requested operation. Events are also used by the stack to notify the application of any important information, such as the state of the connection.

The stack relies on platform specific event system to deliver events to the application. The application is expected to subscribe to SL_EVENT_CLASS_WISUN event class and SL_WISUN_EVENT_IND_MASK event mask to receive these events. Because all events share a common header, they can be differentiated using a switch statement. The event-specific data can be accessed through the [sl_wisun_evt_t::evt](sl-wisun-evt-t#evt) union.

The API is thread-safe, which means it can be called from multiple RTOS tasks. The stack guarantees that only a single request is executed at a time and that requests are handled in the order they were made. Note that the events need to be handled in a different context so the API functions can be called directly. 

#### Modules

[API events](sl-wisun-evt)

[API type definitions](sl-wisun-types)

[API availability](api-availability)

[Regional Regulation API](sl-wisun-regulation-api)

[Message API](sl-wisun-msg-api)

[Border Router API](sl-wisun-br-api)

[Border Router Message API](sl-wisun-br-msg-api)

[Socket API](sl-wisun-socket-api)

[Select API](sl-wisun-select-api)

#### Callbacks

##### sl_wisun_on_event

`void sl_wisun_on_event(sl_wisun_evt_t *evt)`

**Description:** Function called to receive events from the Wi-SUN stack.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_evt_t](sl-wisun-evt-t) *|[out]|evt|The event to be handled|

The component wisun_event_task provides a default implementation of a task that can be used to receive the events published by the stack and redirect them to the function [sl_wisun_on_event()](sl-wisun-api#sl-wisun-on-event). The application needs to implement this function to receive the events published by the stack and handle them accordingly. The function is called from a task context different from the Wi-SUN stack so the API functions can be called directly.

```c
void sl_wisun_on_event(sl_wisun_evt_t *evt)
{
  switch (evt->header.id) {
    case SL_WISUN_MSG_CONNECTED_IND_ID:
      handle_connected_event(evt->evt.connected);
      break;
    default:
      break;
  }
}

```

**Note**

- The application can use the component wisun_disable_event_task to implement its own event handling logic instead of using the default implementation provided by the component wisun_event_task.

**See Also**

- [API events](sl-wisun-evt)

#### Functions

##### sl_wisun_accept_direct_connect_link

`sl_status_t sl_wisun_accept_direct_connect_link(in6_addr_t *link_local_ipv6)`

**Description:** Accept a Direct Connect link.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[in6_addr_t](sl-wisun-socket-api#in6-addr-t) *|[in]|link_local_ipv6|Link-Local IPv6 address of the client|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_advert_direct_connect_server_id

`sl_status_t sl_wisun_advert_direct_connect_server_id(const in6_addr_t *link_local_ipv6, const sl_wisun_dc_id_t *dc_id)`

**Description:** Advertise the Direct Connect Server identity in response to a discovery request.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [in6_addr_t](sl-wisun-socket-api#in6-addr-t) *|[in]|link_local_ipv6|Pointer to the link-local IPv6 address of the client that sent the identification solicitation.|
|const [sl_wisun_dc_id_t](sl-wisun-dc-id-t) *|[in]|dc_id|Pointer to the Direct Connect Server Identifier (DC ID). The format and length of this identifier are application-defined.|

This function is used by a Direct Connect Server to advertise its identity to a client that has initiated a discovery scan.

When a SL_WISUN_MSG_DIRECT_CONNECT_ID_SOLICIT_IND_ID event is received, the application should inspect the DC ID contained in the event. If the DC ID is recognized as valid for identification or scanning purposes, this function should be called to respond to the client.

The advertisement process stops automatically when:

- The client acknowledges the DCI (identification frame), or
- The configured maximum number of Identity Advertisement (max_advert_count) is reached.

**Note**

- - This function must only be called upon reception of a SL_WISUN_MSG_DIRECT_CONNECT_ID_SOLICIT_IND_ID event.  
  - The DC ID format and matching logic are defined by the application.

**Returns**

- SL_STATUS_OK if the advertisement process started successfully. Error code otherwise (e.g. invalid parameters or transmission failure).

Available in libraries: Full, FFN (see [API availability](api-availability)). 

##### sl_wisun_allow_mac_address

`sl_status_t sl_wisun_allow_mac_address(const sl_wisun_mac_address_t *address)`

**Description:** Add a MAC address to the list of allowed addresses.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|address|MAC address<br/><br/>- **sl_wisun_broadcast_mac**: allow all MAC addresses<br/>- **unicast address**: allow the given MAC address|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function adds a MAC address to the list of allowed addresses. When the first address is added to the list, the list of denied addresses is cleared and the device will start preventing communication with any device whose MAC address does not match any of addresses on the list. By default, all MAC addresses are allowed. Up to 10 MAC addresses may be added to the list. The access list affects only directly connected nodes such as parents, children, and neighbors. The list is persistent when the device disconnects or stops.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_clear_credential_cache

`sl_status_t sl_wisun_clear_credential_cache()`

**Description:** Clear the credential cache.

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function clears the cached authentication credentials stored in non-volatile storage. The function is intended for test purposes. Note that clearing the credential cache may prevent the node from reconnecting to the same parent until the corresponding cache entry has expired on the parent.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_clear_event_filters

`sl_status_t sl_wisun_clear_event_filters(void)`

**Description:** Clear filters for event logger.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function clears all event logger filters set by `sl_wisun_set_event_filter` for all event types and addresses. This function can be called at any time.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_config_concurrent_detection

`sl_status_t sl_wisun_config_concurrent_detection(bool enable_tx, uint8_t reserved)`

**Description:** Configure concurrent detection.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|enable_tx|TX state<br/><br/>- **true**: TX is allowed with an alternate PHY<br/>- **false**: TX is not allowed with an alternate PHY|
|uint8_t|[in]|reserved|Reserved for future use, set to zero.|

**Returns**

- SL_STATUS_OK if the operation is successful, an error code otherwise.

This function configures whether an alternate PHY can be used concurrently with the base PHY. The alternate PHY must be enabled in the radio configuration to utilize this feature. When enabled, the alternate PHY is always accepted on receive. When TX state is set to true, the node will transmit to nodes that support the feature using the alternate PHY, instead of using the standard mode switch. TX is disabled by default.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_config_mode_switch

`sl_status_t sl_wisun_config_mode_switch(uint8_t mode, uint8_t phy_mode_id, const sl_wisun_mac_address_t *neighbor_address, bool reserved)`

**Description:** Configure per‑neighbor mode switch behavior.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|mode|Mode switch configuration of the neighbor. If set to [SL_WISUN_MODE_SWITCH_DEFAULT](sl-wisun-types#sl-wisun-mode-switch-default), the configuration of the neighbor is reset back to the default mode switch behavior.|
|uint8_t|[in]|phy_mode_id|PhyModeId to use when mode is set to [SL_WISUN_MODE_SWITCH_ENABLED](sl-wisun-types#sl-wisun-mode-switch-enabled), ignored otherwise.|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|neighbor_address|MAC address of the neighbor to configure. If set to [sl_wisun_broadcast_mac](sl-wisun-types#sl-wisun-broadcast-mac), configures the default mode switch behavior for all non-configured neighbors.|
|bool|[in]|reserved|Reserved for future use, set to false.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_config_neighbor_table

`sl_status_t sl_wisun_config_neighbor_table(uint8_t max_child_count, uint8_t max_neighbor_count, uint16_t max_security_neighbor_count)`

**Description:** Configure neighbor table size.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|max_child_count|Maximum number of RPL children Increasing this parameter means a higher number of potential neighbors while lowering it means reduced RAM consumption. The default value is 22.|
|uint8_t|[in]|max_neighbor_count|Maximum number of neighbors including children, parent, and temporary neighbors The default value is 32|
|uint16_t|[in]|max_security_neighbor_count|Maximum number of neigbors in the security table. Entries in the security table are removed on key expirations. Default value is 300|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

max_neighbor_count must be greater than max_child_count. max_neighbor_count - max_child_count represents the available neighbors for RPL parents and temporary neighbors (neighbors not yet registered, parent candidate or neighbors sending multicast). max_security_neighbor_count must be greater or equal than max_neighbor_count Each entry in the neighbor table consumes about 450 bytes of RAM. Each entry in the security neighbor table consumes about 50 bytes of RAM. Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_connect_to_direct_connect_server

`sl_status_t sl_wisun_connect_to_direct_connect_server(const sl_wisun_mac_address_t *mac_address, uint32_t pmk_id, uint8_t max_solicits_count)`

**Description:** Establish or switch a Direct Connect link to a selected server.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|mac_address|MAC address of the target server.|
|uint32_t|[in]|pmk_id|Pairwise Master Key identifier to use.|
|uint8_t|[in]|max_solicits_count|Max solicitation retries for this connection.|

Starts (or restarts) authentication and link establishment with `mac_address` using `pmk_id`. If a connection is in progress or active, it is aborted and the new target is attempted. Scanning is not affected by this API.

**Returns**

- SL_STATUS_OK on success; error code otherwise.

**Note**

- This API may be called while scanning, connecting, or connected to switch the active/attempted connection to a newly discovered target.

Available in libraries: Full, FFN (see [API availability](api-availability)). 

##### sl_wisun_deny_mac_address

`sl_status_t sl_wisun_deny_mac_address(const sl_wisun_mac_address_t *address)`

**Description:** Add a MAC address to the list of denied addresses.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|address|MAC address<br/><br/>- **sl_wisun_broadcast_mac**: deny all MAC addresses<br/>- **unicast address**: deny the given MAC address|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function adds a MAC address to the list of denied addresses. When the first address is added to the list, the list of allowed addresses is cleared and the device will start preventing communication with any device whose MAC address matches any of the addresses on the list. By default, all MAC addresses are allowed. Up to 10 MAC addresses may be added to the list. The access list affects only directly connected nodes such as parents, children, and neighbors. The list is persistent when the device disconnects os stops.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_disconnect

`sl_status_t sl_wisun_disconnect()`

**Description:** Disconnect from the Wi-SUN network.

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function disconnects an active connection or cancels an ongoing connection attempt.

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_get_excluded_channel_mask

`sl_status_t sl_wisun_get_excluded_channel_mask(sl_wisun_channel_mask_type_t type, sl_wisun_channel_mask_t *channel_mask, uint32_t *channel_count)`

**Description:** Get the mask of channels excluded from channel plan.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_channel_mask_type_t](sl-wisun-types#sl-wisun-channel-mask-type-t)|[in]|type|Type of channel mask to retrieve|
|[sl_wisun_channel_mask_t](sl-wisun-channel-mask-t) *|[out]|channel_mask|Pointer where channel mask is written|
|uint32_t *|[out]|channel_count|Number of channels in the mask|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_ip_address

`sl_status_t sl_wisun_get_ip_address(sl_wisun_ip_address_type_t address_type, in6_addr_t *address)`

**Description:** Read an IP address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_ip_address_type_t](sl-wisun-types#sl-wisun-ip-address-type-t)|[in]|address_type|Type of the IP address to read<br/><br/>- [SL_WISUN_IP_ADDRESS_TYPE_LINK_LOCAL](sl-wisun-types#sl-wisun-ip-address-type-link-local): Link-local IPv6 address of the device<br/>- [SL_WISUN_IP_ADDRESS_TYPE_GLOBAL](sl-wisun-types#sl-wisun-ip-address-type-global): Global unicast IPv6 address of the device<br/>- [SL_WISUN_IP_ADDRESS_TYPE_BORDER_ROUTER](sl-wisun-types#sl-wisun-ip-address-type-border-router): Global unicast IPv6 address of the border router<br/>- [SL_WISUN_IP_ADDRESS_TYPE_PRIMARY_PARENT](sl-wisun-types#sl-wisun-ip-address-type-primary-parent): Link-local IPv6 address of the primary parent<br/>- [SL_WISUN_IP_ADDRESS_TYPE_SECONDARY_PARENT](sl-wisun-types#sl-wisun-ip-address-type-secondary-parent): Link-local IPv6 address of the secondary parent|
|[in6_addr_t](sl-wisun-socket-api#in6-addr-t) *|[out]|address|IP address to read|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise.

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_get_join_state

`sl_status_t sl_wisun_get_join_state(sl_wisun_join_state_t *join_state)`

**Description:** Get the current join state.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_join_state_t](sl-wisun-types#sl-wisun-join-state-t) *|[out]|join_state|Join state|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function retrieves the current state of the connection process. The function can only be used once a connection has been initiated.

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_get_mac_address

`sl_status_t sl_wisun_get_mac_address(sl_wisun_mac_address_t *address)`

**Description:** Get the current device MAC address in use.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[out]|address|MAC address|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_neighbor_count

`sl_status_t sl_wisun_get_neighbor_count(uint8_t *neighbor_count)`

**Description:** Get the number of RPL neighbors (parents and children).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|neighbor_count|Number of neighbors|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_neighbor_info

`sl_status_t sl_wisun_get_neighbor_info(const sl_wisun_mac_address_t *neighbor_mac_address, sl_wisun_neighbor_info_t *neighbor_info)`

**Description:** Get information about a RPL neighbor (parent or child).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|neighbor_mac_address|Pointer to neighbor MAC address|
|[sl_wisun_neighbor_info_t](sl-wisun-neighbor-info-t) *|[out]|neighbor_info|Pointer to where the read information is stored|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_neighbors

`sl_status_t sl_wisun_get_neighbors(uint8_t *neighbor_count, sl_wisun_mac_address_t *neighbor_mac_addresses)`

**Description:** Get a list of RPL neighbor (parents and children) MAC addresses.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[inout]|neighbor_count|Maximum number of neighbors to read on input, number of neighbors read on output|
|[sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[out]|neighbor_mac_addresses|Pointer to memory where to store neighbor MAC addresses|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_network_info

`sl_status_t sl_wisun_get_network_info(sl_wisun_network_info_t *network_info)`

**Description:** Get Wi-SUN network information.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_network_info_t](sl-wisun-network-info-t) *|[out]|network_info|Pointer where network information is written|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_pom_ie

`sl_status_t sl_wisun_get_pom_ie(uint8_t *phy_mode_id_count, uint8_t *phy_mode_ids, uint8_t *is_mdr_command_capable)`

**Description:** Get the list of PHY operating modes the device will use for mode switch operations.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|phy_mode_id_count|Number of PhyModeId retrieved|
|uint8_t *|[out]|phy_mode_ids|List of phy_mode_id_count PhyModeId. Caller must allocate space for at least [SL_WISUN_MAX_PHY_MODE_ID_COUNT](sl-wisun-types#sl-wisun-max-phy-mode-id-count) entries.|
|uint8_t *|[out]|is_mdr_command_capable|Set to 1 if the device supports MAC mode switch, 0 otherwise|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function retrieves the PHY operating mode information advertised to neighboring nodes.

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_rpl_info

`sl_status_t sl_wisun_get_rpl_info(sl_wisun_rpl_info_t *rpl_info)`

**Description:** Get RPL information.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_rpl_info_t](sl-wisun-rpl-info-t) *|[out]|rpl_info|Pointer where RPL information is written|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_stack_version

`sl_status_t sl_wisun_get_stack_version(uint8_t *major, uint8_t *minor, uint8_t *patch, uint16_t *build)`

**Description:** Get the Wi-SUN stack version.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|major|Wi-SUN stack version major|
|uint8_t *|[out]|minor|Wi-SUN stack version minor|
|uint8_t *|[out]|patch|Wi-SUN stack version patch|
|uint16_t *|[out]|build|Build number, set to 0 in public versions|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_get_statistics

`sl_status_t sl_wisun_get_statistics(sl_wisun_statistics_type_t statistics_type, sl_wisun_statistics_t *statistics)`

**Description:** Read a set of statistics.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_statistics_type_t](sl-wisun-types#sl-wisun-statistics-type-t)|[in]|statistics_type|Type of statistics to read<br/><br/>- [SL_WISUN_STATISTICS_TYPE_PHY](sl-wisun-types#sl-wisun-statistics-type-phy): PHY/RF statistics<br/>- [SL_WISUN_STATISTICS_TYPE_MAC](sl-wisun-types#sl-wisun-statistics-type-mac): MAC statistics<br/>- [SL_WISUN_STATISTICS_TYPE_FHSS](sl-wisun-types#sl-wisun-statistics-type-fhss): Frequency hopping statistics<br/>- [SL_WISUN_STATISTICS_TYPE_WISUN](sl-wisun-types#sl-wisun-statistics-type-wisun): Wi-SUN statistics<br/>- [SL_WISUN_STATISTICS_TYPE_NETWORK](sl-wisun-types#sl-wisun-statistics-type-network): 6LoWPAN/IP stack statistics<br/>- [SL_WISUN_STATISTICS_TYPE_REGULATION](sl-wisun-types#sl-wisun-statistics-type-regulation): Regional regulation statistics<br/>- [SL_WISUN_STATISTICS_TYPE_HEAP](sl-wisun-types#sl-wisun-statistics-type-heap): Heap usage statistics|
|[sl_wisun_statistics_t](sl-wisun-statistics-t) *|[out]|statistics|Set of statistics read|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise.

This function reads a set of statistics from the stack. Statistics are cumulative and reset when a connection is initiated or by calling [sl_wisun_reset_statistics()](sl-wisun-api#sl-wisun-reset-statistics).

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_join

`sl_status_t sl_wisun_join(const uint8_t *name, sl_wisun_phy_config_t *phy_config)`

**Description:** Initiate a connection to a Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|name|Name of the Wi-SUN network as a zero-terminated string|
|[sl_wisun_phy_config_t](sl-wisun-phy-config-t) *|[in]|phy_config|Pointer to PHY configuration|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function initiates connection to a Wi-SUN network. Completion of the request is indicated with a [SL_WISUN_MSG_CONNECTED_IND_ID](sl-wisun-evt#sl-wisun-msg-connected-ind-id) event.

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_reset_parameters

`sl_status_t sl_wisun_reset_parameters(void)`

**Description:** Reset all parameters and options to defaults and re-enable auto mode.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- SL_STATUS_OK on success.
- SL_STATUS_INVALID_STATE if the stack is not in disconnected state.

This function restores all connection parameters and options to their default values and re-enables the automatic adjustment of parameters based on the PAN Size advertised in the Wi-SUN PAN-IE.

After calling this function, the stack switches back to auto mode. Calls to [sl_wisun_set_option](sl-wisun-api#sl-wisun-set-option), [sl_wisun_set_ffn_advanced_parameters](sl-wisun-api#sl-wisun-set-ffn-advanced-parameters), [sl_wisun_set_lfn_advanced_parameters](sl-wisun-api#sl-wisun-set-lfn-advanced-parameters), [sl_wisun_br_set_advanced_parameters](sl-wisun-br-api#sl-wisun-br-set-advanced-parameters) are allowed again.

Any parameter or option customization previously applied through those functions is discarded.

This function can only be called before joining a network, i.e. before calling [sl_wisun_join](sl-wisun-api#sl-wisun-join).

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_reset_regulation_duty_cycle

`sl_status_t sl_wisun_reset_regulation_duty_cycle(void)`

**Description:** Reset all the past hour transmissions counters.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_reset_statistics

`sl_status_t sl_wisun_reset_statistics(sl_wisun_statistics_type_t statistics_type)`

**Description:** Reset a set of statistics in the stack.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_statistics_type_t](sl-wisun-types#sl-wisun-statistics-type-t)|[in]|statistics_type|Type of statistics to reset<br/><br/>- [SL_WISUN_STATISTICS_TYPE_PHY](sl-wisun-types#sl-wisun-statistics-type-phy): PHY/RF statistics<br/>- [SL_WISUN_STATISTICS_TYPE_MAC](sl-wisun-types#sl-wisun-statistics-type-mac): MAC statistics<br/>- [SL_WISUN_STATISTICS_TYPE_FHSS](sl-wisun-types#sl-wisun-statistics-type-fhss): Frequency hopping statistics<br/>- [SL_WISUN_STATISTICS_TYPE_WISUN](sl-wisun-types#sl-wisun-statistics-type-wisun): Wi-SUN statistics<br/>- [SL_WISUN_STATISTICS_TYPE_NETWORK](sl-wisun-types#sl-wisun-statistics-type-network): 6LoWPAN/IP stack statistics|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_advert_fragment_duration

`sl_status_t sl_wisun_set_advert_fragment_duration(uint32_t fragment_duration_ms)`

**Description:** Set the async transmission fragmentation parameters.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|fragment_duration_ms|Max duration of a fragment in ms (min 500 ms)|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Async transmissions, such as Wi-SUN PAN advertisement packets, are sent to every allowed operating channel and may therefore block broadcast and unicast traffic. This impact can be reduced by splitting the channel list into fragments based on the maximum transmission duration and by forcing a delay between the fragments, allowing other traffic to occur. This function sets the maximum duration of a PA, PAS, PC, and PCS advertisement period fragments. A small value trades off longer connection times for shorter latencies. Setting the duration to [SL_WISUN_ADVERT_FRAGMENT_DISABLE](sl-wisun-types#sl-wisun-advert-fragment-disable) disables async transmission fragmentation.

By default, the maximum fragment duration is set to 500 ms.

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_allowed_channel_mask

`sl_status_t sl_wisun_set_allowed_channel_mask(const sl_wisun_channel_mask_t *channel_mask)`

**Description:** Restrict channel use to a subset of allowed channels in the current channel plan.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_channel_mask_t](sl-wisun-channel-mask-t) *|[in]|channel_mask|Mask of operating channels|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets a mask of channels the device is allowed to operate in for unicast frequency hopping. By default, all channels in the channel plan are allowed. The mask can only be used to further restrict the channels. Channels outside the channel plan or channels internally excluded are ignored. This mask will be used in the following connections.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

**Warnings**

- By comparison to the Wi-SUN FAN specification, the channel mask logic is inverted. The specification references a mask of excluded channels.

##### sl_wisun_set_channel_mask

`sl_status_t sl_wisun_set_channel_mask(const sl_wisun_channel_mask_t *channel_mask)`

**Description:** Restrict channel use to a subset of allowed channels in the current channel plan.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_channel_mask_t](sl-wisun-channel-mask-t) *|[in]|channel_mask|Mask of operating channels|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets a mask of channels the device is allowed to operate in for unicast frequency hopping. By default, all channels in the channel plan are allowed. The mask can only be used to further restrict the channels. Channels outside the channel plan or channels internally excluded are ignored. This mask will be used in the following connections.

**Deprecated**This function is an alias for [sl_wisun_set_allowed_channel_mask()](sl-wisun-api#sl-wisun-set-allowed-channel-mask). It is maintained for backward compatibility.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_connection_parameters

`sl_status_t sl_wisun_set_connection_parameters(const sl_wisun_connection_params_t *params)`

**Description:** Configure the FFN parameter set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_connection_params_t](sl-wisun-connection-params-t) *|[in]|params|Parameter set to use|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the FFN parameter set. These parameters impact connection time, bandwidth usage, and latency. Use of a predefined parameter set is recommended ([Predefined FFN parameter sets](sl-wisun-ffn-parameter-sets)). Small profile will be used by default for all missing configurations. The function must be called before initiating a connection.

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_set_device_certificate

`sl_status_t sl_wisun_set_device_certificate(uint16_t certificate_options, uint16_t certificate_length, const uint8_t *certificate)`

**Description:** Set the device certificate used to authenticate to the authentication server.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|certificate_options|Options for the certificate.<br/><br/>- [SL_WISUN_CERTIFICATE_OPTION_APPEND](sl-wisun-types#sl-wisun-certificate-option-append): Append the certificate to the list of device certificates instead of replacing the previous entries|
|uint16_t|[in]|certificate_length|Size of the certificate data|
|const uint8_t *|[in]|certificate|Pointer to the certificate data|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the device certificate used during the authentication process. The corresponding device private key must be set using [sl_wisun_set_device_private_key()](sl-wisun-api#sl-wisun-set-device-private-key) or [sl_wisun_set_device_private_key_id()](sl-wisun-api#sl-wisun-set-device-private-key-id). The supported certificate formats depend on application's Mbed TLS configuration. The default configuration supports PEM and DER formats.

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_set_device_private_key

`sl_status_t sl_wisun_set_device_private_key(uint16_t key_options, uint16_t key_length, const uint8_t *key)`

**Description:** Set the device private key used to authenticate to the authentication server.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|key_options|Options for the private key|
|uint16_t|[in]|key_length|Size of the private key data|
|const uint8_t *|[in]|key|Pointer to the private key data|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the device private key used during the authentication process. The corresponding device certificate must be set using [sl_wisun_set_device_certificate()](sl-wisun-api#sl-wisun-set-device-certificate). The supported key formats depend on application's Mbed TLS configuration. The default configuration supports unencrypted PKCS#8 and SEC1 keys in PEM and DER formats.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_device_private_key_id

`sl_status_t sl_wisun_set_device_private_key_id(uint32_t key_id)`

**Description:** Set the device private key used to authenticate to the authentication server.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|key_id|Key ID of the private key|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the device private key using a key identifier, referencing a key stored in PSA cryptography module. The corresponding device certificate must be set using [sl_wisun_set_device_certificate()](sl-wisun-api#sl-wisun-set-device-certificate). The stored key must have correct PSA key attributes, see the Wi-SUN FAN Security Concepts and Design Considerations document for details.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_device_type

`sl_status_t sl_wisun_set_device_type(sl_wisun_device_type_t device_type)`

**Description:** Set the device type (FFN/LFN/BR).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_device_type_t](sl-wisun-types#sl-wisun-device-type-t)|[in]|device_type|Type of the device|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the operational mode of the node.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

**Note**

- This is a no-op with BR, FFN and LFN libraries.

##### sl_wisun_set_dhcpv6_vendor_data

`sl_status_t sl_wisun_set_dhcpv6_vendor_data(uint32_t enterprise_number, const uint8_t *data, uint16_t length)`

**Description:** Set DHCPv6 vendor-specific information data to be inserted in DHCPv6 Solicits.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|enterprise_number|The IANA-assigned Private Enterprise Number identifying the vendor.|
|const uint8_t *|[in]|data|Pointer to the vendor-specific data buffer. To clear any previously set vendor-specific data, set length to 0. According to RFC 3315, the vendor-option-data field MUST be encoded as a sequence of code/length/value fields in big endian with format:<br/><br/>- Code: 2 bytes, vendor-specific option code<br/>- Length: 2 bytes<br/>- Value: variable length corresponding to Length field|
|uint16_t|[in]|length|Length of the vendor-specific data in bytes.|

**Returns**

- SL_STATUS_OK if successful, SL_STATUS_INVALID_PARAMETER if data is NULL while length is non-zero, SL_STATUS_ALLOCATION_FAILED if the stack failed to allocate the necessary memory.

**Note**

- This API does not check the integrity or correctness of the provided vendor data.

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_set_direct_connect_pmk

`sl_status_t sl_wisun_set_direct_connect_pmk(const uint32_t pmk_key_id)`

**Description:** Set the Pairwise Master Key (PMK) to use for Direct Connect.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint32_t|[in]|pmk_key_id|The Pairwise Master Key (PMK) ID to use.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the Direct Connect PMK using a key identifier, referencing a key stored in PSA cryptography module. The stored key must have correct PSA key attributes, see the Wi-SUN FAN Security Concepts and Design Considerations document for details.

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_set_direct_connect_state

`sl_status_t sl_wisun_set_direct_connect_state(bool is_enabled)`

**Description:** Enable/disable Direct Connect.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|is_enabled|Direct Connect status<br/><br/>- **true**: Direct Connect is enabled<br/>- **false**: Direct Connect is disabled|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN (see [API availability](api-availability))

**Note**

- Enabling this feature may increase connection time.

##### sl_wisun_set_eap_identity

`sl_status_t sl_wisun_set_eap_identity(uint8_t identity_length, const uint8_t *identity)`

**Description:** Set EAP identity for authentication.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|identity_length|Length of EAP identity in bytes|
|const uint8_t *|[in]|identity|EAP identity to use|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the identity used in the EAP Identity Response during EAP authentication. The function must be called before initiating a connection. No checks are performed on the identity, the caller is responsible for formatting it correctly. In particular, RFC3748 requires that the identity must not be NULL terminated. If not set, the identity defaults to "Anonymous".

Available in libraries: Full, FFN, LFN (see [API availability](api-availability)) 

##### sl_wisun_set_event_filter

`sl_status_t sl_wisun_set_event_filter(const sl_wisun_mac_address_t *address, uint64_t events)`

**Description:** Set filters for event logger.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|address|MAC address to filter events<br/><br/>- **unicast address**: set the filter for the given MAC address<br/>- **sl_wisun_broadcast_mac**: set the filter for all MAC addresses|
|uint64_t|[in]|events|Bitmask of accepted events.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function configures a filter for the event logger based on the specified MAC address and a bitmask of `sl_wisun_logger_event_type_t` that defines the filtered events. The events are delivered through Silicon Labs’ Event System API[1](https://docs.silabs.com/gecko-platform/5.2.1/platform-common/event-system). To receive them, user must call `sl_event_subscribe` with `SL_EVENT_CLASS_WISUN`. To disable a filter, set the events bitmask to 0. This function can be called at any time.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_fan_tps_version

`sl_status_t sl_wisun_set_fan_tps_version(uint8_t fan_tps_version)`

**Description:** Set the FAN TPS Version.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|fan_tps_version|FAN TPS Version to set|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the FAN TPS Version advertised in PAN Information Element.

- [SL_WISUN_FAN_VERSION_DEFAULT](sl-wisun-types#sl-wisun-fan-version-default): to keep the stack's default FAN TPS version
- [SL_WISUN_FAN_VERSION_1_0](sl-wisun-types#sl-wisun-fan-version-1-0): to force the stack to behave like a FAN 1.0 certified node
- [SL_WISUN_FAN_VERSION_1_1](sl-wisun-types#sl-wisun-fan-version-1-1): to force the stack to behave like a FAN 1.1 certified node

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_ffn_advanced_parameters

`sl_status_t sl_wisun_set_ffn_advanced_parameters(const sl_wisun_ffn_advanced_parameters_t *params)`

**Description:** Set advanced Wi-SUN connection parameters.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_ffn_advanced_parameters_t](sl-wisun-ffn-advanced-parameters-t) *|[in]|params|Pointer to the advanced connection parameters.|

**Returns**

- SL_STATUS_OK on success.
- SL_STATUS_INVALID_STATE if the stack is not in disconnected state, or if [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters) was called previously.
- SL_STATUS_INVALID_PARAMETER if one or more parameters are invalid.

By default, the stack automatically adapts its behavior based on the PAN Size advertised in the Wi-SUN PAN-IE. This automatic adaptation is optimized for use with a Silicon Labs Border Router.

This function overrides that automatic adjustment with explicit values.

When connecting to a non-Silicon Labs Border Router, automatic adaptation may not always provide the desired behavior. In that case, it is recommended to use this function to explicitly set the parameters.

This function and [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters) are mutually exclusive. If [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters) has been called, any subsequent call to this function will fail with SL_STATUS_INVALID_STATE.

This restriction remains in effect even if the stack is later disconnected. To switch back to auto mode and allow this function again, call [sl_wisun_reset_parameters](sl-wisun-api#sl-wisun-reset-parameters).

A later call to [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters) also overrides any overlapping settings previously applied with this function.

This function can be used together with [sl_wisun_set_option](sl-wisun-api#sl-wisun-set-option).

This function can only be called before joining a network, i.e. before calling [sl_wisun_join](sl-wisun-api#sl-wisun-join).

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_set_first_breath

`sl_status_t sl_wisun_set_first_breath(bool enable)`

**Description:** Enable or disable Wi-SUN First Breath on the FFN.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|enable|First Breath state<br/><br/>- **true**: enable First Breath (route/next-hop handling and discovery per First Breath rules)<br/>- **false**: disable First Breath and tear down the associated route|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

When the stack is ready to route datagrams, the event [sl_wisun_msg_fb_ready_ind](sl-wisun-msg-fb-ready-ind-id) is raised to notify the application. On reception of the event, the application needs to use a socket with DSCP set to DSCP_EF to send First Breath data.

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_set_last_gasp

`sl_status_t sl_wisun_set_last_gasp(bool enable)`

**Description:** Configure the Last Gasp mode.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|enable|Enable (true) or disable (false) Last Gasp mode|

**Returns**

- SL_STATUS_OK if successful, SL_STATUS_INVALID_STATE if the stack is not ready

This function configures the Last Gasp mode. It can be called after the Wi-SUN network is joined with enable set to true to activate Last Gasp mode. After a successful call to this function with enable set to true the stack enters low energy mode. If application needs to send Last Gasp data, it needs to use a socket with DSCP set to DSCP_EF. Last Gasp mode can only be enabled once. If it is already enabled, the function returns SL_STATUS_INVALID_STATE. When called with enable set to false, the Last Gasp mode is disabled. The stack returns to normal operation.

Available in libraries: Full, FFN, (see [API availability](api-availability)) 

##### sl_wisun_set_leaf

`sl_status_t sl_wisun_set_leaf(bool is_leaf)`

**Description:** Allow or prevent the node from parenting other nodes.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|is_leaf|RPL leaf mode<br/><br/>- **true**: RPL leaf mode is enabled<br/>- **false**: RPL leaf mode is disabled|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function configures RPL leaf mode on FFNs. When enabled, it prevents the FFN from parenting other nodes (FFN or LFN).

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_set_lfn_advanced_parameters

`sl_status_t sl_wisun_set_lfn_advanced_parameters(const sl_wisun_lfn_advanced_parameters_t *params)`

**Description:** Set advanced Wi-SUN LFN connection parameters.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_lfn_advanced_parameters_t](sl-wisun-lfn-advanced-parameters-t) *|[in]|params|Pointer to the advanced LFN parameters.|

**Returns**

- SL_STATUS_OK on success.
- SL_STATUS_INVALID_STATE if the stack is not in disconnected state, or if [sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters) was called previously.
- SL_STATUS_INVALID_PARAMETER if one or more parameters are invalid.

By default, the stack automatically adapts its behavior based on the PAN Size advertised in the Wi-SUN PAN-IE. This automatic adaptation is optimized for use with a Silicon Labs Border Router.

This function overrides that automatic adjustment with explicit values.

When connecting to a non-Silicon Labs Border Router, automatic adaptation may not always provide the desired behavior. In that case, it is recommended to use this function to explicitly set the parameters.

This function and [sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters) are mutually exclusive. If [sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters) has been called, any subsequent call to this function will fail with SL_STATUS_INVALID_STATE.

This restriction remains in effect even if the stack is later disconnected. To switch back to auto mode and allow this function again, call [sl_wisun_reset_parameters](sl-wisun-api#sl-wisun-reset-parameters).

A later call to [sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters) also overrides any overlapping settings previously applied with this function.

This function can be used together with [sl_wisun_set_option](sl-wisun-api#sl-wisun-set-option).

This function can only be called before joining a network, i.e. before calling [sl_wisun_join](sl-wisun-api#sl-wisun-join).

Available in libraries: Full, LFN (see [API availability](api-availability)) 

##### sl_wisun_set_lfn_parameters

`sl_status_t sl_wisun_set_lfn_parameters(const sl_wisun_lfn_params_t *params)`

**Description:** Configure the LFN parameter set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_lfn_params_t](sl-wisun-lfn-params-t) *|[in]|params|Parameter set to use|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the LFN parameter set. These parameters impact connection time, bandwidth usage, power consumption, and latency. Use of a predefined parameter set is recommended ([Predefined LFN parameter sets](sl-wisun-lfn-parameter-sets)). Test profile will be used by default for all missing configurations. The function must be called before initiating a connection.

Available in libraries: Full, LFN (see [API availability](api-availability)) 

##### sl_wisun_set_lfn_support

`sl_status_t sl_wisun_set_lfn_support(uint8_t lfn_limit)`

**Description:** Configure LFN parenting support.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|lfn_limit|Maximum number of LFN children<br/><br/>- **0**: LFN parenting is disabled in the node<br/>- **> 0**: Maximum number of LFN children the node can parent|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the maximum number of LFN children this node can parent. Set [sl_wisun_config_neighbor_table](sl-wisun-api#sl-wisun-config-neighbor-table) accordingly.

Available in libraries: Full, FFN (see [API availability](api-availability)) 

##### sl_wisun_set_mac_address

`sl_status_t sl_wisun_set_mac_address(const sl_wisun_mac_address_t *address)`

**Description:** Set the device MAC address to be used.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|address|MAC address|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the MAC address for use in the following connections. By default, the device will use the built-in unique device MAC address. The address is reset to the built-in value upon power up.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_mode_switch

`sl_status_t sl_wisun_set_mode_switch(uint8_t mode, uint8_t phy_mode_id, const sl_wisun_mac_address_t *neighbor_address)`

**Description:** Set the PHY mode switch configuration.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|mode|Mode switch configuration of the neighbor. If set to [SL_WISUN_MODE_SWITCH_DEFAULT](sl-wisun-types#sl-wisun-mode-switch-default), the configuration of the neighbor is reset back to the default mode switch behavior.|
|uint8_t|[in]|phy_mode_id|PhyModeId to use when mode is set to [SL_WISUN_MODE_SWITCH_ENABLED](sl-wisun-types#sl-wisun-mode-switch-enabled), ignored otherwise.|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|neighbor_address|MAC address of the neighbor to configure. If set to [sl_wisun_broadcast_mac](sl-wisun-types#sl-wisun-broadcast-mac), configures the default mode switch behavior for all non-configured neighbors.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_neighbor_table_size

`sl_status_t sl_wisun_set_neighbor_table_size(uint8_t size) SL_DEPRECATED_API_SDK_2025_6`

**Description:** Set neighbor table size.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|size|Size of the neighbor table|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the limit of regular neighbors supported by the node [1, 245], without considering temporary or RPL parents. Increasing this parameter means a higher number of potential neighbors while lowering it means reduced RAM consumption. The default value is 22.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

**Deprecated**This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_config_neighbor_table()](sl-wisun-api#sl-wisun-config-neighbor-table) instead.

##### sl_wisun_set_option

`sl_status_t sl_wisun_set_option(sl_wisun_option_id_t id, const void *val, uint16_t val_len)`

**Description:** Set a Wi-SUN option.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_option_id_t](sl-wisun-types#sl-wisun-option-id-t)|[in]|id|Option to set (see [sl_wisun_option_id_t](sl-wisun-types#sl-wisun-option-id-t)).|
|const void *|[in]|val|Pointer to the new value. The stack reads val_len bytes from this address.|
|uint16_t|[in]|val_len|Size in bytes of the value. Must equal the size of the type associated with id.|

**Returns**

- SL_STATUS_OK on success.
- SL_STATUS_INVALID_STATE if the stack state does not allow the option to be set, or if [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters), [sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters), or [sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) has been called previously.
- SL_STATUS_INVALID_PARAMETER if id is not recognized, val_len does not match the expected size for id, or the value is out of the allowed range for that option.

By default, the stack automatically adapts its behavior based on the PAN Size advertised in the Wi-SUN PAN-IE. This automatic adaptation is optimized for use with a Silicon Labs Border Router.

This function is intended for fine-grained configuration of parameters that are not automatically adapted by the stack and therefore remain fixed unless explicitly changed.

This function and [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters)[sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters)[sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) are mutually exclusive. If any of these legacy connection parameters APIs has been called, any subsequent call to this function will fail with SL_STATUS_INVALID_STATE. When using the Full library, this applies regardless of the role the option targets: a previous call to any of the three legacy APIs locks this function out entirely.

This restriction remains in effect even if the stack is later disconnected. To switch back to auto mode and allow this function again, call [sl_wisun_reset_parameters](sl-wisun-api#sl-wisun-reset-parameters).

A later call to [sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters), [sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters), or [sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) also overrides any overlapping settings previously applied with this function.

This function can be used together with [sl_wisun_set_ffn_advanced_parameters](sl-wisun-api#sl-wisun-set-ffn-advanced-parameters)[sl_wisun_set_lfn_advanced_parameters](sl-wisun-api#sl-wisun-set-lfn-advanced-parameters)[sl_wisun_br_set_advanced_parameters](sl-wisun-br-api#sl-wisun-br-set-advanced-parameters)

Most options can only be set before joining a network, i.e. before calling [sl_wisun_join](sl-wisun-api#sl-wisun-join). When this restriction does not apply, it is stated as a note in the individual option ID documentation (see [sl_wisun_option_id_t](sl-wisun-types#sl-wisun-option-id-t)).

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_phy_sensitivity

`sl_status_t sl_wisun_set_phy_sensitivity(uint8_t phy_mode_id, int16_t sensitivity_dbm)`

**Description:** Set the radio sensitivity for the given PHY.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|phy_mode_id|PHY mode ID|
|int16_t|[in]|sensitivity_dbm|Sensitivity in dBm|

**Returns**

- SL_STATUS_OK if successful, SL_STATUS_INVALID_PARAMETER if the PHY mode ID is invalid, SL_STATUS_FULL if you a have already set SL_WISUN_MAX_PHY_MODE_ID_COUNT different entries

This function sets the radio sensitivity for RX state. It allows to fine tune it according to the user's hardware and needs. The stack possesses a set of default values for each PHY mode, but the user can override them with this function. User's modifications generated by this API are not saved in the NVM.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

**Warnings**

- Changing the RX sensitivity can have a significant impact on the network's behavior and performance and should be done with caution. The stack follows the Wi-SUN specification, and as such, takes a margin around the given sensitivity (hysteresis). It is strongly advised to only use this API when using a Low-noise amplifier with an FEM.

##### sl_wisun_set_pom_ie

`sl_status_t sl_wisun_set_pom_ie(uint8_t phy_mode_id_count, uint8_t phy_mode_ids[SL_WISUN_MAX_PHY_MODE_ID_COUNT], uint8_t is_mdr_command_capable)`

**Description:** Configure the list of PHY operating modes the device will use for mode switch operations.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|phy_mode_id_count|Number of PhyModeId to configure. If set to 0, it removes POM-IE and disables mode switch feature.|
|uint8_t|[in]|phy_mode_ids|List of phy_mode_id_count PhyModeId. It must not contain the base operating mode.|
|uint8_t|[in]|is_mdr_command_capable|Indicate if the device supports MAC mode switch. Feature currently unsupported, must be set to 0.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the PHY operating mode information advertised to neighboring nodes. By default the PhyModeId list contains the first fifteen PhyModeId listed in radio multi-PHY configuration, MAC mode switch is disabled.

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_preferred_pan

`sl_status_t sl_wisun_set_preferred_pan(uint16_t pan_id)`

**Description:** Set the preferred PAN for this device.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|pan_id|Preferred PAN ID. Set to 0xFFFF to disable.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets a preferred PAN ID that the device will always select during connection if available, or seek to roam to while connected to another PAN.

**Note**

- Available in libraries: Full, FFN (see [API availability](api-availability))

##### sl_wisun_set_pti_state

`sl_status_t sl_wisun_set_pti_state(bool pti_state)`

**Description:** Enable or disable the Packet Trace Interface (PTI).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|pti_state|PTI state<br/><br/>- **true**: PTI is enabled<br/>- **false**: PTI is disabled|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets Packet Trace Interface (PTI) state. PTI is enabled by default.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_regulation

`sl_status_t sl_wisun_set_regulation(sl_wisun_regulation_t regulation) SL_DEPRECATED_API_SDK_2025_12`

**Description:** Set the regional regulation.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_regulation_t](sl-wisun-types#sl-wisun-regulation-t)|[in]|regulation|Regional regulation|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function applies the appropriate parameter set from [Predefined regional regulation parameter sets](sl-wisun-regulation-parameter-sets) to be used for upcoming connections. The selected regional regulation will impact both the Wi-SUN stack performance and its behavior. See regulation standards for details. No regulation is set by default.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

**Note**

- This function uses a copy of the regulation parameter sets, modifying a predefined set in [sl_wisun_regulation_api.h](sl-wisun-regulation-api-8h-source#sl-wisun-regulation-api-8h-source) will not affect the regulation set used by this function. To change the regulation parameters, use [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters).

**Deprecated**This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters) instead.

##### sl_wisun_set_regulation_parameters

`sl_status_t sl_wisun_set_regulation_parameters(const sl_wisun_regulation_params_t *params)`

**Description:** Configure the regional regulation parameter set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_regulation_params_t](sl-wisun-regulation-params-t) *|[in]|params|Parameter set to use|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_regulation_tx_thresholds

`sl_status_t sl_wisun_set_regulation_tx_thresholds(int8_t warning_threshold, int8_t alert_threshold)`

**Description:** Set the thresholds for transmission duration level event.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int8_t|[in]|warning_threshold|Warning threshold in percent or -1 to disable|
|int8_t|[in]|alert_threshold|Alert threshold in percent or -1 to disable|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the thresholds for transmission duration level event. When set and when a regional regulation is enabled using [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters), a [SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID](sl-wisun-evt#sl-wisun-msg-regulation-tx-level-ind-id) event is sent when one of the configured thresholds is exceeded. This can be used by the application to prevent exceeding the total transmission duration allowed in the regional regulation. Thresholds are defined as a percentage of the maximum transmission duration permitted by the regional regulation.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_rx_fifo_size

`sl_status_t sl_wisun_set_rx_fifo_size(uint16_t size)`

**Description:** Set the radio RX FIFO size.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|size|Size of the RX FIFO in bytes.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the size of the RX FIFO used by the radio driver. The value must be a power of two between 64 and 4096 bytes.

**Note**

- In practice the minimum size for a device to perform authentication is 1024 bytes.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_security_state

`sl_status_t sl_wisun_set_security_state(uint32_t security_state)`

**Description:** Enable or disable authentication and link encryption.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|security_state|Connection security state<br/><br/>- **0**: Authentication and link encryption are disabled<br/>- **1**: Authentication and link encryption are enabled|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the connection security state. By default, authentication and link encryption are enabled. The function is intended for test purposes.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

**Note**

- Authentication and link encryption can only be disabled when the application is linked against a library supporting this option.

##### sl_wisun_set_trusted_certificate

`sl_status_t sl_wisun_set_trusted_certificate(uint16_t certificate_options, uint16_t certificate_length, const uint8_t *certificate)`

**Description:** Set a trusted CA certificate used to validate the authentication server certificate.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|certificate_options|Options for the certificate<br/><br/>- [SL_WISUN_CERTIFICATE_OPTION_APPEND](sl-wisun-types#sl-wisun-certificate-option-append): Append the certificate to the list of trusted certificates instead of replacing the previous entries|
|uint16_t|[in]|certificate_length|Size of the certificate data|
|const uint8_t *|[in]|certificate|Pointer to the certificate data|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets a trusted CA certificate for validiting the authentication server certificate during the authentication process. The supported certificate formats depend on application's Mbed TLS configuration. The default configuration supports PEM and DER formats. When PEM is used, the certificate data may contain multiple concatenated certificates.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

##### sl_wisun_set_tx_power

`sl_status_t sl_wisun_set_tx_power(int8_t tx_power) SL_DEPRECATED_API_SDK_2024_6`

**Description:** Set the maximum TX power.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int8_t|[in]|tx_power|TX power in dBm|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the maximum TX power. The device may use a lower value based on internal decision making or hardware limitations but will never exceed the given value. The function must be called before initiating a connection.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability)) 

**Deprecated**This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_set_tx_power_ddbm()](sl-wisun-api#sl-wisun-set-tx-power-ddbm) instead.

##### sl_wisun_set_tx_power_ddbm

`sl_status_t sl_wisun_set_tx_power_ddbm(int16_t tx_power_ddbm)`

**Description:** Set the maximum TX power.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int16_t|[in]|tx_power_ddbm|TX power in deci-dBm|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the maximum TX power. The device may use a lower value based on internal decision making or hardware limitations but will never exceed the given value. The function must be called before initiating a connection.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

**Note**

- When replacing [sl_wisun_set_tx_power()](sl-wisun-api#sl-wisun-set-tx-power) function calls with this function, note the change from dBm units to deci-dBm units.

##### sl_wisun_set_unicast_settings

`sl_status_t sl_wisun_set_unicast_settings(uint8_t dwell_interval_ms)`

**Description:** Set the unicast dwell interval (ms) used for channel hopping.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|dwell_interval_ms|Unicast Dwell Interval (15-255 ms)|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the parameters for unicast channel hopping to be used in the following connections. The Unicast Dwell Interval specifies the duration which the node will listen to a channel within its listening schedule. The default value is 255 ms.

Available in libraries: Full, FFN, BR (see [API availability](api-availability)) 

##### sl_wisun_start_direct_connect_client

`sl_status_t sl_wisun_start_direct_connect_client(const sl_wisun_phy_config_t *phy)`

**Description:** Initialize the Direct Connect (DC) client.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_phy_config_t](sl-wisun-phy-config-t) *|[in]|phy|Pointer to the PHY configuration ([sl_wisun_phy_config_t](sl-wisun-phy-config-t)). Supported types: [SL_WISUN_PHY_CONFIG_FAN10](sl-wisun-types#sl-wisun-phy-config-fan10), [SL_WISUN_PHY_CONFIG_FAN11](sl-wisun-types#sl-wisun-phy-config-fan11), or [SL_WISUN_PHY_CONFIG_EXPLICIT](sl-wisun-types#sl-wisun-phy-config-explicit). Must match the DC server configuration.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise.

This function configures and starts the Direct Connect client, enabling point-to-point communication with a DC server. The DC client provides low-latency, single-hop connectivity that can operate standalone or alongside a Wi-SUN mesh network connection.

Upon success, the DC client enters an idle state, ready to perform discovery scans via [sl_wisun_start_direct_connect_scan()](sl-wisun-api#sl-wisun-start-direct-connect-scan) or establish connections via [sl_wisun_connect_to_direct_connect_server()](sl-wisun-api#sl-wisun-connect-to-direct-connect-server). State changes are reported via [SL_WISUN_MSG_DIRECT_CONNECT_CLIENT_STATE_CHANGED_IND_ID](sl-wisun-evt#sl-wisun-msg-direct-connect-client-state-changed-ind-id) events.

Security credentials (PMK) should be configured via [sl_wisun_set_direct_connect_pmk()](sl-wisun-api#sl-wisun-set-direct-connect-pmk).

**Note**

- The behavior depends on when this function is called relative to [sl_wisun_join()](sl-wisun-api#sl-wisun-join):  
  - DC-only mode (called before [sl_wisun_join()](sl-wisun-api#sl-wisun-join)): The stack operates exclusively in DC client mode. [sl_wisun_join()](sl-wisun-api#sl-wisun-join) is blocked until [sl_wisun_stop_direct_connect_client()](sl-wisun-api#sl-wisun-stop-direct-connect-client) is called.  
  - Concurrent mode (called after [sl_wisun_join()](sl-wisun-api#sl-wisun-join)): The DC client operates alongside the Wi-SUN network (whether join is complete or in progress). This enables use cases such as debugging devices that cannot join the mesh by reaching them via DC link.

Available in libraries: Full, FFN (see [API availability](api-availability)). 

##### sl_wisun_start_direct_connect_scan

`sl_status_t sl_wisun_start_direct_connect_scan(const sl_wisun_dc_id_t *dc_id, uint8_t max_solicits_count)`

**Description:** Start a Direct Connect client discovery scan.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_dc_id_t](sl-wisun-dc-id-t) *|[in]|dc_id|Pointer to the application-defined Direct Connect ID (see [sl_wisun_dc_id_t](sl-wisun-dc-id-t)).|
|uint8_t|[in]|max_solicits_count|Max solicitation sequences; if 0, the scan is persistent.|

Client starts to transmit Direct Connect identity solicitation frames using `dc_id` up to `max_solicits_count` sequences. Matching servers reply with Direct Connect identification frames (DCI). Scanning runs independently of connection state (idle / connecting / connected).

**Returns**

- SL_STATUS_OK on success; error code otherwise.

**Note**

- The application interprets/validates server identifiers and may call [sl_wisun_connect_to_direct_connect_server()](sl-wisun-api#sl-wisun-connect-to-direct-connect-server) at any time to switch targets. The application must call [sl_wisun_stop_direct_connect_scan()](sl-wisun-api#sl-wisun-stop-direct-connect-scan) to stop the scan when the current scan is no longer needed or need to scan for a different DC ID.

Available in libraries: Full, FFN (see [API availability](api-availability)). 

##### sl_wisun_stop_direct_connect_client

`sl_status_t sl_wisun_stop_direct_connect_client(void)`

**Description:** Stop the Direct Connect client.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Immediately ends any ongoing scan and aborts any ongoing or active connection. After return, the client is idle.

**Returns**

- SL_STATUS_OK if stopped or already idle; error code otherwise.

Available in libraries: Full, FFN (see [API availability](api-availability)). 

##### sl_wisun_stop_direct_connect_scan

`sl_status_t sl_wisun_stop_direct_connect_scan(void)`

**Description:** Stop an ongoing Direct Connect client discovery scan.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

Immediately stops the Direct Connect client from transmitting Direct Connect identity solicitations. This does not affect connection establishment or an already established Direct Connect link.

**Returns**

- SL_STATUS_OK if stopped or not scanning; error code otherwise.

Available in libraries: Full, FFN (see [API availability](api-availability)). 

##### sl_wisun_trigger_frame

`sl_status_t sl_wisun_trigger_frame(sl_wisun_frame_type_t frame_type)`

**Description:** Trigger a transmission of a periodic frame (FAN Discovery, RPL).

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_frame_type_t](sl-wisun-types#sl-wisun-frame-type-t)|[in]|frame_type|Type of frame to transmit<br/><br/>- [SL_WISUN_FRAME_TYPE_PAS](sl-wisun-types#sl-wisun-frame-type-pas): Transmit a PAN Advertisement Solicit frame<br/>- [SL_WISUN_FRAME_TYPE_PA](sl-wisun-types#sl-wisun-frame-type-pa): Transmit a PAN Advertisement frame<br/>- [SL_WISUN_FRAME_TYPE_PCS](sl-wisun-types#sl-wisun-frame-type-pcs): Transmit a PAN Configuration Solicit frame<br/>- [SL_WISUN_FRAME_TYPE_PC](sl-wisun-types#sl-wisun-frame-type-pc): Transmit a PAN Configuration frame<br/>- [SL_WISUN_FRAME_TYPE_DIS](sl-wisun-types#sl-wisun-frame-type-dis): Transmit a DODAG Information Solicitation frame<br/>- [SL_WISUN_FRAME_TYPE_DIO](sl-wisun-types#sl-wisun-frame-type-dio): Transmit a DODAG Information Object frame<br/>- [SL_WISUN_FRAME_TYPE_LPAS](sl-wisun-types#sl-wisun-frame-type-lpas): Transmit a LFN PAN Advertisement Solicit frame|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function causes a periodic frame (FAN Discovery, RPL) to be transmitted immediately. The frame can only be transmitted in the appropriate connection state, i.e. the associated trickle timer must be running. The function is intended for test purposes.

Available in libraries: Full, FFN, LFN, BR (see [API availability](api-availability))

#### API availability

Availability of Wi-SUN API capabilities depends on the library used by the application:

- FFN library contains Full Function Node capability. This library also includes LFN parenting ability for FAN1.1.
- LFN library contains Limited Function Node capability.
- Full library contains both of the above. This larger but more flexible library is provided as a convenience for prototyping. This library allows to choose between FFN and LFN role at runtime, but does not support switching roles on the fly and requires a full board reset to do so.
- BR library contains Border Router functionality.
- DC Client library is a minimal stack limited to Direct Connect client capability, supporting the subset of APIs listed in the table below.
- DC Client plugin library is an add-on that extends the FFN or Full library with Direct Connect client capabilities.

The libraries are selected using Simplicity SDK components:

- FFN library when only wisun_stack_ffn component is selected.
- LFN library when only wisun_stack_lfn component is selected.
- Full library when both components are selected.
- FFN library by default when no component is selected.
- BR library when wisun_br_stack component is selected. This library cannot be combined with the other libraries.
- DC Client library when the wisun_stack_dc_client component is selected without the wisun_stack_ffn component.
- DC Client plugin library when the wisun_stack_dc_client component is selected together with the wisun_stack_ffn component.

The API available to each library may vary according to the table below. A status SL_STATUS_NOT_AVAILABLE is returned if the API called with a library flavor that does not support it.

|API Name|Full|FFN|LFN|BR|DC Client|
|---|---|---|---|---|---|
|[sl_wisun_join](sl-wisun-api#sl-wisun-join)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_ip_address](sl-wisun-api#sl-wisun-get-ip-address)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_disconnect](sl-wisun-api#sl-wisun-disconnect)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_trusted_certificate](sl-wisun-api#sl-wisun-set-trusted-certificate)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_device_certificate](sl-wisun-api#sl-wisun-set-device-certificate)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_device_private_key](sl-wisun-api#sl-wisun-set-device-private-key)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_statistics](sl-wisun-api#sl-wisun-get-statistics)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_tx_power](sl-wisun-api#sl-wisun-set-tx-power)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_allowed_channel_mask](sl-wisun-api#sl-wisun-set-allowed-channel-mask)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_channel_mask](sl-wisun-api#sl-wisun-set-channel-mask)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_allow_mac_address](sl-wisun-api#sl-wisun-allow-mac-address)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_deny_mac_address](sl-wisun-api#sl-wisun-deny-mac-address)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_get_join_state](sl-wisun-api#sl-wisun-get-join-state)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_clear_credential_cache](sl-wisun-api#sl-wisun-clear-credential-cache)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_get_mac_address](sl-wisun-api#sl-wisun-get-mac-address)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_mac_address](sl-wisun-api#sl-wisun-set-mac-address)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_reset_statistics](sl-wisun-api#sl-wisun-reset-statistics)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_get_neighbor_count](sl-wisun-api#sl-wisun-get-neighbor-count)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_neighbors](sl-wisun-api#sl-wisun-get-neighbors)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_neighbor_info](sl-wisun-api#sl-wisun-get-neighbor-info)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_unicast_settings](sl-wisun-api#sl-wisun-set-unicast-settings)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_device_private_key_id](sl-wisun-api#sl-wisun-set-device-private-key-id)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_regulation](sl-wisun-api#sl-wisun-set-regulation)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_regulation_parameters](sl-wisun-api#sl-wisun-set-regulation-parameters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_reset_regulation_duty_cycle](sl-wisun-api#sl-wisun-reset-regulation-duty-cycle)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_config_neighbor_table](sl-wisun-api#sl-wisun-config-neighbor-table)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_regulation_tx_thresholds](sl-wisun-api#sl-wisun-set-regulation-tx-thresholds)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_advert_fragment_duration](sl-wisun-api#sl-wisun-set-advert-fragment-duration)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_device_type](sl-wisun-api#sl-wisun-set-device-type)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_config_mode_switch](sl-wisun-api#sl-wisun-config-mode-switch)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_mode_switch](sl-wisun-api#sl-wisun-set-mode-switch)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_option](sl-wisun-api#sl-wisun-set-option)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_connection_parameters](sl-wisun-api#sl-wisun-set-connection-parameters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_ffn_advanced_parameters](sl-wisun-api#sl-wisun-set-ffn-advanced-parameters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_reset_parameters](sl-wisun-api#sl-wisun-reset-parameters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_pom_ie](sl-wisun-api#sl-wisun-set-pom-ie)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_pom_ie](sl-wisun-api#sl-wisun-get-pom-ie)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_stack_version](sl-wisun-api#sl-wisun-get-stack-version)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_lfn_parameters](sl-wisun-api#sl-wisun-set-lfn-parameters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_lfn_advanced_parameters](sl-wisun-api#sl-wisun-set-lfn-advanced-parameters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_lfn_support](sl-wisun-api#sl-wisun-set-lfn-support)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_pti_state](sl-wisun-api#sl-wisun-set-pti-state)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_trigger_frame](sl-wisun-api#sl-wisun-trigger-frame)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_security_state](sl-wisun-api#sl-wisun-set-security-state)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_get_network_info](sl-wisun-api#sl-wisun-get-network-info)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_rpl_info](sl-wisun-api#sl-wisun-get-rpl-info)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_get_excluded_channel_mask](sl-wisun-api#sl-wisun-get-excluded-channel-mask)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_tx_power_ddbm](sl-wisun-api#sl-wisun-set-tx-power-ddbm)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_leaf](sl-wisun-api#sl-wisun-set-leaf)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_direct_connect_state](sl-wisun-api#sl-wisun-set-direct-connect-state)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_accept_direct_connect_link](sl-wisun-api#sl-wisun-accept-direct-connect-link)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_direct_connect_pmk](sl-wisun-api#sl-wisun-set-direct-connect-pmk)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_advert_direct_connect_server_id](sl-wisun-api#sl-wisun-advert-direct-connect-server-id)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_start_direct_connect_client](sl-wisun-api#sl-wisun-start-direct-connect-client)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_stop_direct_connect_client](sl-wisun-api#sl-wisun-stop-direct-connect-client)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_start_direct_connect_scan](sl-wisun-api#sl-wisun-start-direct-connect-scan)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_stop_direct_connect_scan](sl-wisun-api#sl-wisun-stop-direct-connect-scan)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_connect_to_direct_connect_server](sl-wisun-api#sl-wisun-connect-to-direct-connect-server)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_phy_sensitivity](sl-wisun-api#sl-wisun-set-phy-sensitivity)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_preferred_pan](sl-wisun-api#sl-wisun-set-preferred-pan)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_config_concurrent_detection](sl-wisun-api#sl-wisun-config-concurrent-detection)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_eap_identity](sl-wisun-api#sl-wisun-set-eap-identity)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_event_filter](sl-wisun-api#sl-wisun-set-event-filter)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_clear_event_filters](sl-wisun-api#sl-wisun-clear-event-filters)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_rx_fifo_size](sl-wisun-api#sl-wisun-set-rx-fifo-size)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_fan_tps_version](sl-wisun-api#sl-wisun-set-fan-tps-version)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|
|[sl_wisun_set_dhcpv6_vendor_data](sl-wisun-api#sl-wisun-set-dhcpv6-vendor-data)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_last_gasp](sl-wisun-api#sl-wisun-set-last-gasp)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_set_first_breath](sl-wisun-api#sl-wisun-set-first-breath)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_start](sl-wisun-br-api#sl-wisun-br-start)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_stop](sl-wisun-br-api#sl-wisun-br-stop)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_gtk](sl-wisun-br-api#sl-wisun-br-set-gtk)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_network_size](sl-wisun-br-api#sl-wisun-br-set-network-size)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_get_ip_addresses](sl-wisun-br-api#sl-wisun-br-get-ip-addresses)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_get_gak](sl-wisun-br-api#sl-wisun-br-get-gak)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_get_state](sl-wisun-br-api#sl-wisun-br-get-state)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_device_certificate](sl-wisun-br-api#sl-wisun-br-set-device-certificate)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_broadcast_settings](sl-wisun-br-api#sl-wisun-br-set-broadcast-settings)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_advanced_parameters](sl-wisun-br-api#sl-wisun-br-set-advanced-parameters)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_lfn_parameters](sl-wisun-br-api#sl-wisun-br-set-lfn-parameters)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_lfn_support](sl-wisun-br-api#sl-wisun-br-set-lfn-support)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_pan_defect_advertise](sl-wisun-br-api#sl-wisun-br-pan-defect-advertise)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_ipv6_prefix](sl-wisun-br-api#sl-wisun-br-set-ipv6-prefix)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_set_ipv6_up_handler](sl-wisun-br-api#sl-wisun-br-set-ipv6-up-handler)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_ipv6_down](sl-wisun-br-api#sl-wisun-br-ipv6-down)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_ipv6_route_exists](sl-wisun-br-api#sl-wisun-br-ipv6-route-exists)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_trigger_global_repair](sl-wisun-br-api#sl-wisun-br-trigger-global-repair)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_get_routing_table_entry_count](sl-wisun-br-api#sl-wisun-br-get-routing-table-entry-count)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_get_routing_table](sl-wisun-br-api#sl-wisun-br-get-routing-table)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_revoke_pairwise_keys](sl-wisun-br-api#sl-wisun-br-revoke-pairwise-keys)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|
|[sl_wisun_br_revoke_gtks](sl-wisun-br-api#sl-wisun-br-revoke-gtks)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|![Checkmark](/wisun-stack-api/2.12.0/images/checkmark.png)|![Red X](/wisun-stack-api/2.12.0/images/red-x.png)|

#### Border Router API

Wi-SUN Border Router API contains functions for Border Router specific functionality. 

The API is an extension, not a replacement of [Wi-SUN Stack API](sl-wisun-api). An application implementing Border Router capability may utilize functions from both APIs. See [API availability](api-availability) for further information. 

##### Functions

###### sl_wisun_br_get_gak

`sl_status_t sl_wisun_br_get_gak(uint8_t index, uint8_t *gak)`

**Description:** Get Group AES Key.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|index|Index of the key from 0 to 3 for GAKs and 4 to 6 for LFN GAKs|
|uint8_t *|[out]|gak|Pointer to Group AES Key|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function exports (L)GAK as a plaintext key.

**Note**

- This functionality is only available when using the debug library.

###### sl_wisun_br_get_ip_addresses

`sl_status_t sl_wisun_br_get_ip_addresses(uint8_t *addr_ll, uint8_t *addr_gua, uint8_t *addr_dodagid)`

**Description:** Get the unicast IPv6 addresses configured in the Border Router.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t *|[out]|addr_ll|Pointer to Link-Local address|
|uint8_t *|[out]|addr_gua|Pointer to Unique Local Address or Global Unicast Address|
|uint8_t *|[out]|addr_dodagid|Pointer to DODAG ID|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_br_get_routing_table

`sl_status_t sl_wisun_br_get_routing_table(uint16_t *entry_count, sl_wisun_br_routing_table_entry_t *table)`

**Description:** Get the Routing Table.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[inout]|entry_count|Maximum number of entries to read on input, number of entries read on output|
|[sl_wisun_br_routing_table_entry_t](sl-wisun-br-routing-table-entry-t) *|[out]|table|Pointer to the application allocated memory where the routing table is written|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

The routing table is unordered and only contains the parent-child relationship between the nodes. The table is in the format: | Node GUA/ULA 16 bytes | parent GUA/ULA 16 bytes |

**Note**

- This function should be called after [sl_wisun_br_get_routing_table_entry_count()](sl-wisun-br-api#sl-wisun-br-get-routing-table-entry-count) to get the number of entries in the routing table.

###### sl_wisun_br_get_routing_table_entry_count

`sl_status_t sl_wisun_br_get_routing_table_entry_count(uint16_t *entry_count)`

**Description:** Get the Routing Table Size.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t *|[out]|entry_count|Number of entries in the routing table|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function retrieves the number of entries in the routing table. This allows for allocation before calling [sl_wisun_br_get_routing_table()](sl-wisun-br-api#sl-wisun-br-get-routing-table). The allocated memory should be at least equal to: sizeof(sl_wisun_br_routing_table_entry_t) * entry_count. 

###### sl_wisun_br_get_routing_table_from_index

`sl_status_t sl_wisun_br_get_routing_table_from_index(uint16_t start_index, uint16_t *entry_count, sl_wisun_br_routing_table_entry_t *entries)`

**Description:** Get the Routing Table starting from a specific index.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|start_index|Index to start reading the routing table from|
|uint16_t *|[inout]|entry_count|Maximum number of entries to read on input, number of entries read on output|
|[sl_wisun_br_routing_table_entry_t](sl-wisun-br-routing-table-entry-t) *|[out]|entries|Pointer to the application allocated memory where the routing table is written|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function retrieves **entry_count** entries from the routing table, starting from a specific index. This allows the caller to get any number of entries from the routing table without having to allocate a large buffer. The allocated memory should be at least equal to: sizeof(sl_wisun_br_routing_table_entry_t) * entry_count.

**Note**

- This function should be called after [sl_wisun_br_get_routing_table_entry_count()](sl-wisun-br-api#sl-wisun-br-get-routing-table-entry-count) to get the number of entries in the routing table.

**Warnings**

- If the application does not retrieve the entire routing table in a single read, it may miss updates or changes in the network topology.

###### sl_wisun_br_get_state

`sl_status_t sl_wisun_br_get_state(sl_wisun_br_state_t *state)`

**Description:** Get the Border Router state.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_br_state_t](sl-wisun-types#sl-wisun-br-state-t) *|[out]|state|Pointer to state<br/><br/>- [SL_WISUN_BR_STATE_INITIALIZED](sl-wisun-types#sl-wisun-br-state-initialized): ready to start<br/>- [SL_WISUN_BR_STATE_OPERATIONAL](sl-wisun-types#sl-wisun-br-state-operational): started|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_br_ipv6_down

`sl_status_t sl_wisun_br_ipv6_down(const uint8_t *data, size_t data_length)`

**Description:** Forward an IPv6 packet to Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|data|Pointer to IPv6 header|
|size_t|[out]|data_length|Length of IPv6 packet data in bytes|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function forwards an IPv6 packet to Wi-SUN network. The destination address must belong to the DODAG prefix. This function is used for handling downlink packets from the backhaul interface, see [sl_wisun_br_set_ipv6_up_handler()](sl-wisun-br-api#sl-wisun-br-set-ipv6-up-handler) for uplink. It's recommended to use [sl_wisun_br_ipv6_route_exists()](sl-wisun-br-api#sl-wisun-br-ipv6-route-exists) before forwarding a packet. 

###### sl_wisun_br_ipv6_route_exists

`sl_status_t sl_wisun_br_ipv6_route_exists(const uint8_t *ipv6_address, bool *exists)`

**Description:** Check if the IPv6 destination address is routable in the Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|ipv6_address|Pointer to IPv6 destination address|
|bool *|[out]|exists|Whether the address is routable<br/><br/>- **true**: address is routable<br/>- **false**: address is not routable|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function checks if the given IPv6 address is a valid destination in the Wi-SUN network. The destination address must belong to the Border Router or one of the connected nodes. 

###### sl_wisun_br_pan_defect_advertise

`sl_status_t sl_wisun_br_pan_defect_advertise(bool defect_advertise, uint32_t min_scan_duration_s, uint32_t max_scan_duration_s)`

**Description:** Start or stop PAN Defect advertisement.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|defect_advertise|True to start PAN Defect procedure, false to stop it.|
|uint32_t|[in]|min_scan_duration_s|Minimum duration after which devices are allowed to switch their PAN if an alternative one is available.|
|uint32_t|[in]|max_scan_duration_s|Duration after which devices should systemically switch to the alternative PAN if one is available.|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise.

**Note**

- The values for `min_scan_duration_s` and `max_scan_duration_s` should be chosen based on the estimated performance of the backup power source. Specifically, `max_scan_duration_s` should be set to a value smaller than the estimated lifetime of the backup power source to ensure a seamless transition to the alternative PAN without long connection interruptions.

###### sl_wisun_br_revoke_gtks

`sl_status_t sl_wisun_br_revoke_gtks(bool revoke_lgtks, const uint8_t *gtk)`

**Description:** Revoke (LFN) Group Transient Keys and installs a new key.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|bool|[in]|revoke_lgtks|True to revoke LGTKs, false to revoke GTKs|
|const uint8_t *|[in]|gtk|(LFN) Group Transient Key|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Destroy all (L)GTKs except the current active one (and potentially the next key), reduce the current (or next) key's lifetime, and add a new key, as described in the Wi-SUN FAN specification section 6.5.2.5.

**Note**

- The gtk parameter is provided for test and debug purposes: setting a specific key in production is not recommended. Set to NULL to generate a random key.

###### sl_wisun_br_revoke_pairwise_keys

`sl_status_t sl_wisun_br_revoke_pairwise_keys(const sl_wisun_mac_address_t *address)`

**Description:** Remove pairwise keys associated with a node.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_mac_address_t](sl-wisun-mac-address-t) *|[in]|address|EUI-64 of the target node|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

Remove the Pairwise Transient Key (PTK) and Pairwise Master Key (PMK) associated with a node as described in the Wi-SUN FAN specification section 6.5.2.5.

**Note**

- To permanently revoke access to the node, its certificate must be banned at the authentication authority (e.g. RADIUS server).

###### sl_wisun_br_set_advanced_parameters

`sl_status_t sl_wisun_br_set_advanced_parameters(const sl_wisun_br_advanced_parameters_t *params)`

**Description:** Set advanced Border Router connection parameters.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_br_advanced_parameters_t](sl-wisun-br-advanced-parameters-t) *|[in]|params|Pointer to the advanced parameter structure|

**Returns**

- SL_STATUS_OK on success.
- SL_STATUS_INVALID_STATE if the border router is started, or if [sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) has been called previously.
- SL_STATUS_INVALID_PARAMETER if one or more parameters are invalid.

By default, the stack automatically adapts its behavior based on the PAN Size advertised in the Wi-SUN PAN-IE.

This function overrides that automatic adjustment with explicit values.

This function and [sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) are mutually exclusive. If [sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) has been called, any subsequent call to this function will fail with SL_STATUS_INVALID_STATE.

This restriction remains in effect even if the border router is later stopped. To switch back to auto mode and allow this function again, call [sl_wisun_reset_parameters](sl-wisun-api#sl-wisun-reset-parameters).

A later call to [sl_wisun_br_set_connection_parameters](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) also overrides any overlapping settings previously applied with this function.

This function can be used together with [sl_wisun_set_option](sl-wisun-api#sl-wisun-set-option).

This function must be called before starting the border router. 

###### sl_wisun_br_set_broadcast_settings

`sl_status_t sl_wisun_br_set_broadcast_settings(uint32_t interval_ms, uint8_t dwell_interval_ms)`

**Description:** Set broadcast settings.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint32_t|[in]|interval_ms|Broadcast Interval (BDI < BI <= 16777215 ms) (default: 1020 ms)|
|uint8_t|[in]|dwell_interval_ms|Broadcast Dwell Interval (100-255 ms) (default: 255 ms)|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the broadcast channel hopping schedule. The Broadcast Interval is the duration, between Broadcast Dwell Intervals within the advertising node’s broadcast schedule. Its resolution is limited to 24 bits (16777215 ms). The Broadcast Dwell Interval specifies the duration during which the node may transmit a broadcast message. It is recommended a BI value of 4.0 times the maximum of (UDI, BDI). These values affect the whole PAN, since they are propagated from parent to children. This function must be called before starting the Border Router. 

###### sl_wisun_br_set_connection_parameters

`sl_status_t sl_wisun_br_set_connection_parameters(const sl_wisun_br_connection_params_t *params)`

**Description:** Configure the Border Router parameter set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_br_connection_params_t](sl-wisun-br-connection-params-t) *|[in]|params|Parameter set to use|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This functions sets the Border Router parameter set. These parameters impact connection time, bandwidth usage, and latency. Use of a predefined parameter set is recommended ([Predefined BR parameter sets](sl-wisun-br-parameter-sets)). Small profile will be used by default for all missing configurations. This function must be called before starting the Border Router. 

###### sl_wisun_br_set_device_certificate

`sl_status_t sl_wisun_br_set_device_certificate(uint16_t certificate_options, uint16_t certificate_length, const uint8_t *certificate)`

**Description:** Set the Border Router device certificate.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint16_t|[in]|certificate_options|Options for the certificate. <br />**SL_WISUN_CERTIFICATE_OPTION_APPEND**: Append the certificate to the list of server certificates instead of replacing the previous entries|
|uint16_t|[in]|certificate_length|Size of the certificate data|
|const uint8_t *|[in]|certificate|Pointer to the certificate data|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_br_set_gtk

`sl_status_t sl_wisun_br_set_gtk(const uint8_t *gtk, uint8_t index)`

**Description:** Set Group Transient Key.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|gtk|Group Transient Key|
|uint8_t|[in]|index|Index of the key from 0 to 3 for GTKs and 4 to 6 for LGTKs|

**Note**

- This API is provided for test and debug purposes: setting a specific key in production is not recommended. The keys set using this API are saved to NVM, and subsequent calls to this API are ignored until the NVM is cleared using [sl_wisun_clear_credential_cache](sl-wisun-api#sl-wisun-clear-credential-cache).

**Returns**

- SL_STATUS_OK if successful, SL_STATUS_ALREADY_EXISTS when ignored, an error code otherwise

###### sl_wisun_br_set_ipv6_prefix

`sl_status_t sl_wisun_br_set_ipv6_prefix(const uint8_t *ipv6_prefix, uint8_t prefix_length)`

**Description:** Set IPv6 prefix for the Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|ipv6_prefix|IPv6 prefix|
|uint8_t|[in]|prefix_length|Prefix length. Currently, only 64 bit prefixes are supported.|

**Note**

- Must not be called after the border router is started

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the prefix used to generate IP addresses for RPL traffic (DODAGID will derive from it). This function must be called before starting the Border Router. 

###### sl_wisun_br_set_ipv6_up_handler

`sl_status_t sl_wisun_br_set_ipv6_up_handler(sl_wisun_ipv6_up_handler_t handler)`

**Description:** Register a function to handle IPv6 packets received from Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_ipv6_up_handler_t](sl-wisun-types#sl-wisun-ipv6-up-handler-t)|[in]|handler|Pointer to handler function|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function registers a handler function that will be called when the destination address of a received IPv6 packet is outside the DODAG prefix. Setting the handler function to NULL disables the forwarding. This function is used for handling uplink packets towards the backhaul interface, see [sl_wisun_br_ipv6_down()](sl-wisun-br-api#sl-wisun-br-ipv6-down) for downlink. 

###### sl_wisun_br_set_lfn_parameters

`sl_status_t sl_wisun_br_set_lfn_parameters(const sl_wisun_br_lfn_params_t *params)`

**Description:** Configure LFN parenting parameter set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const [sl_wisun_br_lfn_params_t](sl-wisun-br-lfn-params-t) *|[in]|params|Parameter set to use|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the LFN parenting parameter set. These parameters impact battery life of all LFNs in the PAN. Use of a predefined parameter set is recommended ([Predefined BR LFN-parenting parameter sets](sl-wisun-br-lfn-parameter-sets)). This function must be called before starting the Border Router. 

###### sl_wisun_br_set_lfn_support

`sl_status_t sl_wisun_br_set_lfn_support(uint8_t lfn_limit, bool lfn_support_pan)`

**Description:** Configure LFN parenting support.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|uint8_t|[in]|lfn_limit|Maximum number of LFN children<br/><br/>- **0**: LFN parenting is disabled in the Border Router<br/>- **> 0**: Maximum number of LFN children the Border Router can parent|
|bool|[in]|lfn_support_pan|LFN parenting support in the PAN<br/><br/>- **true**: LFN parenting is enabled in the PAN<br/>- **false**: LFN parenting is disabled in the PAN|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function configures LFN parenting support in the Border Router and in the PAN. Set [sl_wisun_config_neighbor_table](sl-wisun-api#sl-wisun-config-neighbor-table) accordingly. 

###### sl_wisun_br_set_network_size

`sl_status_t sl_wisun_br_set_network_size(sl_wisun_network_size_t size) SL_DEPRECATED_API_SDK_2026_6`

**Description:** Set the size of the Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|[sl_wisun_network_size_t](sl-wisun-types#sl-wisun-network-size-t)|[in]|size|Size of the network <br />**SL_WISUN_NETWORK_SIZE_AUTOMATIC**: network size is managed automatically <br />**SL_WISUN_NETWORK_SIZE_SMALL**: less than 100 nodes <br />**SL_WISUN_NETWORK_SIZE_MEDIUM**: 100 to 800 nodes <br />**SL_WISUN_NETWORK_SIZE_LARGE**: 800 to 1500 nodes|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

This function sets the size of the network. The size is used to set various stack parameters, such as timing parameters to optimize device behavior in regards to node count. The device will function with any setting but may exhibit non-optimal behavior. Setting the size too large may cause slow connection speed and increased latency. Conversely, a value too small may cause increased network traffic.

**Deprecated**This function will be removed in the future versions of the Wi-SUN stack, use [sl_wisun_br_set_connection_parameters()](sl-wisun-br-api#sl-wisun-br-set-connection-parameters) instead.

###### sl_wisun_br_start

`sl_status_t sl_wisun_br_start(const uint8_t *name, const sl_wisun_phy_config_t *phy_config)`

**Description:** Start the Border Router.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const uint8_t *|[in]|name|Name of the Wi-SUN network as a zero-terminated string|
|const [sl_wisun_phy_config_t](sl-wisun-phy-config-t) *|[in]|phy_config|Pointer to PHY configuration|

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_br_stop

`sl_status_t sl_wisun_br_stop(void)`

**Description:** Stop the Border Router.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_br_trigger_global_repair

`sl_status_t sl_wisun_br_trigger_global_repair(void)`

**Description:** Trigger a global repair process from the Border Router.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

**Returns**

- SL_STATUS_OK if successful SL_STATUS_NOT_READY if the Border Router is not started SL_STATUS_FAIL if the DODAG Version is not incremented

Increments the RPL DODAG Version to allow nodes in the network to choose a new position whose rank is not constrained by their rank within the old DODAG Version. The new DODAG Version is propagated through DIOs in the entire network and will cause all nodes to re-run a parent selection within the new DODAG Version, effectively temporarily disconnecting them from the network.

**Note**

- This operation will disrupt network communications as the repair process is carried out. It is not recommended to trigger a global repair more often than once every 24 hours.

##### Macros

`#define sl_wisun_set_br_device_certificate sl_wisun_br_set_device_certificate`

**Description**: Define sl_wisun_set_br_device_certificate for legacy.

#### API events

##### Modules

[sl_wisun_evt_t](sl-wisun-evt-t)

[sl_wisun_msg_connected_ind](sl-wisun-msg-connected-ind)

[sl_wisun_msg_pan_defect_ind](sl-wisun-msg-pan-defect-ind)

[sl_wisun_msg_network_update_ind](sl-wisun-msg-network-update-ind)

[sl_wisun_msg_socket_data_ind](sl-wisun-msg-socket-data-ind)

[sl_wisun_msg_socket_data_available_ind](sl-wisun-msg-socket-data-available-ind)

[sl_wisun_msg_socket_connected_ind](sl-wisun-msg-socket-connected-ind)

[sl_wisun_msg_logger_event_ind](sl-wisun-msg-logger-event-ind-id)

[sl_wisun_msg_socket_connection_available_ind](sl-wisun-msg-socket-connection-available-ind)

[sl_wisun_msg_socket_closing_ind](sl-wisun-msg-socket-closing-ind)

[sl_wisun_msg_disconnected_ind](sl-wisun-msg-disconnected-ind)

[sl_wisun_msg_connection_lost_ind](sl-wisun-msg-connection-lost-ind)

[sl_wisun_msg_socket_data_sent_ind](sl-wisun-msg-socket-data-sent-ind)

[sl_wisun_msg_error_ind](sl-wisun-msg-error-ind)

[sl_wisun_msg_join_state_ind](sl-wisun-msg-join-state-ind)

[sl_wisun_msg_regulation_tx_level_ind](sl-wisun-msg-regulation-tx-level-ind)

[sl_wisun_mode_switch_fallback_level_ind](sl-wisun-msg-mode-switch-fallback-ind)

[sl_wisun_msg_rx_frame_ind](sl-wisun-msg-rx-frame-ind)

[sl_wisun_msg_lfn_wake_up_ind](sl-wisun-msg-lfn-wake-up-ind)

[sl_wisun_msg_lfn_multicast_reg_ind](sl-wisun-msg-lfn-multicast-reg-ind)

[sl_wisun_msg_dhcp_vendor_data_ind](sl-wisun-msg-dhcp-vendor-data-ind)

[sl_wisun_msg_direct_connect_link_available_ind](sl-wisun-msg-direct-connect-link-available-ind)

[sl_wisun_msg_direct_connect_id_solicit_ind](sl-wisun-msg-direct-connect-id-solicit-ind)

[sl_wisun_msg_direct_connect_id_received_ind](sl-wisun-msg-direct-connect-id-received-ind)

[sl_wisun_msg_direct_connect_link_status_ind](sl-wisun-msg-direct-connect-link-status-ind)

[sl_wisun_msg_direct_connect_client_state_changed_ind](sl-wisun-msg-direct-connect-client-state-changed-ind)

[sl_wisun_br_msg_stopped_ind](sl-wisun-br-msg-stopped-ind)

[sl_wisun_br_msg_routing_table_update_ind](sl-wisun-br-msg-routing-table-update-ind-id)

[sl_wisun_msg_fb_ready_ind](sl-wisun-msg-fb-ready-ind-id)

##### Enumerations

###### sl_wisun_msg_ind_id_t

```
enum sl_wisun_msg_ind_id_t {
    SL_WISUN_MSG_CONNECTED_IND_ID = 0x81
    SL_WISUN_MSG_SOCKET_DATA_IND_ID = 0x82
    SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID = 0x83
    SL_WISUN_MSG_SOCKET_CONNECTED_IND_ID = 0x84
    SL_WISUN_MSG_SOCKET_CONNECTION_AVAILABLE_IND_ID = 0x85
    SL_WISUN_MSG_SOCKET_CLOSING_IND_ID = 0x86
    SL_WISUN_MSG_DISCONNECTED_IND_ID = 0x87
    SL_WISUN_MSG_CONNECTION_LOST_IND_ID = 0x88
    SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID = 0x89
    SL_WISUN_MSG_ERROR_IND_ID = 0x8A
    SL_WISUN_MSG_JOIN_STATE_IND_ID = 0x8B
    SL_WISUN_MSG_NETWORK_UPDATE_IND_ID = 0x8C
    SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID = 0x8D
    SL_WISUN_MSG_MODE_SWITCH_FALLBACK_IND_ID = 0x8E
    SL_WISUN_MSG_RX_FRAME_IND_ID = 0x8F
    SL_WISUN_MSG_LFN_WAKE_UP_IND_ID = 0x90
    SL_WISUN_MSG_LFN_MULTICAST_REG_IND_ID = 0x91
    SL_WISUN_MSG_DHCP_VENDOR_DATA_IND_ID = 0x92
    SL_WISUN_MSG_PAN_DEFECT_IND_ID = 0x93
    SL_WISUN_MSG_DIRECT_CONNECT_LINK_AVAILABLE_IND_ID = 0x94
    SL_WISUN_MSG_DIRECT_CONNECT_LINK_STATUS_IND_ID = 0x95
    SL_WISUN_BR_MSG_STOPPED_IND_ID = 0x96
    SL_WISUN_BR_MSG_ROUTING_TABLE_UPDATE_IND_ID = 0x97
    SL_WISUN_MSG_LOGGER_EVENT_IND_ID = 0x98
    SL_WISUN_MSG_DIRECT_CONNECT_ID_SOLICIT_IND_ID = 0x99
    SL_WISUN_MSG_DIRECT_CONNECT_ID_RECEIVED_IND_ID = 0x9A
    SL_WISUN_MSG_DIRECT_CONNECT_CLIENT_STATE_CHANGED_IND_ID = 0x9B
    SL_WISUN_MSG_FB_READY_IND_ID = 0x9C
}
```

**Description:**

Wi-SUN Message API indication IDs.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_MSG_CONNECTED_IND_ID|This indication is sent when a connection request has been completed.|
|SL_WISUN_MSG_SOCKET_DATA_IND_ID|This indication is sent when data has been received on a socket.|
|SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID|This indication is sent when there is buffered data available on a socket.|
|SL_WISUN_MSG_SOCKET_CONNECTED_IND_ID|This indication is sent when a socket connect request has been completed.|
|SL_WISUN_MSG_SOCKET_CONNECTION_AVAILABLE_IND_ID|This indication is sent when there is a socket connection request waiting.|
|SL_WISUN_MSG_SOCKET_CLOSING_IND_ID|This event is sent when a socket is waiting to be closed.|
|SL_WISUN_MSG_DISCONNECTED_IND_ID|This event is sent when a disconnection request has been completed.|
|SL_WISUN_MSG_CONNECTION_LOST_IND_ID|This event is sent when a connection to Wi-SUN network has been lost and the device is trying to regain the connection.|
|SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID|This event is sent when part of the buffered socket data has been sent.|
|SL_WISUN_MSG_ERROR_IND_ID|This event is sent when an internal stack error has occurred.|
|SL_WISUN_MSG_JOIN_STATE_IND_ID|This event is sent when the join state changes.|
|SL_WISUN_MSG_NETWORK_UPDATE_IND_ID|This event is sent when the network has been updated.|
|SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID|This event is sent when regional regulation transmission level changes.|
|SL_WISUN_MSG_MODE_SWITCH_FALLBACK_IND_ID|This event is sent when the mode switch is disabled.|
|SL_WISUN_MSG_RX_FRAME_IND_ID|This event is sent on frame reception.|
|SL_WISUN_MSG_LFN_WAKE_UP_IND_ID|This event is sent on LFN wake up.|
|SL_WISUN_MSG_LFN_MULTICAST_REG_IND_ID|This event is sent when an LFN multicast group registration finishes.|
|SL_WISUN_MSG_DHCP_VENDOR_DATA_IND_ID|This event is sent when DHCPv6 vendor-specific information is received.|
|SL_WISUN_MSG_PAN_DEFECT_IND_ID|This event is sent to state a PAN defect state change (true for defective PAN, false for a recovery).|
|SL_WISUN_MSG_DIRECT_CONNECT_LINK_AVAILABLE_IND_ID|This event is sent when a Direct Connect Link is available.|
|SL_WISUN_MSG_DIRECT_CONNECT_LINK_STATUS_IND_ID|This event is sent when the status of a Direct Connect Link changes.|
|SL_WISUN_BR_MSG_STOPPED_IND_ID|This event is sent when a BR stop request has been completed.|
|SL_WISUN_BR_MSG_ROUTING_TABLE_UPDATE_IND_ID|This event is sent once the routing table is updated (topology change).|
|SL_WISUN_MSG_LOGGER_EVENT_IND_ID|This event is sent once an event has been logged.|
|SL_WISUN_MSG_DIRECT_CONNECT_ID_SOLICIT_IND_ID|This event is sent when a Direct Connect client is requesting servers to identify themselves.|
|SL_WISUN_MSG_DIRECT_CONNECT_ID_RECEIVED_IND_ID|This event is sent when a Direct Connect Identifier (DC ID) is received.|
|SL_WISUN_MSG_DIRECT_CONNECT_CLIENT_STATE_CHANGED_IND_ID|This event is sent when the state of the DC client changes.|
|SL_WISUN_MSG_FB_READY_IND_ID|This event is sent when the device is ready to send First Breath datagram.|

Wi-SUN event definitions. 

This structure contains a Wi-SUN API event and its associated data. 

###### Public Attributes

###### br_routing_table_update (heading level 7)

```
sl_wisun_br_msg_routing_table_update_ind_body_t sl_wisun_evt_t::br_routing_table_update
```

**Description:** [SL_WISUN_BR_MSG_ROUTING_TABLE_UPDATE_IND_ID](sl-wisun-evt#sl-wisun-br-msg-routing-table-update-ind-id) event data

###### br_stopped (heading level 7)

```
sl_wisun_br_msg_stopped_ind_body_t sl_wisun_evt_t::br_stopped
```

**Description:** [SL_WISUN_BR_MSG_STOPPED_IND_ID](sl-wisun-evt#sl-wisun-br-msg-stopped-ind-id) event data

###### connected (heading level 7)

```
sl_wisun_msg_connected_ind_body_t sl_wisun_evt_t::connected
```

**Description:** [SL_WISUN_MSG_CONNECTED_IND_ID](sl-wisun-evt#sl-wisun-msg-connected-ind-id) event data

###### connection_lost (heading level 7)

```
sl_wisun_msg_connection_lost_ind_body_t sl_wisun_evt_t::connection_lost
```

**Description:** [SL_WISUN_MSG_CONNECTION_LOST_IND_ID](sl-wisun-evt#sl-wisun-msg-connection-lost-ind-id) event data

###### dhcp_vendor_data (heading level 7)

```
sl_wisun_msg_dhcp_vendor_data_ind_body_t sl_wisun_evt_t::dhcp_vendor_data
```

**Description:** [SL_WISUN_MSG_DHCP_VENDOR_DATA_IND_ID](sl-wisun-evt#sl-wisun-msg-dhcp-vendor-data-ind-id) event data

###### direct_connect_client_state_changed (heading level 7)

```
sl_wisun_msg_direct_connect_client_state_changed_ind_body_t sl_wisun_evt_t::direct_connect_client_state_changed
```

**Description:** [SL_WISUN_MSG_DIRECT_CONNECT_CLIENT_STATE_CHANGED_IND_ID](sl-wisun-evt#sl-wisun-msg-direct-connect-client-state-changed-ind-id) event data

###### direct_connect_id_received (heading level 7)

```
sl_wisun_msg_direct_connect_id_received_ind_body_t sl_wisun_evt_t::direct_connect_id_received
```

**Description:** [SL_WISUN_MSG_DIRECT_CONNECT_ID_RECEIVED_IND_ID](sl-wisun-evt#sl-wisun-msg-direct-connect-id-received-ind-id) event data

###### direct_connect_id_solicit (heading level 7)

```
sl_wisun_msg_direct_connect_id_solicit_ind_body_t sl_wisun_evt_t::direct_connect_id_solicit
```

**Description:** [SL_WISUN_MSG_DIRECT_CONNECT_ID_SOLICIT_IND_ID](sl-wisun-evt#sl-wisun-msg-direct-connect-id-solicit-ind-id) event data

###### direct_connect_link_available (heading level 7)

```
sl_wisun_msg_direct_connect_link_available_ind_body_t sl_wisun_evt_t::direct_connect_link_available
```

**Description:** [SL_WISUN_MSG_DIRECT_CONNECT_LINK_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-direct-connect-link-available-ind-id) event data

###### direct_connect_link_status (heading level 7)

```
sl_wisun_msg_direct_connect_link_status_ind_body_t sl_wisun_evt_t::direct_connect_link_status
```

**Description:** [SL_WISUN_MSG_DIRECT_CONNECT_LINK_STATUS_IND_ID](sl-wisun-evt#sl-wisun-msg-direct-connect-link-status-ind-id) event data

###### disconnected (heading level 7)

```
sl_wisun_msg_disconnected_ind_body_t sl_wisun_evt_t::disconnected
```

**Description:** [SL_WISUN_MSG_DISCONNECTED_IND_ID](sl-wisun-evt#sl-wisun-msg-disconnected-ind-id) event data

###### error (heading level 7)

```
sl_wisun_msg_error_ind_body_t sl_wisun_evt_t::error
```

**Description:** [SL_WISUN_MSG_ERROR_IND_ID](sl-wisun-evt#sl-wisun-msg-error-ind-id) event data

###### evt (heading level 7)

```
union sl_wisun_evt_t::@0 sl_wisun_evt_t::evt
```

**Description:** Event-specific data.

**Details:** This structure contains the event-specific data.

###### fb_ready (heading level 7)

```
sl_wisun_msg_fb_ready_ind_body_t sl_wisun_evt_t::fb_ready
```

**Description:** [SL_WISUN_MSG_FB_READY_IND_ID](sl-wisun-evt#sl-wisun-msg-fb-ready-ind-id) event data

###### header (heading level 7)

```
sl_wisun_msg_header_t sl_wisun_evt_t::header
```

**Description:** Common event header.

**Details:** This structure contains common information for all events. ID of the event is stored in the [sl_wisun_msg_header_t.id](sl-wisun-msg-header-t#id) field and is one of the values of [sl_wisun_msg_ind_id_t](sl-wisun-evt#sl-wisun-msg-ind-id-t). The other fields can be ignored.

###### join_state (heading level 7)

```
sl_wisun_msg_join_state_ind_body_t sl_wisun_evt_t::join_state
```

**Description:** [SL_WISUN_MSG_JOIN_STATE_IND_ID](sl-wisun-evt#sl-wisun-msg-join-state-ind-id) event data

###### lfn_multicast_reg (heading level 7)

```
sl_wisun_msg_lfn_multicast_reg_ind_body_t sl_wisun_evt_t::lfn_multicast_reg
```

**Description:** [SL_WISUN_MSG_LFN_MULTICAST_REG_IND_ID](sl-wisun-evt#sl-wisun-msg-lfn-multicast-reg-ind-id) event data

###### lfn_wake_up (heading level 7)

```
sl_wisun_msg_lfn_wake_up_ind_body_t sl_wisun_evt_t::lfn_wake_up
```

**Description:** [SL_WISUN_MSG_LFN_WAKE_UP_IND_ID](sl-wisun-evt#sl-wisun-msg-lfn-wake-up-ind-id) event data

###### logger_event (heading level 7)

```
sl_wisun_msg_logger_event_ind_body_t sl_wisun_evt_t::logger_event
```

**Description:** [SL_WISUN_MSG_LOGGER_EVENT_IND_ID](sl-wisun-evt#sl-wisun-msg-logger-event-ind-id) event data

###### mode_switch_fallback (heading level 7)

```
sl_wisun_msg_mode_switch_fallback_ind_body_t sl_wisun_evt_t::mode_switch_fallback
```

**Description:** [SL_WISUN_MSG_MODE_SWITCH_FALLBACK_IND_ID](sl-wisun-evt#sl-wisun-msg-mode-switch-fallback-ind-id) event data

###### network_update (heading level 7)

```
sl_wisun_msg_network_update_ind_body_t sl_wisun_evt_t::network_update
```

**Description:** [SL_WISUN_MSG_NETWORK_UPDATE_IND_ID](sl-wisun-evt#sl-wisun-msg-network-update-ind-id) event data

###### pan_defect (heading level 7)

```
sl_wisun_msg_pan_defect_ind_body_t sl_wisun_evt_t::pan_defect
```

**Description:** [SL_WISUN_MSG_PAN_DEFECT_IND_ID](sl-wisun-evt#sl-wisun-msg-pan-defect-ind-id) event data

###### regulation_tx_level (heading level 7)

```
sl_wisun_msg_regulation_tx_level_ind_body_t sl_wisun_evt_t::regulation_tx_level
```

**Description:** [SL_WISUN_MSG_REGULATION_TX_LEVEL_IND_ID](sl-wisun-evt#sl-wisun-msg-regulation-tx-level-ind-id) event data

###### rx_frame (heading level 7)

```
sl_wisun_msg_rx_frame_ind_body_t sl_wisun_evt_t::rx_frame
```

**Description:** [SL_WISUN_MSG_RX_FRAME_IND_ID](sl-wisun-evt#sl-wisun-msg-rx-frame-ind-id) event data

###### socket_closing (heading level 7)

```
sl_wisun_msg_socket_closing_ind_body_t sl_wisun_evt_t::socket_closing
```

**Description:** [SL_WISUN_MSG_SOCKET_CLOSING_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-closing-ind-id) event data

###### socket_connected (heading level 7)

```
sl_wisun_msg_socket_connected_ind_body_t sl_wisun_evt_t::socket_connected
```

**Description:** [SL_WISUN_MSG_SOCKET_CONNECTED_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-connected-ind-id) event data

###### socket_connection_available (heading level 7)

```
sl_wisun_msg_socket_connection_available_ind_body_t sl_wisun_evt_t::socket_connection_available
```

**Description:** [SL_WISUN_MSG_SOCKET_CONNECTION_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-connection-available-ind-id) event data

###### socket_data (heading level 7)

```
sl_wisun_msg_socket_data_ind_body_t sl_wisun_evt_t::socket_data
```

**Description:** [SL_WISUN_MSG_SOCKET_DATA_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-ind-id) event data

###### socket_data_available (heading level 7)

```
sl_wisun_msg_socket_data_available_ind_body_t sl_wisun_evt_t::socket_data_available
```

**Description:** [SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-available-ind-id) event data

###### socket_data_sent (heading level 7)

```
sl_wisun_msg_socket_data_sent_ind_body_t sl_wisun_evt_t::socket_data_sent
```

**Description:** [SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-sent-ind-id) event data

##### sl_wisun_msg_connected_ind

###### Modules

[sl_wisun_msg_connected_ind_body_t](sl-wisun-msg-connected-ind-body-t)

[sl_wisun_msg_connected_ind_t](sl-wisun-msg-connected-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_connected_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_connected_ind_body_t sl_wisun_msg_connected_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_connected_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_pan_defect_ind

###### Modules

[sl_wisun_msg_pan_defect_ind_body_t](sl-wisun-msg-pan-defect-ind-body-t)

[sl_wisun_msg_pan_defect_ind_t](sl-wisun-msg-pan-defect-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### pan_id (heading level 8)

```
uint32_t sl_wisun_msg_pan_defect_ind_body_t::pan_id
```

**Description:** PAN ID.

###### state (heading level 8)

```
uint32_t sl_wisun_msg_pan_defect_ind_body_t::state
```

**Description:** State of the PAN defect.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_pan_defect_ind_body_t sl_wisun_msg_pan_defect_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_pan_defect_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_network_update_ind

###### Modules

[sl_wisun_msg_network_update_ind_body_t](sl-wisun-msg-network-update-ind-body-t)

[sl_wisun_msg_network_update_ind_t](sl-wisun-msg-network-update-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### flags (heading level 8)

```
uint32_t sl_wisun_msg_network_update_ind_body_t::flags
```

**Description:** Bit mask indicating the changes.

**Details:** - bit [SL_WISUN_NETWORK_UPDATE_FLAGS_GLOBAL_IP](sl-wisun-types#sl-wisun-network-update-flags-global-ip): Global IP address has changed
- bit [SL_WISUN_NETWORK_UPDATE_FLAGS_PRIMARY_PARENT](sl-wisun-types#sl-wisun-network-update-flags-primary-parent): primary parent has changed
- bit [SL_WISUN_NETWORK_UPDATE_FLAGS_SECONDARY_PARENT](sl-wisun-types#sl-wisun-network-update-flags-secondary-parent): secondary parent has changed
- bit [SL_WISUN_NETWORK_UPDATE_FLAGS_HOP_COUNT](sl-wisun-types#sl-wisun-network-update-flags-hop-count): estimated hop count has changed

###### status (heading level 8)

```
uint32_t sl_wisun_msg_network_update_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_network_update_ind_body_t sl_wisun_msg_network_update_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_network_update_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_data_ind

###### Modules

[sl_wisun_msg_socket_data_ind_body_t](sl-wisun-msg-socket-data-ind-body-t)

[sl_wisun_msg_socket_data_ind_t](sl-wisun-msg-socket-data-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_socket_data_ind_body_t::data[]
```

**Description:** Received data.

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_socket_data_ind_body_t::data_length
```

**Description:** Amount of received data.

###### remote_address (heading level 8)

```
in6_addr_t sl_wisun_msg_socket_data_ind_body_t::remote_address
```

**Description:** IP address of the sender.

###### remote_port (heading level 8)

```
uint16_t sl_wisun_msg_socket_data_ind_body_t::remote_port
```

**Description:** Port number of the sender.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_data_ind_body_t::socket_id
```

**Description:** ID of the socket.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_data_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_data_ind_body_t sl_wisun_msg_socket_data_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_data_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_data_available_ind

###### Modules

[sl_wisun_msg_socket_data_available_ind_body_t](sl-wisun-msg-socket-data-available-ind-body-t)

[sl_wisun_msg_socket_data_available_ind_t](sl-wisun-msg-socket-data-available-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_socket_data_available_ind_body_t::data_length
```

**Description:** Amount of data that can be read.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_socket_data_available_ind_body_t::reserved
```

**Description:** Reserved, set to zero.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_data_available_ind_body_t::socket_id
```

**Description:** ID of the socket.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_data_available_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_data_available_ind_body_t sl_wisun_msg_socket_data_available_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_data_available_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_connected_ind

###### Modules

[sl_wisun_msg_socket_connected_ind_body_t](sl-wisun-msg-socket-connected-ind-body-t)

[sl_wisun_msg_socket_connected_ind_t](sl-wisun-msg-socket-connected-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_connected_ind_body_t::socket_id
```

**Description:** ID of the socket.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_connected_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_connected_ind_body_t sl_wisun_msg_socket_connected_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_connected_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_logger_event_ind

###### Modules

[sl_wisun_msg_logger_event_ind_body_t](sl-wisun-msg-logger-event-ind-body-t)

[sl_wisun_msg_logger_event_ind_t](sl-wisun-msg-logger-event-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### logger_event (heading level 8)

```
sl_wisun_logger_event_t sl_wisun_msg_logger_event_ind_body_t::logger_event
```

**Description:** Logger event data.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_logger_event_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_logger_event_ind_body_t sl_wisun_msg_logger_event_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_logger_event_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_connection_available_ind

###### Modules

[sl_wisun_msg_socket_connection_available_ind_body_t](sl-wisun-msg-socket-connection-available-ind-body-t)

[sl_wisun_msg_socket_connection_available_ind_t](sl-wisun-msg-socket-connection-available-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_connection_available_ind_body_t::socket_id
```

**Description:** ID of the socket.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_connection_available_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_connection_available_ind_body_t sl_wisun_msg_socket_connection_available_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_connection_available_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_closing_ind

###### Modules

[sl_wisun_msg_socket_closing_ind_body_t](sl-wisun-msg-socket-closing-ind-body-t)

[sl_wisun_msg_socket_closing_ind_t](sl-wisun-msg-socket-closing-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_closing_ind_body_t::socket_id
```

**Description:** ID of the socket.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_closing_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_closing_ind_body_t sl_wisun_msg_socket_closing_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_closing_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_disconnected_ind

###### Modules

[sl_wisun_msg_disconnected_ind_body_t](sl-wisun-msg-disconnected-ind-body-t)

[sl_wisun_msg_disconnected_ind_t](sl-wisun-msg-disconnected-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_disconnected_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_disconnected_ind_body_t sl_wisun_msg_disconnected_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_disconnected_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_connection_lost_ind

###### Modules

[sl_wisun_msg_connection_lost_ind_body_t](sl-wisun-msg-connection-lost-ind-body-t)

[sl_wisun_msg_connection_lost_ind_t](sl-wisun-msg-connection-lost-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_connection_lost_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_connection_lost_ind_body_t sl_wisun_msg_connection_lost_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_connection_lost_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_data_sent_ind

###### Modules

[sl_wisun_msg_socket_data_sent_ind_body_t](sl-wisun-msg-socket-data-sent-ind-body-t)

[sl_wisun_msg_socket_data_sent_ind_t](sl-wisun-msg-socket-data-sent-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_data_sent_ind_body_t::socket_id
```

**Description:** ID of the socket.

###### socket_space_left (heading level 8)

```
uint32_t sl_wisun_msg_socket_data_sent_ind_body_t::socket_space_left
```

**Description:** Amount of free space in the transmission buffer.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_data_sent_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_data_sent_ind_body_t sl_wisun_msg_socket_data_sent_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_data_sent_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_error_ind

###### Modules

[sl_wisun_msg_error_ind_body_t](sl-wisun-msg-error-ind-body-t)

[sl_wisun_msg_error_ind_t](sl-wisun-msg-error-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
sl_status_t sl_wisun_msg_error_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_error_ind_body_t sl_wisun_msg_error_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_error_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_join_state_ind

###### Modules

[sl_wisun_msg_join_state_ind_body_t](sl-wisun-msg-join-state-ind-body-t)

[sl_wisun_msg_join_state_ind_t](sl-wisun-msg-join-state-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### join_state (heading level 8)

```
uint32_t sl_wisun_msg_join_state_ind_body_t::join_state
```

**Description:** Join state.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_join_state_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_join_state_ind_body_t sl_wisun_msg_join_state_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_join_state_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_regulation_tx_level_ind

###### Modules

[sl_wisun_msg_regulation_tx_level_ind_body_t](sl-wisun-msg-regulation-tx-level-ind-body-t)

[sl_wisun_msg_regulation_tx_level_ind_t](sl-wisun-msg-regulation-tx-level-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_regulation_tx_level_ind_body_t::reserved[3]
```

**Description:** Reserved.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_regulation_tx_level_ind_body_t::status
```

**Description:** Status of the indication.

###### tx_duration_ms (heading level 8)

```
uint32_t sl_wisun_msg_regulation_tx_level_ind_body_t::tx_duration_ms
```

**Description:** Sum of transmission durations during last hour in milliseconds.

###### tx_level (heading level 8)

```
uint8_t sl_wisun_msg_regulation_tx_level_ind_body_t::tx_level
```

**Description:** Transmission level, one value of [sl_wisun_regulation_tx_level_t](sl-wisun-types#sl-wisun-regulation-tx-level-t).

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_regulation_tx_level_ind_body_t sl_wisun_msg_regulation_tx_level_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_regulation_tx_level_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_mode_switch_fallback_level_ind

###### Modules

[sl_wisun_msg_mode_switch_fallback_ind_body_t](sl-wisun-msg-mode-switch-fallback-ind-body-t)

[sl_wisun_msg_mode_switch_fallback_ind_t](sl-wisun-msg-mode-switch-fallback-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_mode_switch_fallback_ind_body_t::address
```

**Description:** MAC address of the peer triggering the fallback.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_mode_switch_fallback_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_mode_switch_fallback_ind_body_t sl_wisun_msg_mode_switch_fallback_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_mode_switch_fallback_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_rx_frame_ind

###### Modules

[sl_wisun_msg_rx_frame_ind_body_t](sl-wisun-msg-rx-frame-ind-body-t)

[sl_wisun_msg_rx_frame_ind_t](sl-wisun-msg-rx-frame-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### frame (heading level 8)

```
uint8_t sl_wisun_msg_rx_frame_ind_body_t::frame[]
```

**Description:** Received frame.

###### length (heading level 8)

```
uint16_t sl_wisun_msg_rx_frame_ind_body_t::length
```

**Description:** Frame length in bytes.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_rx_frame_ind_body_t::status
```

**Description:** Status of the indication.

###### timestamp_us (heading level 8)

```
uint64_t sl_wisun_msg_rx_frame_ind_body_t::timestamp_us
```

**Description:** Timestamp in microseconds.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_rx_frame_ind_body_t sl_wisun_msg_rx_frame_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_rx_frame_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_lfn_wake_up_ind

###### Modules

[sl_wisun_msg_lfn_wake_up_ind_body_t](sl-wisun-msg-lfn-wake-up-ind-body-t)

[sl_wisun_msg_lfn_wake_up_ind_t](sl-wisun-msg-lfn-wake-up-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### next_wup_us (heading level 8)

```
uint64_t sl_wisun_msg_lfn_wake_up_ind_body_t::next_wup_us
```

**Description:** Expected time to next wake-up in microseconds.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_lfn_wake_up_ind_body_t::status
```

**Description:** Status of the indication.

###### wup_duration_us (heading level 8)

```
uint32_t sl_wisun_msg_lfn_wake_up_ind_body_t::wup_duration_us
```

**Description:** Expected wake-up duration in microseconds.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_lfn_wake_up_ind_body_t sl_wisun_msg_lfn_wake_up_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_lfn_wake_up_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_lfn_multicast_reg_ind

###### Modules

[sl_wisun_msg_lfn_multicast_reg_ind_body_t](sl-wisun-msg-lfn-multicast-reg-ind-body-t)

[sl_wisun_msg_lfn_multicast_reg_ind_t](sl-wisun-msg-lfn-multicast-reg-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### ip_address (heading level 8)

```
in6_addr_t sl_wisun_msg_lfn_multicast_reg_ind_body_t::ip_address
```

**Description:** Registered multicast IP address.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_lfn_multicast_reg_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_lfn_multicast_reg_ind_body_t sl_wisun_msg_lfn_multicast_reg_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_lfn_multicast_reg_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_dhcp_vendor_data_ind

###### Modules

[sl_wisun_msg_dhcp_vendor_data_ind_body_t](sl-wisun-msg-dhcp-vendor-data-ind-body-t)

[sl_wisun_msg_dhcp_vendor_data_ind_t](sl-wisun-msg-dhcp-vendor-data-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_dhcp_vendor_data_ind_body_t::data[]
```

**Description:** Vendor specific data.

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_dhcp_vendor_data_ind_body_t::data_length
```

**Description:** Length of Vendor specific data.

###### enterprise_number (heading level 8)

```
uint32_t sl_wisun_msg_dhcp_vendor_data_ind_body_t::enterprise_number
```

**Description:** Vendor Specific Enterprise Number.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_dhcp_vendor_data_ind_body_t sl_wisun_msg_dhcp_vendor_data_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_dhcp_vendor_data_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_direct_connect_link_available_ind

###### Modules

[sl_wisun_msg_direct_connect_link_available_ind_body_t](sl-wisun-msg-direct-connect-link-available-ind-body-t)

[sl_wisun_msg_direct_connect_link_available_ind_t](sl-wisun-msg-direct-connect-link-available-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### link_local_ipv6 (heading level 8)

```
in6_addr_t sl_wisun_msg_direct_connect_link_available_ind_body_t::link_local_ipv6
```

**Description:** Link Local IPv6 address of the client.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_direct_connect_link_available_ind_body_t sl_wisun_msg_direct_connect_link_available_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_direct_connect_link_available_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_direct_connect_id_solicit_ind

###### Modules

[sl_wisun_msg_direct_connect_id_solicit_ind_body_t](sl-wisun-msg-direct-connect-id-solicit-ind-body-t)

[sl_wisun_msg_direct_connect_id_solicit_ind_t](sl-wisun-msg-direct-connect-id-solicit-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### dc_id (heading level 8)

```
sl_wisun_dc_id_t sl_wisun_msg_direct_connect_id_solicit_ind_body_t::dc_id
```

**Description:** DC ID used for scanning.

###### link_local_ipv6 (heading level 8)

```
in6_addr_t sl_wisun_msg_direct_connect_id_solicit_ind_body_t::link_local_ipv6
```

**Description:** Link Local IPv6 address of the client.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_direct_connect_id_solicit_ind_body_t sl_wisun_msg_direct_connect_id_solicit_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_direct_connect_id_solicit_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_direct_connect_id_received_ind

###### Modules

[sl_wisun_msg_direct_connect_id_received_ind_body_t](sl-wisun-msg-direct-connect-id-received-ind-body-t)

[sl_wisun_msg_direct_connect_id_received_ind_t](sl-wisun-msg-direct-connect-id-received-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### dc_id (heading level 8)

```
sl_wisun_dc_id_t sl_wisun_msg_direct_connect_id_received_ind_body_t::dc_id
```

**Description:** DC ID of the server.

###### mac_address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_direct_connect_id_received_ind_body_t::mac_address
```

**Description:** MAC address of the server.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_direct_connect_id_received_ind_body_t sl_wisun_msg_direct_connect_id_received_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_direct_connect_id_received_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_direct_connect_link_status_ind

###### Modules

[sl_wisun_msg_direct_connect_link_status_ind_body_t](sl-wisun-msg-direct-connect-link-status-ind-body-t)

[sl_wisun_msg_direct_connect_link_status_ind_t](sl-wisun-msg-direct-connect-link-status-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### link_local_ipv6 (heading level 8)

```
in6_addr_t sl_wisun_msg_direct_connect_link_status_ind_body_t::link_local_ipv6
```

**Description:** Link Local IPv6 address of the client.

###### link_status (heading level 8)

```
uint32_t sl_wisun_msg_direct_connect_link_status_ind_body_t::link_status
```

**Description:** Link status.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_direct_connect_link_status_ind_body_t sl_wisun_msg_direct_connect_link_status_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_direct_connect_link_status_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_direct_connect_client_state_changed_ind

###### Modules

[sl_wisun_msg_direct_connect_client_state_changed_ind_body_t](sl-wisun-msg-direct-connect-client-state-changed-ind-body-t)

[sl_wisun_msg_direct_connect_client_state_changed_ind_t](sl-wisun-msg-direct-connect-client-state-changed-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### link_local_ipv6 (heading level 8)

```
in6_addr_t sl_wisun_msg_direct_connect_client_state_changed_ind_body_t::link_local_ipv6
```

**Description:** link local IPv6 address of the server

###### state (heading level 8)

```
uint32_t sl_wisun_msg_direct_connect_client_state_changed_ind_body_t::state
```

**Description:** State of the Direct Connect client.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_direct_connect_client_state_changed_ind_body_t sl_wisun_msg_direct_connect_client_state_changed_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_direct_connect_client_state_changed_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_stopped_ind

###### Modules

[sl_wisun_br_msg_stopped_ind_body_t](sl-wisun-br-msg-stopped-ind-body-t)

[sl_wisun_br_msg_stopped_ind_t](sl-wisun-br-msg-stopped-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_stopped_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_stopped_ind_body_t sl_wisun_br_msg_stopped_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_stopped_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_routing_table_update_ind

###### Modules

[sl_wisun_br_msg_routing_table_update_ind_body_t](sl-wisun-br-msg-routing-table-update-ind-body-t)

[sl_wisun_br_msg_routing_table_update_ind_t](sl-wisun-br-msg-routing-table-update-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### event (heading level 8)

```
uint32_t sl_wisun_br_msg_routing_table_update_ind_body_t::event
```

**Description:** Routing table update event SL_WISUN_ROUTING_TABLE_UPDATE_ROUTE_CHANGED: route changed.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_routing_table_update_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_routing_table_update_ind_body_t sl_wisun_br_msg_routing_table_update_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_routing_table_update_ind_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_fb_ready_ind

###### Modules

[sl_wisun_msg_fb_ready_ind_body_t](sl-wisun-msg-fb-ready-ind-body-t)

[sl_wisun_msg_fb_ready_ind_t](sl-wisun-msg-fb-ready-ind-t)

Indication message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_fb_ready_ind_body_t::status
```

**Description:** Status of the indication.

Indication message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_fb_ready_ind_body_t sl_wisun_msg_fb_ready_ind_t::body
```

**Description:** Indication message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_fb_ready_ind_t::header
```

**Description:** Common message header.

#### API type definitions

##### Modules

[sl_wisun_br_advanced_parameters_t](sl-wisun-br-advanced-parameters-t)

[sl_wisun_br_connection_params_t](sl-wisun-br-connection-params-t)

[sl_wisun_br_lfn_params_t](sl-wisun-br-lfn-params-t)

[sl_wisun_br_params_configuration_s](sl-wisun-br-params-configuration-s)

[sl_wisun_br_params_dhcp_s](sl-wisun-br-params-dhcp-s)

[sl_wisun_br_params_discovery_s](sl-wisun-br-params-discovery-s)

[sl_wisun_br_params_eapol_s](sl-wisun-br-params-eapol-s)

[sl_wisun_br_params_lfn_parent_s](sl-wisun-br-params-lfn-parent-s)

[sl_wisun_br_params_misc_s](sl-wisun-br-params-misc-s)

[sl_wisun_br_params_mpl_s](sl-wisun-br-params-mpl-s)

[sl_wisun_br_params_rpl_s](sl-wisun-br-params-rpl-s)

[sl_wisun_br_params_traffic_s](sl-wisun-br-params-traffic-s)

[sl_wisun_br_routing_table_entry_t](sl-wisun-br-routing-table-entry-t)

[sl_wisun_channel_mask_t](sl-wisun-channel-mask-t)

[sl_wisun_connection_params_t](sl-wisun-connection-params-t)

[sl_wisun_dc_id_t](sl-wisun-dc-id-t)

[sl_wisun_ffn_advanced_parameters_t](sl-wisun-ffn-advanced-parameters-t)

[sl_wisun_ffn_advanced_rpl_params_t](sl-wisun-ffn-advanced-rpl-params-t)

[sl_wisun_key_lifetimes_params_t](sl-wisun-key-lifetimes-params-t)

[sl_wisun_lfn_advanced_parameters_t](sl-wisun-lfn-advanced-parameters-t)

[sl_wisun_lfn_params_connection_t](sl-wisun-lfn-params-connection-t)

[sl_wisun_lfn_params_data_layer_t](sl-wisun-lfn-params-data-layer-t)

[sl_wisun_lfn_params_eapol_t](sl-wisun-lfn-params-eapol-t)

[sl_wisun_lfn_params_network_t](sl-wisun-lfn-params-network-t)

[sl_wisun_lfn_params_power_t](sl-wisun-lfn-params-power-t)

[sl_wisun_lfn_params_t](sl-wisun-lfn-params-t)

[sl_wisun_logger_event_frame_received_t](sl-wisun-logger-event-frame-received-t)

[sl_wisun_logger_event_neighbor_lifetime_changed_t](sl-wisun-logger-event-neighbor-lifetime-changed-t)

[sl_wisun_logger_event_pa_data_t](sl-wisun-logger-event-pa-data-t)

[sl_wisun_logger_event_rf_test_rx_t](sl-wisun-logger-event-rf-test-rx-t)

[sl_wisun_logger_event_rf_test_t](sl-wisun-logger-event-rf-test-t)

[sl_wisun_logger_event_t](sl-wisun-logger-event-t)

[sl_wisun_logger_event_tx_failure_t](sl-wisun-logger-event-tx-failure-t)

[sl_wisun_mac_address_t](sl-wisun-mac-address-t)

[sl_wisun_mac_params_t](sl-wisun-mac-params-t)

[sl_wisun_msg_header_t](sl-wisun-msg-header-t)

[sl_wisun_neighbor_info_t](sl-wisun-neighbor-info-t)

[sl_wisun_network_info_t](sl-wisun-network-info-t)

[sl_wisun_params_configuration_s](sl-wisun-params-configuration-s)

[sl_wisun_params_dhcp_s](sl-wisun-params-dhcp-s)

[sl_wisun_params_discovery_s](sl-wisun-params-discovery-s)

[sl_wisun_params_eapol_s](sl-wisun-params-eapol-s)

[sl_wisun_params_lfn_parent_s](sl-wisun-params-lfn-parent-s)

[sl_wisun_params_misc_s](sl-wisun-params-misc-s)

[sl_wisun_params_mpl_s](sl-wisun-params-mpl-s)

[sl_wisun_params_rpl_s](sl-wisun-params-rpl-s)

[sl_wisun_params_traffic_s](sl-wisun-params-traffic-s)

[sl_wisun_phy_config_custom_fsk_t](sl-wisun-phy-config-custom-fsk-t)

[sl_wisun_phy_config_custom_ofdm_t](sl-wisun-phy-config-custom-ofdm-t)

[sl_wisun_phy_config_custom_oqpsk_t](sl-wisun-phy-config-custom-oqpsk-t)

[sl_wisun_phy_config_explicit_t](sl-wisun-phy-config-explicit-t)

[sl_wisun_phy_config_fan10_t](sl-wisun-phy-config-fan10-t)

[sl_wisun_phy_config_fan11_t](sl-wisun-phy-config-fan11-t)

[sl_wisun_phy_config_ids_t](sl-wisun-phy-config-ids-t)

[sl_wisun_phy_config_t](sl-wisun-phy-config-t)

[sl_wisun_rate_stats_t](sl-wisun-rate-stats-t)

[sl_wisun_rate_t](sl-wisun-rate-t)

[sl_wisun_rfc8415_txalg_params_t](sl-wisun-rfc8415-txalg-params-t)

[sl_wisun_rpl_info_t](sl-wisun-rpl-info-t)

[sl_wisun_socket_option_data_t](sl-wisun-socket-option-data-t)

[sl_wisun_socket_option_edfe_mode_t](sl-wisun-socket-option-edfe-mode-t)

[sl_wisun_socket_option_event_mode_t](sl-wisun-socket-option-event-mode-t)

[sl_wisun_socket_option_multicast_group_t](sl-wisun-socket-option-multicast-group-t)

[sl_wisun_socket_option_multicast_hop_limit](sl-wisun-socket-option-multicast-hop-limit)

[sl_wisun_socket_option_send_buffer_limit_t](sl-wisun-socket-option-send-buffer-limit-t)

[sl_wisun_socket_option_unicast_hop_limit](sl-wisun-socket-option-unicast-hop-limit)

[sl_wisun_statistics_arib_regulation_t](sl-wisun-statistics-arib-regulation-t)

[sl_wisun_statistics_fhss_t](sl-wisun-statistics-fhss-t)

[sl_wisun_statistics_heap_t](sl-wisun-statistics-heap-t)

[sl_wisun_statistics_mac_t](sl-wisun-statistics-mac-t)

[sl_wisun_statistics_network_t](sl-wisun-statistics-network-t)

[sl_wisun_statistics_phy_t](sl-wisun-statistics-phy-t)

[sl_wisun_statistics_regulation_t](sl-wisun-statistics-regulation-t)

[sl_wisun_statistics_t](sl-wisun-statistics-t)

[sl_wisun_statistics_wisun_t](sl-wisun-statistics-wisun-t)

[sl_wisun_trace_group_config_t](sl-wisun-trace-group-config-t)

[sl_wisun_trickle_params_t](sl-wisun-trickle-params-t)

[Predefined FFN parameter sets](sl-wisun-ffn-parameter-sets)

[Predefined LFN parameter sets](sl-wisun-lfn-parameter-sets)

[Predefined BR parameter sets](sl-wisun-br-parameter-sets)

[Predefined BR LFN-parenting parameter sets](sl-wisun-br-lfn-parameter-sets)

##### Enumerations

###### sl_direct_connect_link_status_t

```
enum sl_direct_connect_link_status_t {
    SL_WISUN_DIRECT_CONNECT_LINK_STATUS_CONNECTED
    SL_WISUN_DIRECT_CONNECT_LINK_STATUS_ERROR
    SL_WISUN_DIRECT_CONNECT_LINK_STATUS_DISCONNECTED
}
```

**Description:**

Enumeration for Direct Connect Link status.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_DIRECT_CONNECT_LINK_STATUS_CONNECTED|Direct Connect Link connected.|
|SL_WISUN_DIRECT_CONNECT_LINK_STATUS_ERROR|Direct Connect Link error.|
|SL_WISUN_DIRECT_CONNECT_LINK_STATUS_DISCONNECTED|Direct Connect Link disconnected.|

###### sl_wisun_br_state_t

```
enum sl_wisun_br_state_t {
    SL_WISUN_BR_STATE_INITIALIZED = 0
    SL_WISUN_BR_STATE_OPERATIONAL = 1
}
```

**Description:**

Border Router state.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_BR_STATE_INITIALIZED|Border Router is initialized.|
|SL_WISUN_BR_STATE_OPERATIONAL|Border Router is started.|

###### sl_wisun_certificate_option_t

```
enum sl_wisun_certificate_option_t {
    SL_WISUN_CERTIFICATE_OPTION_NONE = 0
    SL_WISUN_CERTIFICATE_OPTION_APPEND = 1
    SL_WISUN_CERTIFICATE_OPTION_IS_REF = 2
    SL_WISUN_CERTIFICATE_OPTION_HAS_KEY = 4
}
```

**Description:**

Enumerations for certificate options.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_CERTIFICATE_OPTION_NONE|Empty option.|
|SL_WISUN_CERTIFICATE_OPTION_APPEND|Certificate is appended to a chain.|
|SL_WISUN_CERTIFICATE_OPTION_IS_REF|Deprecated/Ignored: Certificate is stored into a parsed form internally.|
|SL_WISUN_CERTIFICATE_OPTION_HAS_KEY|Deprecated/Ignored: Device certificates must have a key.|

###### sl_wisun_channel_exclusion_mode_t

```
enum sl_wisun_channel_exclusion_mode_t {
    SL_WISUN_CHANNEL_EXCLUSION_MODE_BY_RANGE = 1
    SL_WISUN_CHANNEL_EXCLUSION_MODE_BY_MASK = 2
}
```

**Description:**

Enumeration for channel exclusion modes.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_CHANNEL_EXCLUSION_MODE_BY_RANGE|Channels are excluded by range if possible (3 ranges maximum), otherwise channels will be excluded by mask.|
|SL_WISUN_CHANNEL_EXCLUSION_MODE_BY_MASK|Channels are excluded by mask.|

###### sl_wisun_channel_mask_type_t

```
enum sl_wisun_channel_mask_type_t {
    SL_WISUN_CHANNEL_MASK_TYPE_REGULATORY
    SL_WISUN_CHANNEL_MASK_TYPE_REGIONAL = SL_WISUN_CHANNEL_MASK_TYPE_REGULATORY
    SL_WISUN_CHANNEL_MASK_TYPE_ADVERTISED_UNICAST
    SL_WISUN_CHANNEL_MASK_TYPE_ADVERTISED_BROADCAST
    SL_WISUN_CHANNEL_MASK_TYPE_EFFECTIVE_ASYNC
    SL_WISUN_CHANNEL_MASK_TYPE_EFFECTIVE_UNICAST
    SL_WISUN_CHANNEL_MASK_TYPE_EFFECTIVE_BROADCAST
}
```

**Description:**

Enumeration for channel mask types.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_CHANNEL_MASK_TYPE_REGULATORY|Regulatory excluded channel mask (not advertised)|
|SL_WISUN_CHANNEL_MASK_TYPE_REGIONAL|Regional excluded channel mask (not advertised)|
|SL_WISUN_CHANNEL_MASK_TYPE_ADVERTISED_UNICAST|Excluded channel mask advertised in us-ie.|
|SL_WISUN_CHANNEL_MASK_TYPE_ADVERTISED_BROADCAST|Excluded channel mask advertised in bs-ie.|
|SL_WISUN_CHANNEL_MASK_TYPE_EFFECTIVE_ASYNC|Excluded channel mask applied to async frames.|
|SL_WISUN_CHANNEL_MASK_TYPE_EFFECTIVE_UNICAST|Excluded channel mask applied to unicast frequency hopping.|
|SL_WISUN_CHANNEL_MASK_TYPE_EFFECTIVE_BROADCAST|Excluded channel mask applied to broadcast frequency hopping.|

###### sl_wisun_channel_spacing_t

```
enum sl_wisun_channel_spacing_t {
    SL_WISUN_CHANNEL_SPACING_100KHZ = 0
    SL_WISUN_CHANNEL_SPACING_200KHZ = 1
    SL_WISUN_CHANNEL_SPACING_400KHZ = 2
    SL_WISUN_CHANNEL_SPACING_600KHZ = 3
    SL_WISUN_CHANNEL_SPACING_250KHZ = 4
    SL_WISUN_CHANNEL_SPACING_800KHZ = 5
    SL_WISUN_CHANNEL_SPACING_1200KHZ = 6
}
```

**Description:**

Enumerations for channel spacing.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_CHANNEL_SPACING_100KHZ|100 kHz|
|SL_WISUN_CHANNEL_SPACING_200KHZ|200 kHz|
|SL_WISUN_CHANNEL_SPACING_400KHZ|400 kHz|
|SL_WISUN_CHANNEL_SPACING_600KHZ|600 kHz|
|SL_WISUN_CHANNEL_SPACING_250KHZ|250 kHz|
|SL_WISUN_CHANNEL_SPACING_800KHZ|800 kHz|
|SL_WISUN_CHANNEL_SPACING_1200KHZ|1200 kHz|

###### sl_wisun_crc_type_t

```
enum sl_wisun_crc_type_t {
    SL_WISUN_NO_CRC = 0
    SL_WISUN_2_BYTES_CRC = 1
    SL_WISUN_4_BYTES_CRC = 2
}
```

**Description:**

Enumeration for CRC type.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_NO_CRC|No CRC (OFDM and OQPSK only)|
|SL_WISUN_2_BYTES_CRC|2 bytes CRC|
|SL_WISUN_4_BYTES_CRC|4 bytes CRC|

###### sl_wisun_dc_client_state_t

```
enum sl_wisun_dc_client_state_t {
    SL_WISUN_DC_CLIENT_STATE_CONNECTED = 0
    SL_WISUN_DC_CLIENT_STATE_CONNECTION_LOST = 1
    SL_WISUN_DC_CLIENT_STATE_CONNECTION_FAILED = 2
    SL_WISUN_DC_CLIENT_STATE_STOPPED = 3
    SL_WISUN_DC_CLIENT_STATE_SCAN_COMPLETE = 4
}
```

**Description:**

Enumeration for the state of the Direct Connect client.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_DC_CLIENT_STATE_CONNECTED|Connected state.|
|SL_WISUN_DC_CLIENT_STATE_CONNECTION_LOST|Connection lost state.|
|SL_WISUN_DC_CLIENT_STATE_CONNECTION_FAILED|Connection establishment failed.|
|SL_WISUN_DC_CLIENT_STATE_STOPPED|Stopped state.|
|SL_WISUN_DC_CLIENT_STATE_SCAN_COMPLETE|Scan complete state.|

###### sl_wisun_device_type_t

```
enum sl_wisun_device_type_t {
    SL_WISUN_ROUTER = 0
    SL_WISUN_LFN = 1
    SL_WISUN_BORDER_ROUTER = 2
}
```

**Description:**

Enumerations for device type.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_ROUTER|FFN Router.|
|SL_WISUN_LFN|LFN Router (experimental, for evaluation purposes only)|
|SL_WISUN_BORDER_ROUTER|Border Router.|

###### sl_wisun_fan_version_t

```
enum sl_wisun_fan_version_t {
    SL_WISUN_FAN_VERSION_DEFAULT = 0
    SL_WISUN_FAN_VERSION_1_0 = 1
    SL_WISUN_FAN_VERSION_1_1 = 2
}
```

**Description:**

Enumeration for FAN versions to which the node is certified.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_FAN_VERSION_DEFAULT|Keep node's default FAN TPS version.|
|SL_WISUN_FAN_VERSION_1_0|FAN 1.0 certified node.|
|SL_WISUN_FAN_VERSION_1_1|FAN 1.1 certified node.|

###### sl_wisun_frame_type_t

```
enum sl_wisun_frame_type_t {
    SL_WISUN_FRAME_TYPE_PAS = 0
    SL_WISUN_FRAME_TYPE_PA = 1
    SL_WISUN_FRAME_TYPE_PCS = 2
    SL_WISUN_FRAME_TYPE_PC = 3
    SL_WISUN_FRAME_TYPE_DIS = 4
    SL_WISUN_FRAME_TYPE_DIO = 5
    SL_WISUN_FRAME_RESERVED1 = 6
    SL_WISUN_FRAME_TYPE_LPAS = 7
}
```

**Description:**

Enumeration for types of frame that can be triggered.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_FRAME_TYPE_PAS|PAN Advertisement Solicit.|
|SL_WISUN_FRAME_TYPE_PA|PAN Advertisement.|
|SL_WISUN_FRAME_TYPE_PCS|PAN Configuration Solicit.|
|SL_WISUN_FRAME_TYPE_PC|PAN Configuration.|
|SL_WISUN_FRAME_TYPE_DIS|DODAG Information Solicitation.|
|SL_WISUN_FRAME_TYPE_DIO|DODAG Information Object.|
|SL_WISUN_FRAME_RESERVED1|Reserved.|
|SL_WISUN_FRAME_TYPE_LPAS|LFN PAN Advertisement Solicit.|

###### sl_wisun_ip_address_type_t

```
enum sl_wisun_ip_address_type_t {
    SL_WISUN_IP_ADDRESS_TYPE_LINK_LOCAL = 0
    SL_WISUN_IP_ADDRESS_TYPE_GLOBAL = 1
    SL_WISUN_IP_ADDRESS_TYPE_BORDER_ROUTER = 2
    SL_WISUN_IP_ADDRESS_TYPE_PRIMARY_PARENT = 3
    SL_WISUN_IP_ADDRESS_TYPE_SECONDARY_PARENT = 4
}
```

**Description:**

Enumerations for IP address type.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_IP_ADDRESS_TYPE_LINK_LOCAL|Device link-local address.|
|SL_WISUN_IP_ADDRESS_TYPE_GLOBAL|Device global unicast address.|
|SL_WISUN_IP_ADDRESS_TYPE_BORDER_ROUTER|Border router global unicast address.|
|SL_WISUN_IP_ADDRESS_TYPE_PRIMARY_PARENT|Link-local address of the primary parent.|
|SL_WISUN_IP_ADDRESS_TYPE_SECONDARY_PARENT|Link-local address of the secondary parent.|

###### sl_wisun_join_state_t

```
enum sl_wisun_join_state_t {
    SL_WISUN_JOIN_STATE_DISCONNECTED = 0
    SL_WISUN_JOIN_STATE_SELECT_PAN = 1
    SL_WISUN_JOIN_STATE_AUTHENTICATE = 2
    SL_WISUN_JOIN_STATE_ACQUIRE_PAN_CONFIG = 3
    SL_WISUN_JOIN_STATE_CONFIGURE_ROUTING = 4
    SL_WISUN_JOIN_STATE_OPERATIONAL = 5
    SL_WISUN_JOIN_STATE_DISCONNECTING = 6
    SL_WISUN_JOIN_STATE_PARENT_SELECT = 41
    SL_WISUN_JOIN_STATE_DHCP = 42
    SL_WISUN_JOIN_STATE_EARO = 43
    SL_WISUN_JOIN_STATE_DAO = 44
}
```

**Description:**

Enumerations for join state.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_JOIN_STATE_DISCONNECTED|Join state 0: Disconnected.|
|SL_WISUN_JOIN_STATE_SELECT_PAN|Join state 1: Select PAN.|
|SL_WISUN_JOIN_STATE_AUTHENTICATE|Join state 2: Authenticate.|
|SL_WISUN_JOIN_STATE_ACQUIRE_PAN_CONFIG|Join state 3: Acquire PAN config.|
|SL_WISUN_JOIN_STATE_CONFIGURE_ROUTING|Join state 4: Configure routing.|
|SL_WISUN_JOIN_STATE_OPERATIONAL|Join state 5: Operational.|
|SL_WISUN_JOIN_STATE_DISCONNECTING|Disconnecting.|
|SL_WISUN_JOIN_STATE_PARENT_SELECT|Join state 4: Preferred parent selection.|
|SL_WISUN_JOIN_STATE_DHCP|Join state 4: DHCP address acquisition.|
|SL_WISUN_JOIN_STATE_EARO|Join state 4: Address registration.|
|SL_WISUN_JOIN_STATE_DAO|Join state 4: DAO registration.|

###### sl_wisun_lfn_profile_t

```
enum sl_wisun_lfn_profile_t {
    SL_WISUN_LFN_PROFILE_TEST = 0
    SL_WISUN_LFN_PROFILE_BALANCED = 1
    SL_WISUN_LFN_PROFILE_ECO = 2
    SL_WISUN_LFN_PROFILE_AUTOMATIC = 3
}
```

**Description:**

Enumeration for LFN configuration profile.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_LFN_PROFILE_TEST|Profile for test usage, best performance but highest power consumption.|
|SL_WISUN_LFN_PROFILE_BALANCED|Profile providing balance between power consumption and performance.|
|SL_WISUN_LFN_PROFILE_ECO|Profile optimized for low power consumption.|
|SL_WISUN_LFN_PROFILE_AUTOMATIC|Profile for automatic connection parameters adjustment.|

###### sl_wisun_logger_event_frame_type_t

```
enum sl_wisun_logger_event_frame_type_t {
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PAS = 0
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PA = 1
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPAS = 2
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPA = 3
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_EAPOL = 4
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PCS = 5
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PC = 6
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPCS = 7
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPC = 8
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LTS = 9
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_DATA = 10
    SL_WISUN_LOGGER_EVENT_FRAME_TYPE_UNDEF = 255
}
```

**Description:**

Enumeration for event log frame types.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PAS|PAN Advertisement Solicit frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PA|PAN Advertisement frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPAS|LFN PAN Advertisement Solicit frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPA|LFN PAN Advertisement frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_EAPOL|EAPOL frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PCS|PAN Configuration Solicit frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_PC|PAN Configuration frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPCS|LFN PAN Configuration Solicit frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LPC|LFN PAN Configuration frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_LTS|LFN Time Sync.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_DATA|Data frame.|
|SL_WISUN_LOGGER_EVENT_FRAME_TYPE_UNDEF|Undefined frame type.|

###### sl_wisun_logger_event_type_t

```
enum sl_wisun_logger_event_type_t {
    SL_WISUN_LOGGER_EVENT_TYPE_NONE = 0
    SL_WISUN_LOGGER_EVENT_TYPE_NEIGHBOR_LIFETIME_CHANGED = 1
    SL_WISUN_LOGGER_EVENT_TYPE_FRAME_RECEIVED = 2
    SL_WISUN_LOGGER_EVENT_TYPE_FRAME_COUNTER_FAILURE = 4
    SL_WISUN_LOGGER_EVENT_TYPE_TX_FAILURE = 8
    SL_WISUN_LOGGER_EVENT_TYPE_RF_TEST = 16
}
```

**Description:**

Enumeration for event types.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_LOGGER_EVENT_TYPE_NONE||
|SL_WISUN_LOGGER_EVENT_TYPE_NEIGHBOR_LIFETIME_CHANGED|Event published when a neighbor's lifetime changes.|
|SL_WISUN_LOGGER_EVENT_TYPE_FRAME_RECEIVED|Event published when a frame is received.|
|SL_WISUN_LOGGER_EVENT_TYPE_FRAME_COUNTER_FAILURE|Event published when a frame is dropped due to frame counter failure.|
|SL_WISUN_LOGGER_EVENT_TYPE_TX_FAILURE|Event published when a tx fails.|
|SL_WISUN_LOGGER_EVENT_TYPE_RF_TEST|Event published when RF test receives a packet or completes a TX.|

###### sl_wisun_mode_switch_mode_t

```
enum sl_wisun_mode_switch_mode_t {
    SL_WISUN_MODE_SWITCH_DISABLED = 0
    SL_WISUN_MODE_SWITCH_ENABLED = 1
    SL_WISUN_MODE_SWITCH_DEFAULT = 2
}
```

**Description:**

Enumeration for Mode Switch mode.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_MODE_SWITCH_DISABLED|Mode switch is not allowed.|
|SL_WISUN_MODE_SWITCH_ENABLED|Mode switch is allowed for all unicast data frames. Specified PhyModeId is used.|
|SL_WISUN_MODE_SWITCH_DEFAULT|Mode switch is allowed for all unicast data frames. Default PhyModeId is used.|

###### sl_wisun_multicast_group_action_t

```
enum sl_wisun_multicast_group_action_t {
    SL_WISUN_MULTICAST_GROUP_ACTION_JOIN = 0
    SL_WISUN_MULTICAST_GROUP_ACTION_LEAVE = 1
}
```

**Description:**

Enumerations for multicast group action.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_MULTICAST_GROUP_ACTION_JOIN|Join a multicast group.|
|SL_WISUN_MULTICAST_GROUP_ACTION_LEAVE|Leave a multicast group.|

###### sl_wisun_neighbor_type_t

```
enum sl_wisun_neighbor_type_t {
    SL_WISUN_NEIGHBOR_TYPE_PRIMARY_PARENT = 0
    SL_WISUN_NEIGHBOR_TYPE_SECONDARY_PARENT = 1
    SL_WISUN_NEIGHBOR_TYPE_CHILD = 2
}
```

**Description:**

Enumeration for RPL neighbor types.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_NEIGHBOR_TYPE_PRIMARY_PARENT|Primary parent.|
|SL_WISUN_NEIGHBOR_TYPE_SECONDARY_PARENT|Secondary parent.|
|SL_WISUN_NEIGHBOR_TYPE_CHILD|Child.|

###### sl_wisun_network_size_t

```
enum sl_wisun_network_size_t {
    SL_WISUN_NETWORK_SIZE_AUTOMATIC = 0
    SL_WISUN_NETWORK_SIZE_SMALL = 1
    SL_WISUN_NETWORK_SIZE_MEDIUM = 2
    SL_WISUN_NETWORK_SIZE_LARGE = 3
    SL_WISUN_NETWORK_SIZE_TEST = 4
    SL_WISUN_NETWORK_SIZE_CERTIFICATION = 5
}
```

**Description:**

Enumerations for network size.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_NETWORK_SIZE_AUTOMATIC|Determine the size from PAN advertisements.|
|SL_WISUN_NETWORK_SIZE_SMALL|Small size (less than 100 nodes)|
|SL_WISUN_NETWORK_SIZE_MEDIUM|Medium size (100 to 800 nodes)|
|SL_WISUN_NETWORK_SIZE_LARGE|Large size (800 to 1500 nodes)|
|SL_WISUN_NETWORK_SIZE_TEST|Test network (a few nodes)|
|SL_WISUN_NETWORK_SIZE_CERTIFICATION|Certification configuration.|

###### sl_wisun_network_update_flags_t

```
enum sl_wisun_network_update_flags_t {
    SL_WISUN_NETWORK_UPDATE_FLAGS_GLOBAL_IP = 0
    SL_WISUN_NETWORK_UPDATE_FLAGS_PRIMARY_PARENT = 1
    SL_WISUN_NETWORK_UPDATE_FLAGS_SECONDARY_PARENT = 2
    SL_WISUN_NETWORK_UPDATE_FLAGS_HOP_COUNT = 3
}
```

**Description:**

Enumerations for network update flags.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_NETWORK_UPDATE_FLAGS_GLOBAL_IP|Global IP modification flag bit.|
|SL_WISUN_NETWORK_UPDATE_FLAGS_PRIMARY_PARENT|Primary Parent modification flag bit.|
|SL_WISUN_NETWORK_UPDATE_FLAGS_SECONDARY_PARENT|Secondary parent modification flag bit.|
|SL_WISUN_NETWORK_UPDATE_FLAGS_HOP_COUNT|Hop count modification flag bit.|

###### sl_wisun_operating_class_t

```
enum sl_wisun_operating_class_t {
    SL_WISUN_OPERATING_CLASS_1 = 1
    SL_WISUN_OPERATING_CLASS_2 = 2
    SL_WISUN_OPERATING_CLASS_3 = 3
    SL_WISUN_OPERATING_CLASS_4 = 4
    SL_WISUN_OPERATING_CLASS_5 = 5
    SL_WISUN_OPERATING_CLASS_APP = 255
}
```

**Description:**

Enumerations for operating class.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_OPERATING_CLASS_1|Operating class# 1.|
|SL_WISUN_OPERATING_CLASS_2|Operating class# 2.|
|SL_WISUN_OPERATING_CLASS_3|Operating class# 3.|
|SL_WISUN_OPERATING_CLASS_4|Operating class# 4.|
|SL_WISUN_OPERATING_CLASS_5|Operating class# 5.|
|SL_WISUN_OPERATING_CLASS_APP|Application-specific class.|

###### sl_wisun_operating_mode_t

```
enum sl_wisun_operating_mode_t {
    SL_WISUN_OPERATING_MODE_1A = 0x1a
    SL_WISUN_OPERATING_MODE_1B = 0x1b
    SL_WISUN_OPERATING_MODE_2A = 0x2a
    SL_WISUN_OPERATING_MODE_2B = 0x2b
    SL_WISUN_OPERATING_MODE_3 = 0x03
    SL_WISUN_OPERATING_MODE_4A = 0x4a
    SL_WISUN_OPERATING_MODE_4B = 0x4b
    SL_WISUN_OPERATING_MODE_5 = 0x05
}
```

**Description:**

Enumerations for operating mode.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_OPERATING_MODE_1A|Operating mode# 1a.|
|SL_WISUN_OPERATING_MODE_1B|Operating mode# 1b.|
|SL_WISUN_OPERATING_MODE_2A|Operating mode# 2a.|
|SL_WISUN_OPERATING_MODE_2B|Operating mode# 2b.|
|SL_WISUN_OPERATING_MODE_3|Operating mode# 3.|
|SL_WISUN_OPERATING_MODE_4A|Operating mode# 4a.|
|SL_WISUN_OPERATING_MODE_4B|Operating mode# 4b.|
|SL_WISUN_OPERATING_MODE_5|Operating mode# 5.|

###### sl_wisun_option_id_t

```
enum sl_wisun_option_id_t {
    SL_WISUN_OPTION_PAN_TIMEOUT_M = 0
    SL_WISUN_OPTION_EAPOL_TARGET_MIN_SENS = 1
    SL_WISUN_OPTION_ALLOW_DISCOVERY_SKIP = 2
    SL_WISUN_OPTION_ALLOW_EAPOL_SKIP = 3
    SL_WISUN_OPTION_LFN_LPC_RETRY_COUNT = 4
    SL_WISUN_OPTION_JOIN_NODE_COUNT = 5
    SL_WISUN_OPTION_GTK_MAX_MISMATCH_M = 65
    SL_WISUN_OPTION_LGTK_MAX_MISMATCH_M = 66
    SL_WISUN_OPTION_RPL_PARENTS_MAX = 6
    SL_WISUN_OPTION_RPL_PARENT_CANDIDATES_MAX = 7
    SL_WISUN_OPTION_RPL_DIS_MAX_DELAY_S = 8
    SL_WISUN_OPTION_RPL_PARENT_SELECTION_DELAY_S = 9
    SL_WISUN_OPTION_RPL_ETX_SAMPLES_INIT = 10
    SL_WISUN_OPTION_RPL_ETX_SAMPLES_REFRESH = 11
    SL_WISUN_OPTION_REGISTRATION_LIFETIME_S = 12
    SL_WISUN_OPTION_TRAFFIC_LOWPAN_MTU_BYTES = 13
    SL_WISUN_OPTION_TRAFFIC_IPV6_MRU_BYTES = 14
    SL_WISUN_OPTION_TRAFFIC_MAX_EDFE_FRAGMENT_COUNT = 15
    SL_WISUN_OPTION_MAC_BACKOFF_PERIOD_US = 16
    SL_WISUN_OPTION_MAC_MIN_BE = 17
    SL_WISUN_OPTION_MAC_MAX_BE = 18
    SL_WISUN_OPTION_MAC_MAX_CCA_RETRIES = 19
    SL_WISUN_OPTION_MAC_MAX_FRAME_RETRIES = 20
    SL_WISUN_OPTION_MPL_TRICKLE_IMIN_S = 21
    SL_WISUN_OPTION_MPL_TRICKLE_IMAX_S = 22
    SL_WISUN_OPTION_MPL_TRICKLE_K = 23
    SL_WISUN_OPTION_MPL_SEED_SET_ENTRY_LIFETIME_S = 24
    SL_WISUN_OPTION_MPL_TRICKLE_E = 25
    SL_WISUN_OPTION_MPL_SEED_ID_TYPE = 26
    SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MAX_DELAY_S = 27
    SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_IRT_S = 28
    SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MRT_S = 29
    SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MRC = 30
    SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MRD_S = 31
    SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_RAND = 32
    SL_WISUN_OPTION_LFN_DISCOVERY_SLOT_TIME_MS = 33
    SL_WISUN_OPTION_LFN_DISCOVERY_SLOTS = 34
    SL_WISUN_OPTION_LFN_LPAS_INTERVAL_S = 67
    SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MS = 35
    SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MIN_MS = 36
    SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MAX_MS = 37
    SL_WISUN_OPTION_LFN_EAPOL_UNICAST_INTERVAL_MS = 38
    SL_WISUN_OPTION_LFN_MAINTAIN_PARENT_TIME = 39
    SL_WISUN_OPTION_LFN_REGISTRATION_LIFETIME_M = 40
    SL_WISUN_OPTION_LFN_LISTENING_WINDOW_MIN_US = 41
    SL_WISUN_OPTION_LFN_WINDOW_MARGIN_MIN_US = 42
    SL_WISUN_OPTION_LFN_BROADCAST_LTS_ONLY = 43
    SL_WISUN_OPTION_BR_EAPOL_PMK_LIFETIME_M = 44
    SL_WISUN_OPTION_BR_EAPOL_LPMK_LIFETIME_M = 45
    SL_WISUN_OPTION_BR_EAPOL_PTK_LIFETIME_M = 46
    SL_WISUN_OPTION_BR_EAPOL_LPTK_LIFETIME_M = 47
    SL_WISUN_OPTION_BR_EAPOL_GTK_EXPIRE_OFFSET_M = 48
    SL_WISUN_OPTION_BR_EAPOL_LGTK_EXPIRE_OFFSET_M = 49
    SL_WISUN_OPTION_BR_EAPOL_GTK_NEW_ACTIVATION_TIME = 50
    SL_WISUN_OPTION_BR_EAPOL_LGTK_NEW_ACTIVATION_TIME = 51
    SL_WISUN_OPTION_BR_EAPOL_GTK_NEW_INSTALL_REQUIRED = 52
    SL_WISUN_OPTION_BR_EAPOL_LGTK_NEW_INSTALL_REQUIRED = 53
    SL_WISUN_OPTION_BR_EAPOL_FFN_REVOCATION_LIFETIME_REDUCTION = 54
    SL_WISUN_OPTION_BR_EAPOL_LFN_REVOCATION_LIFETIME_REDUCTION = 55
    SL_WISUN_OPTION_BR_RPL_MIN_HOP_RANK_INCREASE = 56
    SL_WISUN_OPTION_BR_RPL_DAG_MAX_RANK_INCREASE = 57
    SL_WISUN_OPTION_BR_RPL_DEFAULT_LIFETIME_UNIT = 58
    SL_WISUN_OPTION_BR_RPL_DIO_INTERVAL_MIN = 59
    SL_WISUN_OPTION_BR_RPL_DIO_INTERVAL_DOUBLINGS = 60
    SL_WISUN_OPTION_BR_RPL_DIO_REDUNDANCY_CONSTANT = 61
    SL_WISUN_OPTION_BR_RPL_DEFAULT_LIFETIME = 62
    SL_WISUN_OPTION_BR_PAN_CAPACITY = 63
    SL_WISUN_OPTION_BR_ENABLE_FFN10 = 64
    SL_WISUN_OPTION_MAX = 68
}
```

**Description:**

Wi-SUN option identifiers for [sl_wisun_set_option](sl-wisun-api#sl-wisun-set-option).

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_OPTION_PAN_TIMEOUT_M|Border router communication timeout PAN_TIMEOUT in minutes.|
|SL_WISUN_OPTION_EAPOL_TARGET_MIN_SENS|Minimum signal level for a node to be selected as the EAPOL target for authentication in join state 1 immediately after a PAN Advertisement reception.|
|SL_WISUN_OPTION_ALLOW_DISCOVERY_SKIP|Allow join state 1 to be skipped using cached information from the previous connection.|
|SL_WISUN_OPTION_ALLOW_EAPOL_SKIP|Allow join state 2 to be skipped using cached credentials from the previous connection.|
|SL_WISUN_OPTION_LFN_LPC_RETRY_COUNT|Number of broadcast LFN Pan Config retries when LFN Version is incremented.|
|SL_WISUN_OPTION_JOIN_NODE_COUNT|Expected number of nodes in the PAN.|
|SL_WISUN_OPTION_GTK_MAX_MISMATCH_M|GTK_MAX_MISMATCH (minutes).|
|SL_WISUN_OPTION_LGTK_MAX_MISMATCH_M|LGTK_MAX_MISMATCH (minutes).|
|SL_WISUN_OPTION_RPL_PARENTS_MAX|Maximum number of RPL parents.|
|SL_WISUN_OPTION_RPL_PARENT_CANDIDATES_MAX|Maximum number of RPL candidate parents.|
|SL_WISUN_OPTION_RPL_DIS_MAX_DELAY_S|Maximum delay before sending an RPL DIS message (seconds).|
|SL_WISUN_OPTION_RPL_PARENT_SELECTION_DELAY_S|Delay after the first DIO reception before selecting a parent (seconds).|
|SL_WISUN_OPTION_RPL_ETX_SAMPLES_INIT|Number of samples used to calculate ETX during join state 4.|
|SL_WISUN_OPTION_RPL_ETX_SAMPLES_REFRESH|Number of samples used to refresh ETX.|
|SL_WISUN_OPTION_REGISTRATION_LIFETIME_S|Amount of time a parent should retain a registered GUA/ULA (seconds).|
|SL_WISUN_OPTION_TRAFFIC_LOWPAN_MTU_BYTES|Maximum Transmission Unit (MTU) for 6LoWPAN packets in bytes.|
|SL_WISUN_OPTION_TRAFFIC_IPV6_MRU_BYTES|Maximum Receive Unit (MRU) for fragmented IPv6 packets in bytes.|
|SL_WISUN_OPTION_TRAFFIC_MAX_EDFE_FRAGMENT_COUNT|Maximum number of frames to send in a single EDFE transaction (0 to 10).|
|SL_WISUN_OPTION_MAC_BACKOFF_PERIOD_US|Length of one backoff period in microseconds.|
|SL_WISUN_OPTION_MAC_MIN_BE|Minimum value of CSMA-CA backoff exponent.|
|SL_WISUN_OPTION_MAC_MAX_BE|Maximum value of CSMA-CA backoff exponent.|
|SL_WISUN_OPTION_MAC_MAX_CCA_RETRIES|Maximum number of CCA retries.|
|SL_WISUN_OPTION_MAC_MAX_FRAME_RETRIES|Maximum number of transmission retries.|
|SL_WISUN_OPTION_MPL_TRICKLE_IMIN_S|MPL trickle timer minimum interval size (seconds).|
|SL_WISUN_OPTION_MPL_TRICKLE_IMAX_S|MPL trickle timer maximum interval size (seconds).|
|SL_WISUN_OPTION_MPL_TRICKLE_K|MPL trickle redundancy constant, 0 for infinity.|
|SL_WISUN_OPTION_MPL_SEED_SET_ENTRY_LIFETIME_S|MPL seed set entry lifetime (seconds).|
|SL_WISUN_OPTION_MPL_TRICKLE_E|MPL trickle timer expirations.|
|SL_WISUN_OPTION_MPL_SEED_ID_TYPE|MPL seed-id type.|
|SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MAX_DELAY_S|Direct Connect EAPOL TX algorithm: max delay of first key request (seconds).|
|SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_IRT_S|Direct Connect EAPOL TX algorithm: initial retransmission time (seconds).|
|SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MRT_S|Direct Connect EAPOL TX algorithm: maximum retransmission time (seconds).|
|SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MRC|Direct Connect EAPOL TX algorithm: maximum retransmission count.|
|SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_MRD_S|Direct Connect EAPOL TX algorithm: maximum retransmission duration (seconds).|
|SL_WISUN_OPTION_DIRECT_CONNECT_TXALG_RAND|Direct Connect EAPOL TX algorithm: randomization factor.|
|SL_WISUN_OPTION_LFN_DISCOVERY_SLOT_TIME_MS|LFN PAN Advertisement (LPA) listening slot duration (milliseconds).|
|SL_WISUN_OPTION_LFN_DISCOVERY_SLOTS|Number of LPA slots for which an LFN shall listen for LPA frames.|
|SL_WISUN_OPTION_LFN_LPAS_INTERVAL_S|Delay between two LFN PAN Advertistement Solicit messages.|
|SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MS|Initial LFN Unicast interval proposed by the LFN (milliseconds).|
|SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MIN_MS|Minimum acceptable LFN unicast interval (milliseconds).|
|SL_WISUN_OPTION_LFN_UNICAST_INTERVAL_MAX_MS|Maximum acceptable LFN unicast interval (milliseconds).|
|SL_WISUN_OPTION_LFN_EAPOL_UNICAST_INTERVAL_MS|Shorter LFN Unicast interval used during the EAPOL exchange (milliseconds).|
|SL_WISUN_OPTION_LFN_MAINTAIN_PARENT_TIME|Number of broadcast sync periods with no message from the parent before the LFN assumes the parent is lost.|
|SL_WISUN_OPTION_LFN_REGISTRATION_LIFETIME_M|Address registration lifetime (IPv6 lease duration) the LFN requires to the Border Router (minutes).|
|SL_WISUN_OPTION_LFN_LISTENING_WINDOW_MIN_US|Minimum duration of the listening window (microseconds).|
|SL_WISUN_OPTION_LFN_WINDOW_MARGIN_MIN_US|Minimum margin added to the listening window, before and after (microseconds).|
|SL_WISUN_OPTION_LFN_BROADCAST_LTS_ONLY|If true, the LFN wakes up only for broadcast slots containing synchronization information.|
|SL_WISUN_OPTION_BR_EAPOL_PMK_LIFETIME_M|BR EAPOL PMK lifetime (minutes).|
|SL_WISUN_OPTION_BR_EAPOL_LPMK_LIFETIME_M|BR EAPOL LPMK lifetime (minutes).|
|SL_WISUN_OPTION_BR_EAPOL_PTK_LIFETIME_M|BR EAPOL PTK lifetime (minutes).|
|SL_WISUN_OPTION_BR_EAPOL_LPTK_LIFETIME_M|BR EAPOL LPTK lifetime (minutes).|
|SL_WISUN_OPTION_BR_EAPOL_GTK_EXPIRE_OFFSET_M|GTK_EXPIRE_OFFSET (minutes).|
|SL_WISUN_OPTION_BR_EAPOL_LGTK_EXPIRE_OFFSET_M|LGTK_EXPIRE_OFFSET (minutes).|
|SL_WISUN_OPTION_BR_EAPOL_GTK_NEW_ACTIVATION_TIME|GTK_NEW_ACTIVATION_TIME (fraction 1/X of GTK_EXPIRE_OFFSET).|
|SL_WISUN_OPTION_BR_EAPOL_LGTK_NEW_ACTIVATION_TIME|LGTK_NEW_ACTIVATION_TIME (fraction 1/X of LGTK_EXPIRE_OFFSET).|
|SL_WISUN_OPTION_BR_EAPOL_GTK_NEW_INSTALL_REQUIRED|GTK_NEW_INSTALL_REQUIRED (percentage).|
|SL_WISUN_OPTION_BR_EAPOL_LGTK_NEW_INSTALL_REQUIRED|LGTK_NEW_INSTALL_REQUIRED (percentage).|
|SL_WISUN_OPTION_BR_EAPOL_FFN_REVOCATION_LIFETIME_REDUCTION|FFN_REVOCATION_LIFETIME_REDUCTION.|
|SL_WISUN_OPTION_BR_EAPOL_LFN_REVOCATION_LIFETIME_REDUCTION|LFN_REVOCATION_LIFETIME_REDUCTION.|
|SL_WISUN_OPTION_BR_RPL_MIN_HOP_RANK_INCREASE|RPL MinHopRankIncrease (RFC 6550 3.5.1).|
|SL_WISUN_OPTION_BR_RPL_DAG_MAX_RANK_INCREASE|RPL allowable increase in rank for local repair (RFC 6550 6.7.6).|
|SL_WISUN_OPTION_BR_RPL_DEFAULT_LIFETIME_UNIT|RPL default lifetime unit (RFC 6550 6.7.6).|
|SL_WISUN_OPTION_BR_RPL_DIO_INTERVAL_MIN|RPL trickle Imin: DIO interval equals 2^rpl_dio_interval_min ms (RFC 6550 8.3.1).|
|SL_WISUN_OPTION_BR_RPL_DIO_INTERVAL_DOUBLINGS|RPL trickle Imax: DIOIntervalDoublings (RFC 6550 8.3.1).|
|SL_WISUN_OPTION_BR_RPL_DIO_REDUNDANCY_CONSTANT|RPL trickle k: DIORedundancyConstant (RFC 6550 8.3.1).|
|SL_WISUN_OPTION_BR_RPL_DEFAULT_LIFETIME|RPL default lifetime for routes in lifetime units (RFC 6550 6.7.6).|
|SL_WISUN_OPTION_BR_PAN_CAPACITY|Maximum number of nodes supported by the border router.|
|SL_WISUN_OPTION_BR_ENABLE_FFN10|Enable authentication of FAN 1.0 routers.|
|SL_WISUN_OPTION_MAX||

###### sl_wisun_phy_config_type_t

```
enum sl_wisun_phy_config_type_t {
    SL_WISUN_PHY_CONFIG_FAN10 = 0
    SL_WISUN_PHY_CONFIG_FAN11 = 1
    SL_WISUN_PHY_CONFIG_EXPLICIT = 2
    SL_WISUN_PHY_CONFIG_IDS = 3
    SL_WISUN_PHY_CONFIG_CUSTOM_FSK = 4
    SL_WISUN_PHY_CONFIG_CUSTOM_OFDM = 5
    SL_WISUN_PHY_CONFIG_CUSTOM_OQPSK = 6
}
```

**Description:**

Enumerations for PHY config type.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_PHY_CONFIG_FAN10|FAN1.0 PHY configuration.|
|SL_WISUN_PHY_CONFIG_FAN11|FAN1.1 PHY configuration.|
|SL_WISUN_PHY_CONFIG_EXPLICIT|Explicit PHY configuration.|
|SL_WISUN_PHY_CONFIG_IDS|Explicit RAIL configuration.|
|SL_WISUN_PHY_CONFIG_CUSTOM_FSK|Custom FSK PHY configuration.|
|SL_WISUN_PHY_CONFIG_CUSTOM_OFDM|Custom OFDM PHY configuration.|
|SL_WISUN_PHY_CONFIG_CUSTOM_OQPSK|Custom OQPSK PHY configuration.|

###### sl_wisun_private_key_option_t

```
enum sl_wisun_private_key_option_t {
    SL_WISUN_PRIVATE_KEY_OPTION_NONE = 0
    SL_WISUN_PRIVATE_KEY_OPTION_IS_REF = 1
}
```

**Description:**

Enumerations for private key options.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_PRIVATE_KEY_OPTION_NONE|Empty option.|
|SL_WISUN_PRIVATE_KEY_OPTION_IS_REF|Deprecated/Ignored: Private key is stored into a parsed form internally.|

###### sl_wisun_regulation_t

```
enum sl_wisun_regulation_t {
    SL_WISUN_REGULATION_NONE = 0
    SL_WISUN_REGULATION_ARIB = 1
    SL_WISUN_REGULATION_WPC = 2
    SL_WISUN_REGULATION_ETSI = 3
}
```

**Description:**

Enumerations for regional regulation.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_REGULATION_NONE|No regulation.|
|SL_WISUN_REGULATION_ARIB|ARIB, should only be used with JP regulatory domain.|
|SL_WISUN_REGULATION_WPC|WPC, should only be used with IN regulatory domain.|
|SL_WISUN_REGULATION_ETSI|ETSI, should only be used with EU regulatory domain.|

###### sl_wisun_regulation_tx_level_t

```
enum sl_wisun_regulation_tx_level_t {
    SL_WISUN_REGULATION_TX_LEVEL_LOW = 0
    SL_WISUN_REGULATION_TX_LEVEL_WARNING = 1
    SL_WISUN_REGULATION_TX_LEVEL_ALERT = 2
}
```

**Description:**

Enumeration for regional regulation transmission level.

**Details:**

Thresholds are define with [sl_wisun_set_regulation_tx_thresholds](sl-wisun-api#sl-wisun-set-regulation-tx-thresholds).

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_REGULATION_TX_LEVEL_LOW|Transmission duration is compliant with regional regulation.|
|SL_WISUN_REGULATION_TX_LEVEL_WARNING|Transmission duration is above warning threshold.|
|SL_WISUN_REGULATION_TX_LEVEL_ALERT|Transmission duration is above alert threshold.|

###### sl_wisun_regulatory_domain_t

```
enum sl_wisun_regulatory_domain_t {
    SL_WISUN_REGULATORY_DOMAIN_WW = 0
    SL_WISUN_REGULATORY_DOMAIN_NA = 1
    SL_WISUN_REGULATORY_DOMAIN_JP = 2
    SL_WISUN_REGULATORY_DOMAIN_EU = 3
    SL_WISUN_REGULATORY_DOMAIN_CN = 4
    SL_WISUN_REGULATORY_DOMAIN_IN = 5
    SL_WISUN_REGULATORY_DOMAIN_MX = 6
    SL_WISUN_REGULATORY_DOMAIN_BZ = 7
    SL_WISUN_REGULATORY_DOMAIN_AZ = 8
    SL_WISUN_REGULATORY_DOMAIN_NZ = 8
    SL_WISUN_REGULATORY_DOMAIN_KR = 9
    SL_WISUN_REGULATORY_DOMAIN_PH = 10
    SL_WISUN_REGULATORY_DOMAIN_MY = 11
    SL_WISUN_REGULATORY_DOMAIN_HK = 12
    SL_WISUN_REGULATORY_DOMAIN_SG = 13
    SL_WISUN_REGULATORY_DOMAIN_TH = 14
    SL_WISUN_REGULATORY_DOMAIN_VN = 15
    SL_WISUN_REGULATORY_DOMAIN_APP = 255
}
```

**Description:**

Enumerations for regulatory domain.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_REGULATORY_DOMAIN_WW|World-wide (2.4 GHz)|
|SL_WISUN_REGULATORY_DOMAIN_NA|North America.|
|SL_WISUN_REGULATORY_DOMAIN_JP|Japan.|
|SL_WISUN_REGULATORY_DOMAIN_EU|Europe.|
|SL_WISUN_REGULATORY_DOMAIN_CN|China.|
|SL_WISUN_REGULATORY_DOMAIN_IN|India.|
|SL_WISUN_REGULATORY_DOMAIN_MX|Mexico.|
|SL_WISUN_REGULATORY_DOMAIN_BZ|Brazil.|
|SL_WISUN_REGULATORY_DOMAIN_AZ|Australia.|
|SL_WISUN_REGULATORY_DOMAIN_NZ|New Zealand.|
|SL_WISUN_REGULATORY_DOMAIN_KR|South Korea.|
|SL_WISUN_REGULATORY_DOMAIN_PH|Philippines.|
|SL_WISUN_REGULATORY_DOMAIN_MY|Malaysia.|
|SL_WISUN_REGULATORY_DOMAIN_HK|Hong Kong.|
|SL_WISUN_REGULATORY_DOMAIN_SG|Singapore.|
|SL_WISUN_REGULATORY_DOMAIN_TH|Thailand.|
|SL_WISUN_REGULATORY_DOMAIN_VN|Vietnam.|
|SL_WISUN_REGULATORY_DOMAIN_APP|Application-specific domain.|

###### sl_wisun_routing_table_update_event_t

```
enum sl_wisun_routing_table_update_event_t {
    SL_WISUN_ROUTING_TABLE_UPDATE_ROUTE_CHANGED = 0
}
```

**Description:**

Enumeration for routing table update types.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_ROUTING_TABLE_UPDATE_ROUTE_CHANGED|At least one route is updated in the routing table.|

###### sl_wisun_socket_option_t

```
enum sl_wisun_socket_option_t {
    SL_WISUN_SOCKET_OPTION_EVENT_MODE = 0
    SL_WISUN_SOCKET_OPTION_MULTICAST_GROUP = 1
    SL_WISUN_SOCKET_OPTION_SEND_BUFFER_LIMIT = 2
    SL_WISUN_SOCKET_OPTION_EDFE_MODE = 3
    SL_WISUN_SOCKET_OPTION_UNICAST_HOP_LIMIT = 4
    SL_WISUN_SOCKET_OPTION_MULTICAST_HOP_LIMIT = 5
}
```

**Description:**

Enumerations for socket option Deprecated since v2.0 MUST NOT be used with POSIX socket API.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_SOCKET_OPTION_EVENT_MODE|Option for socket event mode.|
|SL_WISUN_SOCKET_OPTION_MULTICAST_GROUP|Option for multicast group.|
|SL_WISUN_SOCKET_OPTION_SEND_BUFFER_LIMIT|Option for send buffer limit.|
|SL_WISUN_SOCKET_OPTION_EDFE_MODE|Option to enable/disable Extended Directed Frame Exchange mode.|
|SL_WISUN_SOCKET_OPTION_UNICAST_HOP_LIMIT|Option to set socket unicast hop limit.|
|SL_WISUN_SOCKET_OPTION_MULTICAST_HOP_LIMIT|Option to set socket multicast hop limit.|

###### sl_wisun_socket_protocol_t

```
enum sl_wisun_socket_protocol_t {
    SL_WISUN_SOCKET_PROTOCOL_UDP = 0
    SL_WISUN_SOCKET_PROTOCOL_TCP = 1
    SL_WISUN_SOCKET_PROTOCOL_ICMP = 2
}
```

**Description:**

Enumerations for socket protocol Deprecated since v2.0 MUST NOT be used with POSIX socket API.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_SOCKET_PROTOCOL_UDP|User Datagram Protocol (UDP)|
|SL_WISUN_SOCKET_PROTOCOL_TCP|Transmission Control Protocol (TCP)|
|SL_WISUN_SOCKET_PROTOCOL_ICMP|Internet Control Message Protocol (ICMP)|

###### sl_wisun_statistics_type_t

```
enum sl_wisun_statistics_type_t {
    SL_WISUN_STATISTICS_TYPE_PHY = 0
    SL_WISUN_STATISTICS_TYPE_MAC = 1
    SL_WISUN_STATISTICS_TYPE_FHSS = 2
    SL_WISUN_STATISTICS_TYPE_WISUN = 3
    SL_WISUN_STATISTICS_TYPE_NETWORK = 4
    SL_WISUN_STATISTICS_TYPE_REGULATION = 5
    SL_WISUN_STATISTICS_TYPE_HEAP = 6
}
```

**Description:**

Enumerations for statistics type.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_STATISTICS_TYPE_PHY|PHY/RF statistics.|
|SL_WISUN_STATISTICS_TYPE_MAC|MAC statistics.|
|SL_WISUN_STATISTICS_TYPE_FHSS|Frequency hopping statistics.|
|SL_WISUN_STATISTICS_TYPE_WISUN|Wi-SUN statistics.|
|SL_WISUN_STATISTICS_TYPE_NETWORK|6LoWPAN/IP stack statistics|
|SL_WISUN_STATISTICS_TYPE_REGULATION|Regional regulation.|
|SL_WISUN_STATISTICS_TYPE_HEAP|Heap usage.|

###### sl_wisun_trace_group_t

```
enum sl_wisun_trace_group_t {
    SL_WISUN_TRACE_GROUP_MAC = 0
    SL_WISUN_TRACE_GROUP_NW = 1
    SL_WISUN_TRACE_GROUP_LLC = 2
    SL_WISUN_TRACE_GROUP_6LO = 3
    SL_WISUN_TRACE_GROUP_IPV6 = 4
    SL_WISUN_TRACE_GROUP_TCP = 5
    SL_WISUN_TRACE_GROUP_UDP = 6
    SL_WISUN_TRACE_GROUP_ICMP = 7
    SL_WISUN_TRACE_GROUP_DHCP = 8
    SL_WISUN_TRACE_GROUP_MPL = 9
    SL_WISUN_TRACE_GROUP_DNS = 10
    SL_WISUN_TRACE_GROUP_RPL = 11
    SL_WISUN_TRACE_GROUP_TRIC = 12
    SL_WISUN_TRACE_GROUP_WS = 15
    SL_WISUN_TRACE_GROUP_BOOT = 16
    SL_WISUN_TRACE_GROUP_WSR = 17
    SL_WISUN_TRACE_GROUP_WSBR = 18
    SL_WISUN_TRACE_GROUP_SEC = 19
    SL_WISUN_TRACE_GROUP_TIME = 20
    SL_WISUN_TRACE_GROUP_NEIGH = 21
    SL_WISUN_TRACE_GROUP_STAT = 22
    SL_WISUN_TRACE_GROUP_BUFF = 23
    SL_WISUN_TRACE_GROUP_ADDR = 24
    SL_WISUN_TRACE_GROUP_MON = 25
    SL_WISUN_TRACE_GROUP_SOCK = 26
    SL_WISUN_TRACE_GROUP_DENY = 27
    SL_WISUN_TRACE_GROUP_ETX = 28
    SL_WISUN_TRACE_GROUP_FHSS = 29
    SL_WISUN_TRACE_GROUP_ROUT = 30
    SL_WISUN_TRACE_GROUP_EVLP = 31
    SL_WISUN_TRACE_GROUP_NVM = 32
    SL_WISUN_TRACE_GROUP_CRYPTO = 33
    SL_WISUN_TRACE_GROUP_RF = 34
    Sl_WISUN_TRACE_GROUP_WSIE = 35
    SL_WISUN_TRACE_GROUP_CONFIG = 36
    SL_WISUN_TRACE_GROUP_TIM_SRV = 37
    SL_WISUN_TRACE_GROUP_LFN_TIM = 38
    SL_WISUN_TRACE_GROUP_RALG = 39
    SL_WISUN_TRACE_GROUP_FSM = 40
    SL_WISUN_TRACE_GROUP_WS_FSM = 40
    SL_WISUN_TRACE_GROUP_APP = 41
    SL_WISUN_TRACE_GROUP_DC = 42
    SL_WISUN_TRACE_GROUP_REG = 43
    SL_WISUN_TRACE_GROUP_TXALG = 44
    SL_WISUN_TRACE_GROUP_MAC_FSM = 45
    SL_WISUN_TRACE_GROUP_FB = 46
    SL_WISUN_TRACE_GROUP_INT = 63
    SL_WISUN_TRACE_GROUP_COUNT = 64
}
```

**Description:**

Enumeration for trace group.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_TRACE_GROUP_MAC|Mac.|
|SL_WISUN_TRACE_GROUP_NW|Network.|
|SL_WISUN_TRACE_GROUP_LLC|LLC.|
|SL_WISUN_TRACE_GROUP_6LO|6lowpan|
|SL_WISUN_TRACE_GROUP_IPV6|IPV6.|
|SL_WISUN_TRACE_GROUP_TCP|TCP.|
|SL_WISUN_TRACE_GROUP_UDP|UDP.|
|SL_WISUN_TRACE_GROUP_ICMP|ICMP.|
|SL_WISUN_TRACE_GROUP_DHCP|DHCP.|
|SL_WISUN_TRACE_GROUP_MPL|MPL.|
|SL_WISUN_TRACE_GROUP_DNS|DNS.|
|SL_WISUN_TRACE_GROUP_RPL|RPL.|
|SL_WISUN_TRACE_GROUP_TRIC|Trickle.|
|SL_WISUN_TRACE_GROUP_WS|Wi-SUN Stack.|
|SL_WISUN_TRACE_GROUP_BOOT|Wi-SUN Bootstrap.|
|SL_WISUN_TRACE_GROUP_WSR|Wi-SUN Router.|
|SL_WISUN_TRACE_GROUP_WSBR|Border router.|
|SL_WISUN_TRACE_GROUP_SEC|Security.|
|SL_WISUN_TRACE_GROUP_TIME|Time and timers.|
|SL_WISUN_TRACE_GROUP_NEIGH|Neighbor.|
|SL_WISUN_TRACE_GROUP_STAT|Statistics.|
|SL_WISUN_TRACE_GROUP_BUFF|Dynamic Buffer.|
|SL_WISUN_TRACE_GROUP_ADDR|Address Manipulation.|
|SL_WISUN_TRACE_GROUP_MON|Monitoring.|
|SL_WISUN_TRACE_GROUP_SOCK|Socket.|
|SL_WISUN_TRACE_GROUP_DENY|Deny list.|
|SL_WISUN_TRACE_GROUP_ETX|ETX.|
|SL_WISUN_TRACE_GROUP_FHSS|FHSS.|
|SL_WISUN_TRACE_GROUP_ROUT|Routing table.|
|SL_WISUN_TRACE_GROUP_EVLP|Event loop.|
|SL_WISUN_TRACE_GROUP_NVM|NVM.|
|SL_WISUN_TRACE_GROUP_CRYPTO|Crypto.|
|SL_WISUN_TRACE_GROUP_RF|Wi-SUN RF Driver.|
|Sl_WISUN_TRACE_GROUP_WSIE|Wi-SUN IE.|
|SL_WISUN_TRACE_GROUP_CONFIG|Configuration.|
|SL_WISUN_TRACE_GROUP_TIM_SRV|Timer service.|
|SL_WISUN_TRACE_GROUP_LFN_TIM|LFN timing measurement.|
|SL_WISUN_TRACE_GROUP_RALG|Adaptive rate algorithms.|
|SL_WISUN_TRACE_GROUP_FSM|Finite state machine. Kept for backward compatibility.|
|SL_WISUN_TRACE_GROUP_WS_FSM|Wi-SUN Finite state machine.|
|SL_WISUN_TRACE_GROUP_APP|Application.|
|SL_WISUN_TRACE_GROUP_DC|Direct Connect.|
|SL_WISUN_TRACE_GROUP_REG|Regional regulation.|
|SL_WISUN_TRACE_GROUP_TXALG|RFC 8415 TX algorithm.|
|SL_WISUN_TRACE_GROUP_MAC_FSM|MAC Finite state machine.|
|SL_WISUN_TRACE_GROUP_FB|First breath.|
|SL_WISUN_TRACE_GROUP_INT|Internal usage.|
|SL_WISUN_TRACE_GROUP_COUNT|Max number of trace group in this enum.|

###### sl_wisun_trace_level_t

```
enum sl_wisun_trace_level_t {
    SL_WISUN_TRACE_LEVEL_NONE = 0
    SL_WISUN_TRACE_LEVEL_ERROR = 1
    SL_WISUN_TRACE_LEVEL_WARN = 2
    SL_WISUN_TRACE_LEVEL_INFO = 3
    SL_WISUN_TRACE_LEVEL_DEBUG = 4
}
```

**Description:**

Enumerations for trace level.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_TRACE_LEVEL_NONE|No trace.|
|SL_WISUN_TRACE_LEVEL_ERROR|Error only.|
|SL_WISUN_TRACE_LEVEL_WARN|Warning + error.|
|SL_WISUN_TRACE_LEVEL_INFO|Info + warning + error.|
|SL_WISUN_TRACE_LEVEL_DEBUG|Debug + info + warning + error.|

##### Typedefs

###### sl_wisun_br_params_configuration

`typedef struct sl_wisun_br_params_configuration_s sl_wisun_br_params_configuration`

**Description:**

PAN configuration parameter set.

###### sl_wisun_br_params_configuration_t

`typedef struct sl_wisun_br_params_configuration_s sl_wisun_br_params_configuration_t`

**Description:**

PAN configuration parameter set.

###### sl_wisun_br_params_dhcp

`typedef struct sl_wisun_br_params_dhcp_s sl_wisun_br_params_dhcp`

**Description:**

DHCP server parameter set.

###### sl_wisun_br_params_dhcp_t

`typedef struct sl_wisun_br_params_dhcp_s sl_wisun_br_params_dhcp_t`

**Description:**

DHCP server parameter set.

###### sl_wisun_br_params_discovery

`typedef struct sl_wisun_br_params_discovery_s sl_wisun_br_params_discovery`

**Description:**

PAN discovery parameter set.

###### sl_wisun_br_params_discovery_t

`typedef struct sl_wisun_br_params_discovery_s sl_wisun_br_params_discovery_t`

**Description:**

PAN discovery parameter set.

###### sl_wisun_br_params_eapol

`typedef struct sl_wisun_br_params_eapol_s sl_wisun_br_params_eapol`

**Description:**

Authentication parameter set.

###### sl_wisun_br_params_eapol_t

`typedef struct sl_wisun_br_params_eapol_s sl_wisun_br_params_eapol_t`

**Description:**

Authentication parameter set.

###### sl_wisun_br_params_lfn_parent

`typedef struct sl_wisun_br_params_lfn_parent_s sl_wisun_br_params_lfn_parent`

**Description:**

LFN parent parameter set.

###### sl_wisun_br_params_lfn_parent_t

`typedef struct sl_wisun_br_params_lfn_parent_s sl_wisun_br_params_lfn_parent_t`

**Description:**

LFN parent parameter set.

###### sl_wisun_br_params_misc

`typedef struct sl_wisun_br_params_misc_s sl_wisun_br_params_misc`

**Description:**

Misc parameter set.

###### sl_wisun_br_params_misc_t

`typedef struct sl_wisun_br_params_misc_s sl_wisun_br_params_misc_t`

**Description:**

Misc parameter set.

###### sl_wisun_br_params_mpl

`typedef struct sl_wisun_br_params_mpl_s sl_wisun_br_params_mpl`

**Description:**

MPL parameter set.

###### sl_wisun_br_params_mpl_t

`typedef struct sl_wisun_br_params_mpl_s sl_wisun_br_params_mpl_t`

**Description:**

MPL parameter set.

###### sl_wisun_br_params_rpl

`typedef struct sl_wisun_br_params_rpl_s sl_wisun_br_params_rpl`

**Description:**

RPL parameter set.

###### sl_wisun_br_params_rpl_t

`typedef struct sl_wisun_br_params_rpl_s sl_wisun_br_params_rpl_t`

**Description:**

RPL parameter set.

###### sl_wisun_br_params_traffic_t

`typedef struct sl_wisun_br_params_traffic_s sl_wisun_br_params_traffic_t`

**Description:**

Traffic parameter set.

###### sl_wisun_ip_address_t

`typedef in6_addr_t sl_wisun_ip_address_t`

**Description:**

IPv6 address structure.

###### sl_wisun_ipv6_up_handler_t

`typedef sl_status_t(* sl_wisun_ipv6_up_handler_t) (const uint8_t *data, size_t data_length)`

**Description:**

Handler called for an IPv6 packet from Wi-SUN network.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
||[in]|data|Pointer to IPv6 header|
||[out]|data_length|Length of IPv6 packet data in bytes|

**Details:**

**Returns**

- SL_STATUS_OK if successful, an error code otherwise

###### sl_wisun_params_configuration

`typedef struct sl_wisun_params_configuration_s sl_wisun_params_configuration`

**Description:**

PAN configuration parameter set.

###### sl_wisun_params_configuration_t

`typedef struct sl_wisun_params_configuration_s sl_wisun_params_configuration_t`

**Description:**

PAN configuration parameter set.

###### sl_wisun_params_dhcp

`typedef struct sl_wisun_params_dhcp_s sl_wisun_params_dhcp`

**Description:**

DHCP parameter set.

###### sl_wisun_params_dhcp_t

`typedef struct sl_wisun_params_dhcp_s sl_wisun_params_dhcp_t`

**Description:**

DHCP parameter set.

###### sl_wisun_params_discovery

`typedef struct sl_wisun_params_discovery_s sl_wisun_params_discovery`

**Description:**

PAN discovery parameter set.

###### sl_wisun_params_discovery_t

`typedef struct sl_wisun_params_discovery_s sl_wisun_params_discovery_t`

**Description:**

PAN discovery parameter set.

###### sl_wisun_params_eapol

`typedef struct sl_wisun_params_eapol_s sl_wisun_params_eapol`

**Description:**

Authentication parameter set.

###### sl_wisun_params_eapol_t

`typedef struct sl_wisun_params_eapol_s sl_wisun_params_eapol_t`

**Description:**

Authentication parameter set.

###### sl_wisun_params_lfn_parent

`typedef struct sl_wisun_params_lfn_parent_s sl_wisun_params_lfn_parent`

**Description:**

LFN parent parameter set.

###### sl_wisun_params_lfn_parent_t

`typedef struct sl_wisun_params_lfn_parent_s sl_wisun_params_lfn_parent_t`

**Description:**

LFN parent parameter set.

###### sl_wisun_params_misc

`typedef struct sl_wisun_params_misc_s sl_wisun_params_misc`

**Description:**

Misc parameter set.

###### sl_wisun_params_misc_t

`typedef struct sl_wisun_params_misc_s sl_wisun_params_misc_t`

**Description:**

Misc parameter set.

###### sl_wisun_params_mpl

`typedef struct sl_wisun_params_mpl_s sl_wisun_params_mpl`

**Description:**

MPL parameter set.

###### sl_wisun_params_mpl_t

`typedef struct sl_wisun_params_mpl_s sl_wisun_params_mpl_t`

**Description:**

MPL parameter set.

###### sl_wisun_params_rpl

`typedef struct sl_wisun_params_rpl_s sl_wisun_params_rpl`

**Description:**

RPL parameter set.

###### sl_wisun_params_rpl_t

`typedef struct sl_wisun_params_rpl_s sl_wisun_params_rpl_t`

**Description:**

RPL parameter set.

###### sl_wisun_params_traffic_t

`typedef struct sl_wisun_params_traffic_s sl_wisun_params_traffic_t`

**Description:**

Traffic parameter set.

##### Variables

###### sl_wisun_broadcast_mac

```
const sl_wisun_mac_address_t sl_wisun_broadcast_mac
```

**Description:** Broadcast MAC address.

##### Macros

`#define SL_WISUN_ADVERT_FRAGMENT_DISABLE UINT32_MAX`

**Description**: Maximum fragment duration. Disables advert fragmentation.

`#define SL_WISUN_CHANNEL_MASK_SIZE 32`

**Description**: Size of a channel mask.

`#define SL_WISUN_CHANNEL_SPACING_100HZ SL_WISUN_CHANNEL_SPACING_100KHZ`

**Description**: Channel spacing 100 kHz for backward compatibility.

`#define SL_WISUN_CHANNEL_SPACING_200HZ SL_WISUN_CHANNEL_SPACING_200KHZ`

**Description**: Channel spacing 200 kHz for backward compatibility.

`#define SL_WISUN_CHANNEL_SPACING_400HZ SL_WISUN_CHANNEL_SPACING_400KHZ`

**Description**: Channel spacing 400 kHz for backward compatibility.

`#define SL_WISUN_CHANNEL_SPACING_600HZ SL_WISUN_CHANNEL_SPACING_600KHZ`

**Description**: Channel spacing 600 kHz for backward compatibility.

`#define SL_WISUN_DC_ID_LEN 32`

**Description**: Maximum size of the Direct Connect ID.

`#define SL_WISUN_EAP_IDENTITY_SIZE 32`

**Description**: Maximum size of EAP identity.

`#define SL_WISUN_FILTER_BITFIELD_SIZE ((SL_WISUN_TRACE_GROUP_COUNT + 7) / 8)`

**Description**: Size of the filter bitfield.

`#define SL_WISUN_GAK_LEN 16`

**Description**: Length of a GAK in bytes.

`#define SL_WISUN_GTK_LEN 16`

**Description**: Length of a GTK in bytes.

`#define SL_WISUN_GTK_NUM 4`

**Description**: Number of GTKs returned by sl_wisun_get_gtks()

`#define SL_WISUN_LGTK_NUM 3`

**Description**: Number of LGTKs returned by sl_wisun_get_gtks()

`#define SL_WISUN_MAC_ADDRESS_SIZE 8`

**Description**: Size of a MAC address.

`#define SL_WISUN_MAX_PHY_MODE_ID_COUNT 15`

**Description**: Maximum number of PhyModeId allowed in POM-IE.

`#define SL_WISUN_NETWORK_NAME_SIZE 32`

**Description**: Maximum size of the Wi-SUN network name.

`#define SL_WISUN_PMK_LEN 32`

**Description**: Length of a PMK in bytes.

`#define SL_WISUN_RF_TEST_RSSI_NOT_AVAILABLE (-128)`

**Description**: Value for rssi when not applicable (e.g. TX or non-RX events)

`#define SL_WISUN_TRACE_THREAD_EVENT_LOOP "EVL"`

**Description**: Thread identifier "ws_evl".

`#define SL_WISUN_TRACE_THREAD_EVENT_TASK "EVT"`

**Description**: Thread identifier "ws_evt".

`#define SL_WISUN_TRACE_THREAD_MAC "MAC"`

**Description**: Thread identifier "ws_rf".

`#define SL_WISUN_TRACE_THREAD_WISUN "WS"`

**Description**: Thread identifier "ws_task".

BR advanced connection parameters for [sl_wisun_br_set_advanced_parameters](sl-wisun-br-api#sl-wisun-br-set-advanced-parameters). 

###### Public Attributes

###### trickle_pa (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_br_advanced_parameters_t::trickle_pa
```

**Description:** PAN advertisement trickle timer parameters.

###### trickle_pc (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_br_advanced_parameters_t::trickle_pc
```

**Description:** PAN configuration trickle timer parameters.

###### version (heading level 7)

```
uint32_t sl_wisun_br_advanced_parameters_t::version
```

**Description:** Version of [sl_wisun_br_advanced_parameters_t](sl-wisun-br-advanced-parameters-t).

**Details:** Set to `SL_WISUN_BR_ADVANCED_PARAMS_API_VERSION`.

Used to identify the layout of the structure when applying advanced BR connection parameters. Older supported versions may be accepted and updated internally to the current format, while unsupported versions are rejected.

BR parameter set. 

###### Public Attributes

###### configuration (heading level 7)

```
sl_wisun_br_params_configuration_t sl_wisun_br_connection_params_t::configuration
```

**Description:** PAN configuration parameter set.

###### dhcp (heading level 7)

```
sl_wisun_br_params_dhcp_t sl_wisun_br_connection_params_t::dhcp
```

**Description:** DHCP server parameter set.

###### discovery (heading level 7)

```
sl_wisun_br_params_discovery_t sl_wisun_br_connection_params_t::discovery
```

**Description:** PAN discovery parameter set.

###### eapol (heading level 7)

```
sl_wisun_br_params_eapol_t sl_wisun_br_connection_params_t::eapol
```

**Description:** Authentication parameter set.

###### enable_ffn10 (heading level 7)

```
uint8_t sl_wisun_br_connection_params_t::enable_ffn10
```

**Description:** Enable authentication of FAN 1.0 routers.

###### lfn_parent (heading level 7)

```
sl_wisun_br_params_lfn_parent_t sl_wisun_br_connection_params_t::lfn_parent
```

**Description:** LFN parent parameter set.

###### mac (heading level 7)

```
sl_wisun_mac_params_t sl_wisun_br_connection_params_t::mac
```

**Description:** MAC parameter set.

###### misc (heading level 7)

```
sl_wisun_br_params_misc_t sl_wisun_br_connection_params_t::misc
```

**Description:** Misc parameter set.

###### mpl (heading level 7)

```
sl_wisun_br_params_mpl_t sl_wisun_br_connection_params_t::mpl
```

**Description:** MPL parameter set.

###### pan_capacity (heading level 7)

```
uint32_t sl_wisun_br_connection_params_t::pan_capacity
```

**Description:** Maximum number of nodes supported by border router at once.

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_connection_params_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### rpl (heading level 7)

```
sl_wisun_br_params_rpl_t sl_wisun_br_connection_params_t::rpl
```

**Description:** RPL parameter set.

###### traffic (heading level 7)

```
sl_wisun_br_params_traffic_t sl_wisun_br_connection_params_t::traffic
```

**Description:** Traffic parameter set.

###### version (heading level 7)

```
uint32_t sl_wisun_br_connection_params_t::version
```

**Description:** Version of this API.

**Details:** This field allows to store the parameters in an NVM and check on reload that they are compatible with the stack if there was an update.

BR LFN parenting parameter set. 

###### Public Attributes

###### lfn_broadcast_interval_ms (heading level 7)

```
uint32_t sl_wisun_br_lfn_params_t::lfn_broadcast_interval_ms
```

**Description:** Time between LFN Broadcast windows (millisecond) Specification range [10000, 600000] (10s to 10m)

###### lfn_broadcast_sync_period (heading level 7)

```
uint8_t sl_wisun_br_lfn_params_t::lfn_broadcast_sync_period
```

**Description:** Number of LFN Broadcast Intervals between broadcast sync messages Specification range [1, 60].

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_lfn_params_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### version (heading level 7)

```
uint32_t sl_wisun_br_lfn_params_t::version
```

**Description:** Version of this API, must be the first field.

**Details:** This field allows to store the parameters in an NVM and check on reload that they are compatible with the stack if there was an update.

PAN configuration parameter set. 

###### Public Attributes

###### trickle_pc (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_br_params_configuration_s::trickle_pc
```

**Description:** PAN configuration trickle timer.

DHCP server parameter set. 

###### Public Attributes

###### dhcp_address_lifetime_s (heading level 7)

```
uint32_t sl_wisun_br_params_dhcp_s::dhcp_address_lifetime_s
```

**Description:** Deprecated.

PAN discovery parameter set. 

###### Public Attributes

###### trickle_pa (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_br_params_discovery_s::trickle_pa
```

**Description:** PAN advertisement trickle timer.

Authentication parameter set. 

###### Public Attributes

###### key_lifetimes (heading level 7)

```
sl_wisun_key_lifetimes_params_t sl_wisun_br_params_eapol_s::key_lifetimes
```

**Description:** Security key lifetimes.

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_params_eapol_s::reserved
```

**Description:** Reserved, set to zero.

###### sec_prot_trickle (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_br_params_eapol_s::sec_prot_trickle
```

**Description:** Deprecated.

###### sec_prot_trickle_expirations (heading level 7)

```
uint8_t sl_wisun_br_params_eapol_s::sec_prot_trickle_expirations
```

**Description:** Deprecated.

###### temp_min_timeout_s (heading level 7)

```
uint16_t sl_wisun_br_params_eapol_s::temp_min_timeout_s
```

**Description:** Deprecated.

LFN parent parameter set. 

###### Public Attributes

###### lfn_lpc_retry_count (heading level 7)

```
uint8_t sl_wisun_br_params_lfn_parent_s::lfn_lpc_retry_count
```

**Description:** Number of broadcast LFN Pan Config retries when LFN Version is incremented Referred to as LFN_MAINTAIN_PARENT_TIME in FAN TPS 1.1.

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_params_lfn_parent_s::reserved[3]
```

**Description:** Reserved, set to zero.

Misc parameter set. 

###### Public Attributes

###### reserved (heading level 7)

```
uint16_t sl_wisun_br_params_misc_s::reserved
```

**Description:** Reserved, set to zero.

###### temp_link_min_timeout_s (heading level 7)

```
uint16_t sl_wisun_br_params_misc_s::temp_link_min_timeout_s
```

**Description:** Deprecated.

MPL parameter set. 

###### Public Attributes

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_params_mpl_s::reserved
```

**Description:** Reserved, set to zero.

###### seed_set_entry_lifetime_s (heading level 7)

```
uint16_t sl_wisun_br_params_mpl_s::seed_set_entry_lifetime_s
```

**Description:** MPL seed set entry lifetime.

###### trickle (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_br_params_mpl_s::trickle
```

**Description:** Warning: MPL parameters may be overwritten for border router MPL trickle timer.

###### trickle_expirations (heading level 7)

```
uint8_t sl_wisun_br_params_mpl_s::trickle_expirations
```

**Description:** MPL trickle timer expirations.

RPL parameter set. 

###### Public Attributes

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_params_rpl_s::reserved[2]
```

**Description:** Reserved, set to zero.

###### rpl_dag_max_rank_increase (heading level 7)

```
uint16_t sl_wisun_br_params_rpl_s::rpl_dag_max_rank_increase
```

**Description:** RPL allowable increase in rank in support of local repair RFC 6550 6.7.6.

###### rpl_default_lifetime (heading level 7)

```
uint8_t sl_wisun_br_params_rpl_s::rpl_default_lifetime
```

**Description:** RPL default lifetime for routes (lifetime units) RFC6550 6.7.6.

###### rpl_default_lifetime_unit (heading level 7)

```
uint16_t sl_wisun_br_params_rpl_s::rpl_default_lifetime_unit
```

**Description:** RPL default lifetime unit RFC6550 6.7.6.

###### rpl_dio_interval_doublings (heading level 7)

```
uint8_t sl_wisun_br_params_rpl_s::rpl_dio_interval_doublings
```

**Description:** RPL trickle Imax (DIOIntervalDoublings)

###### rpl_dio_interval_min (heading level 7)

```
uint8_t sl_wisun_br_params_rpl_s::rpl_dio_interval_min
```

**Description:** RPL trickle Imin equals (2^rpl_dio_interval_min) ms.

###### rpl_dio_redundancy_constant (heading level 7)

```
uint8_t sl_wisun_br_params_rpl_s::rpl_dio_redundancy_constant
```

**Description:** RPL trickle k DIORedundancyConstant.

###### rpl_min_hop_rank_increase (heading level 7)

```
uint16_t sl_wisun_br_params_rpl_s::rpl_min_hop_rank_increase
```

**Description:** RPL MinHopRankIncrease RFC6550 3.5.1.

Traffic parameter set. 

###### Public Attributes

###### ipv6_mru (heading level 7)

```
uint16_t sl_wisun_br_params_traffic_s::ipv6_mru
```

**Description:** Maximum Receive Unit (MRU) for fragmented IPv6 packets in bytes. A larger packet will be silently discarded.

###### lowpan_mtu (heading level 7)

```
uint16_t sl_wisun_br_params_traffic_s::lowpan_mtu
```

**Description:** Maximum Transmission Unit (MTU) for 6LoWPAN packets in bytes. A larger packet will be fragmented using 6LoWPAN fragmentation.

###### max_edfe_fragment_count (heading level 7)

```
uint8_t sl_wisun_br_params_traffic_s::max_edfe_fragment_count
```

**Description:** Maximum number of 6LoWPAN/IPv6 fragments to send in a single EDFE transaction (0 to 10). 0 disables EDFE for fragmented packets.

###### reserved (heading level 7)

```
uint8_t sl_wisun_br_params_traffic_s::reserved[3]
```

**Description:** Reserved, set to zero.

Border Router routing table entry. 

###### Public Attributes

###### backup (heading level 7)

```
in6_addr_t sl_wisun_br_routing_table_entry_t::backup
```

**Description:** GUA/ULA of the routed node's backup parent. INADDR_ANY if not set.

###### preferred (heading level 7)

```
in6_addr_t sl_wisun_br_routing_table_entry_t::preferred
```

**Description:** GUA/ULA of the routed node's preferred parent.

###### target (heading level 7)

```
in6_addr_t sl_wisun_br_routing_table_entry_t::target
```

**Description:** GUA/ULA of the routed node.

Channel mask. 

###### Public Attributes

###### mask (heading level 7)

```
uint8_t sl_wisun_channel_mask_t::mask[SL_WISUN_CHANNEL_MASK_SIZE]
```

**Description:** Bit mask of channels.

**Details:** This field specifies a bit mask of channels, one bit per channel. First byte of the array represents channel numbers 0 - 7, with bit 0 being channel 0. Second byte represents channel numbers 8 - 15 and so forth.

FFN parameter set. 

###### Public Attributes

###### configuration (heading level 7)

```
sl_wisun_params_configuration_t sl_wisun_connection_params_t::configuration
```

**Description:** PAN configuration parameter set.

###### dhcp (heading level 7)

```
sl_wisun_params_dhcp_t sl_wisun_connection_params_t::dhcp
```

**Description:** DHCP parameter set.

###### direct_connect_eapol (heading level 7)

```
sl_wisun_params_eapol_t sl_wisun_connection_params_t::direct_connect_eapol
```

**Description:** Direct Connect Authentication parameter set.

###### discovery (heading level 7)

```
sl_wisun_params_discovery_t sl_wisun_connection_params_t::discovery
```

**Description:** PAN discovery parameter set.

###### eapol (heading level 7)

```
sl_wisun_params_eapol_t sl_wisun_connection_params_t::eapol
```

**Description:** Authentication parameter set.

###### lfn_parent (heading level 7)

```
sl_wisun_params_lfn_parent_t sl_wisun_connection_params_t::lfn_parent
```

**Description:** LFN parent parameter set.

###### mac (heading level 7)

```
sl_wisun_mac_params_t sl_wisun_connection_params_t::mac
```

**Description:** MAC parameter set.

###### misc (heading level 7)

```
sl_wisun_params_misc_t sl_wisun_connection_params_t::misc
```

**Description:** Misc parameter set.

###### mpl (heading level 7)

```
sl_wisun_params_mpl_t sl_wisun_connection_params_t::mpl
```

**Description:** MPL parameter set.

###### rpl (heading level 7)

```
sl_wisun_params_rpl_t sl_wisun_connection_params_t::rpl
```

**Description:** RPL parameter set.

###### traffic (heading level 7)

```
sl_wisun_params_traffic_t sl_wisun_connection_params_t::traffic
```

**Description:** Traffic parameter set.

###### version (heading level 7)

```
uint32_t sl_wisun_connection_params_t::version
```

**Description:** Version of this API.

**Details:** This field allows to store the parameters in an NVM and check on reload that they are compatible with the stack if there was an update.

Direct Connect ID. 

###### Public Attributes

###### id (heading level 7)

```
uint8_t sl_wisun_dc_id_t::id[SL_WISUN_DC_ID_LEN]
```

**Description:** Direct Connect ID.

**Details:** **Note**

- The format of the identifier is application-specific.

FFN advanced connection parameters for [sl_wisun_set_ffn_advanced_parameters](sl-wisun-api#sl-wisun-set-ffn-advanced-parameters). 

###### Public Attributes

###### dhcp_solicit_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_ffn_advanced_parameters_t::dhcp_solicit_txalg
```

**Description:** RFC8415 TX algorithm for DHCP solicitation transmissions.

###### key_request_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_ffn_advanced_parameters_t::key_request_txalg
```

**Description:** RFC8415 TX algorithm for EAPOL Key-request transmissions.

###### rpl (heading level 7)

```
sl_wisun_ffn_advanced_rpl_params_t sl_wisun_ffn_advanced_parameters_t::rpl
```

**Description:** Advanced RPL parameters.

###### trickle_pa (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_ffn_advanced_parameters_t::trickle_pa
```

**Description:** PAN advertisement trickle timer parameters.

###### trickle_pas (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_ffn_advanced_parameters_t::trickle_pas
```

**Description:** PAN advertisement Solicit trickle timer parameters.

###### trickle_pc (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_ffn_advanced_parameters_t::trickle_pc
```

**Description:** PAN configuration trickle timer parameters.

###### trickle_pcs (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_ffn_advanced_parameters_t::trickle_pcs
```

**Description:** PAN configuration Solicit trickle timer parameters.

###### version (heading level 7)

```
uint32_t sl_wisun_ffn_advanced_parameters_t::version
```

**Description:** Version of [sl_wisun_ffn_advanced_parameters_t](sl-wisun-ffn-advanced-parameters-t).

**Details:** Set to `SL_WISUN_FFN_ADVANCED_PARAMS_API_VERSION`.

Used to identify the layout of the structure when applying advanced connection parameters. Older supported versions may be accepted and updated internally to the current format, while unsupported versions are rejected.

Advanced RPL parameters for [sl_wisun_set_ffn_advanced_parameters](sl-wisun-api#sl-wisun-set-ffn-advanced-parameters). 

###### Public Attributes

###### dao_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_ffn_advanced_rpl_params_t::dao_txalg
```

**Description:** RFC8415 TX algorithm parameters for DAO transmission rand specification range [0.0, 1.0] irt_s specification range [1, 60] mrt_s specification range [0, 600] mrd_s specification range [0, 3600] mrc specification range [0, 15].

###### etx_probe_max_delay_s (heading level 7)

```
uint16_t sl_wisun_ffn_advanced_rpl_params_t::etx_probe_max_delay_s
```

**Description:** Maximum delay before sending an ETX probe (seconds).

###### first_dis_max_delay_s (heading level 7)

```
uint16_t sl_wisun_ffn_advanced_rpl_params_t::first_dis_max_delay_s
```

**Description:** Maximum delay before sending the first RPL DIS (unicast/multicast) packet following transition to Join State 4 - Preferred Parent Selection (seconds)

Key lifetimes parameter set. 

###### Public Attributes

###### ffn_revocation_lifetime_reduction (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::ffn_revocation_lifetime_reduction
```

**Description:** FFN_REVOCATION_LIFETIME_REDUCTION Factor by which the active GTK lifetime is reduced during node revocation procedures.

###### gtk_expire_offset_m (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::gtk_expire_offset_m
```

**Description:** GTK_EXPIRE_OFFSET (minutes) The expiration time of a GTK is calculated as the expiration time of the GTK most recently installed at the Border Router plus GTK_EXPIRE_OFFSET.

###### gtk_new_activation_time (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::gtk_new_activation_time
```

**Description:** GTK_NEW_ACTIVATION_TIME The time at which the Border Router activates the next GTK prior to expiration of the currently activated GTK.

###### gtk_new_install_required (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::gtk_new_install_required
```

**Description:** GTK_NEW_INSTALL_REQUIRED The percentage of time elapsed in the active GTK’s lifetime at which a new GTK must be installed on the Border Router.

###### lfn_revocation_lifetime_reduction (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::lfn_revocation_lifetime_reduction
```

**Description:** LFN_REVOCATION_LIFETIME_REDUCTION Factor by which the active LGTK lifetime is reduced during node revocation procedures.

###### lgtk_expire_offset_m (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::lgtk_expire_offset_m
```

**Description:** LGTK_EXPIRE_OFFSET (minutes) The expiration time of a LGTK is calculated as the expiration time of the GTK most recently installed at the Border Router plus LGTK_EXPIRE_OFFSET.

###### lgtk_new_activation_time (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::lgtk_new_activation_time
```

**Description:** LGTK_NEW_ACTIVATION_TIME The time at which the Border Router activates the next LGTK prior to expiration of the currently activated LGTK.

###### lgtk_new_install_required (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::lgtk_new_install_required
```

**Description:** LGTK_NEW_INSTALL_REQUIRED The percentage of time elapsed in the active LGTK’s lifetime at which a new LGTK must be installed on the Border Router.

###### lpmk_lifetime_m (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::lpmk_lifetime_m
```

**Description:** LPMK lifetime (minutes)

###### lptk_lifetime_m (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::lptk_lifetime_m
```

**Description:** LPTK lifetime (minutes)

###### pmk_lifetime_m (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::pmk_lifetime_m
```

**Description:** PMK lifetime (minutes)

###### ptk_lifetime_m (heading level 7)

```
uint32_t sl_wisun_key_lifetimes_params_t::ptk_lifetime_m
```

**Description:** PTK lifetime (minutes)

LFN advanced connection parameters for [sl_wisun_set_lfn_advanced_parameters](sl-wisun-api#sl-wisun-set-lfn-advanced-parameters). 

###### Public Attributes

###### dhcp_solicit_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_lfn_advanced_parameters_t::dhcp_solicit_txalg
```

**Description:** RFC8415 TX algorithm for DHCP solicitation transmissions.

###### key_request_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_lfn_advanced_parameters_t::key_request_txalg
```

**Description:** RFC8415 TX algorithm for EAPOL Key-request transmissions.

###### lfn_na_wait_duration_m (heading level 7)

```
uint8_t sl_wisun_lfn_advanced_parameters_t::lfn_na_wait_duration_m
```

**Description:** Duration for which an LFN waits for a registration confirmation (minutes).

###### reserved (heading level 7)

```
uint8_t sl_wisun_lfn_advanced_parameters_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### version (heading level 7)

```
uint32_t sl_wisun_lfn_advanced_parameters_t::version
```

**Description:** Version of [sl_wisun_lfn_advanced_parameters_t](sl-wisun-lfn-advanced-parameters-t).

**Details:** Set to `SL_WISUN_LFN_ADVANCED_PARAMS_API_VERSION`.

Used to identify the layout of the structure when applying advanced LFN parameters. Older supported versions may be accepted and updated internally to the current format, while unsupported versions are rejected.

LFN connection parameters. 

###### Public Attributes

###### discovery_slot_time_ms (heading level 7)

```
uint8_t sl_wisun_lfn_params_connection_t::discovery_slot_time_ms
```

**Description:** Duration of LFN PAN Advertisement (LPA) listening slot (millisecond) Specification range [15, 255].

###### discovery_slots (heading level 7)

```
uint8_t sl_wisun_lfn_params_connection_t::discovery_slots
```

**Description:** Number of LPA slots for which an LFN shall listen for LPA frames Specification range [1, 255].

###### lpas_interval_s (heading level 7)

```
uint16_t sl_wisun_lfn_params_connection_t::lpas_interval_s
```

**Description:** Delay between two LFN PAN Advertistement Solicit messages.

**Details:** The delay is applied between the end of the response period and the next LPAS. Range [1, 65535]

LFN data layer parameters. 

###### Public Attributes

###### eapol_unicast_interval_ms (heading level 7)

```
uint32_t sl_wisun_lfn_params_data_layer_t::eapol_unicast_interval_ms
```

**Description:** Shorter LFN Unicast interval used during the EAPOL exchange (milliseconds).

**Details:** Wi-SUN FAN TPS mandates this to be greater or equal than unicast_interval_min_ms

###### lfn_maintain_parent_time (heading level 7)

```
uint8_t sl_wisun_lfn_params_data_layer_t::lfn_maintain_parent_time
```

**Description:** The LFN assumes its parent is lost after [lfn_maintain_parent_time] number of Broadcast sync periods with no message received from its parent.

**Details:** Specification range [1, 60]

###### reserved (heading level 7)

```
uint8_t sl_wisun_lfn_params_data_layer_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### unicast_interval_max_ms (heading level 7)

```
uint32_t sl_wisun_lfn_params_data_layer_t::unicast_interval_max_ms
```

**Description:** Maximum acceptable LFN unicast interval (milliseconds)

###### unicast_interval_min_ms (heading level 7)

```
uint32_t sl_wisun_lfn_params_data_layer_t::unicast_interval_min_ms
```

**Description:** Minimum acceptable LFN unicast interval (milliseconds)

###### unicast_interval_ms (heading level 7)

```
uint32_t sl_wisun_lfn_params_data_layer_t::unicast_interval_ms
```

**Description:** Initial LFN Unicast interval proposed by the LFN (milliseconds).

**Details:** The real unicast interval duration is negotiated with the LFN parent, between unicast_interval_min_ms and unicast_interval_max_ms.

LFN EAPOL parameters. 

###### Public Attributes

###### allow_skip (heading level 7)

```
uint8_t sl_wisun_lfn_params_eapol_t::allow_skip
```

**Description:** If true, allow join state 2 to be skipped using cached credentials from the previous connection.

###### initial_key_max_s (heading level 7)

```
uint16_t sl_wisun_lfn_params_eapol_t::initial_key_max_s
```

**Description:** Max delay of first key request (seconds)

###### initial_key_retry_limit (heading level 7)

```
uint8_t sl_wisun_lfn_params_eapol_t::initial_key_retry_limit
```

**Description:** Maximum retransmission count.

###### initial_key_retry_max_limit_s (heading level 7)

```
uint16_t sl_wisun_lfn_params_eapol_t::initial_key_retry_max_limit_s
```

**Description:** Maximum duration for retransmissions (seconds)

###### initial_key_retry_min_s (heading level 7)

```
uint16_t sl_wisun_lfn_params_eapol_t::initial_key_retry_min_s
```

**Description:** Initial retransmission time (seconds)

###### lgtk_max_mismatch_m (heading level 7)

```
uint16_t sl_wisun_lfn_params_eapol_t::lgtk_max_mismatch_m
```

**Description:** LGTK_MAX_MISMATCH (minutes) Maximum time between a SUP detecting a LGTKHASH mismatch and the SUP initiating Msg1 of the authentication flow.

###### reserved (heading level 7)

```
uint8_t sl_wisun_lfn_params_eapol_t::reserved[2]
```

**Description:** Reserved, set to zero.

LFN network parameters. 

###### Public Attributes

###### lfn_na_wait_duration_m (heading level 7)

```
uint8_t sl_wisun_lfn_params_network_t::lfn_na_wait_duration_m
```

**Description:** Duration for which an LFN waits for a registration confirmation (minutes).

**Details:** This value is administratively configured and should be consistent throughout the network. Make sure that the value is equal to or greather than the corresponding field on FFNs. Specification range [30, 120] (set lower for test purposes)

###### lfn_registration_lifetime_m (heading level 7)

```
uint16_t sl_wisun_lfn_params_network_t::lfn_registration_lifetime_m
```

**Description:** Address registration lifetime (IPv6 lease duration) the LFN requires to the Border Router (minutes).

**Details:** Specification range [1440, 5040]

###### reserved (heading level 7)

```
uint8_t sl_wisun_lfn_params_network_t::reserved
```

**Description:** Reserved, set to zero.

LFN power parameters. 

###### Public Attributes

###### broadcast_lts_only (heading level 7)

```
uint8_t sl_wisun_lfn_params_power_t::broadcast_lts_only
```

**Description:** If true, the LFN wakes up only for broadcast slots containing synchronization information.

**Details:** If false, the node wakes up on every LFN broadcast slot.

###### listening_window_min_us (heading level 7)

```
uint16_t sl_wisun_lfn_params_power_t::listening_window_min_us
```

**Description:** Minimum duration of the listening window.

**Details:** Applies to both Unicast and Broadcast slots.

###### reserved (heading level 7)

```
uint8_t sl_wisun_lfn_params_power_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### window_margin_min_us (heading level 7)

```
uint16_t sl_wisun_lfn_params_power_t::window_margin_min_us
```

**Description:** Minimum margin added to the listening window (before and after).

**Details:** The real margin increases with aging synchronization info.

LFN parameter set. 

###### Public Attributes

###### connection (heading level 7)

```
sl_wisun_lfn_params_connection_t sl_wisun_lfn_params_t::connection
```

**Description:** LFN connection parameters.

###### data_layer (heading level 7)

```
sl_wisun_lfn_params_data_layer_t sl_wisun_lfn_params_t::data_layer
```

**Description:** LFN data layer parameters.

###### dhcp (heading level 7)

```
sl_wisun_params_dhcp_t sl_wisun_lfn_params_t::dhcp
```

**Description:** DHCP parameter set.

###### eapol (heading level 7)

```
sl_wisun_lfn_params_eapol_t sl_wisun_lfn_params_t::eapol
```

**Description:** LFN EAPOL parameters.

###### mac (heading level 7)

```
sl_wisun_mac_params_t sl_wisun_lfn_params_t::mac
```

**Description:** MAC parameter set.

###### network (heading level 7)

```
sl_wisun_lfn_params_network_t sl_wisun_lfn_params_t::network
```

**Description:** LFN network parameters.

###### power (heading level 7)

```
sl_wisun_lfn_params_power_t sl_wisun_lfn_params_t::power
```

**Description:** LFN power parameters.

###### traffic (heading level 7)

```
sl_wisun_params_traffic_t sl_wisun_lfn_params_t::traffic
```

**Description:** Traffic parameter set.

###### version (heading level 7)

```
uint32_t sl_wisun_lfn_params_t::version
```

**Description:** Version of this API.

**Details:** This field allows to store the parameters in an NVM and check on reload that they are compatible with the stack if there was an update.

Frame received information. 

###### Public Attributes

###### data (heading level 7)

```
union sl_wisun_logger_event_frame_received_t::@4 sl_wisun_logger_event_frame_received_t::data
```

**Description:** Data of the received frame.

###### pa (heading level 7)

```
sl_wisun_logger_event_pa_data_t sl_wisun_logger_event_frame_received_t::pa
```

**Description:** PAN Advertisement information.

###### rssi (heading level 7)

```
int8_t sl_wisun_logger_event_frame_received_t::rssi
```

**Description:** RSSI of the received frame.

###### type (heading level 7)

```
uint32_t sl_wisun_logger_event_frame_received_t::type
```

**Description:** Frame type.

Neighbor lifetime change information. 

###### Public Attributes

###### lifetime (heading level 7)

```
uint32_t sl_wisun_logger_event_neighbor_lifetime_changed_t::lifetime
```

**Description:** Lifetime of the neighbor in seconds after update.

Wisun Pan Advertisement information. 

###### Public Attributes

###### load_factor (heading level 7)

```
uint8_t sl_wisun_logger_event_pa_data_t::load_factor
```

**Description:** Load factor.

###### pan_id (heading level 7)

```
uint16_t sl_wisun_logger_event_pa_data_t::pan_id
```

**Description:** PAN ID.

###### pan_size (heading level 7)

```
uint16_t sl_wisun_logger_event_pa_data_t::pan_size
```

**Description:** PAN size.

###### routing_cost (heading level 7)

```
uint16_t sl_wisun_logger_event_pa_data_t::routing_cost
```

**Description:** Routing cost.

RF test RX event information (valid when SL_RAIL_EVENT_RX_PACKET_RECEIVED is set) 

###### Public Attributes

###### reserved (heading level 7)

```
uint8_t sl_wisun_logger_event_rf_test_rx_t::reserved[3]
```

**Description:** Reserved for future use.

###### rssi (heading level 7)

```
int8_t sl_wisun_logger_event_rf_test_rx_t::rssi
```

**Description:** RSSI in dBm; [SL_WISUN_RF_TEST_RSSI_NOT_AVAILABLE](sl-wisun-types#sl-wisun-rf-test-rssi-not-available) when not applicable.

RF test event information. 

###### Public Attributes

###### events (heading level 7)

```
uint64_t sl_wisun_logger_event_rf_test_t::events
```

**Description:** RAIL events associated with the RF test event.

###### rx (heading level 7)

```
sl_wisun_logger_event_rf_test_rx_t sl_wisun_logger_event_rf_test_t::rx
```

**Description:** RX packet received information (when SL_RAIL_EVENT_RX_PACKET_RECEIVED is set in events)

###### u (heading level 7)

```
union sl_wisun_logger_event_rf_test_t::@5 sl_wisun_logger_event_rf_test_t::u
```

**Description:** Event-specific data.

Wisun Event information. 

###### Public Attributes

###### address (heading level 7)

```
sl_wisun_mac_address_t sl_wisun_logger_event_t::address
```

**Description:** Address of the node.

###### frame_received (heading level 7)

```
sl_wisun_logger_event_frame_received_t sl_wisun_logger_event_t::frame_received
```

**Description:** Frame received information.

###### neighbor_lifetime_changed (heading level 7)

```
sl_wisun_logger_event_neighbor_lifetime_changed_t sl_wisun_logger_event_t::neighbor_lifetime_changed
```

**Description:** Neighbor lifetime change information.

###### rf_test (heading level 7)

```
sl_wisun_logger_event_rf_test_t sl_wisun_logger_event_t::rf_test
```

**Description:** RF test event information.

###### tx_failure (heading level 7)

```
sl_wisun_logger_event_tx_failure_t sl_wisun_logger_event_t::tx_failure
```

**Description:** TX failure information.

###### type (heading level 7)

```
uint64_t sl_wisun_logger_event_t::type
```

**Description:** Event type.

###### u (heading level 7)

```
union sl_wisun_logger_event_t::@6 sl_wisun_logger_event_t::u
```

**Description:** Event specific data.

TX failure information. 

###### Public Attributes

###### type (heading level 7)

```
uint32_t sl_wisun_logger_event_tx_failure_t::type
```

**Description:** Frame type.

MAC address. 

###### Public Attributes

###### address (heading level 7)

```
uint8_t sl_wisun_mac_address_t::address[SL_WISUN_MAC_ADDRESS_SIZE]
```

**Description:** MAC address.

**Details:** This field contains a MAC address (EUI-64) stored in canonical format where the first byte of the array is the most-significant byte of the MAC address.

MAC parameter set. 

###### Public Attributes

###### backoff_period_us (heading level 7)

```
uint16_t sl_wisun_mac_params_t::backoff_period_us
```

**Description:** Length of one backoff period in microseconds.

**Details:** If 0, the length will be calculated based on the PHY. The default value is 0.

###### max_be (heading level 7)

```
uint8_t sl_wisun_mac_params_t::max_be
```

**Description:** Maximum value of CSMA-CA backoff exponent. The default value is 5.

###### max_cca_retries (heading level 7)

```
uint8_t sl_wisun_mac_params_t::max_cca_retries
```

**Description:** Maximum number of CCA retries.

**Details:** The transmission is aborted if the channel is still busy after 1 + max_cca_retries attempts. The default value is 8.

###### max_frame_retries (heading level 7)

```
uint8_t sl_wisun_mac_params_t::max_frame_retries
```

**Description:** Maximum number of transmission retries.

**Details:** The transmission is aborted if no acknowledgment has been received after 1 + max_frame_retries attempts. The default value is 7.

###### min_be (heading level 7)

```
uint8_t sl_wisun_mac_params_t::min_be
```

**Description:** Minimum value of CSMA-CA backoff exponent. The default value is 3.

###### reserved (heading level 7)

```
uint8_t sl_wisun_mac_params_t::reserved[2]
```

**Description:** Reserved, set to zero.

Wi-SUN Message API common header. 

###### Public Attributes

###### id (heading level 7)

```
uint8_t sl_wisun_msg_header_t::id
```

**Description:** ID (request, confirmation, indication) of the message.

###### info (heading level 7)

```
uint8_t sl_wisun_msg_header_t::info
```

**Description:** Processing metadata for the message.

###### length (heading level 7)

```
uint16_t sl_wisun_msg_header_t::length
```

**Description:** Total length of the message in bytes, this field included.

RPL neighbor information. 

###### Public Attributes

###### etx (heading level 7)

```
uint16_t sl_wisun_neighbor_info_t::etx
```

**Description:** Measured ETX value if known (0xffff if unknown)

###### global_address (heading level 7)

```
in6_addr_t sl_wisun_neighbor_info_t::global_address
```

**Description:** ULA/GUA address (unspecified address :: if unknown)

###### is_lfn (heading level 7)

```
uint8_t sl_wisun_neighbor_info_t::is_lfn
```

**Description:** Indicate if the device is an LFN. 1 = LFN, 0 = FFN.

###### is_mdr_command_capable (heading level 7)

```
uint8_t sl_wisun_neighbor_info_t::is_mdr_command_capable
```

**Description:** Indicate if the neighbor supports MAC mode switch.

###### lifetime (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::lifetime
```

**Description:** Remaining lifetime (Link lifetime for parents, EARO lifetime for children) in seconds.

###### link_local_address (heading level 7)

```
in6_addr_t sl_wisun_neighbor_info_t::link_local_address
```

**Description:** Link-local address.

###### mac_rx_count (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::mac_rx_count
```

**Description:** MAC RX packet count.

###### mac_tx_cd_count (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::mac_tx_cd_count
```

**Description:** MAC TX packet count using concurrent detection.

###### mac_tx_count (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::mac_tx_count
```

**Description:** MAC TX packet count.

###### mac_tx_failed_count (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::mac_tx_failed_count
```

**Description:** MAC TX failed count.

###### mac_tx_ms_count (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::mac_tx_ms_count
```

**Description:** MAC TX packet count using mode switch.

###### mac_tx_ms_failed_count (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::mac_tx_ms_failed_count
```

**Description:** MAC TX failed count using mode switch.

###### pan_size (heading level 7)

```
uint16_t sl_wisun_neighbor_info_t::pan_size
```

**Description:** Number devices connected to Border Router.

###### phy_mode_id_count (heading level 7)

```
uint8_t sl_wisun_neighbor_info_t::phy_mode_id_count
```

**Description:** Number of PhyModeId supported.

###### phy_mode_ids (heading level 7)

```
uint8_t sl_wisun_neighbor_info_t::phy_mode_ids[SL_WISUN_MAX_PHY_MODE_ID_COUNT]
```

**Description:** List of phy_mode_id_count PhyModeId.

###### routing_cost (heading level 7)

```
uint16_t sl_wisun_neighbor_info_t::routing_cost
```

**Description:** ETX to Border Router.

###### rpl_rank (heading level 7)

```
uint16_t sl_wisun_neighbor_info_t::rpl_rank
```

**Description:** RPL Rank value for parents (0xffff if unknown or child)

###### rsl_in (heading level 7)

```
uint8_t sl_wisun_neighbor_info_t::rsl_in
```

**Description:** Parent RSSI In measured RSSI value (0xff if unknown) Calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.

###### rsl_out (heading level 7)

```
uint8_t sl_wisun_neighbor_info_t::rsl_out
```

**Description:** Parent RSSI Out measured RSSI value (0xff if unknown) Calculated using EWMA specified by Wi-SUN from range of -174 (0) to +80 (254) dBm.

###### rssi (heading level 7)

```
int8_t sl_wisun_neighbor_info_t::rssi
```

**Description:** RSSI of the last received packet in integer dBm. */.

###### type (heading level 7)

```
uint32_t sl_wisun_neighbor_info_t::type
```

**Description:** Neighbor type ([sl_wisun_neighbor_type_t](sl-wisun-types#sl-wisun-neighbor-type-t))

Wi-SUN network information. 

###### Public Attributes

###### hop_count (heading level 7)

```
uint8_t sl_wisun_network_info_t::hop_count
```

**Description:** Hop count.

###### pan_id (heading level 7)

```
uint16_t sl_wisun_network_info_t::pan_id
```

**Description:** PAN ID.

###### reserved (heading level 7)

```
uint8_t sl_wisun_network_info_t::reserved
```

**Description:** Reserved, set to zero.

PAN configuration parameter set. 

###### Public Attributes

###### trickle_pc (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_params_configuration_s::trickle_pc
```

**Description:** PAN Configuration trickle timer.

###### trickle_pcs (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_params_configuration_s::trickle_pcs
```

**Description:** PAN Configuration Solicit trickle timer.

DHCP parameter set. 

###### Public Attributes

###### sol_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_params_dhcp_s::sol_txalg
```

**Description:** RFC8415 TX algorithm parameters for DHCP solicitation.

PAN discovery parameter set. 

###### Public Attributes

###### allow_skip (heading level 7)

```
uint8_t sl_wisun_params_discovery_s::allow_skip
```

**Description:** If true, allow join state 1 to be skipped using cached information from the previous connection.

###### eapol_target_min_sens (heading level 7)

```
uint8_t sl_wisun_params_discovery_s::eapol_target_min_sens
```

**Description:** Minimum signal level for a node to be selected as the EAPOL target for authentication immediately after a PAN Advertisement reception.

**Details:** Range from -174 (0) to +80 (254) dBm, 255 to disable feature. Enabling this feature may speed up connection times, but at the cost of increased simultaneous authentication traffic. It may be preferable to disable it when connecting hundreds of nodes at once.

###### reserved (heading level 7)

```
uint8_t sl_wisun_params_discovery_s::reserved[2]
```

**Description:** Reserved, set to zero.

###### trickle_pa (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_params_discovery_s::trickle_pa
```

**Description:** PAN Advertisement trickle timer.

###### trickle_pas (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_params_discovery_s::trickle_pas
```

**Description:** PAN Advertisement Solicit trickle timer.

Authentication parameter set. 

###### Public Attributes

###### allow_skip (heading level 7)

```
uint8_t sl_wisun_params_eapol_s::allow_skip
```

**Description:** If true, allow join state 2 to be skipped using cached credentials from the previous connection.

###### gtk_max_mismatch_m (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::gtk_max_mismatch_m
```

**Description:** GTK_MAX_MISMATCH (minutes) Maximum time between a SUP detecting a GTKHASH mismatch and the SUP initiating Msg1 of the authentication flow.

###### gtk_request_imax_m (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::gtk_request_imax_m
```

**Description:** Deprecated.

###### gtk_request_imin_m (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::gtk_request_imin_m
```

**Description:** Deprecated.

###### initial_key_max_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::initial_key_max_s
```

**Description:** Max delay of first key request (seconds)

###### initial_key_min_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::initial_key_min_s
```

**Description:** Deprecated.

###### initial_key_retry_limit (heading level 7)

```
uint8_t sl_wisun_params_eapol_s::initial_key_retry_limit
```

**Description:** Maximum retransmission count.

###### initial_key_retry_max_limit_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::initial_key_retry_max_limit_s
```

**Description:** Maximum duration for retransmissions (seconds)

###### initial_key_retry_max_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::initial_key_retry_max_s
```

**Description:** Deprecated.

###### initial_key_retry_min_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::initial_key_retry_min_s
```

**Description:** Initial retransmission time (seconds)

###### lgtk_max_mismatch_m (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::lgtk_max_mismatch_m
```

**Description:** LGTK_MAX_MISMATCH (minutes) Maximum time between a SUP detecting a LGTKHASH mismatch and the SUP initiating Msg1 of the authentication flow.

###### pmk_lifetime_m (heading level 7)

```
uint32_t sl_wisun_params_eapol_s::pmk_lifetime_m
```

**Description:** PMK lifetime (minutes)

###### ptk_lifetime_m (heading level 7)

```
uint32_t sl_wisun_params_eapol_s::ptk_lifetime_m
```

**Description:** PTK lifetime (minutes)

###### reserved (heading level 7)

```
uint8_t sl_wisun_params_eapol_s::reserved[3]
```

**Description:** Reserved, set to zero.

###### sec_prot_retry_timeout_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::sec_prot_retry_timeout_s
```

**Description:** Deprecated.

###### sec_prot_trickle (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_params_eapol_s::sec_prot_trickle
```

**Description:** Deprecated.

###### sec_prot_trickle_expirations (heading level 7)

```
uint8_t sl_wisun_params_eapol_s::sec_prot_trickle_expirations
```

**Description:** Deprecated.

###### temp_min_timeout_s (heading level 7)

```
uint16_t sl_wisun_params_eapol_s::temp_min_timeout_s
```

**Description:** Deprecated.

LFN parent parameter set. 

###### Public Attributes

###### lfn_lpc_retry_count (heading level 7)

```
uint8_t sl_wisun_params_lfn_parent_s::lfn_lpc_retry_count
```

**Description:** Number of broadcast LFN Pan Config retries when LFN Version is incremented Referred to as LFN_MAINTAIN_PARENT_TIME in FAN TPS 1.1.

###### lfn_na_wait_duration_m (heading level 7)

```
uint8_t sl_wisun_params_lfn_parent_s::lfn_na_wait_duration_m
```

**Description:** Deprecated.

###### lfn_pan_timeout_m (heading level 7)

```
uint16_t sl_wisun_params_lfn_parent_s::lfn_pan_timeout_m
```

**Description:** Deprecated.

Misc parameter set. 

###### Public Attributes

###### pan_timeout_m (heading level 7)

```
uint8_t sl_wisun_params_misc_s::pan_timeout_m
```

**Description:** Border router communication timeout PAN_TIMEOUT.

###### reserved (heading level 7)

```
uint8_t sl_wisun_params_misc_s::reserved
```

**Description:** Reserved, set to zero.

###### temp_link_min_timeout_s (heading level 7)

```
uint16_t sl_wisun_params_misc_s::temp_link_min_timeout_s
```

**Description:** Deprecated.

MPL parameter set. 

###### Public Attributes

###### seed_id_type (heading level 7)

```
uint8_t sl_wisun_params_mpl_s::seed_id_type
```

**Description:** MPL seed-id type, 0 indicates the seed-id is elided and is the IPv6 source address, 3 indicates the seed-id is the 128-bit ULA/GUA of the source.

###### seed_set_entry_lifetime_s (heading level 7)

```
uint16_t sl_wisun_params_mpl_s::seed_set_entry_lifetime_s
```

**Description:** MPL seed set entry lifetime (seconds)

###### trickle (heading level 7)

```
sl_wisun_trickle_params_t sl_wisun_params_mpl_s::trickle
```

**Description:** MPL trickle timer.

###### trickle_expirations (heading level 7)

```
uint8_t sl_wisun_params_mpl_s::trickle_expirations
```

**Description:** MPL trickle timer expirations.

RPL parameter set. 

###### Public Attributes

###### address_registration_lifetime_s (heading level 7)

```
uint16_t sl_wisun_params_rpl_s::address_registration_lifetime_s
```

**Description:** Amount of time a parent should retain a registered GUA/ULA (seconds)

###### candidate_parents_max (heading level 7)

```
uint8_t sl_wisun_params_rpl_s::candidate_parents_max
```

**Description:** RPL max candidate parents.

###### dao_txalg (heading level 7)

```
sl_wisun_rfc8415_txalg_params_t sl_wisun_params_rpl_s::dao_txalg
```

**Description:** RFC8415 TX algorithm parameters for DAO transmission rand specification range [0.1, 0.5] irt_s specification range [1, 60] mrt_s specification range [0, 600] mrd_s specification range [0, 3600] mrc specification range [0, 15].

###### dis_max_delay_first_s (heading level 7)

```
uint16_t sl_wisun_params_rpl_s::dis_max_delay_first_s
```

**Description:** RPL first DIS maximum delay (seconds)

###### dis_max_delay_s (heading level 7)

```
uint16_t sl_wisun_params_rpl_s::dis_max_delay_s
```

**Description:** RPL DIS maximum delay (seconds)

###### etx_probe_period_max_s (heading level 7)

```
uint16_t sl_wisun_params_rpl_s::etx_probe_period_max_s
```

**Description:** Maximum period of NS probes used to get samples for ETX calculation (seconds)

###### etx_samples_init (heading level 7)

```
uint8_t sl_wisun_params_rpl_s::etx_samples_init
```

**Description:** Number of samples used to calculate ETX during join state 4.

###### etx_samples_refresh (heading level 7)

```
uint8_t sl_wisun_params_rpl_s::etx_samples_refresh
```

**Description:** Number of samples used to refresh ETX.

###### init_parent_selection_s (heading level 7)

```
uint16_t sl_wisun_params_rpl_s::init_parent_selection_s
```

**Description:** Delay for preferred parent selection after first DIO reception (seconds)

###### parents_max (heading level 7)

```
uint8_t sl_wisun_params_rpl_s::parents_max
```

**Description:** RPL max parents, capped at 4 due to Path Control field size in DAO.

###### reserved (heading level 7)

```
uint8_t sl_wisun_params_rpl_s::reserved[2]
```

**Description:** Reserved, set to zero.

Traffic parameter set. 

###### Public Attributes

###### ipv6_mru (heading level 7)

```
uint16_t sl_wisun_params_traffic_s::ipv6_mru
```

**Description:** Maximum Receive Unit (MRU) for fragmented IPv6 packets in bytes. A larger packet will be silently discarded.

###### lowpan_mtu (heading level 7)

```
uint16_t sl_wisun_params_traffic_s::lowpan_mtu
```

**Description:** Maximum Transmission Unit (MTU) for 6LoWPAN packets in bytes. A larger packet will be fragmented using 6LoWPAN fragmentation.

###### max_edfe_fragment_count (heading level 7)

```
uint8_t sl_wisun_params_traffic_s::max_edfe_fragment_count
```

**Description:** Maximum number of 6LoWPAN/IPv6 fragments to send in a single EDFE transaction (0 to 10). 0 disables EDFE for fragmented packets.

###### reserved (heading level 7)

```
uint8_t sl_wisun_params_traffic_s::reserved[3]
```

**Description:** Reserved, set to zero.

Custom FSK PHY configuration. 

###### Public Attributes

###### ch0_frequency_khz (heading level 7)

```
uint32_t sl_wisun_phy_config_custom_fsk_t::ch0_frequency_khz
```

**Description:** Ch0 center frequency in kHz.

###### channel_spacing_khz (heading level 7)

```
uint16_t sl_wisun_phy_config_custom_fsk_t::channel_spacing_khz
```

**Description:** Channel spacing in kHz.

###### crc_type (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_fsk_t::crc_type
```

**Description:** FSK CRC type ([sl_wisun_crc_type_t](sl-wisun-types#sl-wisun-crc-type-t))

###### number_of_channels (heading level 7)

```
uint16_t sl_wisun_phy_config_custom_fsk_t::number_of_channels
```

**Description:** Number of channels.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_fsk_t::phy_mode_id
```

**Description:** PHY mode ID.

###### preamble_length (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_fsk_t::preamble_length
```

**Description:** FSK preamble length in bits.

###### reserved (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_fsk_t::reserved[1]
```

**Description:** Reserved, set to zero.

Custom OFDM PHY configuration. 

###### Public Attributes

###### ch0_frequency_khz (heading level 7)

```
uint32_t sl_wisun_phy_config_custom_ofdm_t::ch0_frequency_khz
```

**Description:** Ch0 center frequency in kHz.

###### channel_spacing_khz (heading level 7)

```
uint16_t sl_wisun_phy_config_custom_ofdm_t::channel_spacing_khz
```

**Description:** Channel spacing in kHz.

###### crc_type (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_ofdm_t::crc_type
```

**Description:** OFDM CRC type ([sl_wisun_crc_type_t](sl-wisun-types#sl-wisun-crc-type-t))

###### number_of_channels (heading level 7)

```
uint16_t sl_wisun_phy_config_custom_ofdm_t::number_of_channels
```

**Description:** Number of channels.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_ofdm_t::phy_mode_id
```

**Description:** PHY mode ID.

###### reserved (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_ofdm_t::reserved[1]
```

**Description:** Reserved, set to zero.

###### stf_length (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_ofdm_t::stf_length
```

**Description:** STF length in number of symbols.

Custom OQPSK PHY configuration. 

###### Public Attributes

###### ch0_frequency_khz (heading level 7)

```
uint32_t sl_wisun_phy_config_custom_oqpsk_t::ch0_frequency_khz
```

**Description:** Ch0 center frequency in kHz.

###### channel_spacing_khz (heading level 7)

```
uint16_t sl_wisun_phy_config_custom_oqpsk_t::channel_spacing_khz
```

**Description:** Channel spacing in kHz.

###### crc_type (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_oqpsk_t::crc_type
```

**Description:** OFDM CRC type ([sl_wisun_crc_type_t](sl-wisun-types#sl-wisun-crc-type-t))

###### number_of_channels (heading level 7)

```
uint16_t sl_wisun_phy_config_custom_oqpsk_t::number_of_channels
```

**Description:** Number of channels.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_oqpsk_t::phy_mode_id
```

**Description:** PHY mode ID.

###### preamble_length (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_oqpsk_t::preamble_length
```

**Description:** OQPSK preamble length in bits.

###### reserved (heading level 7)

```
uint8_t sl_wisun_phy_config_custom_oqpsk_t::reserved[1]
```

**Description:** Reserved, set to zero.

Explicit PHY configuration. 

###### Public Attributes

###### ch0_frequency_khz (heading level 7)

```
uint32_t sl_wisun_phy_config_explicit_t::ch0_frequency_khz
```

**Description:** Ch0 center frequency in kHz.

###### channel_mask (heading level 7)

```
uint8_t sl_wisun_phy_config_explicit_t::channel_mask[SL_WISUN_CHANNEL_MASK_SIZE]
```

**Description:** Specifies the set of channels on which the device is permitted to transmit.

**Details:** This mask applies to asynchronous (PAS, PA, ...), unicast and broadcast frames. The channel mask is advertised in both US-IE and BS-IE elements.

###### channel_spacing (heading level 7)

```
uint8_t sl_wisun_phy_config_explicit_t::channel_spacing
```

**Description:** Channel spacing ([sl_wisun_channel_spacing_t](sl-wisun-types#sl-wisun-channel-spacing-t))

###### number_of_channels (heading level 7)

```
uint16_t sl_wisun_phy_config_explicit_t::number_of_channels
```

**Description:** Number of channels.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_phy_config_explicit_t::phy_mode_id
```

**Description:** PHY mode ID.

FAN1.0 PHY configuration. 

###### Public Attributes

###### fec (heading level 7)

```
uint8_t sl_wisun_phy_config_fan10_t::fec
```

**Description:** 1 if FEC is enabled, 0 if not

###### op_class (heading level 7)

```
uint8_t sl_wisun_phy_config_fan10_t::op_class
```

**Description:** Operating class ([sl_wisun_operating_class_t](sl-wisun-types#sl-wisun-operating-class-t))

###### op_mode (heading level 7)

```
uint8_t sl_wisun_phy_config_fan10_t::op_mode
```

**Description:** Operating mode ([sl_wisun_operating_mode_t](sl-wisun-types#sl-wisun-operating-mode-t))

###### reg_domain (heading level 7)

```
uint8_t sl_wisun_phy_config_fan10_t::reg_domain
```

**Description:** Regulatory domain ([sl_wisun_regulatory_domain_t](sl-wisun-types#sl-wisun-regulatory-domain-t))

FAN1.1 PHY configuration. 

###### Public Attributes

###### chan_plan_id (heading level 7)

```
uint8_t sl_wisun_phy_config_fan11_t::chan_plan_id
```

**Description:** Channel plan ID.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_phy_config_fan11_t::phy_mode_id
```

**Description:** PHY mode ID.

###### reg_domain (heading level 7)

```
uint8_t sl_wisun_phy_config_fan11_t::reg_domain
```

**Description:** Regulatory domain ([sl_wisun_regulatory_domain_t](sl-wisun-types#sl-wisun-regulatory-domain-t))

Explicit RAIL configuration. 

###### Public Attributes

###### channel_id (heading level 7)

```
uint16_t sl_wisun_phy_config_ids_t::channel_id
```

**Description:** Channel ID.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_phy_config_ids_t::phy_mode_id
```

**Description:** PHY mode ID.

###### protocol_id (heading level 7)

```
uint16_t sl_wisun_phy_config_ids_t::protocol_id
```

**Description:** Protocol ID.

###### reserved (heading level 7)

```
uint8_t sl_wisun_phy_config_ids_t::reserved[3]
```

**Description:** Reserved, set to zero.

PHY configuration. 

###### Public Attributes

###### config (heading level 7)

```
union sl_wisun_phy_config_t::@3 sl_wisun_phy_config_t::config
```

**Description:** Configuration.

###### custom_fsk (heading level 7)

```
sl_wisun_phy_config_custom_fsk_t sl_wisun_phy_config_t::custom_fsk
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_CUSTOM_FSK](sl-wisun-types#sl-wisun-phy-config-custom-fsk) type.

###### custom_ofdm (heading level 7)

```
sl_wisun_phy_config_custom_ofdm_t sl_wisun_phy_config_t::custom_ofdm
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_CUSTOM_OFDM](sl-wisun-types#sl-wisun-phy-config-custom-ofdm) type.

###### custom_oqpsk (heading level 7)

```
sl_wisun_phy_config_custom_oqpsk_t sl_wisun_phy_config_t::custom_oqpsk
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_CUSTOM_OQPSK](sl-wisun-types#sl-wisun-phy-config-custom-oqpsk) type.

###### explicit_plan (heading level 7)

```
sl_wisun_phy_config_explicit_t sl_wisun_phy_config_t::explicit_plan
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_EXPLICIT](sl-wisun-types#sl-wisun-phy-config-explicit) type.

###### fan10 (heading level 7)

```
sl_wisun_phy_config_fan10_t sl_wisun_phy_config_t::fan10
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_FAN10](sl-wisun-types#sl-wisun-phy-config-fan10) type.

###### fan11 (heading level 7)

```
sl_wisun_phy_config_fan11_t sl_wisun_phy_config_t::fan11
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_FAN11](sl-wisun-types#sl-wisun-phy-config-fan11) type.

###### ids (heading level 7)

```
sl_wisun_phy_config_ids_t sl_wisun_phy_config_t::ids
```

**Description:** Configuration for [SL_WISUN_PHY_CONFIG_IDS](sl-wisun-types#sl-wisun-phy-config-ids) type.

###### type (heading level 7)

```
uint32_t sl_wisun_phy_config_t::type
```

**Description:** Configuration type ([sl_wisun_phy_config_type_t](sl-wisun-types#sl-wisun-phy-config-type-t))

Adaptive rate algorithm rate stats. 

###### Public Attributes

###### fail_count (heading level 7)

```
uint16_t sl_wisun_rate_stats_t::fail_count
```

**Description:** Number of tx without acknowledgement.

###### frame_duration_us (heading level 7)

```
uint32_t sl_wisun_rate_stats_t::frame_duration_us
```

**Description:** Frame tx time.

###### probe_limit (heading level 7)

```
int8_t sl_wisun_rate_stats_t::probe_limit
```

**Description:** Indicates if the rate can be probed.

###### reserved (heading level 7)

```
uint8_t sl_wisun_rate_stats_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### sample_count (heading level 7)

```
uint32_t sl_wisun_rate_stats_t::sample_count
```

**Description:** Number of times the rate was selected.

###### skipped_sample_count (heading level 7)

```
uint8_t sl_wisun_rate_stats_t::skipped_sample_count
```

**Description:** Number of times this rate was skipped.

###### success_count (heading level 7)

```
uint16_t sl_wisun_rate_stats_t::success_count
```

**Description:** Number of successful transmissions.

###### success_probability (heading level 7)

```
float sl_wisun_rate_stats_t::success_probability
```

**Description:** Estimated chance of success.

###### throughput (heading level 7)

```
float sl_wisun_rate_stats_t::throughput
```

**Description:** Estimated throughput in kb/s.

Adaptive rate algorithm rates. 

###### Public Attributes

###### index (heading level 7)

```
uint8_t sl_wisun_rate_t::index
```

**Description:** Rate index on the rate list.

###### is_supported (heading level 7)

```
uint8_t sl_wisun_rate_t::is_supported
```

**Description:** Indicates if rate is supported by both the node and the neighbor.

###### max_retries (heading level 7)

```
uint8_t sl_wisun_rate_t::max_retries
```

**Description:** Maximum amount of retries with current rate.

###### phy_mode_id (heading level 7)

```
uint8_t sl_wisun_rate_t::phy_mode_id
```

**Description:** Rate phy mode id.

###### rate (heading level 7)

```
uint32_t sl_wisun_rate_t::rate
```

**Description:** Rate in kb/s.

###### stats (heading level 7)

```
sl_wisun_rate_stats_t sl_wisun_rate_t::stats
```

**Description:** Struct containing the rate's tx statistics.

RFC8415 TX algorithm parameter set. 

###### Public Attributes

###### irt_s (heading level 7)

```
uint16_t sl_wisun_rfc8415_txalg_params_t::irt_s
```

**Description:** Initial retransmission time [RFC8415] (seconds).

###### max_delay_s (heading level 7)

```
uint16_t sl_wisun_rfc8415_txalg_params_t::max_delay_s
```

**Description:** Initial transmission maximum delay [RFC8415] (seconds).

###### mrc (heading level 7)

```
uint8_t sl_wisun_rfc8415_txalg_params_t::mrc
```

**Description:** Maximum retransmission count [RFC8415].

###### mrd_s (heading level 7)

```
uint16_t sl_wisun_rfc8415_txalg_params_t::mrd_s
```

**Description:** Maximum retransmission duration [RFC8415] (seconds).

###### mrt_s (heading level 7)

```
uint16_t sl_wisun_rfc8415_txalg_params_t::mrt_s
```

**Description:** Maximum retransmission time [RFC8415] (seconds).

###### rand (heading level 7)

```
float sl_wisun_rfc8415_txalg_params_t::rand
```

**Description:** Randomization factor magnitude [RFC8415] for retransmission.

**Details:** Randomization factor is uniformly distributed between -rand and +rand

###### reserved (heading level 7)

```
uint8_t sl_wisun_rfc8415_txalg_params_t::reserved[3]
```

**Description:** Reserved, set to zero.

RPL information. 

###### Public Attributes

###### dag_max_rank_increase (heading level 7)

```
uint16_t sl_wisun_rpl_info_t::dag_max_rank_increase
```

**Description:** DAG max rank increase, the allowable increase in Rank in support of local repair (0 to disable the mechanism)

###### default_lifetime (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::default_lifetime
```

**Description:** Default lifetime, lifetime that is used as default for all RPL routes.

**Details:** Expressed in units of Lifetime Units.

###### dio_interval_doublings (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::dio_interval_doublings
```

**Description:** DIO interval doublings, used to configure Imax of the DIO Trickle timer.

###### dio_interval_min (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::dio_interval_min
```

**Description:** DIO minimum interval, used to configure Imin of the DIO Trickle timer.

###### dio_redundancy_constant (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::dio_redundancy_constant
```

**Description:** DIO redundancy constant, used to configure k of the DIO Trickle timer.

###### dodag_dtsn (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::dodag_dtsn
```

**Description:** Destination Advertisement Trigger Sequence Number (DTSN)

###### dodag_preference (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::dodag_preference
```

**Description:** DODAG Preference, defines how preferable the root of this DODAG is compared to other DODAG roots within the instance.

**Details:** DAGPreference ranges from 0x00 (least preferred) to 0x07 (most preferred).

###### dodag_rank (heading level 7)

```
uint16_t sl_wisun_rpl_info_t::dodag_rank
```

**Description:** DODAG rank or the node.

###### dodag_version_number (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::dodag_version_number
```

**Description:** DODAG version number, set by the DODAG root.

###### grounded (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::grounded
```

**Description:** Grounded, indicates whether the DODAG advertised can satisfy the application-defined goal.

**Details:** If set, the DODAG is grounded. If cleared, the DODAG is floating.

###### instance_id (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::instance_id
```

**Description:** Instance ID, set by the DODAG root, it indicates of which RPL Instance the DODAG is a part.

###### lifetime_unit (heading level 7)

```
uint16_t sl_wisun_rpl_info_t::lifetime_unit
```

**Description:** Lifetime unit, unit in seconds that is used to express route lifetimes in RPL.

###### min_hop_rank_increase (heading level 7)

```
uint16_t sl_wisun_rpl_info_t::min_hop_rank_increase
```

**Description:** Min hop rank increase, minimum increase in Rank between a node and any of its DODAG parents.

###### mode_of_operation (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::mode_of_operation
```

**Description:** Mode of Operation (MOP), must be 1 for Non-Storing Mode of Operation.

###### reserved (heading level 7)

```
uint8_t sl_wisun_rpl_info_t::reserved[2]
```

**Description:** Reserved, set to zero.

Socket options Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### edfe_mode (heading level 7)

```
sl_wisun_socket_option_edfe_mode_t sl_wisun_socket_option_data_t::edfe_mode
```

**Description:** Socket EDFE mode Deprecated.

###### event_mode (heading level 7)

```
sl_wisun_socket_option_event_mode_t sl_wisun_socket_option_data_t::event_mode
```

**Description:** Socket event mode Deprecated.

###### ipv6_address (heading level 7)

```
in6_addr_t sl_wisun_socket_option_data_t::ipv6_address
```

**Description:** IPv6 address.

###### multicast_group (heading level 7)

```
sl_wisun_socket_option_multicast_group_t sl_wisun_socket_option_data_t::multicast_group
```

**Description:** Socket multicast group Deprecated.

###### multicast_hop_limit (heading level 7)

```
sl_wisun_socket_option_multicast_hop_limit sl_wisun_socket_option_data_t::multicast_hop_limit
```

**Description:** Socket multicast hop limit Deprecated.

###### send_buffer_limit (heading level 7)

```
sl_wisun_socket_option_send_buffer_limit_t sl_wisun_socket_option_data_t::send_buffer_limit
```

**Description:** Socket send buffer limit Deprecated.

###### unicast_hop_limit (heading level 7)

```
sl_wisun_socket_option_unicast_hop_limit sl_wisun_socket_option_data_t::unicast_hop_limit
```

**Description:** Socket unicast hop limit Deprecated.

###### value (heading level 7)

```
int32_t sl_wisun_socket_option_data_t::value
```

**Description:** Option-specific value.

Socket option for EDFE mode Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### mode (heading level 7)

```
uint32_t sl_wisun_socket_option_edfe_mode_t::mode
```

**Description:** Socket EDFE mode (1 to enable, 0 to disable)

Socket option for event mode Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### mode (heading level 7)

```
uint32_t sl_wisun_socket_option_event_mode_t::mode
```

**Description:** Socket event mode.

Socket option for multicast group Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### action (heading level 7)

```
uint32_t sl_wisun_socket_option_multicast_group_t::action
```

**Description:** Multicast group action.

###### address (heading level 7)

```
sl_wisun_ip_address_t sl_wisun_socket_option_multicast_group_t::address
```

**Description:** Multicast group address.

Socket option for socket multicast hop limit Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### hop_limit (heading level 7)

```
int16_t sl_wisun_socket_option_multicast_hop_limit::hop_limit
```

**Description:** Socket multicast hop limit (0 to 255 hops, -1 to use default)

###### reserved (heading level 7)

```
uint16_t sl_wisun_socket_option_multicast_hop_limit::reserved
```

**Description:** Reserved, set to 0.

Socket option for send buffer limit Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### limit (heading level 7)

```
uint32_t sl_wisun_socket_option_send_buffer_limit_t::limit
```

**Description:** Send buffer limit.

Socket option for socket unicast hop limit Deprecated since v2.0 MUST NOT be used with POSIX socket API. 

###### Public Attributes

###### hop_limit (heading level 7)

```
int16_t sl_wisun_socket_option_unicast_hop_limit::hop_limit
```

**Description:** Socket unicast hop limit (0 to 255 hops, -1 to use default)

###### reserved (heading level 7)

```
uint16_t sl_wisun_socket_option_unicast_hop_limit::reserved
```

**Description:** Reserved, set to 0.

ARIB regulation statistics. 

###### Public Attributes

###### tx_duration_ms (heading level 7)

```
uint32_t sl_wisun_statistics_arib_regulation_t::tx_duration_ms
```

**Description:** Sum of transmission durations during the last hour in milliseconds.

Frequency hopping statistics. 

###### Public Attributes

###### drift_compensation (heading level 7)

```
int16_t sl_wisun_statistics_fhss_t::drift_compensation
```

**Description:** Estimated clock drift to the parent in microseconds.

###### hop_count (heading level 7)

```
uint16_t sl_wisun_statistics_fhss_t::hop_count
```

**Description:** Estimated number of hops to the border router based on RPL rank.

###### prev_avg_synch_fix (heading level 7)

```
int16_t sl_wisun_statistics_fhss_t::prev_avg_synch_fix
```

**Description:** Deprecated.

###### synch_interval (heading level 7)

```
uint16_t sl_wisun_statistics_fhss_t::synch_interval
```

**Description:** Number of seconds since last timing information from the parent.

###### synch_lost (heading level 7)

```
uint32_t sl_wisun_statistics_fhss_t::synch_lost
```

**Description:** Deprecated.

###### unknown_neighbor (heading level 7)

```
uint32_t sl_wisun_statistics_fhss_t::unknown_neighbor
```

**Description:** Number of times a transmission attempt has failed due to lack of timing information.

Heap usage statistics. 

###### Public Attributes

###### arena (heading level 7)

```
uint32_t sl_wisun_statistics_heap_t::arena
```

**Description:** Highest heap usage in bytes.

###### free (heading level 7)

```
uint32_t sl_wisun_statistics_heap_t::free
```

**Description:** Current remaining heap in bytes.

###### total (heading level 7)

```
uint32_t sl_wisun_statistics_heap_t::total
```

**Description:** Total available heap in bytes.

###### uordblks (heading level 7)

```
uint32_t sl_wisun_statistics_heap_t::uordblks
```

**Description:** Current heap usage in bytes.

MAC statistics. 

###### Public Attributes

###### bc_rx_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::bc_rx_count
```

**Description:** Number of successfully received broadcast MAC frames.

###### bc_tx_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::bc_tx_count
```

**Description:** Number of transmitted broadcast MAC frames.

###### cca_attempts_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::cca_attempts_count
```

**Description:** Number of MAC CCA attempts.

###### failed_cca_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::failed_cca_count
```

**Description:** Number of failed MAC transmissions due to CCA.

###### idle_duration_s (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::idle_duration_s
```

**Description:** Cumulated idle duration in seconds.

###### radio_tx_duration_ms (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::radio_tx_duration_ms
```

**Description:** Radio TX duration in milliseconds.

###### reserved (heading level 7)

```
uint8_t sl_wisun_statistics_mac_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### retry_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::retry_count
```

**Description:** Number of retried MAC transmissions.

###### rx_availability_percentage (heading level 7)

```
uint8_t sl_wisun_statistics_mac_t::rx_availability_percentage
```

**Description:** MAC RX availability percentage.

###### rx_bytes (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::rx_bytes
```

**Description:** Amount of successfully received MAC data in bytes. FCS is not included.

###### rx_cd_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::rx_cd_count
```

**Description:** Number of successfully received MAC frames using concurrent detection.

###### rx_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::rx_count
```

**Description:** Number of successfully received MAC frames.

###### rx_drop_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::rx_drop_count
```

**Description:** Number of successfully received MAC frames discarded during processing.

###### rx_ms_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::rx_ms_count
```

**Description:** Number of successfully received MAC frames using mode_switch.

###### rx_ms_failed_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::rx_ms_failed_count
```

**Description:** Number of failed reception using mode switch (no data after PHR or MDR Command).

###### tx_bytes (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::tx_bytes
```

**Description:** Amount of transmitted MAC data in bytes. FCS is not included.

###### tx_cd_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::tx_cd_count
```

**Description:** Number of transmitted MAC frames using concurrent detection.

###### tx_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::tx_count
```

**Description:** Number of transmitted MAC frames.

###### tx_failed_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::tx_failed_count
```

**Description:** Number of failed MAC transmissions.

###### tx_ms_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::tx_ms_count
```

**Description:** Number of transmitted MAC frames using mode switch.

###### tx_ms_failed_count (heading level 7)

```
uint32_t sl_wisun_statistics_mac_t::tx_ms_failed_count
```

**Description:** Number of failed MAC frames transmission using mode switch.

###### tx_queue_peak (heading level 7)

```
uint16_t sl_wisun_statistics_mac_t::tx_queue_peak
```

**Description:** Highest number of frames in the MAC transmission queue.

###### tx_queue_size (heading level 7)

```
uint16_t sl_wisun_statistics_mac_t::tx_queue_size
```

**Description:** Current number of frames in the MAC transmission queue.

6LoWPAN/IP stack statistics 

###### Public Attributes

###### adapt_layer_tx_queue_peak (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::adapt_layer_tx_queue_peak
```

**Description:** Highest number of frames in the adaptation layer transmission queue.

###### adapt_layer_tx_queue_size (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::adapt_layer_tx_queue_size
```

**Description:** Current number of frames in the adaptation layer transmission queue.

###### buf_alloc (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::buf_alloc
```

**Description:** Number of data buffer allocation attempts.

###### buf_headroom_fail (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::buf_headroom_fail
```

**Description:** Number of times data buffer resizing has failed.

###### buf_headroom_realloc (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::buf_headroom_realloc
```

**Description:** Number of times data buffers have been resized due to lack of header space.

###### buf_headroom_shuffle (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::buf_headroom_shuffle
```

**Description:** Number of times data buffers have been reorganized due to lack of header space.

###### etx_1st_parent (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::etx_1st_parent
```

**Description:** ETX of the primary parent.

###### etx_2nd_parent (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::etx_2nd_parent
```

**Description:** ETX of the secondary parent.

###### frag_rx_errors (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::frag_rx_errors
```

**Description:** Number of fragmentation errors in received IPv6 packets.

###### frag_tx_errors (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::frag_tx_errors
```

**Description:** Number of fragmentation errors in transmitted IPv6 packets.

###### ip_cksum_error (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_cksum_error
```

**Description:** Number of discarded IPv6 packets due to a checksum error.

###### ip_no_route (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_no_route
```

**Description:** Number of discarded IPv6 packets due to lack of routing information.

###### ip_routed_up (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_routed_up
```

**Description:** Amount of forwarded IPv6 data in bytes.

###### ip_routeloop_detect (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_routeloop_detect
```

**Description:** Number of RPL packet forwarding errors due to inconsistent routing information.

###### ip_rx_bytes (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_rx_bytes
```

**Description:** Amount of received IPv6 data in bytes.

###### ip_rx_count (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_rx_count
```

**Description:** Number of received IPv6 packets.

###### ip_rx_drop (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_rx_drop
```

**Description:** Number of discarded IPv6 packets during processing.

###### ip_tx_bytes (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_tx_bytes
```

**Description:** Amount of transmitted IPv6 data in bytes.

###### ip_tx_count (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::ip_tx_count
```

**Description:** Number of transmitted IPv6 packets.

###### mpl_forwarded_messages_count (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::mpl_forwarded_messages_count
```

**Description:** Number of forwarded MPL messages.

###### mpl_freed_messages_count (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::mpl_freed_messages_count
```

**Description:** Number of freed MPL messages.

###### mpl_new_messages_count (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::mpl_new_messages_count
```

**Description:** Number of new MPL messages.

###### mpl_not_tx_count (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::mpl_not_tx_count
```

**Description:** Number of deleted MPL messages that were never sent.

###### mpl_rx_count (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::mpl_rx_count
```

**Description:** Number of received MPL messages.

###### neighbor_alloc_fail (heading level 7)

```
uint16_t sl_wisun_statistics_network_t::neighbor_alloc_fail
```

**Description:** Number of failed neighbor allocation attempts.

###### rpl_global_repair (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_global_repair
```

**Description:** Number of times a global repair has been triggered by the border router.

###### rpl_local_repair (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_local_repair
```

**Description:** Number of times a local repair procedure has been triggered by the node.

###### rpl_malformed_message (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_malformed_message
```

**Description:** Number of discarded RPL packets due to malformed content.

###### rpl_memory_overflow (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_memory_overflow
```

**Description:** Sum of RPL object sizes that have failed allocation in bytes.

###### rpl_parent_tx_fail (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_parent_tx_fail
```

**Description:** Number of failed RPL transmissions to the parent.

###### rpl_route_routecost_better_change (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_route_routecost_better_change
```

**Description:** Number of RPL parent changes due to better route cost.

###### rpl_time_no_next_hop (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_time_no_next_hop
```

**Description:** Number of seconds without an RPL parent.

###### rpl_total_memory (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_total_memory
```

**Description:** Amount of memory currently allocated for RPL objects in bytes.

###### rpl_unknown_instance (heading level 7)

```
uint32_t sl_wisun_statistics_network_t::rpl_unknown_instance
```

**Description:** Number of discarded RPL packets due to an unknown DODAG instance.

PHY/RF statistics. 

###### Public Attributes

###### crc_fails (heading level 7)

```
uint32_t sl_wisun_statistics_phy_t::crc_fails
```

**Description:** Number of CRC failures on reception.

###### rx_timeouts (heading level 7)

```
uint32_t sl_wisun_statistics_phy_t::rx_timeouts
```

**Description:** Number of reception timeouts.

###### tx_timeouts (heading level 7)

```
uint32_t sl_wisun_statistics_phy_t::tx_timeouts
```

**Description:** Number of transmission timeouts.

Regional regulation statistics. 

###### Public Attributes

###### @2 (heading level 7)

```
struct sl_wisun_statistics_regulation_t::@1 sl_wisun_statistics_regulation_t::@2
```

**Description:** Regional regulation statistics.

###### arib (heading level 7)

```
sl_wisun_statistics_arib_regulation_t sl_wisun_statistics_regulation_t::arib
```

**Description:** ARIB statistics.

###### duty_cycle_alert_threshold_ms (heading level 7)

```
uint32_t sl_wisun_statistics_regulation_t::duty_cycle_alert_threshold_ms
```

**Description:** Duty cycle alert threshold in milliseconds.

###### duty_cycle_alert_threshold_per_channel_ms (heading level 7)

```
uint32_t sl_wisun_statistics_regulation_t::duty_cycle_alert_threshold_per_channel_ms
```

**Description:** Duty cycle alert threshold per channel in milliseconds.

###### duty_cycle_warning_threshold_ms (heading level 7)

```
uint32_t sl_wisun_statistics_regulation_t::duty_cycle_warning_threshold_ms
```

**Description:** Duty cycle warning threshold in milliseconds.

###### duty_cycle_warning_threshold_per_channel_ms (heading level 7)

```
uint32_t sl_wisun_statistics_regulation_t::duty_cycle_warning_threshold_per_channel_ms
```

**Description:** Duty cycle warning threshold per channel in milliseconds.

###### tx_duration_ms (heading level 7)

```
uint32_t sl_wisun_statistics_regulation_t::tx_duration_ms
```

**Description:** Sum of transmission durations during the last hour in milliseconds.

###### tx_duration_per_channel_ms (heading level 7)

```
uint32_t sl_wisun_statistics_regulation_t::tx_duration_per_channel_ms
```

**Description:** Sum of transmission durations per channel during the last hour in milliseconds.

Statistics. 

###### Public Attributes

###### fhss (heading level 7)

```
sl_wisun_statistics_fhss_t sl_wisun_statistics_t::fhss
```

**Description:** Frequency hopping statistics.

###### heap (heading level 7)

```
sl_wisun_statistics_heap_t sl_wisun_statistics_t::heap
```

**Description:** Heap usage statistics.

###### mac (heading level 7)

```
sl_wisun_statistics_mac_t sl_wisun_statistics_t::mac
```

**Description:** MAC statistics.

###### network (heading level 7)

```
sl_wisun_statistics_network_t sl_wisun_statistics_t::network
```

**Description:** 6LoWPAN/IP stack statistics

###### phy (heading level 7)

```
sl_wisun_statistics_phy_t sl_wisun_statistics_t::phy
```

**Description:** PHY/RF statistics.

###### regulation (heading level 7)

```
sl_wisun_statistics_regulation_t sl_wisun_statistics_t::regulation
```

**Description:** Regional regulation statistics.

###### wisun (heading level 7)

```
sl_wisun_statistics_wisun_t sl_wisun_statistics_t::wisun
```

**Description:** Wi-SUN statistics.

Wi-SUN statistics. 

###### Public Attributes

###### pan_control_rx_count (heading level 7)

```
uint32_t sl_wisun_statistics_wisun_t::pan_control_rx_count
```

**Description:** Number of received PAN control frames.

###### pan_control_tx_count (heading level 7)

```
uint32_t sl_wisun_statistics_wisun_t::pan_control_tx_count
```

**Description:** Number of completed PAN control transmission requests.

Configure the trace level of 1 group. 

###### Public Attributes

###### group_id (heading level 7)

```
uint8_t sl_wisun_trace_group_config_t::group_id
```

**Description:** Trace Group ID. Coded with enum sl_wisun_trace_group_t.

###### trace_level (heading level 7)

```
uint8_t sl_wisun_trace_group_config_t::trace_level
```

**Description:** Maximum trace level to display for this group.

**Details:** It is coded using enum sl_wisun_trace_level_t.

Trickle parameter set. 

###### Public Attributes

###### imax_s (heading level 7)

```
uint16_t sl_wisun_trickle_params_t::imax_s
```

**Description:** Maximum interval size (seconds)

###### imin_s (heading level 7)

```
uint16_t sl_wisun_trickle_params_t::imin_s
```

**Description:** Minimum interval size (seconds)

###### k (heading level 7)

```
uint8_t sl_wisun_trickle_params_t::k
```

**Description:** Redundancy constant (0 for infinity)

###### reserved (heading level 7)

```
uint8_t sl_wisun_trickle_params_t::reserved[3]
```

**Description:** Reserved, set to zero.

##### Predefined FFN parameter sets

Predefined FFN parameter sets for [sl_wisun_set_connection_parameters()](sl-wisun-api#sl-wisun-set-connection-parameters). 

These parameter sets can be used either as-is or used as an initialization value for an application-specific parameter set. 

###### Variables

###### SL_WISUN_PARAMS_PROFILE_CERTIF (heading level 7)

```
const sl_wisun_connection_params_t SL_WISUN_PARAMS_PROFILE_CERTIF
```

**Description:** Profile for certification testing.

###### SL_WISUN_PARAMS_PROFILE_LARGE (heading level 7)

```
const sl_wisun_connection_params_t SL_WISUN_PARAMS_PROFILE_LARGE
```

**Description:** Profile for a large network.

###### SL_WISUN_PARAMS_PROFILE_MEDIUM (heading level 7)

```
const sl_wisun_connection_params_t SL_WISUN_PARAMS_PROFILE_MEDIUM
```

**Description:** Profile for a medium network.

###### SL_WISUN_PARAMS_PROFILE_SMALL (heading level 7)

```
const sl_wisun_connection_params_t SL_WISUN_PARAMS_PROFILE_SMALL
```

**Description:** Profile for a small network.

###### SL_WISUN_PARAMS_PROFILE_TEST (heading level 7)

```
const sl_wisun_connection_params_t SL_WISUN_PARAMS_PROFILE_TEST
```

**Description:** Profile for development (shorter connection time)

##### Predefined LFN parameter sets

Predefined LFN parameter sets for [sl_wisun_set_lfn_parameters()](sl-wisun-api#sl-wisun-set-lfn-parameters). 

These parameter sets can be used either as-is or used as an initialization value for an application-specific parameter set. 

###### Variables

###### SL_WISUN_PARAMS_LFN_BALANCED (heading level 7)

```
const sl_wisun_lfn_params_t SL_WISUN_PARAMS_LFN_BALANCED
```

**Description:** Profile providing balance between power consumption and performance.

###### SL_WISUN_PARAMS_LFN_ECO (heading level 7)

```
const sl_wisun_lfn_params_t SL_WISUN_PARAMS_LFN_ECO
```

**Description:** Profile optimized for low power consumption.

###### SL_WISUN_PARAMS_LFN_TEST (heading level 7)

```
const sl_wisun_lfn_params_t SL_WISUN_PARAMS_LFN_TEST
```

**Description:** Profile for test usage, best performance but highest power consumption.

##### Predefined BR parameter sets

Predefined BR parameter sets for [sl_wisun_br_set_connection_parameters()](sl-wisun-br-api#sl-wisun-br-set-connection-parameters). 

These parameter sets can be used either as-is to replicate the behavior of [sl_wisun_br_set_network_size()](sl-wisun-br-api#sl-wisun-br-set-network-size), or used as an initialization value for an application-specific parameter set. 

###### Variables

###### SL_WISUN_BR_PARAMS_PROFILE_LARGE (heading level 7)

```
const sl_wisun_br_connection_params_t SL_WISUN_BR_PARAMS_PROFILE_LARGE
```

**Description:** Profile for a large network.

###### SL_WISUN_BR_PARAMS_PROFILE_MEDIUM (heading level 7)

```
const sl_wisun_br_connection_params_t SL_WISUN_BR_PARAMS_PROFILE_MEDIUM
```

**Description:** Profile for a medium network.

###### SL_WISUN_BR_PARAMS_PROFILE_SMALL (heading level 7)

```
const sl_wisun_br_connection_params_t SL_WISUN_BR_PARAMS_PROFILE_SMALL
```

**Description:** Profile for a small network.

###### SL_WISUN_BR_PARAMS_PROFILE_TEST (heading level 7)

```
const sl_wisun_br_connection_params_t SL_WISUN_BR_PARAMS_PROFILE_TEST
```

**Description:** Profile for development (shorter connection time)

##### Predefined BR LFN-parenting parameter sets

Predefined LFN parameter sets for [sl_wisun_br_set_lfn_parameters()](sl-wisun-br-api#sl-wisun-br-set-lfn-parameters). 

These parameter sets can be used either as-is or used as an initialization value for an application-specific parameter set. 

###### Variables

###### SL_WISUN_BR_PARAMS_LFN_BALANCED (heading level 7)

```
const sl_wisun_br_lfn_params_t SL_WISUN_BR_PARAMS_LFN_BALANCED
```

**Description:** Profile providing balance between battery life and performance.

###### SL_WISUN_BR_PARAMS_LFN_ECO (heading level 7)

```
const sl_wisun_br_lfn_params_t SL_WISUN_BR_PARAMS_LFN_ECO
```

**Description:** Profile with a higher battery life.

###### SL_WISUN_BR_PARAMS_LFN_TEST (heading level 7)

```
const sl_wisun_br_lfn_params_t SL_WISUN_BR_PARAMS_LFN_TEST
```

**Description:** Profile for use during tests.

#### Regional Regulation API

Wi-SUN Regional Regulation API provides the parameters for regional regulation compliance. 

The API allows the application to set the duty cycle budget, thresholds for warnings and alerts, and other parameters related to the regional regulation. The Wi-SUN stack provides predefined parameter sets for the following regulations:

- ARIB (Japan)
- WPC (India)
- ETSI (Europe)

The regional regulation is configured with [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters). Predefined parameter sets can be used for common regulatory requirements (see [Predefined regional regulation parameter sets](sl-wisun-regulation-parameter-sets)).

Special attention must be taken with frame length when ARIB regulation is used in Japan. The maximum length of a radio frame is indirectly constrained by the channel bandwidth. This is because the regulation imposes a maximum transmission duration per frame, which varies depending on the bandwidth used:

- with a 200 kHz bandwidth, frame duration must be less than 400 ms
- with a 400 kHz bandwidth, frame duration must be less than 200 ms
- with 600 and 800 kHz bandwidths, frame duration must be less than 100 ms

The Wi-SUN stack doesn't currently enforce these constraints, and defers the responsibility to the application. Depending on the selected PHY, the application must ensure that the transmission duration complies with the ARIB regulation by:

- reducing the frame length
- adjusting the 6LoWPAN MTU leading to fragmentation for larger packets

##### Modules

[sl_wisun_regulation_params_t](sl-wisun-regulation-params-t)

[Predefined regional regulation parameter sets](sl-wisun-regulation-parameter-sets)

Regional regulation parameter set. 

###### Public Attributes

###### duty_cycle_alert_threshold_percent (heading level 7)

```
int8_t sl_wisun_regulation_params_t::duty_cycle_alert_threshold_percent
```

**Description:** Duty cycle alert threshold in percent, -1 to disable duty cycle alert threshold.

###### duty_cycle_arib_skip_ack (heading level 7)

```
uint8_t sl_wisun_regulation_params_t::duty_cycle_arib_skip_ack
```

**Description:** Skip responses from sum of transmissions (ARIB conditions)

###### duty_cycle_budget_per_channel_s (heading level 7)

```
int16_t sl_wisun_regulation_params_t::duty_cycle_budget_per_channel_s
```

**Description:** Duty cycle budget per channel in seconds per hour, -1 to disable duty cycle budget per channel.

###### duty_cycle_budget_s (heading level 7)

```
int16_t sl_wisun_regulation_params_t::duty_cycle_budget_s
```

**Description:** Duty cycle budget in seconds per hour, -1 to disable duty cycle budget.

###### duty_cycle_skip_ack (heading level 7)

```
uint8_t sl_wisun_regulation_params_t::duty_cycle_skip_ack
```

**Description:** Skip ACKs from sum of transmissions.

###### duty_cycle_warning_threshold_percent (heading level 7)

```
int8_t sl_wisun_regulation_params_t::duty_cycle_warning_threshold_percent
```

**Description:** Duty cycle warning threshold in percent, -1 to disable duty cycle warning threshold.

###### enable_apc (heading level 7)

```
uint8_t sl_wisun_regulation_params_t::enable_apc
```

**Description:** Enable Adaptive Power Control.

###### enable_arib_channel_access (heading level 7)

```
uint8_t sl_wisun_regulation_params_t::enable_arib_channel_access
```

**Description:** Ensure a min IFS before ACKs (ARIB conditions)

###### fixed_cca_threshold_dbm (heading level 7)

```
int8_t sl_wisun_regulation_params_t::fixed_cca_threshold_dbm
```

**Description:** Fixed CCA threshold in dBm, INT8_MAX to use adaptive CCA threshold.

###### max_edfe_duration_ms (heading level 7)

```
uint32_t sl_wisun_regulation_params_t::max_edfe_duration_ms
```

**Description:** Maximum Extended Directed Frame Exchange (EDFE) duration in milliseconds, 0 to forbid EDFE.

###### reserved (heading level 7)

```
uint8_t sl_wisun_regulation_params_t::reserved
```

**Description:** Reserved, set to zero.

###### version (heading level 7)

```
uint32_t sl_wisun_regulation_params_t::version
```

**Description:** Version of this API.

**Details:** This field allows to store the parameters in an NVM and check on reload that they are compatible with the stack if there was an update.

##### Predefined regional regulation parameter sets

Predefined regional regulation parameter sets for [sl_wisun_set_regulation_parameters()](sl-wisun-api#sl-wisun-set-regulation-parameters). 

These parameter sets can be used either as-is or used as an initialization value for an application-specific parameter set. 

###### Variables

###### SL_WISUN_REGULATION_PARAMS_ARIB (heading level 7)

```
const sl_wisun_regulation_params_t SL_WISUN_REGULATION_PARAMS_ARIB
```

**Description:** Parameter set for ARIB regional regulation (ARIB-STD-T108).

**Details:** This parameter set is used for Japan and other ARIB compliant regions.

###### SL_WISUN_REGULATION_PARAMS_ETSI (heading level 7)

```
const sl_wisun_regulation_params_t SL_WISUN_REGULATION_PARAMS_ETSI
```

**Description:** Parameter set for ETSI regional regulation (ETSI EN 300 220-1).

**Details:** This parameter set is used for Europe and other ETSI compliant regions.

###### SL_WISUN_REGULATION_PARAMS_NONE (heading level 7)

```
const sl_wisun_regulation_params_t SL_WISUN_REGULATION_PARAMS_NONE
```

**Description:** Default parameter set for no regional regulation.

**Details:** This parameter set is used when no regional regulation is applied.

###### SL_WISUN_REGULATION_PARAMS_WPC (heading level 7)

```
const sl_wisun_regulation_params_t SL_WISUN_REGULATION_PARAMS_WPC
```

**Description:** Parameter set for WPC regional regulation.

**Details:** This parameter set is used for India and other WPC compliant regions.

#### Message API

Wi-SUN Message API provides a message-based API for managing and configuring the Wi-SUN protocol stack for Network Co-Processor (NCP) use-cases. 

The API is functionally equivalent of [Wi-SUN Stack API](sl-wisun-api). It is based on requests from the host application to the NCP application running on the device, which sends the requests to the stack using [sl_wisun_send_request()](sl-wisun-msg-api#sl-wisun-send-request). Depending on the request, the required action is either performed immediately or an internal stack operation is started, terminating with an event once the operation finishes. All events contain a status code, indicating the result of the requested operation. Events are also used by the stack to notify the application of any important information, such as the state of the connection. 

##### Modules

[sl_wisun_msg_generic](sl-wisun-msg-generic)

[sl_wisun_msg_set_network_size](sl-wisun-msg-set-network-size)

[sl_wisun_msg_get_ip_address](sl-wisun-msg-get-ip-address)

[sl_wisun_msg_open_socket](sl-wisun-msg-open-socket)

[sl_wisun_msg_close_socket](sl-wisun-msg-close-socket)

[sl_wisun_msg_sendto_on_socket](sl-wisun-msg-sendto-on-socket)

[sl_wisun_msg_socket_sendmsg](sl-wisun-msg-socket-sendmsg)

[sl_wisun_msg_listen_on_socket](sl-wisun-msg-listen-on-socket)

[sl_wisun_msg_accept_on_socket](sl-wisun-msg-accept-on-socket)

[sl_wisun_msg_connect_socket](sl-wisun-msg-connect-socket)

[sl_wisun_msg_bind_socket](sl-wisun-msg-bind-socket)

[sl_wisun_msg_send_on_socket](sl-wisun-msg-send-on-socket)

[sl_wisun_msg_receive_on_socket](sl-wisun-msg-receive-on-socket)

[sl_wisun_msg_socket_recvmsg](sl-wisun-msg-socket-recvmsg)

[sl_wisun_msg_socket_getsockname](sl-wisun-msg-socket-getsockname)

[sl_wisun_msg_socket_getpeername](sl-wisun-msg-socket-getpeername)

[sl_wisun_msg_disconnect](sl-wisun-msg-disconnect)

[sl_wisun_msg_set_trusted_certificate](sl-wisun-msg-set-trusted-certificate)

[sl_wisun_msg_set_device_certificate](sl-wisun-msg-set-device-certificate)

[sl_wisun_msg_set_device_private_key](sl-wisun-msg-set-device-private-key)

[sl_wisun_msg_get_statistics](sl-wisun-msg-get-statistics)

[sl_wisun_msg_set_socket_option](sl-wisun-msg-set-socket-option)

[sl_wisun_msg_set_tx_power](sl-wisun-msg-set-tx-power)

[sl_wisun_msg_set_channel_mask](sl-wisun-msg-set-channel-mask)

[sl_wisun_msg_allow_mac_address](sl-wisun-msg-allow-mac-address)

[sl_wisun_msg_deny_mac_address](sl-wisun-msg-deny-mac-address)

[sl_wisun_msg_get_socket_option](sl-wisun-msg-get-socket-option)

[sl_wisun_msg_get_join_state](sl-wisun-msg-get-join-state)

[sl_wisun_msg_clear_credential_cache](sl-wisun-msg-clear-credential-cache)

[sl_wisun_msg_get_mac_address](sl-wisun-msg-get-mac-address)

[sl_wisun_msg_set_mac_address](sl-wisun-msg-set-mac-address)

[sl_wisun_msg_reset_statistics](sl-wisun-msg-reset-statistics)

[sl_wisun_msg_get_neighbor_count](sl-wisun-msg-get-neighbor-count)

[sl_wisun_msg_get_neighbors](sl-wisun-msg-get-neighbors)

[sl_wisun_msg_get_neighbor_info](sl-wisun-msg-get-neighbor-info)

[sl_wisun_msg_set_unicast_settings](sl-wisun-msg-set-unicast-settings)

[sl_wisun_msg_set_trace_level](sl-wisun-msg-set-trace-level)

[sl_wisun_msg_set_trace_filter](sl-wisun-msg-set-trace-filter)

[sl_wisun_set_regulation](sl-wisun-msg-set-regulation)

[sl_wisun_msg_set_device_private_key_id](sl-wisun-msg-set-device-private-key-id)

[sl_wisun_set_advert_fragment_duration](sl-wisun-msg-set-async-fragmentation)

[sl_wisun_msg_set_rate_algorithm](sl-wisun-msg-set-rate-algorithm)

[sl_wisun_msg_get_rate_algorithm_stats](sl-wisun-msg-get-rate-algorithm-stats)

[sl_wisun_msg_set_mode_switch](sl-wisun-msg-set-mode-switch)

[sl_wisun_set_regulation_tx_thresholds](sl-wisun-msg-set-regulation-tx-thresholds)

[sl_wisun_set_device_type](sl-wisun-msg-set-device-type)

[sl_wisun_msg_set_connection_params](sl-wisun-msg-set-connection-params)

[sl_wisun_msg_set_option](sl-wisun-msg-set-option)

[sl_wisun_msg_set_ffn_advanced_params](sl-wisun-msg-set-ffn-advanced-params)

[sl_wisun_msg_set_lfn_advanced_params](sl-wisun-msg-set-lfn-advanced-params)

[sl_wisun_msg_reset_params](sl-wisun-msg-reset-params)

[sl_wisun_msg_join](sl-wisun-msg-join)

[sl_wisun_msg_set_pom_ie](sl-wisun-msg-set-pom-ie)

[sl_wisun_msg_get_pom_ie](sl-wisun-msg-get-pom-ie)

[sl_wisun_msg_get_stack_version](sl-wisun-msg-get-stack-version)

[sl_wisun_msg_set_lfn_params](sl-wisun-msg-set-lfn-params)

[sl_wisun_msg_set_lfn_support](sl-wisun-msg-set-lfn-support)

[sl_wisun_msg_set_pti_state](sl-wisun-msg-set-pti-state)

[sl_wisun_set_tbu_settings](sl-wisun-msg-set-tbu-settings)

[sl_wisun_get_gtks](sl-wisun-msg-get-gtks)

[sl_wisun_msg_trigger_frame](sl-wisun-msg-trigger-frame)

[sl_wisun_msg_set_security_state](sl-wisun-msg-set-security-state)

[sl_wisun_msg_get_network_info](sl-wisun-msg-network-info)

[sl_wisun_msg_get_rpl_info](sl-wisun-msg-rpl-info)

[sl_wisun_msg_get_excluded_channel_mask](sl-wisun-msg-get-excluded-channel-mask)

[sl_wisun_msg_set_neighbor_table_size](sl-wisun-msg-set-neighbor-table-size)

[sl_wisun_msg_config_neighbor_table_size](sl-wisun-msg-config-neighbor-table-size)

[sl_wisun_msg_enable_neighbour_solicitations](sl-wisun-msg-enable-neighbour-solicitations)

[sl_wisun_msg_trigger_neighbor_cache_refresh](sl-wisun-msg-trigger-neighbor-cache-refresh)

[sl_wisun_msg_set_tx_power_ddbm](sl-wisun-msg-set-tx-power-ddbm)

[sl_wisun_msg_set_leaf](sl-wisun-msg-set-leaf)

[sl_wisun_msg_set_event_filter](sl-wisun-msg-set-event-filter)

[sl_wisun_msg_clear_event_filters](sl-wisun-msg-clear-event-filters)

[sl_wisun_msg_set_direct_connect_state](sl-wisun-msg-set-direct-connect-state)

[sl_wisun_msg_accept_direct_connect_link](sl-wisun-msg-accept-direct-connect-link)

[sl_wisun_msg_advert_direct_connect_server_id](sl-wisun-msg-advert-direct-connect-server-id)

[sl_wisun_msg_start_direct_connect_client](sl-wisun-msg-start-direct-connect-client)

[sl_wisun_msg_start_direct_connect_scan](sl-wisun-msg-start-direct-connect-scan)

[sl_wisun_msg_stop_direct_connect_scan](sl-wisun-msg-stop-direct-connect-scan)

[sl_wisun_msg_connect_to_direct_connect_server](sl-wisun-msg-connect-to-direct-connect-server)

[sl_wisun_msg_stop_direct_connect_client](sl-wisun-msg-stop-direct-connect-client)

[sl_wisun_set_phy_sensitivity](sl-wisun-set-phy-sensitivity)

[sl_wisun_msg_set_direct_connect_pmk_id](sl-wisun-msg-set-direct-connect-pmk-id)

[sl_wisun_msg_set_preferred_pan](sl-wisun-msg-set-preferred-pan)

[sl_wisun_msg_set_lfn_timings](sl-wisun-msg-set-lfn-timings)

[sl_wisun_msg_config_concurrent_detection](sl-wisun-msg-config-concurrent-detection)

[sl_wisun_msg_set_regulation_params](sl-wisun-msg-set-regulation-params)

[sl_wisun_msg_reset_regulation_duty_cycle](sl-wisun-msg-reset-regulation-duty-cycle)

[sl_wisun_msg_set_eap_identity](sl-wisun-msg-set-eap-identity)

[sl_wisun_msg_set_fan_tps_version](sl-wisun-msg-set-fan-tps-version)

[sl_wisun_msg_set_rx_fifo_size](sl-wisun-msg-set-rx-fifo-size)

[sl_wisun_msg_register_address](sl-wisun-msg-register-address)

[sl_wisun_msg_set_dhcpv6_vendor_data](sl-wisun-msg-set-dhcpv6-vendor-data)

[sl_wisun_msg_set_last_gasp](sl-wisun-msg-set-last-gasp)

[sl_wisun_msg_set_first_breath](sl-wisun-msg-set-first-breath)

##### Enumerations

###### sl_wisun_msg_cnf_id_t

```
enum sl_wisun_msg_cnf_id_t {
    SL_WISUN_MSG_SET_NETWORK_SIZE_CNF_ID = 0x01
    SL_WISUN_MSG_GET_IP_ADDRESS_CNF_ID = 0x03
    SL_WISUN_MSG_OPEN_SOCKET_CNF_ID = 0x04
    SL_WISUN_MSG_CLOSE_SOCKET_CNF_ID = 0x05
    SL_WISUN_MSG_SENDTO_ON_SOCKET_CNF_ID = 0x06
    SL_WISUN_MSG_LISTEN_ON_SOCKET_CNF_ID = 0x07
    SL_WISUN_MSG_ACCEPT_ON_SOCKET_CNF_ID = 0x08
    SL_WISUN_MSG_CONNECT_SOCKET_CNF_ID = 0x09
    SL_WISUN_MSG_BIND_SOCKET_CNF_ID = 0x0A
    SL_WISUN_MSG_SEND_ON_SOCKET_CNF_ID = 0x0B
    SL_WISUN_MSG_RECEIVE_ON_SOCKET_CNF_ID = 0x0C
    SL_WISUN_MSG_DISCONNECT_CNF_ID = 0x0D
    SL_WISUN_MSG_SET_TRUSTED_CERTIFICATE_CNF_ID = 0x0E
    SL_WISUN_MSG_SET_DEVICE_CERTIFICATE_CNF_ID = 0x0F
    SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_CNF_ID = 0x10
    SL_WISUN_MSG_GET_STATISTICS_CNF_ID = 0x11
    SL_WISUN_MSG_SET_SOCKET_OPTION_CNF_ID = 0x12
    SL_WISUN_MSG_SET_TX_POWER_CNF_ID = 0x13
    SL_WISUN_MSG_SET_CHANNEL_MASK_CNF_ID = 0x15
    SL_WISUN_MSG_ALLOW_MAC_ADDRESS_CNF_ID = 0x16
    SL_WISUN_MSG_DENY_MAC_ADDRESS_CNF_ID = 0x17
    SL_WISUN_MSG_GET_SOCKET_OPTION_CNF_ID = 0x18
    SL_WISUN_MSG_GET_JOIN_STATE_CNF_ID = 0x19
    SL_WISUN_MSG_CLEAR_CREDENTIAL_CACHE_CNF_ID = 0x1A
    SL_WISUN_MSG_GET_MAC_ADDRESS_CNF_ID = 0x1B
    SL_WISUN_MSG_SET_MAC_ADDRESS_CNF_ID = 0x1C
    SL_WISUN_MSG_RESET_STATISTICS_CNF_ID = 0x1D
    SL_WISUN_MSG_GET_NEIGHBOR_COUNT_CNF_ID = 0x1E
    SL_WISUN_MSG_GET_NEIGHBORS_CNF_ID = 0x1F
    SL_WISUN_MSG_GET_NEIGHBOR_INFO_CNF_ID = 0x20
    SL_WISUN_MSG_SET_UNICAST_SETTINGS_CNF_ID = 0x21
    SL_WISUN_MSG_SET_TRACE_LEVEL_CNF_ID = 0x22
    SL_WISUN_MSG_SET_TRACE_FILTER_CNF_ID = 0x23
    SL_WISUN_MSG_SET_REGULATION_CNF_ID = 0x24
    SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_ID_CNF_ID = 0x25
    SL_WISUN_MSG_SET_ASYNC_FRAGMENTATION_CNF_ID = 0x27
    SL_WISUN_MSG_SET_MODE_SWITCH_CNF_ID = 0x28
    SL_WISUN_MSG_SET_REGULATION_TX_THRESHOLDS_CNF_ID = 0x29
    SL_WISUN_MSG_SET_DEVICE_TYPE_CNF_ID = 0x2B
    SL_WISUN_MSG_SET_CONNECTION_PARAMS_CNF_ID = 0x2C
    SL_WISUN_MSG_JOIN_CNF_ID = 0x2D
    SL_WISUN_MSG_SET_POM_IE_CNF_ID = 0x2E
    SL_WISUN_MSG_GET_POM_IE_CNF_ID = 0x2F
    SL_WISUN_MSG_SET_LFN_PARAMS_CNF_ID = 0x30
    SL_WISUN_MSG_SET_LFN_SUPPORT_CNF_ID = 0x31
    SL_WISUN_MSG_SET_PTI_STATE_CNF_ID = 0x32
    SL_WISUN_MSG_SET_TBU_SETTINGS_CNF_ID = 0x33
    SL_WISUN_MSG_GET_GTKS_CNF_ID = 0x34
    SL_WISUN_MSG_TRIGGER_FRAME_CNF_ID = 0x35
    SL_WISUN_MSG_GET_STACK_VERSION_CNF_ID = 0x36
    SL_WISUN_MSG_SET_SECURITY_STATE_CNF_ID = 0x37
    SL_WISUN_MSG_GET_NETWORK_INFO_CNF_ID = 0x38
    SL_WISUN_MSG_GET_RPL_INFO_CNF_ID = 0x39
    SL_WISUN_MSG_GET_EXCLUDED_CHANNEL_MASK_CNF_ID = 0x3A
    SL_WISUN_MSG_SET_NEIGHBOR_TABLE_SIZE_CNF_ID = 0x3B
    SL_WISUN_MSG_SOCKET_RECVMSG_CNF_ID = 0x3C
    SL_WISUN_MSG_SOCKET_SENDMSG_CNF_ID = 0X3D
    SL_WISUN_MSG_SOCKET_GETSOCKNAME_CNF_ID = 0x3E
    SL_WISUN_MSG_SOCKET_GETPEERNAME_CNF_ID = 0x3F
    SL_WISUN_MSG_ENABLE_NEIGHBOUR_SOLICITATIONS_CNF_ID = 0x40
    SL_WISUN_MSG_TRIGGER_NEIGHBOR_CACHE_REFRESH_CNF_ID = 0x41
    SL_WISUN_MSG_SET_RATE_ALGORITHM_CNF_ID = 0x42
    SL_WISUN_MSG_GET_RATE_ALGORITHM_STATS_CNF_ID = 0x43
    SL_WISUN_MSG_SET_TX_POWER_DDBM_CNF_ID = 0x44
    SL_WISUN_MSG_SET_LEAF_CNF_ID = 0x45
    SL_WISUN_MSG_SET_DIRECT_CONNECT_STATE_CNF_ID = 0x46
    SL_WISUN_MSG_ACCEPT_DIRECT_CONNECT_LINK_CNF_ID = 0x47
    SL_WISUN_MSG_SET_PHY_SENSITIVITY_CNF_ID = 0x48
    SL_WISUN_MSG_SET_DIRECT_CONNECT_PMK_ID_CNF_ID = 0x49
    SL_WISUN_MSG_SET_PREFERRED_PAN_CNF_ID = 0x4A
    SL_WISUN_MSG_CONFIG_NEIGHBOR_TABLE_SIZE_CNF_ID = 0x4B
    SL_WISUN_MSG_SET_LFN_TIMINGS_CNF_ID = 0x4C
    SL_WISUN_MSG_CONFIG_CONCURRENT_DETECTION_CNF_ID = 0x4D
    SL_WISUN_MSG_SET_REGULATION_PARAMS_CNF_ID = 0x4E
    SL_WISUN_MSG_RESET_REGULATION_DUTY_CYCLE_CNF_ID = 0x4F
    SL_WISUN_MSG_SET_EAP_IDENTITY_CNF_ID = 0x50
    SL_WISUN_MSG_SET_EVENT_FILTER_CNF_ID = 0x51
    SL_WISUN_MSG_SET_FAN_TPS_VERSION_CNF_ID = 0x52
    SL_WISUN_MSG_SET_RX_FIFO_SIZE_CNF_ID = 0x53
    SL_WISUN_MSG_REGISTER_ADDRESS_CNF_ID = 0x54
    SL_WISUN_MSG_CLEAR_EVENT_FILTERS_CNF_ID = 0x55
    SL_WISUN_MSG_START_DIRECT_CONNECT_CLIENT_CNF_ID = 0x56
    SL_WISUN_MSG_START_DIRECT_CONNECT_SCAN_CNF_ID = 0x57
    SL_WISUN_MSG_STOP_DIRECT_CONNECT_SCAN_CNF_ID = 0x58
    SL_WISUN_MSG_ADVERT_DIRECT_CONNECT_SERVER_ID_CNF_ID = 0x59
    SL_WISUN_MSG_CONNECT_TO_DIRECT_CONNECT_SERVER_CNF_ID = 0x5A
    SL_WISUN_MSG_STOP_DIRECT_CONNECT_CLIENT_CNF_ID = 0x5B
    SL_WISUN_MSG_SET_DHCPV6_VENDOR_DATA_CNF_ID = 0x5C
    SL_WISUN_MSG_SET_LAST_GASP_CNF_ID = 0x5E
    SL_WISUN_MSG_SET_FIRST_BREATH_CNF_ID = 0x5F
    SL_WISUN_MSG_SET_OPTION_CNF_ID = 0x61
    SL_WISUN_MSG_SET_FFN_ADVANCED_PARAMS_CNF_ID = 0x62
    SL_WISUN_MSG_SET_LFN_ADVANCED_PARAMS_CNF_ID = 0x63
    SL_WISUN_MSG_RESET_PARAMS_CNF_ID = 0x64
}
```

**Description:**

Wi-SUN Message API confirmation IDs.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_MSG_SET_NETWORK_SIZE_CNF_ID||
|SL_WISUN_MSG_GET_IP_ADDRESS_CNF_ID||
|SL_WISUN_MSG_OPEN_SOCKET_CNF_ID||
|SL_WISUN_MSG_CLOSE_SOCKET_CNF_ID||
|SL_WISUN_MSG_SENDTO_ON_SOCKET_CNF_ID||
|SL_WISUN_MSG_LISTEN_ON_SOCKET_CNF_ID||
|SL_WISUN_MSG_ACCEPT_ON_SOCKET_CNF_ID||
|SL_WISUN_MSG_CONNECT_SOCKET_CNF_ID||
|SL_WISUN_MSG_BIND_SOCKET_CNF_ID||
|SL_WISUN_MSG_SEND_ON_SOCKET_CNF_ID||
|SL_WISUN_MSG_RECEIVE_ON_SOCKET_CNF_ID||
|SL_WISUN_MSG_DISCONNECT_CNF_ID||
|SL_WISUN_MSG_SET_TRUSTED_CERTIFICATE_CNF_ID||
|SL_WISUN_MSG_SET_DEVICE_CERTIFICATE_CNF_ID||
|SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_CNF_ID||
|SL_WISUN_MSG_GET_STATISTICS_CNF_ID||
|SL_WISUN_MSG_SET_SOCKET_OPTION_CNF_ID||
|SL_WISUN_MSG_SET_TX_POWER_CNF_ID||
|SL_WISUN_MSG_SET_CHANNEL_MASK_CNF_ID||
|SL_WISUN_MSG_ALLOW_MAC_ADDRESS_CNF_ID||
|SL_WISUN_MSG_DENY_MAC_ADDRESS_CNF_ID||
|SL_WISUN_MSG_GET_SOCKET_OPTION_CNF_ID||
|SL_WISUN_MSG_GET_JOIN_STATE_CNF_ID||
|SL_WISUN_MSG_CLEAR_CREDENTIAL_CACHE_CNF_ID||
|SL_WISUN_MSG_GET_MAC_ADDRESS_CNF_ID||
|SL_WISUN_MSG_SET_MAC_ADDRESS_CNF_ID||
|SL_WISUN_MSG_RESET_STATISTICS_CNF_ID||
|SL_WISUN_MSG_GET_NEIGHBOR_COUNT_CNF_ID||
|SL_WISUN_MSG_GET_NEIGHBORS_CNF_ID||
|SL_WISUN_MSG_GET_NEIGHBOR_INFO_CNF_ID||
|SL_WISUN_MSG_SET_UNICAST_SETTINGS_CNF_ID||
|SL_WISUN_MSG_SET_TRACE_LEVEL_CNF_ID||
|SL_WISUN_MSG_SET_TRACE_FILTER_CNF_ID||
|SL_WISUN_MSG_SET_REGULATION_CNF_ID||
|SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_ID_CNF_ID||
|SL_WISUN_MSG_SET_ASYNC_FRAGMENTATION_CNF_ID||
|SL_WISUN_MSG_SET_MODE_SWITCH_CNF_ID||
|SL_WISUN_MSG_SET_REGULATION_TX_THRESHOLDS_CNF_ID||
|SL_WISUN_MSG_SET_DEVICE_TYPE_CNF_ID||
|SL_WISUN_MSG_SET_CONNECTION_PARAMS_CNF_ID||
|SL_WISUN_MSG_JOIN_CNF_ID||
|SL_WISUN_MSG_SET_POM_IE_CNF_ID||
|SL_WISUN_MSG_GET_POM_IE_CNF_ID||
|SL_WISUN_MSG_SET_LFN_PARAMS_CNF_ID||
|SL_WISUN_MSG_SET_LFN_SUPPORT_CNF_ID||
|SL_WISUN_MSG_SET_PTI_STATE_CNF_ID||
|SL_WISUN_MSG_SET_TBU_SETTINGS_CNF_ID||
|SL_WISUN_MSG_GET_GTKS_CNF_ID||
|SL_WISUN_MSG_TRIGGER_FRAME_CNF_ID||
|SL_WISUN_MSG_GET_STACK_VERSION_CNF_ID||
|SL_WISUN_MSG_SET_SECURITY_STATE_CNF_ID||
|SL_WISUN_MSG_GET_NETWORK_INFO_CNF_ID||
|SL_WISUN_MSG_GET_RPL_INFO_CNF_ID||
|SL_WISUN_MSG_GET_EXCLUDED_CHANNEL_MASK_CNF_ID||
|SL_WISUN_MSG_SET_NEIGHBOR_TABLE_SIZE_CNF_ID||
|SL_WISUN_MSG_SOCKET_RECVMSG_CNF_ID||
|SL_WISUN_MSG_SOCKET_SENDMSG_CNF_ID||
|SL_WISUN_MSG_SOCKET_GETSOCKNAME_CNF_ID||
|SL_WISUN_MSG_SOCKET_GETPEERNAME_CNF_ID||
|SL_WISUN_MSG_ENABLE_NEIGHBOUR_SOLICITATIONS_CNF_ID||
|SL_WISUN_MSG_TRIGGER_NEIGHBOR_CACHE_REFRESH_CNF_ID||
|SL_WISUN_MSG_SET_RATE_ALGORITHM_CNF_ID||
|SL_WISUN_MSG_GET_RATE_ALGORITHM_STATS_CNF_ID||
|SL_WISUN_MSG_SET_TX_POWER_DDBM_CNF_ID||
|SL_WISUN_MSG_SET_LEAF_CNF_ID||
|SL_WISUN_MSG_SET_DIRECT_CONNECT_STATE_CNF_ID||
|SL_WISUN_MSG_ACCEPT_DIRECT_CONNECT_LINK_CNF_ID||
|SL_WISUN_MSG_SET_PHY_SENSITIVITY_CNF_ID||
|SL_WISUN_MSG_SET_DIRECT_CONNECT_PMK_ID_CNF_ID||
|SL_WISUN_MSG_SET_PREFERRED_PAN_CNF_ID||
|SL_WISUN_MSG_CONFIG_NEIGHBOR_TABLE_SIZE_CNF_ID||
|SL_WISUN_MSG_SET_LFN_TIMINGS_CNF_ID||
|SL_WISUN_MSG_CONFIG_CONCURRENT_DETECTION_CNF_ID||
|SL_WISUN_MSG_SET_REGULATION_PARAMS_CNF_ID||
|SL_WISUN_MSG_RESET_REGULATION_DUTY_CYCLE_CNF_ID||
|SL_WISUN_MSG_SET_EAP_IDENTITY_CNF_ID||
|SL_WISUN_MSG_SET_EVENT_FILTER_CNF_ID||
|SL_WISUN_MSG_SET_FAN_TPS_VERSION_CNF_ID||
|SL_WISUN_MSG_SET_RX_FIFO_SIZE_CNF_ID||
|SL_WISUN_MSG_REGISTER_ADDRESS_CNF_ID||
|SL_WISUN_MSG_CLEAR_EVENT_FILTERS_CNF_ID||
|SL_WISUN_MSG_START_DIRECT_CONNECT_CLIENT_CNF_ID||
|SL_WISUN_MSG_START_DIRECT_CONNECT_SCAN_CNF_ID||
|SL_WISUN_MSG_STOP_DIRECT_CONNECT_SCAN_CNF_ID||
|SL_WISUN_MSG_ADVERT_DIRECT_CONNECT_SERVER_ID_CNF_ID||
|SL_WISUN_MSG_CONNECT_TO_DIRECT_CONNECT_SERVER_CNF_ID||
|SL_WISUN_MSG_STOP_DIRECT_CONNECT_CLIENT_CNF_ID||
|SL_WISUN_MSG_SET_DHCPV6_VENDOR_DATA_CNF_ID||
|SL_WISUN_MSG_SET_LAST_GASP_CNF_ID||
|SL_WISUN_MSG_SET_FIRST_BREATH_CNF_ID||
|SL_WISUN_MSG_SET_OPTION_CNF_ID||
|SL_WISUN_MSG_SET_FFN_ADVANCED_PARAMS_CNF_ID||
|SL_WISUN_MSG_SET_LFN_ADVANCED_PARAMS_CNF_ID||
|SL_WISUN_MSG_RESET_PARAMS_CNF_ID||

###### sl_wisun_msg_req_id_t

```
enum sl_wisun_msg_req_id_t {
    SL_WISUN_MSG_SET_NETWORK_SIZE_REQ_ID = 0x01
    SL_WISUN_MSG_GET_IP_ADDRESS_REQ_ID = 0x03
    SL_WISUN_MSG_OPEN_SOCKET_REQ_ID = 0x04
    SL_WISUN_MSG_CLOSE_SOCKET_REQ_ID = 0x05
    SL_WISUN_MSG_SENDTO_ON_SOCKET_REQ_ID = 0x06
    SL_WISUN_MSG_LISTEN_ON_SOCKET_REQ_ID = 0x07
    SL_WISUN_MSG_ACCEPT_ON_SOCKET_REQ_ID = 0x08
    SL_WISUN_MSG_CONNECT_SOCKET_REQ_ID = 0x09
    SL_WISUN_MSG_BIND_SOCKET_REQ_ID = 0x0A
    SL_WISUN_MSG_SEND_ON_SOCKET_REQ_ID = 0x0B
    SL_WISUN_MSG_RECEIVE_ON_SOCKET_REQ_ID = 0x0C
    SL_WISUN_MSG_DISCONNECT_REQ_ID = 0x0D
    SL_WISUN_MSG_SET_TRUSTED_CERTIFICATE_REQ_ID = 0x0E
    SL_WISUN_MSG_SET_DEVICE_CERTIFICATE_REQ_ID = 0x0F
    SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_REQ_ID = 0x10
    SL_WISUN_MSG_GET_STATISTICS_REQ_ID = 0x11
    SL_WISUN_MSG_SET_SOCKET_OPTION_REQ_ID = 0x12
    SL_WISUN_MSG_SET_TX_POWER_REQ_ID = 0x13
    SL_WISUN_MSG_SET_CHANNEL_MASK_REQ_ID = 0x15
    SL_WISUN_MSG_ALLOW_MAC_ADDRESS_REQ_ID = 0x16
    SL_WISUN_MSG_DENY_MAC_ADDRESS_REQ_ID = 0x17
    SL_WISUN_MSG_GET_SOCKET_OPTION_REQ_ID = 0x18
    SL_WISUN_MSG_GET_JOIN_STATE_REQ_ID = 0x19
    SL_WISUN_MSG_CLEAR_CREDENTIAL_CACHE_REQ_ID = 0x1A
    SL_WISUN_MSG_GET_MAC_ADDRESS_REQ_ID = 0x1B
    SL_WISUN_MSG_SET_MAC_ADDRESS_REQ_ID = 0x1C
    SL_WISUN_MSG_RESET_STATISTICS_REQ_ID = 0x1D
    SL_WISUN_MSG_GET_NEIGHBOR_COUNT_REQ_ID = 0x1E
    SL_WISUN_MSG_GET_NEIGHBORS_REQ_ID = 0x1F
    SL_WISUN_MSG_GET_NEIGHBOR_INFO_REQ_ID = 0x20
    SL_WISUN_MSG_SET_UNICAST_SETTINGS_REQ_ID = 0x21
    SL_WISUN_MSG_SET_TRACE_LEVEL_REQ_ID = 0x22
    SL_WISUN_MSG_SET_TRACE_FILTER_REQ_ID = 0x23
    SL_WISUN_MSG_SET_REGULATION_REQ_ID = 0x24
    SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_ID_REQ_ID = 0x25
    SL_WISUN_MSG_SET_ASYNC_FRAGMENTATION_REQ_ID = 0x27
    SL_WISUN_MSG_SET_MODE_SWITCH_REQ_ID = 0x28
    SL_WISUN_MSG_SET_REGULATION_TX_THRESHOLDS_REQ_ID = 0x29
    SL_WISUN_MSG_SET_DEVICE_TYPE_REQ_ID = 0x2B
    SL_WISUN_MSG_SET_CONNECTION_PARAMS_REQ_ID = 0x2C
    SL_WISUN_MSG_JOIN_REQ_ID = 0x2D
    SL_WISUN_MSG_SET_POM_IE_REQ_ID = 0x2E
    SL_WISUN_MSG_GET_POM_IE_REQ_ID = 0x2F
    SL_WISUN_MSG_SET_LFN_PARAMS_REQ_ID = 0x30
    SL_WISUN_MSG_SET_LFN_SUPPORT_REQ_ID = 0x31
    SL_WISUN_MSG_SET_PTI_STATE_REQ_ID = 0x32
    SL_WISUN_MSG_SET_TBU_SETTINGS_REQ_ID = 0x33
    SL_WISUN_MSG_GET_GTKS_REQ_ID = 0x34
    SL_WISUN_MSG_TRIGGER_FRAME_REQ_ID = 0x35
    SL_WISUN_MSG_GET_STACK_VERSION_REQ_ID = 0x36
    SL_WISUN_MSG_SET_SECURITY_STATE_REQ_ID = 0x37
    SL_WISUN_MSG_GET_NETWORK_INFO_REQ_ID = 0x38
    SL_WISUN_MSG_GET_RPL_INFO_REQ_ID = 0x39
    SL_WISUN_MSG_GET_EXCLUDED_CHANNEL_MASK_REQ_ID = 0x3A
    SL_WISUN_MSG_SET_NEIGHBOR_TABLE_SIZE_REQ_ID = 0x3B
    SL_WISUN_MSG_SOCKET_RECVMSG_REQ_ID = 0x3C
    SL_WISUN_MSG_SOCKET_SENDMSG_REQ_ID = 0x3D
    SL_WISUN_MSG_SOCKET_GETSOCKNAME_REQ_ID = 0x3E
    SL_WISUN_MSG_SOCKET_GETPEERNAME_REQ_ID = 0x3F
    SL_WISUN_MSG_ENABLE_NEIGHBOUR_SOLICITATIONS_REQ_ID = 0x40
    SL_WISUN_MSG_TRIGGER_NEIGHBOR_CACHE_REFRESH_REQ_ID = 0x41
    SL_WISUN_MSG_SET_RATE_ALGORITHM_REQ_ID = 0x42
    SL_WISUN_MSG_GET_RATE_ALGORITHM_STATS_REQ_ID = 0x43
    SL_WISUN_MSG_SET_TX_POWER_DDBM_REQ_ID = 0x44
    SL_WISUN_MSG_SET_LEAF_REQ_ID = 0x45
    SL_WISUN_MSG_SET_DIRECT_CONNECT_STATE_REQ_ID = 0x46
    SL_WISUN_MSG_ACCEPT_DIRECT_CONNECT_LINK_REQ_ID = 0x47
    SL_WISUN_MSG_SET_PHY_SENSITIVITY_REQ_ID = 0x48
    SL_WISUN_MSG_SET_DIRECT_CONNECT_PMK_ID_REQ_ID = 0x49
    SL_WISUN_MSG_SET_PREFERRED_PAN_REQ_ID = 0x4A
    SL_WISUN_MSG_CONFIG_NEIGHBOR_TABLE_SIZE_REQ_ID = 0x4B
    SL_WISUN_MSG_SET_LFN_TIMINGS_REQ_ID = 0x4C
    SL_WISUN_MSG_CONFIG_CONCURRENT_DETECTION_REQ_ID = 0x4D
    SL_WISUN_MSG_SET_REGULATION_PARAMS_REQ_ID = 0x4E
    SL_WISUN_MSG_RESET_REGULATION_DUTY_CYCLE_REQ_ID = 0x4F
    SL_WISUN_MSG_SET_EAP_IDENTITY_REQ_ID = 0x50
    SL_WISUN_MSG_SET_EVENT_FILTER_REQ_ID = 0x51
    SL_WISUN_MSG_SET_FAN_TPS_VERSION_REQ_ID = 0x52
    SL_WISUN_MSG_SET_RX_FIFO_SIZE_REQ_ID = 0x53
    SL_WISUN_MSG_REGISTER_ADDRESS_REQ_ID = 0x54
    SL_WISUN_MSG_CLEAR_EVENT_FILTERS_REQ_ID = 0x55
    SL_WISUN_MSG_START_DIRECT_CONNECT_CLIENT_REQ_ID = 0x56
    SL_WISUN_MSG_START_DIRECT_CONNECT_SCAN_REQ_ID = 0x57
    SL_WISUN_MSG_STOP_DIRECT_CONNECT_SCAN_REQ_ID = 0x58
    SL_WISUN_MSG_ADVERT_DIRECT_CONNECT_SERVER_ID_REQ_ID = 0x59
    SL_WISUN_MSG_CONNECT_TO_DIRECT_CONNECT_SERVER_REQ_ID = 0x5A
    SL_WISUN_MSG_STOP_DIRECT_CONNECT_CLIENT_REQ_ID = 0x5B
    SL_WISUN_MSG_SET_DHCPV6_VENDOR_DATA_REQ_ID = 0x5C
    SL_WISUN_MSG_SET_LAST_GASP_REQ_ID = 0x5E
    SL_WISUN_MSG_SET_FIRST_BREATH_REQ_ID = 0x5F
    SL_WISUN_MSG_SET_OPTION_REQ_ID = 0x61
    SL_WISUN_MSG_SET_FFN_ADVANCED_PARAMS_REQ_ID = 0x62
    SL_WISUN_MSG_SET_LFN_ADVANCED_PARAMS_REQ_ID = 0x63
    SL_WISUN_MSG_RESET_PARAMS_REQ_ID = 0x64
}
```

**Description:**

Wi-SUN Message API request IDs.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_MSG_SET_NETWORK_SIZE_REQ_ID||
|SL_WISUN_MSG_GET_IP_ADDRESS_REQ_ID||
|SL_WISUN_MSG_OPEN_SOCKET_REQ_ID||
|SL_WISUN_MSG_CLOSE_SOCKET_REQ_ID||
|SL_WISUN_MSG_SENDTO_ON_SOCKET_REQ_ID||
|SL_WISUN_MSG_LISTEN_ON_SOCKET_REQ_ID||
|SL_WISUN_MSG_ACCEPT_ON_SOCKET_REQ_ID||
|SL_WISUN_MSG_CONNECT_SOCKET_REQ_ID||
|SL_WISUN_MSG_BIND_SOCKET_REQ_ID||
|SL_WISUN_MSG_SEND_ON_SOCKET_REQ_ID||
|SL_WISUN_MSG_RECEIVE_ON_SOCKET_REQ_ID||
|SL_WISUN_MSG_DISCONNECT_REQ_ID||
|SL_WISUN_MSG_SET_TRUSTED_CERTIFICATE_REQ_ID||
|SL_WISUN_MSG_SET_DEVICE_CERTIFICATE_REQ_ID||
|SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_REQ_ID||
|SL_WISUN_MSG_GET_STATISTICS_REQ_ID||
|SL_WISUN_MSG_SET_SOCKET_OPTION_REQ_ID||
|SL_WISUN_MSG_SET_TX_POWER_REQ_ID||
|SL_WISUN_MSG_SET_CHANNEL_MASK_REQ_ID||
|SL_WISUN_MSG_ALLOW_MAC_ADDRESS_REQ_ID||
|SL_WISUN_MSG_DENY_MAC_ADDRESS_REQ_ID||
|SL_WISUN_MSG_GET_SOCKET_OPTION_REQ_ID||
|SL_WISUN_MSG_GET_JOIN_STATE_REQ_ID||
|SL_WISUN_MSG_CLEAR_CREDENTIAL_CACHE_REQ_ID||
|SL_WISUN_MSG_GET_MAC_ADDRESS_REQ_ID||
|SL_WISUN_MSG_SET_MAC_ADDRESS_REQ_ID||
|SL_WISUN_MSG_RESET_STATISTICS_REQ_ID||
|SL_WISUN_MSG_GET_NEIGHBOR_COUNT_REQ_ID||
|SL_WISUN_MSG_GET_NEIGHBORS_REQ_ID||
|SL_WISUN_MSG_GET_NEIGHBOR_INFO_REQ_ID||
|SL_WISUN_MSG_SET_UNICAST_SETTINGS_REQ_ID||
|SL_WISUN_MSG_SET_TRACE_LEVEL_REQ_ID||
|SL_WISUN_MSG_SET_TRACE_FILTER_REQ_ID||
|SL_WISUN_MSG_SET_REGULATION_REQ_ID||
|SL_WISUN_MSG_SET_DEVICE_PRIVATE_KEY_ID_REQ_ID||
|SL_WISUN_MSG_SET_ASYNC_FRAGMENTATION_REQ_ID||
|SL_WISUN_MSG_SET_MODE_SWITCH_REQ_ID||
|SL_WISUN_MSG_SET_REGULATION_TX_THRESHOLDS_REQ_ID||
|SL_WISUN_MSG_SET_DEVICE_TYPE_REQ_ID||
|SL_WISUN_MSG_SET_CONNECTION_PARAMS_REQ_ID||
|SL_WISUN_MSG_JOIN_REQ_ID||
|SL_WISUN_MSG_SET_POM_IE_REQ_ID||
|SL_WISUN_MSG_GET_POM_IE_REQ_ID||
|SL_WISUN_MSG_SET_LFN_PARAMS_REQ_ID||
|SL_WISUN_MSG_SET_LFN_SUPPORT_REQ_ID||
|SL_WISUN_MSG_SET_PTI_STATE_REQ_ID||
|SL_WISUN_MSG_SET_TBU_SETTINGS_REQ_ID||
|SL_WISUN_MSG_GET_GTKS_REQ_ID||
|SL_WISUN_MSG_TRIGGER_FRAME_REQ_ID||
|SL_WISUN_MSG_GET_STACK_VERSION_REQ_ID||
|SL_WISUN_MSG_SET_SECURITY_STATE_REQ_ID||
|SL_WISUN_MSG_GET_NETWORK_INFO_REQ_ID||
|SL_WISUN_MSG_GET_RPL_INFO_REQ_ID||
|SL_WISUN_MSG_GET_EXCLUDED_CHANNEL_MASK_REQ_ID||
|SL_WISUN_MSG_SET_NEIGHBOR_TABLE_SIZE_REQ_ID||
|SL_WISUN_MSG_SOCKET_RECVMSG_REQ_ID||
|SL_WISUN_MSG_SOCKET_SENDMSG_REQ_ID||
|SL_WISUN_MSG_SOCKET_GETSOCKNAME_REQ_ID||
|SL_WISUN_MSG_SOCKET_GETPEERNAME_REQ_ID||
|SL_WISUN_MSG_ENABLE_NEIGHBOUR_SOLICITATIONS_REQ_ID||
|SL_WISUN_MSG_TRIGGER_NEIGHBOR_CACHE_REFRESH_REQ_ID||
|SL_WISUN_MSG_SET_RATE_ALGORITHM_REQ_ID||
|SL_WISUN_MSG_GET_RATE_ALGORITHM_STATS_REQ_ID||
|SL_WISUN_MSG_SET_TX_POWER_DDBM_REQ_ID||
|SL_WISUN_MSG_SET_LEAF_REQ_ID||
|SL_WISUN_MSG_SET_DIRECT_CONNECT_STATE_REQ_ID||
|SL_WISUN_MSG_ACCEPT_DIRECT_CONNECT_LINK_REQ_ID||
|SL_WISUN_MSG_SET_PHY_SENSITIVITY_REQ_ID||
|SL_WISUN_MSG_SET_DIRECT_CONNECT_PMK_ID_REQ_ID||
|SL_WISUN_MSG_SET_PREFERRED_PAN_REQ_ID||
|SL_WISUN_MSG_CONFIG_NEIGHBOR_TABLE_SIZE_REQ_ID||
|SL_WISUN_MSG_SET_LFN_TIMINGS_REQ_ID||
|SL_WISUN_MSG_CONFIG_CONCURRENT_DETECTION_REQ_ID||
|SL_WISUN_MSG_SET_REGULATION_PARAMS_REQ_ID||
|SL_WISUN_MSG_RESET_REGULATION_DUTY_CYCLE_REQ_ID||
|SL_WISUN_MSG_SET_EAP_IDENTITY_REQ_ID||
|SL_WISUN_MSG_SET_EVENT_FILTER_REQ_ID||
|SL_WISUN_MSG_SET_FAN_TPS_VERSION_REQ_ID||
|SL_WISUN_MSG_SET_RX_FIFO_SIZE_REQ_ID||
|SL_WISUN_MSG_REGISTER_ADDRESS_REQ_ID||
|SL_WISUN_MSG_CLEAR_EVENT_FILTERS_REQ_ID||
|SL_WISUN_MSG_START_DIRECT_CONNECT_CLIENT_REQ_ID||
|SL_WISUN_MSG_START_DIRECT_CONNECT_SCAN_REQ_ID||
|SL_WISUN_MSG_STOP_DIRECT_CONNECT_SCAN_REQ_ID||
|SL_WISUN_MSG_ADVERT_DIRECT_CONNECT_SERVER_ID_REQ_ID||
|SL_WISUN_MSG_CONNECT_TO_DIRECT_CONNECT_SERVER_REQ_ID||
|SL_WISUN_MSG_STOP_DIRECT_CONNECT_CLIENT_REQ_ID||
|SL_WISUN_MSG_SET_DHCPV6_VENDOR_DATA_REQ_ID||
|SL_WISUN_MSG_SET_LAST_GASP_REQ_ID||
|SL_WISUN_MSG_SET_FIRST_BREATH_REQ_ID||
|SL_WISUN_MSG_SET_OPTION_REQ_ID||
|SL_WISUN_MSG_SET_FFN_ADVANCED_PARAMS_REQ_ID||
|SL_WISUN_MSG_SET_LFN_ADVANCED_PARAMS_REQ_ID||
|SL_WISUN_MSG_RESET_PARAMS_REQ_ID||

##### Functions

###### sl_wisun_send_request

`sl_status_t sl_wisun_send_request(const void *req, uint16_t req_len, void *cnf, uint16_t cnf_len)`

**Description:** Send a request to the Wi-SUN stack.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|const void *|[in]|req|Pointer to the request message buffer|
|uint16_t|[in]|req_len|Length of the request message in bytes (must match req->header.length)|
|void *|[out]|cnf|Pointer to confirmation message buffer|
|uint16_t|[in]|cnf_len|Length of the confirmation message buffer in bytes|

This function provides an interface for sending requests to the Wi-SUN stack and receiving confirmations. When using blocking requests, the function blocks until the request is processed and a confirmation is available.

REQ/CNF buffer layout: request: | Header (4B) | Request body (varies) | Trailing data (if any) | confirmation: | Header (4B) | Confirmation body (varies) | Trailing data (if any) |

Header structure:

- length: uint16_t - Total message length including header and trailing data
- id: uint8_t - Message identifier
- info: uint8_t - Message flags and metadata

- req != NULL && cnf != NULL
- req_len >= sizeof(sl_wisun_msg_header_t)
- cnf_len >= sizeof(sl_wisun_msg_header_t) + sizeof(uint32_t) (header + status)
- req->header.length == req_len (length consistency check)

**Returns**

- SL_STATUS_OK Request processed successfully
- SL_STATUS_INVALID_PARAMETER Invalid parameters or buffer size mismatch
- SL_STATUS_NULL_POINTER NULL pointer parameter
- SL_STATUS_FAIL Internal processing error or handler failure

**Note**

- Blocking behavior: When using blocking requests, this function blocks the calling thread until the request is processed.

**See Also**

- [sl_wisun_msg_header_t](sl-wisun-msg-header-t) for header structure details

##### sl_wisun_msg_generic

###### Modules

[sl_wisun_msg_generic_cnf_body_t](sl-wisun-msg-generic-cnf-body-t)

[sl_wisun_msg_generic_cnf_t](sl-wisun-msg-generic-cnf-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_generic_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_generic_cnf_body_t sl_wisun_msg_generic_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_generic_cnf_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_network_size

###### Modules

[sl_wisun_msg_set_network_size_cnf_body_t](sl-wisun-msg-set-network-size-cnf-body-t)

[sl_wisun_msg_set_network_size_cnf_t](sl-wisun-msg-set-network-size-cnf-t)

[sl_wisun_msg_set_network_size_req_body_t](sl-wisun-msg-set-network-size-req-body-t)

[sl_wisun_msg_set_network_size_req_t](sl-wisun-msg-set-network-size-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_network_size_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_network_size_cnf_body_t sl_wisun_msg_set_network_size_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_network_size_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_network_size_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### size (heading level 8)

```
uint8_t sl_wisun_msg_set_network_size_req_body_t::size
```

**Description:** Network size.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_network_size_req_body_t sl_wisun_msg_set_network_size_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_network_size_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_ip_address

###### Modules

[sl_wisun_msg_get_ip_address_cnf_body_t](sl-wisun-msg-get-ip-address-cnf-body-t)

[sl_wisun_msg_get_ip_address_cnf_t](sl-wisun-msg-get-ip-address-cnf-t)

[sl_wisun_msg_get_ip_address_req_body_t](sl-wisun-msg-get-ip-address-req-body-t)

[sl_wisun_msg_get_ip_address_req_t](sl-wisun-msg-get-ip-address-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
in6_addr_t sl_wisun_msg_get_ip_address_cnf_body_t::address
```

**Description:** IP address.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_ip_address_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_ip_address_cnf_body_t sl_wisun_msg_get_ip_address_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_ip_address_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### address_type (heading level 8)

```
uint32_t sl_wisun_msg_get_ip_address_req_body_t::address_type
```

**Description:** Type of the IP address to read.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_ip_address_req_body_t sl_wisun_msg_get_ip_address_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_ip_address_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_open_socket

###### Modules

[sl_wisun_msg_open_socket_cnf_body_t](sl-wisun-msg-open-socket-cnf-body-t)

[sl_wisun_msg_open_socket_cnf_t](sl-wisun-msg-open-socket-cnf-t)

[sl_wisun_msg_open_socket_req_body_t](sl-wisun-msg-open-socket-req-body-t)

[sl_wisun_msg_open_socket_req_t](sl-wisun-msg-open-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_open_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_open_socket_cnf_body_t::socket_id
```

**Description:** ID of the opened socket.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_open_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_open_socket_cnf_body_t sl_wisun_msg_open_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_open_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### domain (heading level 8)

```
uint32_t sl_wisun_msg_open_socket_req_body_t::domain
```

**Description:** Communication domain.

###### protocol (heading level 8)

```
uint32_t sl_wisun_msg_open_socket_req_body_t::protocol
```

**Description:** Protocol to be used.

###### type (heading level 8)

```
uint32_t sl_wisun_msg_open_socket_req_body_t::type
```

**Description:** Communication semantics.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_open_socket_req_body_t sl_wisun_msg_open_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_open_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_close_socket

###### Modules

[sl_wisun_msg_close_socket_cnf_body_t](sl-wisun-msg-close-socket-cnf-body-t)

[sl_wisun_msg_close_socket_cnf_t](sl-wisun-msg-close-socket-cnf-t)

[sl_wisun_msg_close_socket_req_body_t](sl-wisun-msg-close-socket-req-body-t)

[sl_wisun_msg_close_socket_req_t](sl-wisun-msg-close-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_close_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_close_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_close_socket_cnf_body_t sl_wisun_msg_close_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_close_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_close_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_close_socket_req_body_t sl_wisun_msg_close_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_close_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_sendto_on_socket

###### Modules

[sl_wisun_msg_sendto_on_socket_cnf_body_t](sl-wisun-msg-sendto-on-socket-cnf-body-t)

[sl_wisun_msg_sendto_on_socket_cnf_t](sl-wisun-msg-sendto-on-socket-cnf-t)

[sl_wisun_msg_sendto_on_socket_req_body_t](sl-wisun-msg-sendto-on-socket-req-body-t)

[sl_wisun_msg_sendto_on_socket_req_t](sl-wisun-msg-sendto-on-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
int32_t sl_wisun_msg_sendto_on_socket_cnf_body_t::data_length
```

**Description:** Amount of data sent in bytes equal to SOCKET_RETVAL_ERROR in case of failure.

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_sendto_on_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_sendto_on_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_sendto_on_socket_cnf_body_t sl_wisun_msg_sendto_on_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_sendto_on_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_sendto_on_socket_req_body_t::data[]
```

**Description:** Data to write.

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_sendto_on_socket_req_body_t::data_length
```

**Description:** Amount of data to write.

###### remote_address (heading level 8)

```
in6_addr_t sl_wisun_msg_sendto_on_socket_req_body_t::remote_address
```

**Description:** IP address of the remote peer.

###### remote_port (heading level 8)

```
uint16_t sl_wisun_msg_sendto_on_socket_req_body_t::remote_port
```

**Description:** Port number of the remote peer.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_sendto_on_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_sendto_on_socket_req_body_t sl_wisun_msg_sendto_on_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_sendto_on_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_sendmsg

###### Modules

[sl_wisun_msg_socket_sendmsg_cnf_body_t](sl-wisun-msg-socket-sendmsg-cnf-body-t)

[sl_wisun_msg_socket_sendmsg_cnf_t](sl-wisun-msg-socket-sendmsg-cnf-t)

[sl_wisun_msg_socket_sendmsg_req_body_t](sl-wisun-msg-socket-sendmsg-req-body-t)

[sl_wisun_msg_socket_sendmsg_req_t](sl-wisun-msg-socket-sendmsg-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
int32_t sl_wisun_msg_socket_sendmsg_cnf_body_t::data_length
```

**Description:** Amount of data sent in bytes equal to SOCKET_RETVAL_ERROR in case of failure.

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_socket_sendmsg_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_sendmsg_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_sendmsg_cnf_body_t sl_wisun_msg_socket_sendmsg_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_sendmsg_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### flags (heading level 8)

```
int32_t sl_wisun_msg_socket_sendmsg_req_body_t::flags
```

**Description:** Specifies the type of message reception.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_socket_sendmsg_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_sendmsg_req_body_t sl_wisun_msg_socket_sendmsg_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_sendmsg_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_listen_on_socket

###### Modules

[sl_wisun_msg_listen_on_socket_cnf_body_t](sl-wisun-msg-listen-on-socket-cnf-body-t)

[sl_wisun_msg_listen_on_socket_cnf_t](sl-wisun-msg-listen-on-socket-cnf-t)

[sl_wisun_msg_listen_on_socket_req_body_t](sl-wisun-msg-listen-on-socket-req-body-t)

[sl_wisun_msg_listen_on_socket_req_t](sl-wisun-msg-listen-on-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_listen_on_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_listen_on_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_listen_on_socket_cnf_body_t sl_wisun_msg_listen_on_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_listen_on_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_listen_on_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_listen_on_socket_req_body_t sl_wisun_msg_listen_on_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_listen_on_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_accept_on_socket

###### Modules

[sl_wisun_msg_accept_on_socket_cnf_body_t](sl-wisun-msg-accept-on-socket-cnf-body-t)

[sl_wisun_msg_accept_on_socket_cnf_t](sl-wisun-msg-accept-on-socket-cnf-t)

[sl_wisun_msg_accept_on_socket_req_body_t](sl-wisun-msg-accept-on-socket-req-body-t)

[sl_wisun_msg_accept_on_socket_req_t](sl-wisun-msg-accept-on-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_accept_on_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### remote_address (heading level 8)

```
in6_addr_t sl_wisun_msg_accept_on_socket_cnf_body_t::remote_address
```

**Description:** IP address of the remote peer.

###### remote_port (heading level 8)

```
uint16_t sl_wisun_msg_accept_on_socket_cnf_body_t::remote_port
```

**Description:** Port number of the remote peer.

###### remote_socket_id (heading level 8)

```
uint32_t sl_wisun_msg_accept_on_socket_cnf_body_t::remote_socket_id
```

**Description:** ID of the new connected socket.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_accept_on_socket_cnf_body_t::reserved
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_accept_on_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_accept_on_socket_cnf_body_t sl_wisun_msg_accept_on_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_accept_on_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_accept_on_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_accept_on_socket_req_body_t sl_wisun_msg_accept_on_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_accept_on_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_connect_socket

###### Modules

[sl_wisun_msg_connect_socket_cnf_body_t](sl-wisun-msg-connect-socket-cnf-body-t)

[sl_wisun_msg_connect_socket_cnf_t](sl-wisun-msg-connect-socket-cnf-t)

[sl_wisun_msg_connect_socket_req_body_t](sl-wisun-msg-connect-socket-req-body-t)

[sl_wisun_msg_connect_socket_req_t](sl-wisun-msg-connect-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_connect_socket_cnf_body_t::error_code
```

**Description:** error code

###### status (heading level 8)

```
uint32_t sl_wisun_msg_connect_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_connect_socket_cnf_body_t sl_wisun_msg_connect_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_connect_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### remote_address (heading level 8)

```
in6_addr_t sl_wisun_msg_connect_socket_req_body_t::remote_address
```

**Description:** IP address of the remote peer.

###### remote_port (heading level 8)

```
uint16_t sl_wisun_msg_connect_socket_req_body_t::remote_port
```

**Description:** Port number of the remote peer.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_connect_socket_req_body_t::reserved
```

**Description:** Reserved, set to zero.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_connect_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_connect_socket_req_body_t sl_wisun_msg_connect_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_connect_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_bind_socket

###### Modules

[sl_wisun_msg_bind_socket_cnf_body_t](sl-wisun-msg-bind-socket-cnf-body-t)

[sl_wisun_msg_bind_socket_cnf_t](sl-wisun-msg-bind-socket-cnf-t)

[sl_wisun_msg_bind_socket_req_body_t](sl-wisun-msg-bind-socket-req-body-t)

[sl_wisun_msg_bind_socket_req_t](sl-wisun-msg-bind-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_bind_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_bind_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_bind_socket_cnf_body_t sl_wisun_msg_bind_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_bind_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### local_address (heading level 8)

```
in6_addr_t sl_wisun_msg_bind_socket_req_body_t::local_address
```

**Description:** Local IP address to use on the socket.

###### local_port (heading level 8)

```
uint16_t sl_wisun_msg_bind_socket_req_body_t::local_port
```

**Description:** Local port number to use on the socket.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_bind_socket_req_body_t::reserved
```

**Description:** Reserved, set to zero.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_bind_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_bind_socket_req_body_t sl_wisun_msg_bind_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_bind_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_send_on_socket

###### Modules

[sl_wisun_msg_send_on_socket_cnf_body_t](sl-wisun-msg-send-on-socket-cnf-body-t)

[sl_wisun_msg_send_on_socket_cnf_t](sl-wisun-msg-send-on-socket-cnf-t)

[sl_wisun_msg_send_on_socket_req_body_t](sl-wisun-msg-send-on-socket-req-body-t)

[sl_wisun_msg_send_on_socket_req_t](sl-wisun-msg-send-on-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
int32_t sl_wisun_msg_send_on_socket_cnf_body_t::data_length
```

**Description:** Amount of data sent in bytes Equal to SOCKET_RETVAL_ERROR in case of failure.

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_send_on_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_send_on_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_send_on_socket_cnf_body_t sl_wisun_msg_send_on_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_send_on_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_send_on_socket_req_body_t::data[]
```

**Description:** Data to write.

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_send_on_socket_req_body_t::data_length
```

**Description:** Amount of data to write.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_send_on_socket_req_body_t::reserved
```

**Description:** Reserved, set to zero.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_send_on_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_send_on_socket_req_body_t sl_wisun_msg_send_on_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_send_on_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_receive_on_socket

###### Modules

[sl_wisun_msg_receive_on_socket_cnf_body_t](sl-wisun-msg-receive-on-socket-cnf-body-t)

[sl_wisun_msg_receive_on_socket_cnf_t](sl-wisun-msg-receive-on-socket-cnf-t)

[sl_wisun_msg_receive_on_socket_req_body_t](sl-wisun-msg-receive-on-socket-req-body-t)

[sl_wisun_msg_receive_on_socket_req_t](sl-wisun-msg-receive-on-socket-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_receive_on_socket_cnf_body_t::data[]
```

**Description:** Data read.

###### data_length (heading level 8)

```
int16_t sl_wisun_msg_receive_on_socket_cnf_body_t::data_length
```

**Description:** Amount of data read.

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_receive_on_socket_cnf_body_t::error_code
```

**Description:** Error code.

###### remote_address (heading level 8)

```
in6_addr_t sl_wisun_msg_receive_on_socket_cnf_body_t::remote_address
```

**Description:** IP address of the remote peer.

###### remote_port (heading level 8)

```
uint16_t sl_wisun_msg_receive_on_socket_cnf_body_t::remote_port
```

**Description:** Port number of the remote peer.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_receive_on_socket_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_receive_on_socket_cnf_body_t sl_wisun_msg_receive_on_socket_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_receive_on_socket_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_receive_on_socket_req_body_t::data_length
```

**Description:** Amount of data to read.

###### get_remote_addr (heading level 8)

```
uint8_t sl_wisun_msg_receive_on_socket_req_body_t::get_remote_addr
```

**Description:** whether to get or not the remote address

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_receive_on_socket_req_body_t::reserved
```

**Description:** Reserved, set to zero.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_receive_on_socket_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_receive_on_socket_req_body_t sl_wisun_msg_receive_on_socket_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_receive_on_socket_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_recvmsg

###### Modules

[sl_wisun_msg_socket_recvmsg_cnf_body_t](sl-wisun-msg-socket-recvmsg-cnf-body-t)

[sl_wisun_msg_socket_recvmsg_cnf_t](sl-wisun-msg-socket-recvmsg-cnf-t)

[sl_wisun_msg_socket_recvmsg_req_body_t](sl-wisun-msg-socket-recvmsg-req-body-t)

[sl_wisun_msg_socket_recvmsg_req_t](sl-wisun-msg-socket-recvmsg-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
int16_t sl_wisun_msg_socket_recvmsg_cnf_body_t::data_length
```

**Description:** Number of bytes received;.

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_socket_recvmsg_cnf_body_t::error_code
```

**Description:** code of the error

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_socket_recvmsg_cnf_body_t::reserved
```

**Description:** reserved, set to zero

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_recvmsg_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_recvmsg_cnf_body_t sl_wisun_msg_socket_recvmsg_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_recvmsg_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### flags (heading level 8)

```
int32_t sl_wisun_msg_socket_recvmsg_req_body_t::flags
```

**Description:** Specifies the type of message reception.

###### socket (heading level 8)

```
int32_t sl_wisun_msg_socket_recvmsg_req_body_t::socket
```

**Description:** socket ID

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_recvmsg_req_body_t sl_wisun_msg_socket_recvmsg_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_recvmsg_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_getsockname

###### Modules

[sl_wisun_msg_socket_getsockname_cnf_body_t](sl-wisun-msg-socket-getsockname-cnf-body-t)

[sl_wisun_msg_socket_getsockname_cnf_t](sl-wisun-msg-socket-getsockname-cnf-t)

[sl_wisun_msg_socket_getsockname_req_body_t](sl-wisun-msg-socket-getsockname-req-body-t)

[sl_wisun_msg_socket_getsockname_req_t](sl-wisun-msg-socket-getsockname-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_socket_getsockname_cnf_body_t::error_code
```

**Description:** error code

###### local_address (heading level 8)

```
in6_addr_t sl_wisun_msg_socket_getsockname_cnf_body_t::local_address
```

**Description:** Local IP address.

###### local_port (heading level 8)

```
int32_t sl_wisun_msg_socket_getsockname_cnf_body_t::local_port
```

**Description:** Local port.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_getsockname_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_getsockname_cnf_body_t sl_wisun_msg_socket_getsockname_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_getsockname_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### flags (heading level 8)

```
int32_t sl_wisun_msg_socket_getsockname_req_body_t::flags
```

**Description:** Specifies the type of message reception.

###### socket (heading level 8)

```
int32_t sl_wisun_msg_socket_getsockname_req_body_t::socket
```

**Description:** socket ID

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_getsockname_req_body_t sl_wisun_msg_socket_getsockname_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_getsockname_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_socket_getpeername

###### Modules

[sl_wisun_msg_socket_getpeername_cnf_body_t](sl-wisun-msg-socket-getpeername-cnf-body-t)

[sl_wisun_msg_socket_getpeername_cnf_t](sl-wisun-msg-socket-getpeername-cnf-t)

[sl_wisun_msg_socket_getpeername_req_body_t](sl-wisun-msg-socket-getpeername-req-body-t)

[sl_wisun_msg_socket_getpeername_req_t](sl-wisun-msg-socket-getpeername-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_socket_getpeername_cnf_body_t::error_code
```

**Description:** error code

###### remote_address (heading level 8)

```
in6_addr_t sl_wisun_msg_socket_getpeername_cnf_body_t::remote_address
```

**Description:** Remote IP address.

###### remote_port (heading level 8)

```
int32_t sl_wisun_msg_socket_getpeername_cnf_body_t::remote_port
```

**Description:** Remote port.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_socket_getpeername_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_getpeername_cnf_body_t sl_wisun_msg_socket_getpeername_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_getpeername_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### flags (heading level 8)

```
int32_t sl_wisun_msg_socket_getpeername_req_body_t::flags
```

**Description:** Specifies the type of message reception.

###### socket (heading level 8)

```
int32_t sl_wisun_msg_socket_getpeername_req_body_t::socket
```

**Description:** socket ID

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_socket_getpeername_req_body_t sl_wisun_msg_socket_getpeername_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_socket_getpeername_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_disconnect

###### Modules

[sl_wisun_msg_disconnect_cnf_body_t](sl-wisun-msg-disconnect-cnf-body-t)

[sl_wisun_msg_disconnect_cnf_t](sl-wisun-msg-disconnect-cnf-t)

[sl_wisun_msg_disconnect_req_body_t](sl-wisun-msg-disconnect-req-body-t)

[sl_wisun_msg_disconnect_req_t](sl-wisun-msg-disconnect-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_disconnect_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_disconnect_cnf_body_t sl_wisun_msg_disconnect_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_disconnect_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### non_graceful (heading level 8)

```
uint32_t sl_wisun_msg_disconnect_req_body_t::non_graceful
```

**Description:** 1 for non-graceful disconnection

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_disconnect_req_body_t sl_wisun_msg_disconnect_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_disconnect_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_trusted_certificate

###### Modules

[sl_wisun_msg_set_trusted_certificate_cnf_body_t](sl-wisun-msg-set-trusted-certificate-cnf-body-t)

[sl_wisun_msg_set_trusted_certificate_cnf_t](sl-wisun-msg-set-trusted-certificate-cnf-t)

[sl_wisun_msg_set_trusted_certificate_req_body_t](sl-wisun-msg-set-trusted-certificate-req-body-t)

[sl_wisun_msg_set_trusted_certificate_req_t](sl-wisun-msg-set-trusted-certificate-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_trusted_certificate_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_trusted_certificate_cnf_body_t sl_wisun_msg_set_trusted_certificate_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_trusted_certificate_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### certificate (heading level 8)

```
uint8_t sl_wisun_msg_set_trusted_certificate_req_body_t::certificate[]
```

**Description:** Certificate data.

###### certificate_length (heading level 8)

```
uint16_t sl_wisun_msg_set_trusted_certificate_req_body_t::certificate_length
```

**Description:** Size of the certificate data.

###### certificate_options (heading level 8)

```
uint16_t sl_wisun_msg_set_trusted_certificate_req_body_t::certificate_options
```

**Description:** Options for the certificate.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_trusted_certificate_req_body_t sl_wisun_msg_set_trusted_certificate_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_trusted_certificate_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_device_certificate

###### Modules

[sl_wisun_msg_set_device_certificate_cnf_body_t](sl-wisun-msg-set-device-certificate-cnf-body-t)

[sl_wisun_msg_set_device_certificate_cnf_t](sl-wisun-msg-set-device-certificate-cnf-t)

[sl_wisun_msg_set_device_certificate_req_body_t](sl-wisun-msg-set-device-certificate-req-body-t)

[sl_wisun_msg_set_device_certificate_req_t](sl-wisun-msg-set-device-certificate-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_device_certificate_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_certificate_cnf_body_t sl_wisun_msg_set_device_certificate_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_certificate_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### certificate (heading level 8)

```
uint8_t sl_wisun_msg_set_device_certificate_req_body_t::certificate[]
```

**Description:** Certificate data.

###### certificate_length (heading level 8)

```
uint16_t sl_wisun_msg_set_device_certificate_req_body_t::certificate_length
```

**Description:** Size of the certificate data.

###### certificate_options (heading level 8)

```
uint16_t sl_wisun_msg_set_device_certificate_req_body_t::certificate_options
```

**Description:** Options for the certificate.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_certificate_req_body_t sl_wisun_msg_set_device_certificate_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_certificate_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_device_private_key

###### Modules

[sl_wisun_msg_set_device_private_key_cnf_body_t](sl-wisun-msg-set-device-private-key-cnf-body-t)

[sl_wisun_msg_set_device_private_key_cnf_t](sl-wisun-msg-set-device-private-key-cnf-t)

[sl_wisun_msg_set_device_private_key_req_body_t](sl-wisun-msg-set-device-private-key-req-body-t)

[sl_wisun_msg_set_device_private_key_req_t](sl-wisun-msg-set-device-private-key-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_device_private_key_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_private_key_cnf_body_t sl_wisun_msg_set_device_private_key_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_private_key_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### key (heading level 8)

```
uint8_t sl_wisun_msg_set_device_private_key_req_body_t::key[]
```

**Description:** Private key data.

###### key_length (heading level 8)

```
uint16_t sl_wisun_msg_set_device_private_key_req_body_t::key_length
```

**Description:** Size of the private key data.

###### key_options (heading level 8)

```
uint16_t sl_wisun_msg_set_device_private_key_req_body_t::key_options
```

**Description:** Options for the private key.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_private_key_req_body_t sl_wisun_msg_set_device_private_key_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_private_key_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_statistics

###### Modules

[sl_wisun_msg_get_statistics_cnf_body_t](sl-wisun-msg-get-statistics-cnf-body-t)

[sl_wisun_msg_get_statistics_cnf_t](sl-wisun-msg-get-statistics-cnf-t)

[sl_wisun_msg_get_statistics_req_body_t](sl-wisun-msg-get-statistics-req-body-t)

[sl_wisun_msg_get_statistics_req_t](sl-wisun-msg-get-statistics-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### statistics (heading level 8)

```
sl_wisun_statistics_t sl_wisun_msg_get_statistics_cnf_body_t::statistics
```

**Description:** Statistics.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_statistics_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_statistics_cnf_body_t sl_wisun_msg_get_statistics_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_statistics_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### statistics_type (heading level 8)

```
uint32_t sl_wisun_msg_get_statistics_req_body_t::statistics_type
```

**Description:** Type of statistics to read.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_statistics_req_body_t sl_wisun_msg_get_statistics_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_statistics_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_socket_option

###### Modules

[sl_wisun_msg_set_socket_option_cnf_body_t](sl-wisun-msg-set-socket-option-cnf-body-t)

[sl_wisun_msg_set_socket_option_cnf_t](sl-wisun-msg-set-socket-option-cnf-t)

[sl_wisun_msg_set_socket_option_req_body_t](sl-wisun-msg-set-socket-option-req-body-t)

[sl_wisun_msg_set_socket_option_req_t](sl-wisun-msg-set-socket-option-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_set_socket_option_cnf_body_t::error_code
```

**Description:** Error code.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_socket_option_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_socket_option_cnf_body_t sl_wisun_msg_set_socket_option_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_socket_option_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_set_socket_option_req_body_t::data[]
```

**Description:** option value

###### level (heading level 8)

```
int32_t sl_wisun_msg_set_socket_option_req_body_t::level
```

**Description:** Socket protocol level.

###### option_length (heading level 8)

```
uint16_t sl_wisun_msg_set_socket_option_req_body_t::option_length
```

**Description:** option data length

###### option_name (heading level 8)

```
int32_t sl_wisun_msg_set_socket_option_req_body_t::option_name
```

**Description:** Socket option name.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_set_socket_option_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_socket_option_req_body_t sl_wisun_msg_set_socket_option_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_socket_option_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_tx_power

###### Modules

[sl_wisun_msg_set_tx_power_cnf_body_t](sl-wisun-msg-set-tx-power-cnf-body-t)

[sl_wisun_msg_set_tx_power_cnf_t](sl-wisun-msg-set-tx-power-cnf-t)

[sl_wisun_msg_set_tx_power_req_body_t](sl-wisun-msg-set-tx-power-req-body-t)

[sl_wisun_msg_set_tx_power_req_t](sl-wisun-msg-set-tx-power-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_tx_power_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_tx_power_cnf_body_t sl_wisun_msg_set_tx_power_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_tx_power_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_tx_power_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### tx_power (heading level 8)

```
int8_t sl_wisun_msg_set_tx_power_req_body_t::tx_power
```

**Description:** TX power.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_tx_power_req_body_t sl_wisun_msg_set_tx_power_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_tx_power_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_channel_mask

###### Modules

[sl_wisun_msg_set_channel_mask_cnf_body_t](sl-wisun-msg-set-channel-mask-cnf-body-t)

[sl_wisun_msg_set_channel_mask_cnf_t](sl-wisun-msg-set-channel-mask-cnf-t)

[sl_wisun_msg_set_channel_mask_req_body_t](sl-wisun-msg-set-channel-mask-req-body-t)

[sl_wisun_msg_set_channel_mask_req_t](sl-wisun-msg-set-channel-mask-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_channel_mask_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_channel_mask_cnf_body_t sl_wisun_msg_set_channel_mask_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_channel_mask_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### channel_mask (heading level 8)

```
sl_wisun_channel_mask_t sl_wisun_msg_set_channel_mask_req_body_t::channel_mask
```

**Description:** Channel mask.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_channel_mask_req_body_t sl_wisun_msg_set_channel_mask_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_channel_mask_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_allow_mac_address

###### Modules

[sl_wisun_msg_allow_mac_address_cnf_body_t](sl-wisun-msg-allow-mac-address-cnf-body-t)

[sl_wisun_msg_allow_mac_address_cnf_t](sl-wisun-msg-allow-mac-address-cnf-t)

[sl_wisun_msg_allow_mac_address_req_body_t](sl-wisun-msg-allow-mac-address-req-body-t)

[sl_wisun_msg_allow_mac_address_req_t](sl-wisun-msg-allow-mac-address-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_allow_mac_address_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_allow_mac_address_cnf_body_t sl_wisun_msg_allow_mac_address_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_allow_mac_address_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_allow_mac_address_req_body_t::address
```

**Description:** MAC address.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_allow_mac_address_req_body_t sl_wisun_msg_allow_mac_address_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_allow_mac_address_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_deny_mac_address

###### Modules

[sl_wisun_msg_deny_mac_address_cnf_body_t](sl-wisun-msg-deny-mac-address-cnf-body-t)

[sl_wisun_msg_deny_mac_address_cnf_t](sl-wisun-msg-deny-mac-address-cnf-t)

[sl_wisun_msg_deny_mac_address_req_body_t](sl-wisun-msg-deny-mac-address-req-body-t)

[sl_wisun_msg_deny_mac_address_req_t](sl-wisun-msg-deny-mac-address-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_deny_mac_address_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_deny_mac_address_cnf_body_t sl_wisun_msg_deny_mac_address_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_deny_mac_address_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_deny_mac_address_req_body_t::address
```

**Description:** MAC address.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_deny_mac_address_req_body_t sl_wisun_msg_deny_mac_address_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_deny_mac_address_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_socket_option

###### Modules

[sl_wisun_msg_get_socket_option_cnf_body_t](sl-wisun-msg-get-socket-option-cnf-body-t)

[sl_wisun_msg_get_socket_option_cnf_t](sl-wisun-msg-get-socket-option-cnf-t)

[sl_wisun_msg_get_socket_option_req_body_t](sl-wisun-msg-get-socket-option-req-body-t)

[sl_wisun_msg_get_socket_option_req_t](sl-wisun-msg-get-socket-option-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_msg_get_socket_option_cnf_body_t::data[]
```

**Description:** option value

###### error_code (heading level 8)

```
int32_t sl_wisun_msg_get_socket_option_cnf_body_t::error_code
```

**Description:** Error code.

###### option_length (heading level 8)

```
uint16_t sl_wisun_msg_get_socket_option_cnf_body_t::option_length
```

**Description:** Socket option length.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_get_socket_option_cnf_body_t::reserved
```

**Description:** reserved, set to zero

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_socket_option_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_socket_option_cnf_body_t sl_wisun_msg_get_socket_option_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_socket_option_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### level (heading level 8)

```
int32_t sl_wisun_msg_get_socket_option_req_body_t::level
```

**Description:** Socket protocol level.

###### option_length (heading level 8)

```
uint16_t sl_wisun_msg_get_socket_option_req_body_t::option_length
```

**Description:** Socket option length.

###### option_name (heading level 8)

```
int32_t sl_wisun_msg_get_socket_option_req_body_t::option_name
```

**Description:** Socket option to get.

###### socket_id (heading level 8)

```
int32_t sl_wisun_msg_get_socket_option_req_body_t::socket_id
```

**Description:** ID of the socket.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_socket_option_req_body_t sl_wisun_msg_get_socket_option_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_socket_option_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_join_state

###### Modules

[sl_wisun_msg_get_join_state_cnf_body_t](sl-wisun-msg-get-join-state-cnf-body-t)

[sl_wisun_msg_get_join_state_cnf_t](sl-wisun-msg-get-join-state-cnf-t)

[sl_wisun_msg_get_join_state_req_t](sl-wisun-msg-get-join-state-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### join_state (heading level 8)

```
uint32_t sl_wisun_msg_get_join_state_cnf_body_t::join_state
```

**Description:** Join state.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_join_state_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_join_state_cnf_body_t sl_wisun_msg_get_join_state_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_join_state_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_join_state_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_clear_credential_cache

###### Modules

[sl_wisun_msg_clear_credential_cache_cnf_body_t](sl-wisun-msg-clear-credential-cache-cnf-body-t)

[sl_wisun_msg_clear_credential_cache_cnf_t](sl-wisun-msg-clear-credential-cache-cnf-t)

[sl_wisun_msg_clear_credential_cache_req_t](sl-wisun-msg-clear-credential-cache-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_clear_credential_cache_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_clear_credential_cache_cnf_body_t sl_wisun_msg_clear_credential_cache_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_clear_credential_cache_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_clear_credential_cache_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_mac_address

###### Modules

[sl_wisun_msg_get_mac_address_cnf_body_t](sl-wisun-msg-get-mac-address-cnf-body-t)

[sl_wisun_msg_get_mac_address_cnf_t](sl-wisun-msg-get-mac-address-cnf-t)

[sl_wisun_msg_get_mac_address_req_t](sl-wisun-msg-get-mac-address-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_get_mac_address_cnf_body_t::address
```

**Description:** MAC address.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_mac_address_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_mac_address_cnf_body_t sl_wisun_msg_get_mac_address_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_mac_address_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_mac_address_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_mac_address

###### Modules

[sl_wisun_msg_set_mac_address_cnf_body_t](sl-wisun-msg-set-mac-address-cnf-body-t)

[sl_wisun_msg_set_mac_address_cnf_t](sl-wisun-msg-set-mac-address-cnf-t)

[sl_wisun_msg_set_mac_address_req_body_t](sl-wisun-msg-set-mac-address-req-body-t)

[sl_wisun_msg_set_mac_address_req_t](sl-wisun-msg-set-mac-address-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_mac_address_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_mac_address_cnf_body_t sl_wisun_msg_set_mac_address_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_mac_address_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_set_mac_address_req_body_t::address
```

**Description:** MAC address.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_mac_address_req_body_t sl_wisun_msg_set_mac_address_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_mac_address_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_reset_statistics

###### Modules

[sl_wisun_msg_reset_statistics_cnf_body_t](sl-wisun-msg-reset-statistics-cnf-body-t)

[sl_wisun_msg_reset_statistics_cnf_t](sl-wisun-msg-reset-statistics-cnf-t)

[sl_wisun_msg_reset_statistics_req_body_t](sl-wisun-msg-reset-statistics-req-body-t)

[sl_wisun_msg_reset_statistics_req_t](sl-wisun-msg-reset-statistics-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_reset_statistics_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_reset_statistics_cnf_body_t sl_wisun_msg_reset_statistics_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_reset_statistics_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### statistics_type (heading level 8)

```
uint32_t sl_wisun_msg_reset_statistics_req_body_t::statistics_type
```

**Description:** Type of statistics to read.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_reset_statistics_req_body_t sl_wisun_msg_reset_statistics_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_reset_statistics_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_neighbor_count

###### Modules

[sl_wisun_msg_get_neighbor_count_cnf_body_t](sl-wisun-msg-get-neighbor-count-cnf-body-t)

[sl_wisun_msg_get_neighbor_count_cnf_t](sl-wisun-msg-get-neighbor-count-cnf-t)

[sl_wisun_msg_get_neighbor_count_req_t](sl-wisun-msg-get-neighbor-count-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### neighbor_count (heading level 8)

```
uint8_t sl_wisun_msg_get_neighbor_count_cnf_body_t::neighbor_count
```

**Description:** Neighbor count.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_neighbor_count_cnf_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_neighbor_count_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_neighbor_count_cnf_body_t sl_wisun_msg_get_neighbor_count_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_neighbor_count_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_neighbor_count_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_neighbors

###### Modules

[sl_wisun_msg_get_neighbors_cnf_body_t](sl-wisun-msg-get-neighbors-cnf-body-t)

[sl_wisun_msg_get_neighbors_cnf_t](sl-wisun-msg-get-neighbors-cnf-t)

[sl_wisun_msg_get_neighbors_req_body_t](sl-wisun-msg-get-neighbors-req-body-t)

[sl_wisun_msg_get_neighbors_req_t](sl-wisun-msg-get-neighbors-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### neighbor_count (heading level 8)

```
uint8_t sl_wisun_msg_get_neighbors_cnf_body_t::neighbor_count
```

**Description:** Number of neighbors read.

###### neighbor_mac_addresses (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_get_neighbors_cnf_body_t::neighbor_mac_addresses[]
```

**Description:** Neighbor MAC addresses read.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_neighbors_cnf_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_neighbors_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_neighbors_cnf_body_t sl_wisun_msg_get_neighbors_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_neighbors_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### neighbor_count (heading level 8)

```
uint8_t sl_wisun_msg_get_neighbors_req_body_t::neighbor_count
```

**Description:** Number of neighbors to read.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_neighbors_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_neighbors_req_body_t sl_wisun_msg_get_neighbors_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_neighbors_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_neighbor_info

###### Modules

[sl_wisun_msg_get_neighbor_info_cnf_body_t](sl-wisun-msg-get-neighbor-info-cnf-body-t)

[sl_wisun_msg_get_neighbor_info_cnf_t](sl-wisun-msg-get-neighbor-info-cnf-t)

[sl_wisun_msg_get_neighbor_info_req_body_t](sl-wisun-msg-get-neighbor-info-req-body-t)

[sl_wisun_msg_get_neighbor_info_req_t](sl-wisun-msg-get-neighbor-info-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### neighbor_info (heading level 8)

```
sl_wisun_neighbor_info_t sl_wisun_msg_get_neighbor_info_cnf_body_t::neighbor_info
```

**Description:** Information read.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_neighbor_info_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_neighbor_info_cnf_body_t sl_wisun_msg_get_neighbor_info_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_neighbor_info_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### neighbor_mac_address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_get_neighbor_info_req_body_t::neighbor_mac_address
```

**Description:** Neighbor MAC address.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_neighbor_info_req_body_t sl_wisun_msg_get_neighbor_info_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_neighbor_info_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_unicast_settings

###### Modules

[sl_wisun_msg_set_unicast_settings_cnf_body_t](sl-wisun-msg-set-unicast-settings-cnf-body-t)

[sl_wisun_msg_set_unicast_settings_cnf_t](sl-wisun-msg-set-unicast-settings-cnf-t)

[sl_wisun_msg_set_unicast_settings_req_body_t](sl-wisun-msg-set-unicast-settings-req-body-t)

[sl_wisun_msg_set_unicast_settings_req_t](sl-wisun-msg-set-unicast-settings-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_unicast_settings_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_unicast_settings_cnf_body_t sl_wisun_msg_set_unicast_settings_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_unicast_settings_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### dwell_interval_ms (heading level 8)

```
uint8_t sl_wisun_msg_set_unicast_settings_req_body_t::dwell_interval_ms
```

**Description:** Unicast dwell interval.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_unicast_settings_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_unicast_settings_req_body_t sl_wisun_msg_set_unicast_settings_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_unicast_settings_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_trace_level

###### Modules

[sl_wisun_msg_set_trace_level_cnf_body_t](sl-wisun-msg-set-trace-level-cnf-body-t)

[sl_wisun_msg_set_trace_level_cnf_t](sl-wisun-msg-set-trace-level-cnf-t)

[sl_wisun_msg_set_trace_level_req_body_t](sl-wisun-msg-set-trace-level-req-body-t)

[sl_wisun_msg_set_trace_level_req_t](sl-wisun-msg-set-trace-level-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_trace_level_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_trace_level_cnf_body_t sl_wisun_msg_set_trace_level_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_trace_level_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### group_count (heading level 8)

```
uint8_t sl_wisun_msg_set_trace_level_req_body_t::group_count
```

**Description:** Number of groups to configure.

**Details:** Maximum SL_WISUN_TRACE_GROUP_COUNT

###### trace_config (heading level 8)

```
sl_wisun_trace_group_config_t sl_wisun_msg_set_trace_level_req_body_t::trace_config[]
```

**Description:** Table with group_count element filled.

**Details:** It indicates the trace level to be displayed for each group.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_trace_level_req_body_t sl_wisun_msg_set_trace_level_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_trace_level_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_trace_filter

###### Modules

[sl_wisun_msg_set_trace_filter_cnf_body_t](sl-wisun-msg-set-trace-filter-cnf-body-t)

[sl_wisun_msg_set_trace_filter_cnf_t](sl-wisun-msg-set-trace-filter-cnf-t)

[sl_wisun_msg_set_trace_filter_req_body_t](sl-wisun-msg-set-trace-filter-req-body-t)

[sl_wisun_msg_set_trace_filter_req_t](sl-wisun-msg-set-trace-filter-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_trace_filter_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_trace_filter_cnf_body_t sl_wisun_msg_set_trace_filter_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_trace_filter_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### filter (heading level 8)

```
uint8_t sl_wisun_msg_set_trace_filter_req_body_t::filter[SL_WISUN_FILTER_BITFIELD_SIZE]
```

**Description:** Bitfield.

**Details:** Each 1 indicates the trace group ID corresponding is selected for tracing. 0 means the trace group ID corresponding should be filtered out. It follows enum sl_wisun_trace_group_t filter[0] contains ID 0 to 7 filter[1] contains ID 8 to 15...

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_trace_filter_req_body_t sl_wisun_msg_set_trace_filter_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_trace_filter_req_t::header
```

**Description:** Common message header.

##### sl_wisun_set_regulation

###### Modules

[sl_wisun_msg_set_regulation_cnf_body_t](sl-wisun-msg-set-regulation-cnf-body-t)

[sl_wisun_msg_set_regulation_cnf_t](sl-wisun-msg-set-regulation-cnf-t)

[sl_wisun_msg_set_regulation_req_body_t](sl-wisun-msg-set-regulation-req-body-t)

[sl_wisun_msg_set_regulation_req_t](sl-wisun-msg-set-regulation-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_regulation_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_regulation_cnf_body_t sl_wisun_msg_set_regulation_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_regulation_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### regulation (heading level 8)

```
uint32_t sl_wisun_msg_set_regulation_req_body_t::regulation
```

**Description:** Regional regulation.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_regulation_req_body_t sl_wisun_msg_set_regulation_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_regulation_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_device_private_key_id

###### Modules

[sl_wisun_msg_set_device_private_key_id_cnf_body_t](sl-wisun-msg-set-device-private-key-id-cnf-body-t)

[sl_wisun_msg_set_device_private_key_id_cnf_t](sl-wisun-msg-set-device-private-key-id-cnf-t)

[sl_wisun_msg_set_device_private_key_id_req_body_t](sl-wisun-msg-set-device-private-key-id-req-body-t)

[sl_wisun_msg_set_device_private_key_id_req_t](sl-wisun-msg-set-device-private-key-id-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_device_private_key_id_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_private_key_id_cnf_body_t sl_wisun_msg_set_device_private_key_id_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_private_key_id_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### key_id (heading level 8)

```
uint32_t sl_wisun_msg_set_device_private_key_id_req_body_t::key_id
```

**Description:** Private key ID.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_private_key_id_req_body_t sl_wisun_msg_set_device_private_key_id_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_private_key_id_req_t::header
```

**Description:** Common message header.

##### sl_wisun_set_advert_fragment_duration

###### Modules

[sl_wisun_msg_set_async_fragmentation_cnf_body_t](sl-wisun-msg-set-async-fragmentation-cnf-body-t)

[sl_wisun_msg_set_async_fragmentation_cnf_t](sl-wisun-msg-set-async-fragmentation-cnf-t)

[sl_wisun_msg_set_async_fragmentation_req_body_t](sl-wisun-msg-set-async-fragmentation-req-body-t)

[sl_wisun_msg_set_async_fragmentation_req_t](sl-wisun-msg-set-async-fragmentation-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_async_fragmentation_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_async_fragmentation_cnf_body_t sl_wisun_msg_set_async_fragmentation_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_async_fragmentation_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### fragment_duration_ms (heading level 8)

```
uint32_t sl_wisun_msg_set_async_fragmentation_req_body_t::fragment_duration_ms
```

**Description:** Fragment duration (ms)

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_async_fragmentation_req_body_t sl_wisun_msg_set_async_fragmentation_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_async_fragmentation_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_rate_algorithm

###### Modules

[sl_wisun_msg_set_rate_algorithm_cnf_body_t](sl-wisun-msg-set-rate-algorithm-cnf-body-t)

[sl_wisun_msg_set_rate_algorithm_cnf_t](sl-wisun-msg-set-rate-algorithm-cnf-t)

[sl_wisun_msg_set_rate_algorithm_id_req_body_t](sl-wisun-msg-set-rate-algorithm-id-req-body-t)

[sl_wisun_msg_set_rate_algorithm_req_t](sl-wisun-msg-set-rate-algorithm-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_rate_algorithm_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_rate_algorithm_cnf_body_t sl_wisun_msg_set_rate_algorithm_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_rate_algorithm_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### neighbor (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_set_rate_algorithm_id_req_body_t::neighbor
```

**Description:** Neighbor MAC address.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_rate_algorithm_id_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### type (heading level 8)

```
uint8_t sl_wisun_msg_set_rate_algorithm_id_req_body_t::type
```

**Description:** Indicate the rate algorithm type.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_rate_algorithm_id_req_body_t sl_wisun_msg_set_rate_algorithm_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_rate_algorithm_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_rate_algorithm_stats

###### Modules

[sl_wisun_msg_get_rate_algorithm_stats_cnf_body_t](sl-wisun-msg-get-rate-algorithm-stats-cnf-body-t)

[sl_wisun_msg_get_rate_algorithm_stats_cnf_t](sl-wisun-msg-get-rate-algorithm-stats-cnf-t)

[sl_wisun_msg_get_rate_algorithm_stats_id_req_body_t](sl-wisun-msg-get-rate-algorithm-stats-id-req-body-t)

[sl_wisun_msg_get_rate_algorithm_stats_req_t](sl-wisun-msg-get-rate-algorithm-stats-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### rate_count (heading level 8)

```
uint16_t sl_wisun_msg_get_rate_algorithm_stats_cnf_body_t::rate_count
```

**Description:** Number of rates copied.

###### rates (heading level 8)

```
sl_wisun_rate_t sl_wisun_msg_get_rate_algorithm_stats_cnf_body_t::rates[]
```

**Description:** Neighbor MAC addresses read.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_rate_algorithm_stats_cnf_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_rate_algorithm_stats_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_rate_algorithm_stats_cnf_body_t sl_wisun_msg_get_rate_algorithm_stats_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_rate_algorithm_stats_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### allocated_rate_count (heading level 8)

```
uint16_t sl_wisun_msg_get_rate_algorithm_stats_id_req_body_t::allocated_rate_count
```

**Description:** number of rates available in the array space

###### neighbor (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_get_rate_algorithm_stats_id_req_body_t::neighbor
```

**Description:** Neighbor MAC address.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_rate_algorithm_stats_id_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_rate_algorithm_stats_id_req_body_t sl_wisun_msg_get_rate_algorithm_stats_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_rate_algorithm_stats_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_mode_switch

###### Modules

[sl_wisun_msg_set_mode_switch_cnf_body_t](sl-wisun-msg-set-mode-switch-cnf-body-t)

[sl_wisun_msg_set_mode_switch_cnf_t](sl-wisun-msg-set-mode-switch-cnf-t)

[sl_wisun_msg_set_mode_switch_id_req_body_t](sl-wisun-msg-set-mode-switch-id-req-body-t)

[sl_wisun_msg_set_mode_switch_req_t](sl-wisun-msg-set-mode-switch-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_mode_switch_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_mode_switch_cnf_body_t sl_wisun_msg_set_mode_switch_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_mode_switch_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### mode (heading level 8)

```
uint8_t sl_wisun_msg_set_mode_switch_id_req_body_t::mode
```

**Description:** Indicate how the mode switching is allowed.

###### neighbor_address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_set_mode_switch_id_req_body_t::neighbor_address
```

**Description:** Neighbor MAC address.

###### phy_mode_id (heading level 8)

```
uint8_t sl_wisun_msg_set_mode_switch_id_req_body_t::phy_mode_id
```

**Description:** Indicate the PhyModeId to use for mode switching.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_mode_switch_id_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_mode_switch_id_req_body_t sl_wisun_msg_set_mode_switch_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_mode_switch_req_t::header
```

**Description:** Common message header.

##### sl_wisun_set_regulation_tx_thresholds

###### Modules

[sl_wisun_msg_set_regulation_tx_thresholds_cnf_body_t](sl-wisun-msg-set-regulation-tx-thresholds-cnf-body-t)

[sl_wisun_msg_set_regulation_tx_thresholds_cnf_t](sl-wisun-msg-set-regulation-tx-thresholds-cnf-t)

[sl_wisun_msg_set_regulation_tx_thresholds_req_body_t](sl-wisun-msg-set-regulation-tx-thresholds-req-body-t)

[sl_wisun_msg_set_regulation_tx_thresholds_req_t](sl-wisun-msg-set-regulation-tx-thresholds-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_regulation_tx_thresholds_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_regulation_tx_thresholds_cnf_body_t sl_wisun_msg_set_regulation_tx_thresholds_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_regulation_tx_thresholds_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### alert_threshold (heading level 8)

```
int8_t sl_wisun_msg_set_regulation_tx_thresholds_req_body_t::alert_threshold
```

**Description:** Alert threshold in percent.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_regulation_tx_thresholds_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### warning_threshold (heading level 8)

```
int8_t sl_wisun_msg_set_regulation_tx_thresholds_req_body_t::warning_threshold
```

**Description:** Warning threshold in percent.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_regulation_tx_thresholds_req_body_t sl_wisun_msg_set_regulation_tx_thresholds_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_regulation_tx_thresholds_req_t::header
```

**Description:** Common message header.

##### sl_wisun_set_device_type

###### Modules

[sl_wisun_msg_set_device_type_cnf_body_t](sl-wisun-msg-set-device-type-cnf-body-t)

[sl_wisun_msg_set_device_type_cnf_t](sl-wisun-msg-set-device-type-cnf-t)

[sl_wisun_msg_set_device_type_req_body_t](sl-wisun-msg-set-device-type-req-body-t)

[sl_wisun_msg_set_device_type_req_t](sl-wisun-msg-set-device-type-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_device_type_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_type_cnf_body_t sl_wisun_msg_set_device_type_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_type_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_device_type_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### type (heading level 8)

```
uint8_t sl_wisun_msg_set_device_type_req_body_t::type
```

**Description:** Device type.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_device_type_req_body_t sl_wisun_msg_set_device_type_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_device_type_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_connection_params

###### Modules

[sl_wisun_msg_set_connection_params_cnf_body_t](sl-wisun-msg-set-connection-params-cnf-body-t)

[sl_wisun_msg_set_connection_params_cnf_t](sl-wisun-msg-set-connection-params-cnf-t)

[sl_wisun_msg_set_connection_params_req_body_t](sl-wisun-msg-set-connection-params-req-body-t)

[sl_wisun_msg_set_connection_params_req_t](sl-wisun-msg-set-connection-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_connection_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_connection_params_cnf_body_t sl_wisun_msg_set_connection_params_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_connection_params_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### parameters (heading level 8)

```
sl_wisun_connection_params_t sl_wisun_msg_set_connection_params_req_body_t::parameters
```

**Description:** Connection parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_connection_params_req_body_t sl_wisun_msg_set_connection_params_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_connection_params_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_option

###### Modules

[sl_wisun_msg_set_option_cnf_body_t](sl-wisun-msg-set-option-cnf-body-t)

[sl_wisun_msg_set_option_cnf_t](sl-wisun-msg-set-option-cnf-t)

[sl_wisun_msg_set_option_req_body_t](sl-wisun-msg-set-option-req-body-t)

[sl_wisun_msg_set_option_req_t](sl-wisun-msg-set-option-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_option_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_option_cnf_body_t sl_wisun_msg_set_option_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_option_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### id (heading level 8)

```
uint32_t sl_wisun_msg_set_option_req_body_t::id
```

**Description:** Option identifier.

###### val (heading level 8)

```
uint8_t sl_wisun_msg_set_option_req_body_t::val[]
```

**Description:** Value.

###### val_len (heading level 8)

```
uint16_t sl_wisun_msg_set_option_req_body_t::val_len
```

**Description:** Size of the value in bytes.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_option_req_body_t sl_wisun_msg_set_option_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_option_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_ffn_advanced_params

###### Modules

[sl_wisun_msg_set_ffn_advanced_params_cnf_body_t](sl-wisun-msg-set-ffn-advanced-params-cnf-body-t)

[sl_wisun_msg_set_ffn_advanced_params_cnf_t](sl-wisun-msg-set-ffn-advanced-params-cnf-t)

[sl_wisun_msg_set_ffn_advanced_params_req_body_t](sl-wisun-msg-set-ffn-advanced-params-req-body-t)

[sl_wisun_msg_set_ffn_advanced_params_req_t](sl-wisun-msg-set-ffn-advanced-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_ffn_advanced_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_ffn_advanced_params_cnf_body_t sl_wisun_msg_set_ffn_advanced_params_cnf_t::body
```

**Description:** Message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_ffn_advanced_params_cnf_t::header
```

**Description:** Message header.

Request message body. 

###### Public Attributes (heading level 7)

###### params (heading level 8)

```
sl_wisun_ffn_advanced_parameters_t sl_wisun_msg_set_ffn_advanced_params_req_body_t::params
```

**Description:** Advanced connection parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_ffn_advanced_params_req_body_t sl_wisun_msg_set_ffn_advanced_params_req_t::body
```

**Description:** Message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_ffn_advanced_params_req_t::header
```

**Description:** Message header.

##### sl_wisun_msg_set_lfn_advanced_params

###### Modules

[sl_wisun_msg_set_lfn_advanced_params_cnf_body_t](sl-wisun-msg-set-lfn-advanced-params-cnf-body-t)

[sl_wisun_msg_set_lfn_advanced_params_cnf_t](sl-wisun-msg-set-lfn-advanced-params-cnf-t)

[sl_wisun_msg_set_lfn_advanced_params_req_body_t](sl-wisun-msg-set-lfn-advanced-params-req-body-t)

[sl_wisun_msg_set_lfn_advanced_params_req_t](sl-wisun-msg-set-lfn-advanced-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_lfn_advanced_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_advanced_params_cnf_body_t sl_wisun_msg_set_lfn_advanced_params_cnf_t::body
```

**Description:** Message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_advanced_params_cnf_t::header
```

**Description:** Message header.

Request message body. 

###### Public Attributes (heading level 7)

###### params (heading level 8)

```
sl_wisun_lfn_advanced_parameters_t sl_wisun_msg_set_lfn_advanced_params_req_body_t::params
```

**Description:** Advanced LFN parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_advanced_params_req_body_t sl_wisun_msg_set_lfn_advanced_params_req_t::body
```

**Description:** Message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_advanced_params_req_t::header
```

**Description:** Message header.

##### sl_wisun_msg_reset_params

###### Modules

[sl_wisun_msg_reset_params_cnf_body_t](sl-wisun-msg-reset-params-cnf-body-t)

[sl_wisun_msg_reset_params_cnf_t](sl-wisun-msg-reset-params-cnf-t)

[sl_wisun_msg_reset_params_req_t](sl-wisun-msg-reset-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_reset_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_reset_params_cnf_body_t sl_wisun_msg_reset_params_cnf_t::body
```

**Description:** Message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_reset_params_cnf_t::header
```

**Description:** Message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_reset_params_req_t::header
```

**Description:** Message header.

##### sl_wisun_msg_join

###### Modules

[sl_wisun_msg_join_cnf_body_t](sl-wisun-msg-join-cnf-body-t)

[sl_wisun_msg_join_cnf_t](sl-wisun-msg-join-cnf-t)

[sl_wisun_msg_join_req_body_t](sl-wisun-msg-join-req-body-t)

[sl_wisun_msg_join_req_t](sl-wisun-msg-join-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_join_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_join_cnf_body_t sl_wisun_msg_join_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_join_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### name (heading level 8)

```
uint8_t sl_wisun_msg_join_req_body_t::name[SL_WISUN_NETWORK_NAME_SIZE]
```

**Description:** Network name as a NULL terminated string.

###### phy_config (heading level 8)

```
sl_wisun_phy_config_t sl_wisun_msg_join_req_body_t::phy_config
```

**Description:** PHY configuration.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_join_req_body_t sl_wisun_msg_join_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_join_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_pom_ie

###### Modules

[sl_wisun_msg_set_pom_ie_cnf_body_t](sl-wisun-msg-set-pom-ie-cnf-body-t)

[sl_wisun_msg_set_pom_ie_cnf_t](sl-wisun-msg-set-pom-ie-cnf-t)

[sl_wisun_msg_set_pom_ie_req_body_t](sl-wisun-msg-set-pom-ie-req-body-t)

[sl_wisun_msg_set_pom_ie_req_t](sl-wisun-msg-set-pom-ie-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_pom_ie_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_pom_ie_cnf_body_t sl_wisun_msg_set_pom_ie_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_pom_ie_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### is_mdr_command_capable (heading level 8)

```
uint8_t sl_wisun_msg_set_pom_ie_req_body_t::is_mdr_command_capable
```

**Description:** Indicate if the device is supporting MAC mode switch.

**Details:** Feature currently unsupported. Must be set to 0.

###### phy_mode_id_count (heading level 8)

```
uint8_t sl_wisun_msg_set_pom_ie_req_body_t::phy_mode_id_count
```

**Description:** Number of PhyModeId to configure.

###### phy_mode_ids (heading level 8)

```
uint8_t sl_wisun_msg_set_pom_ie_req_body_t::phy_mode_ids[SL_WISUN_MAX_PHY_MODE_ID_COUNT]
```

**Description:** List of phy_mode_id_count PhyModeId.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_pom_ie_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_pom_ie_req_body_t sl_wisun_msg_set_pom_ie_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_pom_ie_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_pom_ie

###### Modules

[sl_wisun_msg_get_pom_ie_cnf_body_t](sl-wisun-msg-get-pom-ie-cnf-body-t)

[sl_wisun_msg_get_pom_ie_cnf_t](sl-wisun-msg-get-pom-ie-cnf-t)

[sl_wisun_msg_get_pom_ie_req_t](sl-wisun-msg-get-pom-ie-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### is_mdr_command_capable (heading level 8)

```
uint8_t sl_wisun_msg_get_pom_ie_cnf_body_t::is_mdr_command_capable
```

**Description:** Indicate if the device is supporting MAC mode switch Feature currently unsupported.

**Details:** Must be set to 0.

###### phy_mode_id_count (heading level 8)

```
uint8_t sl_wisun_msg_get_pom_ie_cnf_body_t::phy_mode_id_count
```

**Description:** Number of PhyModeId to configure.

###### phy_mode_ids (heading level 8)

```
uint8_t sl_wisun_msg_get_pom_ie_cnf_body_t::phy_mode_ids[SL_WISUN_MAX_PHY_MODE_ID_COUNT]
```

**Description:** List of phy_mode_id_count PhyModeId.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_pom_ie_cnf_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_pom_ie_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_pom_ie_cnf_body_t sl_wisun_msg_get_pom_ie_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_pom_ie_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_pom_ie_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_stack_version

###### Modules

[sl_wisun_msg_get_stack_version_cnf_body_t](sl-wisun-msg-get-stack-version-cnf-body-t)

[sl_wisun_msg_get_stack_version_cnf_t](sl-wisun-msg-get-stack-version-cnf-t)

[sl_wisun_msg_get_stack_version_req_t](sl-wisun-msg-get-stack-version-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### build (heading level 8)

```
uint16_t sl_wisun_msg_get_stack_version_cnf_body_t::build
```

**Description:** Build number.

###### major (heading level 8)

```
uint8_t sl_wisun_msg_get_stack_version_cnf_body_t::major
```

**Description:** Wi-SUN stack major version.

###### minor (heading level 8)

```
uint8_t sl_wisun_msg_get_stack_version_cnf_body_t::minor
```

**Description:** Wi-SUN stack minor version.

###### patch (heading level 8)

```
uint8_t sl_wisun_msg_get_stack_version_cnf_body_t::patch
```

**Description:** Wi-SUN stack patch version.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_get_stack_version_cnf_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_stack_version_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_stack_version_cnf_body_t sl_wisun_msg_get_stack_version_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_stack_version_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_stack_version_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_lfn_params

###### Modules

[sl_wisun_msg_set_lfn_params_cnf_body_t](sl-wisun-msg-set-lfn-params-cnf-body-t)

[sl_wisun_msg_set_lfn_params_cnf_t](sl-wisun-msg-set-lfn-params-cnf-t)

[sl_wisun_msg_set_lfn_params_req_body_t](sl-wisun-msg-set-lfn-params-req-body-t)

[sl_wisun_msg_set_lfn_params_req_t](sl-wisun-msg-set-lfn-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_lfn_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_params_cnf_body_t sl_wisun_msg_set_lfn_params_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_params_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### parameters (heading level 8)

```
sl_wisun_lfn_params_t sl_wisun_msg_set_lfn_params_req_body_t::parameters
```

**Description:** LFN parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_params_req_body_t sl_wisun_msg_set_lfn_params_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_params_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_lfn_support

###### Modules

[sl_wisun_msg_set_lfn_support_cnf_body_t](sl-wisun-msg-set-lfn-support-cnf-body-t)

[sl_wisun_msg_set_lfn_support_cnf_t](sl-wisun-msg-set-lfn-support-cnf-t)

[sl_wisun_msg_set_lfn_support_req_body_t](sl-wisun-msg-set-lfn-support-req-body-t)

[sl_wisun_msg_set_lfn_support_req_t](sl-wisun-msg-set-lfn-support-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_lfn_support_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_support_cnf_body_t sl_wisun_msg_set_lfn_support_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_support_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### lfn_limit (heading level 8)

```
uint8_t sl_wisun_msg_set_lfn_support_req_body_t::lfn_limit
```

**Description:** Number of LFN supported [0, 10].

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_support_req_body_t sl_wisun_msg_set_lfn_support_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_support_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_pti_state

###### Modules

[sl_wisun_msg_set_pti_state_cnf_body_t](sl-wisun-msg-set-pti-state-cnf-body-t)

[sl_wisun_msg_set_pti_state_cnf_t](sl-wisun-msg-set-pti-state-cnf-t)

[sl_wisun_msg_set_pti_state_req_body_t](sl-wisun-msg-set-pti-state-req-body-t)

[sl_wisun_msg_set_pti_state_req_t](sl-wisun-msg-set-pti-state-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_pti_state_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_pti_state_cnf_body_t sl_wisun_msg_set_pti_state_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_pti_state_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### pti_state (heading level 8)

```
uint8_t sl_wisun_msg_set_pti_state_req_body_t::pti_state
```

**Description:** Is pti enabled ?

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_pti_state_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_pti_state_req_body_t sl_wisun_msg_set_pti_state_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_pti_state_req_t::header
```

**Description:** Common message header.

##### sl_wisun_set_tbu_settings

###### Modules

[sl_wisun_msg_set_tbu_settings_cnf_body_t](sl-wisun-msg-set-tbu-settings-cnf-body-t)

[sl_wisun_msg_set_tbu_settings_cnf_t](sl-wisun-msg-set-tbu-settings-cnf-t)

[sl_wisun_msg_set_tbu_settings_req_body_t](sl-wisun-msg-set-tbu-settings-req-body-t)

[sl_wisun_msg_set_tbu_settings_req_t](sl-wisun-msg-set-tbu-settings-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_tbu_settings_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_tbu_settings_cnf_body_t sl_wisun_msg_set_tbu_settings_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_tbu_settings_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### channel_exclusion_mode (heading level 8)

```
uint8_t sl_wisun_msg_set_tbu_settings_req_body_t::channel_exclusion_mode
```

**Description:** Channel exclusion mode.

###### mtu_size (heading level 8)

```
uint16_t sl_wisun_msg_set_tbu_settings_req_body_t::mtu_size
```

**Description:** 6LoWPAN MTU size in bytes

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_tbu_settings_req_body_t::reserved
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_tbu_settings_req_body_t sl_wisun_msg_set_tbu_settings_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_tbu_settings_req_t::header
```

**Description:** Common message header.

##### sl_wisun_get_gtks

###### Modules

[sl_wisun_msg_get_gtks_cnf_body_t](sl-wisun-msg-get-gtks-cnf-body-t)

[sl_wisun_msg_get_gtks_cnf_t](sl-wisun-msg-get-gtks-cnf-t)

[sl_wisun_msg_get_gtks_req_t](sl-wisun-msg-get-gtks-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### gtks (heading level 8)

```
uint8_t sl_wisun_msg_get_gtks_cnf_body_t::gtks[SL_WISUN_GTK_NUM][SL_WISUN_GTK_LEN]
```

**Description:** GTKs.

###### lgtks (heading level 8)

```
uint8_t sl_wisun_msg_get_gtks_cnf_body_t::lgtks[SL_WISUN_LGTK_NUM][SL_WISUN_GTK_LEN]
```

**Description:** LGTKs.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_gtks_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_gtks_cnf_body_t sl_wisun_msg_get_gtks_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_gtks_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_gtks_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_trigger_frame

###### Modules

[sl_wisun_msg_trigger_frame_cnf_body_t](sl-wisun-msg-trigger-frame-cnf-body-t)

[sl_wisun_msg_trigger_frame_cnf_t](sl-wisun-msg-trigger-frame-cnf-t)

[sl_wisun_msg_trigger_frame_req_body_t](sl-wisun-msg-trigger-frame-req-body-t)

[sl_wisun_msg_trigger_frame_req_t](sl-wisun-msg-trigger-frame-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_trigger_frame_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_trigger_frame_cnf_body_t sl_wisun_msg_trigger_frame_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_trigger_frame_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### frame_type (heading level 8)

```
uint32_t sl_wisun_msg_trigger_frame_req_body_t::frame_type
```

**Description:** Frame type.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_trigger_frame_req_body_t sl_wisun_msg_trigger_frame_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_trigger_frame_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_security_state

###### Modules

[sl_wisun_msg_set_security_state_cnf_body_t](sl-wisun-msg-set-security-state-cnf-body-t)

[sl_wisun_msg_set_security_state_cnf_t](sl-wisun-msg-set-security-state-cnf-t)

[sl_wisun_msg_set_security_state_req_body_t](sl-wisun-msg-set-security-state-req-body-t)

[sl_wisun_msg_set_security_state_req_t](sl-wisun-msg-set-security-state-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_security_state_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_pti_state_cnf_body_t sl_wisun_msg_set_security_state_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_security_state_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### security_state (heading level 8)

```
uint32_t sl_wisun_msg_set_security_state_req_body_t::security_state
```

**Description:** Security state.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_security_state_req_body_t sl_wisun_msg_set_security_state_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_security_state_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_network_info

###### Modules

[sl_wisun_msg_get_network_info_cnf_body_t](sl-wisun-msg-get-network-info-cnf-body-t)

[sl_wisun_msg_get_network_info_cnf_t](sl-wisun-msg-get-network-info-cnf-t)

[sl_wisun_msg_get_network_info_req_t](sl-wisun-msg-get-network-info-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### network_info (heading level 8)

```
sl_wisun_network_info_t sl_wisun_msg_get_network_info_cnf_body_t::network_info
```

**Description:** Wi-SUN network information.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_network_info_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_network_info_cnf_body_t sl_wisun_msg_get_network_info_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_network_info_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_network_info_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_rpl_info

###### Modules

[sl_wisun_msg_get_rpl_info_cnf_body_t](sl-wisun-msg-get-rpl-info-cnf-body-t)

[sl_wisun_msg_get_rpl_info_cnf_t](sl-wisun-msg-get-rpl-info-cnf-t)

[sl_wisun_msg_get_rpl_info_req_t](sl-wisun-msg-get-rpl-info-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### rpl_info (heading level 8)

```
sl_wisun_rpl_info_t sl_wisun_msg_get_rpl_info_cnf_body_t::rpl_info
```

**Description:** RPL information.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_rpl_info_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_rpl_info_cnf_body_t sl_wisun_msg_get_rpl_info_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_rpl_info_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_rpl_info_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_get_excluded_channel_mask

###### Modules

[sl_wisun_msg_get_excluded_channel_mask_cnf_body_t](sl-wisun-msg-get-excluded-channel-mask-cnf-body-t)

[sl_wisun_msg_get_excluded_channel_mask_cnf_t](sl-wisun-msg-get-excluded-channel-mask-cnf-t)

[sl_wisun_msg_get_excluded_channel_mask_req_body_t](sl-wisun-msg-get-excluded-channel-mask-req-body-t)

[sl_wisun_msg_get_excluded_channel_mask_req_t](sl-wisun-msg-get-excluded-channel-mask-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### channel_count (heading level 8)

```
uint32_t sl_wisun_msg_get_excluded_channel_mask_cnf_body_t::channel_count
```

**Description:** Number of channels in mask.

###### channel_mask (heading level 8)

```
sl_wisun_channel_mask_t sl_wisun_msg_get_excluded_channel_mask_cnf_body_t::channel_mask
```

**Description:** Channel mask.

###### status (heading level 8)

```
uint32_t sl_wisun_msg_get_excluded_channel_mask_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_excluded_channel_mask_cnf_body_t sl_wisun_msg_get_excluded_channel_mask_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_excluded_channel_mask_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### type (heading level 8)

```
uint32_t sl_wisun_msg_get_excluded_channel_mask_req_body_t::type
```

**Description:** Type of channel mask.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_get_excluded_channel_mask_req_body_t sl_wisun_msg_get_excluded_channel_mask_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_get_excluded_channel_mask_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_neighbor_table_size

###### Modules

[sl_wisun_msg_set_neighbor_table_size_cnf_body_t](sl-wisun-msg-set-neighbor-table-size-cnf-body-t)

[sl_wisun_msg_set_neighbor_table_size_cnf_t](sl-wisun-msg-set-neighbor-table-size-cnf-t)

[sl_wisun_msg_set_neighbor_table_size_req_body_t](sl-wisun-msg-set-neighbor-table-size-req-body-t)

[sl_wisun_msg_set_neighbor_table_size_req_t](sl-wisun-msg-set-neighbor-table-size-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_neighbor_table_size_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_neighbor_table_size_cnf_body_t sl_wisun_msg_set_neighbor_table_size_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_neighbor_table_size_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_neighbor_table_size_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### size (heading level 8)

```
uint8_t sl_wisun_msg_set_neighbor_table_size_req_body_t::size
```

**Description:** Neighbor table size.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_network_size_req_body_t sl_wisun_msg_set_neighbor_table_size_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_neighbor_table_size_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_config_neighbor_table_size

###### Modules

[sl_wisun_msg_config_neighbor_table_size_cnf_body_t](sl-wisun-msg-config-neighbor-table-size-cnf-body-t)

[sl_wisun_msg_config_neighbor_table_size_cnf_t](sl-wisun-msg-config-neighbor-table-size-cnf-t)

[sl_wisun_msg_config_neighbor_table_size_req_body_t](sl-wisun-msg-config-neighbor-table-size-req-body-t)

[sl_wisun_msg_config_neighbor_table_size_req_t](sl-wisun-msg-config-neighbor-table-size-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_config_neighbor_table_size_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_config_neighbor_table_size_cnf_body_t sl_wisun_msg_config_neighbor_table_size_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_config_neighbor_table_size_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### max_child_count (heading level 8)

```
uint8_t sl_wisun_msg_config_neighbor_table_size_req_body_t::max_child_count
```

**Description:** Maximum number of RPL children.

###### max_neighbor_count (heading level 8)

```
uint8_t sl_wisun_msg_config_neighbor_table_size_req_body_t::max_neighbor_count
```

**Description:** Maximum number of neighbors including children, parent, and temporary neighbors.

###### max_security_neighbor_count (heading level 8)

```
uint16_t sl_wisun_msg_config_neighbor_table_size_req_body_t::max_security_neighbor_count
```

**Description:** Maximum number of neighbors in the security table.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_config_neighbor_table_size_req_body_t sl_wisun_msg_config_neighbor_table_size_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_config_neighbor_table_size_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_enable_neighbour_solicitations

###### Modules

[sl_wisun_msg_enable_neighbour_solicitations_cnf_body_t](sl-wisun-msg-enable-neighbour-solicitations-cnf-body-t)

[sl_wisun_msg_enable_neighbour_solicitations_cnf_t](sl-wisun-msg-enable-neighbour-solicitations-cnf-t)

[sl_wisun_msg_enable_neighbour_solicitations_req_body_t](sl-wisun-msg-enable-neighbour-solicitations-req-body-t)

[sl_wisun_msg_enable_neighbour_solicitations_req_t](sl-wisun-msg-enable-neighbour-solicitations-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_enable_neighbour_solicitations_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_enable_neighbour_solicitations_cnf_body_t sl_wisun_msg_enable_neighbour_solicitations_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_enable_neighbour_solicitations_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### enable (heading level 8)

```
uint8_t sl_wisun_msg_enable_neighbour_solicitations_req_body_t::enable
```

**Description:** true to enable neighbour solicitations

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_enable_neighbour_solicitations_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_enable_neighbour_solicitations_req_body_t sl_wisun_msg_enable_neighbour_solicitations_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_enable_neighbour_solicitations_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_trigger_neighbor_cache_refresh

###### Modules

[sl_wisun_msg_trigger_neighbor_cache_refresh_cnf_body_t](sl-wisun-msg-trigger-neighbor-cache-refresh-cnf-body-t)

[sl_wisun_msg_trigger_neighbor_cache_refresh_cnf_t](sl-wisun-msg-trigger-neighbor-cache-refresh-cnf-t)

[sl_wisun_msg_trigger_neighbor_cache_refresh_req_t](sl-wisun-msg-trigger-neighbor-cache-refresh-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_trigger_neighbor_cache_refresh_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_trigger_neighbor_cache_refresh_cnf_body_t sl_wisun_msg_trigger_neighbor_cache_refresh_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_trigger_neighbor_cache_refresh_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_trigger_neighbor_cache_refresh_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_tx_power_ddbm

###### Modules

[sl_wisun_msg_set_tx_power_ddbm_cnf_body_t](sl-wisun-msg-set-tx-power-ddbm-cnf-body-t)

[sl_wisun_msg_set_tx_power_ddbm_cnf_t](sl-wisun-msg-set-tx-power-ddbm-cnf-t)

[sl_wisun_msg_set_tx_power_ddbm_req_body_t](sl-wisun-msg-set-tx-power-ddbm-req-body-t)

[sl_wisun_msg_set_tx_power_ddbm_req_t](sl-wisun-msg-set-tx-power-ddbm-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_tx_power_ddbm_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_tx_power_ddbm_cnf_body_t sl_wisun_msg_set_tx_power_ddbm_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_tx_power_ddbm_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_tx_power_ddbm_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### tx_power_ddbm (heading level 8)

```
int16_t sl_wisun_msg_set_tx_power_ddbm_req_body_t::tx_power_ddbm
```

**Description:** TX power.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_tx_power_ddbm_req_body_t sl_wisun_msg_set_tx_power_ddbm_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_tx_power_ddbm_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_leaf

###### Modules

[sl_wisun_msg_set_leaf_cnf_body_t](sl-wisun-msg-set-leaf-cnf-body-t)

[sl_wisun_msg_set_leaf_cnf_t](sl-wisun-msg-set-leaf-cnf-t)

[sl_wisun_msg_set_leaf_req_body_t](sl-wisun-msg-set-leaf-req-body-t)

[sl_wisun_msg_set_leaf_req_t](sl-wisun-msg-set-leaf-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_leaf_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_leaf_cnf_body_t sl_wisun_msg_set_leaf_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_leaf_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### is_leaf (heading level 8)

```
uint8_t sl_wisun_msg_set_leaf_req_body_t::is_leaf
```

**Description:** True to make the node act as an RPL leaf.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_leaf_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_leaf_req_body_t sl_wisun_msg_set_leaf_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_leaf_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_event_filter

###### Modules

[sl_wisun_msg_set_event_filter_cnf_body_t](sl-wisun-msg-set-event-filter-cnf-body-t)

[sl_wisun_msg_set_event_filter_cnf_t](sl-wisun-msg-set-event-filter-cnf-t)

[sl_wisun_msg_set_event_filter_req_body_t](sl-wisun-msg-set-event-filter-req-body-t)

[sl_wisun_msg_set_event_filter_req_t](sl-wisun-msg-set-event-filter-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_event_filter_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_event_filter_cnf_body_t sl_wisun_msg_set_event_filter_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_event_filter_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### events (heading level 8)

```
uint64_t sl_wisun_msg_set_event_filter_req_body_t::events
```

**Description:** Bitmask for the specified events.

###### mac_address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_set_event_filter_req_body_t::mac_address
```

**Description:** neighbor MAC address

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_event_filter_req_body_t sl_wisun_msg_set_event_filter_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_event_filter_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_clear_event_filters

###### Modules

[sl_wisun_msg_clear_event_filters_cnf_body_t](sl-wisun-msg-clear-event-filters-cnf-body-t)

[sl_wisun_msg_clear_event_filters_cnf_t](sl-wisun-msg-clear-event-filters-cnf-t)

[sl_wisun_msg_clear_event_filters_req_t](sl-wisun-msg-clear-event-filters-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_clear_event_filters_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_clear_event_filters_cnf_body_t sl_wisun_msg_clear_event_filters_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_clear_event_filters_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_clear_event_filters_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_direct_connect_state

###### Modules

[sl_wisun_msg_set_direct_connect_state_cnf_body_t](sl-wisun-msg-set-direct-connect-state-cnf-body-t)

[sl_wisun_msg_set_direct_connect_state_cnf_t](sl-wisun-msg-set-direct-connect-state-cnf-t)

[sl_wisun_msg_set_direct_connect_state_req_body_t](sl-wisun-msg-set-direct-connect-state-req-body-t)

[sl_wisun_msg_set_direct_connect_state_req_t](sl-wisun-msg-set-direct-connect-state-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_direct_connect_state_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_direct_connect_state_cnf_body_t sl_wisun_msg_set_direct_connect_state_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_direct_connect_state_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### is_enabled (heading level 8)

```
uint8_t sl_wisun_msg_set_direct_connect_state_req_body_t::is_enabled
```

**Description:** True to enable Direct Connect, false otherwise.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_direct_connect_state_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_direct_connect_state_req_body_t sl_wisun_msg_set_direct_connect_state_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_direct_connect_state_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_accept_direct_connect_link

###### Modules

[sl_wisun_msg_accept_direct_connect_link_cnf_body_t](sl-wisun-msg-accept-direct-connect-link-cnf-body-t)

[sl_wisun_msg_accept_direct_connect_link_cnf_t](sl-wisun-msg-accept-direct-connect-link-cnf-t)

[sl_wisun_msg_accept_direct_connect_link_req_body_t](sl-wisun-msg-accept-direct-connect-link-req-body-t)

[sl_wisun_msg_accept_direct_connect_link_req_t](sl-wisun-msg-accept-direct-connect-link-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_accept_direct_connect_link_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_accept_direct_connect_link_cnf_body_t sl_wisun_msg_accept_direct_connect_link_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_accept_direct_connect_link_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### link_local_ipv6 (heading level 8)

```
in6_addr_t sl_wisun_msg_accept_direct_connect_link_req_body_t::link_local_ipv6
```

**Description:** Link Local IPv6 address of the client.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_accept_direct_connect_link_req_body_t sl_wisun_msg_accept_direct_connect_link_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_accept_direct_connect_link_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_advert_direct_connect_server_id

###### Modules

[sl_wisun_msg_advert_direct_connect_server_id_cnf_body_t](sl-wisun-msg-advert-direct-connect-server-id-cnf-body-t)

[sl_wisun_msg_advert_direct_connect_server_id_cnf_t](sl-wisun-msg-advert-direct-connect-server-id-cnf-t)

[sl_wisun_msg_advert_direct_connect_server_id_req_body_t](sl-wisun-msg-advert-direct-connect-server-id-req-body-t)

[sl_wisun_msg_advert_direct_connect_server_id_req_t](sl-wisun-msg-advert-direct-connect-server-id-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_advert_direct_connect_server_id_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_advert_direct_connect_server_id_cnf_body_t sl_wisun_msg_advert_direct_connect_server_id_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_advert_direct_connect_server_id_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### dc_id (heading level 8)

```
sl_wisun_dc_id_t sl_wisun_msg_advert_direct_connect_server_id_req_body_t::dc_id
```

**Description:** Direct Connect server's ID.

###### link_local_ipv6 (heading level 8)

```
in6_addr_t sl_wisun_msg_advert_direct_connect_server_id_req_body_t::link_local_ipv6
```

**Description:** Link Local IPv6 address of the client that requested the server ID.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_advert_direct_connect_server_id_req_body_t sl_wisun_msg_advert_direct_connect_server_id_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_advert_direct_connect_server_id_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_start_direct_connect_client

###### Modules

[sl_wisun_msg_start_direct_connect_client_cnf_body_t](sl-wisun-msg-start-direct-connect-client-cnf-body-t)

[sl_wisun_msg_start_direct_connect_client_cnf_t](sl-wisun-msg-start-direct-connect-client-cnf-t)

[sl_wisun_msg_start_direct_connect_client_req_body_t](sl-wisun-msg-start-direct-connect-client-req-body-t)

[sl_wisun_msg_start_direct_connect_client_req_t](sl-wisun-msg-start-direct-connect-client-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_start_direct_connect_client_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_start_direct_connect_client_cnf_body_t sl_wisun_msg_start_direct_connect_client_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_start_direct_connect_client_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### phy (heading level 8)

```
sl_wisun_phy_config_t sl_wisun_msg_start_direct_connect_client_req_body_t::phy
```

**Description:** PHY configuration.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_start_direct_connect_client_req_body_t sl_wisun_msg_start_direct_connect_client_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_start_direct_connect_client_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_start_direct_connect_scan

###### Modules

[sl_wisun_msg_start_direct_connect_scan_cnf_body_t](sl-wisun-msg-start-direct-connect-scan-cnf-body-t)

[sl_wisun_msg_start_direct_connect_scan_cnf_t](sl-wisun-msg-start-direct-connect-scan-cnf-t)

[sl_wisun_msg_start_direct_connect_scan_req_body_t](sl-wisun-msg-start-direct-connect-scan-req-body-t)

[sl_wisun_msg_start_direct_connect_scan_req_t](sl-wisun-msg-start-direct-connect-scan-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_start_direct_connect_scan_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_start_direct_connect_scan_cnf_body_t sl_wisun_msg_start_direct_connect_scan_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_start_direct_connect_scan_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### dc_id (heading level 8)

```
sl_wisun_dc_id_t sl_wisun_msg_start_direct_connect_scan_req_body_t::dc_id
```

**Description:** Direct Connect ID.

###### max_solicits_count (heading level 8)

```
uint8_t sl_wisun_msg_start_direct_connect_scan_req_body_t::max_solicits_count
```

**Description:** Maximum number of asynchronous solicitation sequences.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_start_direct_connect_scan_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_start_direct_connect_scan_req_body_t sl_wisun_msg_start_direct_connect_scan_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_start_direct_connect_scan_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_stop_direct_connect_scan

###### Modules

[sl_wisun_msg_stop_direct_connect_scan_cnf_body_t](sl-wisun-msg-stop-direct-connect-scan-cnf-body-t)

[sl_wisun_msg_stop_direct_connect_scan_cnf_t](sl-wisun-msg-stop-direct-connect-scan-cnf-t)

[sl_wisun_msg_stop_direct_connect_scan_req_t](sl-wisun-msg-stop-direct-connect-scan-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_stop_direct_connect_scan_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_stop_direct_connect_scan_cnf_body_t sl_wisun_msg_stop_direct_connect_scan_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_stop_direct_connect_scan_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_stop_direct_connect_scan_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_connect_to_direct_connect_server

###### Modules

[sl_wisun_msg_connect_to_direct_connect_server_cnf_body_t](sl-wisun-msg-connect-to-direct-connect-server-cnf-body-t)

[sl_wisun_msg_connect_to_direct_connect_server_cnf_t](sl-wisun-msg-connect-to-direct-connect-server-cnf-t)

[sl_wisun_msg_connect_to_direct_connect_server_req_body_t](sl-wisun-msg-connect-to-direct-connect-server-req-body-t)

[sl_wisun_msg_connect_to_direct_connect_server_req_t](sl-wisun-msg-connect-to-direct-connect-server-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_connect_to_direct_connect_server_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_connect_to_direct_connect_server_cnf_body_t sl_wisun_msg_connect_to_direct_connect_server_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_connect_to_direct_connect_server_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### mac_address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_connect_to_direct_connect_server_req_body_t::mac_address
```

**Description:** Server MAC address.

###### max_solicits_count (heading level 8)

```
uint8_t sl_wisun_msg_connect_to_direct_connect_server_req_body_t::max_solicits_count
```

**Description:** Maximum number of asynchronous solicitation sequences.

###### pmk_id (heading level 8)

```
uint32_t sl_wisun_msg_connect_to_direct_connect_server_req_body_t::pmk_id
```

**Description:** Pairwise Master Key (PMK) ID.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_connect_to_direct_connect_server_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_connect_to_direct_connect_server_req_body_t sl_wisun_msg_connect_to_direct_connect_server_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_connect_to_direct_connect_server_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_stop_direct_connect_client

###### Modules

[sl_wisun_msg_stop_direct_connect_client_cnf_body_t](sl-wisun-msg-stop-direct-connect-client-cnf-body-t)

[sl_wisun_msg_stop_direct_connect_client_cnf_t](sl-wisun-msg-stop-direct-connect-client-cnf-t)

[sl_wisun_msg_stop_direct_connect_client_req_t](sl-wisun-msg-stop-direct-connect-client-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_stop_direct_connect_client_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_stop_direct_connect_client_cnf_body_t sl_wisun_msg_stop_direct_connect_client_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_stop_direct_connect_client_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_stop_direct_connect_client_req_t::header
```

**Description:** Common message header.

##### sl_wisun_set_phy_sensitivity

###### Modules

[sl_wisun_msg_set_phy_sensitivity_cnf_body_t](sl-wisun-msg-set-phy-sensitivity-cnf-body-t)

[sl_wisun_msg_set_phy_sensitivity_cnf_t](sl-wisun-msg-set-phy-sensitivity-cnf-t)

[sl_wisun_msg_set_phy_sensitivity_req_body_t](sl-wisun-msg-set-phy-sensitivity-req-body-t)

[sl_wisun_msg_set_phy_sensitivity_req_t](sl-wisun-msg-set-phy-sensitivity-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_phy_sensitivity_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_phy_sensitivity_cnf_body_t sl_wisun_msg_set_phy_sensitivity_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_phy_sensitivity_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### phy_mode_id (heading level 8)

```
uint8_t sl_wisun_msg_set_phy_sensitivity_req_body_t::phy_mode_id
```

**Description:** PHY mode ID.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_phy_sensitivity_req_body_t::reserved[1]
```

**Description:** Reserved, set to zero.

###### sensitivity_dbm (heading level 8)

```
int16_t sl_wisun_msg_set_phy_sensitivity_req_body_t::sensitivity_dbm
```

**Description:** Sensitivity in dBm.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_phy_sensitivity_req_body_t sl_wisun_msg_set_phy_sensitivity_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_phy_sensitivity_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_direct_connect_pmk_id

###### Modules

[sl_wisun_msg_set_direct_connect_pmk_id_cnf_body_t](sl-wisun-msg-set-direct-connect-pmk-id-cnf-body-t)

[sl_wisun_msg_set_direct_connect_pmk_id_cnf_t](sl-wisun-msg-set-direct-connect-pmk-id-cnf-t)

[sl_wisun_msg_set_direct_connect_pmk_id_req_body_t](sl-wisun-msg-set-direct-connect-pmk-id-req-body-t)

[sl_wisun_msg_set_direct_connect_pmk_id_req_t](sl-wisun-msg-set-direct-connect-pmk-id-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_direct_connect_pmk_id_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_direct_connect_pmk_id_cnf_body_t sl_wisun_msg_set_direct_connect_pmk_id_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_direct_connect_pmk_id_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### key_id (heading level 8)

```
uint32_t sl_wisun_msg_set_direct_connect_pmk_id_req_body_t::key_id
```

**Description:** Pairwise Master Key (PMK) ID.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_direct_connect_pmk_id_req_body_t sl_wisun_msg_set_direct_connect_pmk_id_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_direct_connect_pmk_id_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_preferred_pan

###### Modules

[sl_wisun_msg_set_preferred_pan_cnf_body_t](sl-wisun-msg-set-preferred-pan-cnf-body-t)

[sl_wisun_msg_set_preferred_pan_cnf_t](sl-wisun-msg-set-preferred-pan-cnf-t)

[sl_wisun_msg_set_preferred_pan_req_body_t](sl-wisun-msg-set-preferred-pan-req-body-t)

[sl_wisun_msg_set_preferred_pan_req_t](sl-wisun-msg-set-preferred-pan-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_preferred_pan_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_preferred_pan_cnf_body_t sl_wisun_msg_set_preferred_pan_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_preferred_pan_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### pan_id (heading level 8)

```
uint16_t sl_wisun_msg_set_preferred_pan_req_body_t::pan_id
```

**Description:** Preferred PAN ID.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_set_preferred_pan_req_body_t::reserved
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_preferred_pan_req_body_t sl_wisun_msg_set_preferred_pan_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_preferred_pan_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_lfn_timings

###### Modules

[sl_wisun_msg_set_lfn_timings_cnf_body_t](sl-wisun-msg-set-lfn-timings-cnf-body-t)

[sl_wisun_msg_set_lfn_timings_cnf_t](sl-wisun-msg-set-lfn-timings-cnf-t)

[sl_wisun_msg_set_lfn_timings_req_body_t](sl-wisun-msg-set-lfn-timings-req-body-t)

[sl_wisun_msg_set_lfn_timings_req_t](sl-wisun-msg-set-lfn-timings-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_lfn_timings_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_timings_cnf_body_t sl_wisun_msg_set_lfn_timings_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_timings_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### listening_interval_ms (heading level 8)

```
uint32_t sl_wisun_msg_set_lfn_timings_req_body_t::listening_interval_ms
```

**Description:** The listening interval desired to be used by the LFN in milliseconds.

###### listening_offset_ms (heading level 8)

```
uint32_t sl_wisun_msg_set_lfn_timings_req_body_t::listening_offset_ms
```

**Description:** Time to advance the beginning of the LFN’s Unicast Listening Interval in milliseconds.

###### mac_address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_msg_set_lfn_timings_req_body_t::mac_address
```

**Description:** LFN's EUI-64.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_lfn_timings_req_body_t sl_wisun_msg_set_lfn_timings_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_lfn_timings_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_config_concurrent_detection

###### Modules

[sl_wisun_msg_config_concurrent_detection_cnf_body_t](sl-wisun-msg-config-concurrent-detection-cnf-body-t)

[sl_wisun_msg_config_concurrent_detection_cnf_t](sl-wisun-msg-config-concurrent-detection-cnf-t)

[sl_wisun_msg_config_concurrent_detection_req_body_t](sl-wisun-msg-config-concurrent-detection-req-body-t)

[sl_wisun_msg_config_concurrent_detection_req_t](sl-wisun-msg-config-concurrent-detection-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_config_concurrent_detection_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_config_concurrent_detection_cnf_body_t sl_wisun_msg_config_concurrent_detection_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_config_concurrent_detection_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### enable_tx (heading level 8)

```
uint8_t sl_wisun_msg_config_concurrent_detection_req_body_t::enable_tx
```

**Description:** True to select alternate PHY for transmissions.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_config_concurrent_detection_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_config_concurrent_detection_req_body_t sl_wisun_msg_config_concurrent_detection_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_config_concurrent_detection_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_regulation_params

###### Modules

[sl_wisun_msg_set_regulation_params_cnf_body_t](sl-wisun-msg-set-regulation-params-cnf-body-t)

[sl_wisun_msg_set_regulation_params_cnf_t](sl-wisun-msg-set-regulation-params-cnf-t)

[sl_wisun_msg_set_regulation_params_req_body_t](sl-wisun-msg-set-regulation-params-req-body-t)

[sl_wisun_msg_set_regulation_params_req_t](sl-wisun-msg-set-regulation-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_regulation_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_regulation_params_cnf_body_t sl_wisun_msg_set_regulation_params_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_regulation_params_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### parameters (heading level 8)

```
sl_wisun_regulation_params_t sl_wisun_msg_set_regulation_params_req_body_t::parameters
```

**Description:** Regional regulation parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_regulation_params_req_body_t sl_wisun_msg_set_regulation_params_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_regulation_params_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_reset_regulation_duty_cycle

###### Modules

[sl_wisun_msg_reset_regulation_duty_cycle_cnf_body_t](sl-wisun-msg-reset-regulation-duty-cycle-cnf-body-t)

[sl_wisun_msg_reset_regulation_duty_cycle_cnf_t](sl-wisun-msg-reset-regulation-duty-cycle-cnf-t)

[sl_wisun_msg_reset_regulation_duty_cycle_req_t](sl-wisun-msg-reset-regulation-duty-cycle-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_reset_regulation_duty_cycle_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_reset_regulation_duty_cycle_cnf_body_t sl_wisun_msg_reset_regulation_duty_cycle_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_reset_regulation_duty_cycle_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_reset_regulation_duty_cycle_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_eap_identity

###### Modules

[sl_wisun_msg_set_eap_identity_cnf_body_t](sl-wisun-msg-set-eap-identity-cnf-body-t)

[sl_wisun_msg_set_eap_identity_cnf_t](sl-wisun-msg-set-eap-identity-cnf-t)

[sl_wisun_msg_set_eap_identity_req_body_t](sl-wisun-msg-set-eap-identity-req-body-t)

[sl_wisun_msg_set_eap_identity_req_t](sl-wisun-msg-set-eap-identity-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_eap_identity_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_eap_identity_cnf_body_t sl_wisun_msg_set_eap_identity_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_eap_identity_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### identity (heading level 8)

```
uint8_t sl_wisun_msg_set_eap_identity_req_body_t::identity[SL_WISUN_EAP_IDENTITY_SIZE]
```

**Description:** EAP identity.

###### identity_length (heading level 8)

```
uint8_t sl_wisun_msg_set_eap_identity_req_body_t::identity_length
```

**Description:** Length of EAP identity.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_eap_identity_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_eap_identity_req_body_t sl_wisun_msg_set_eap_identity_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_eap_identity_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_fan_tps_version

###### Modules

[sl_wisun_msg_set_fan_tps_version_cnf_body_t](sl-wisun-msg-set-fan-tps-version-cnf-body-t)

[sl_wisun_msg_set_fan_tps_version_cnf_t](sl-wisun-msg-set-fan-tps-version-cnf-t)

[sl_wisun_msg_set_fan_tps_version_req_body_t](sl-wisun-msg-set-fan-tps-version-req-body-t)

[sl_wisun_msg_set_fan_tps_version_req_t](sl-wisun-msg-set-fan-tps-version-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_fan_tps_version_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_fan_tps_version_cnf_body_t sl_wisun_msg_set_fan_tps_version_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_fan_tps_version_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### fan_tps_version (heading level 8)

```
uint8_t sl_wisun_msg_set_fan_tps_version_req_body_t::fan_tps_version
```

**Description:** FAN TPS version.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_fan_tps_version_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_fan_tps_version_req_body_t sl_wisun_msg_set_fan_tps_version_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_fan_tps_version_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_rx_fifo_size

###### Modules

[sl_wisun_msg_set_rx_fifo_size_cnf_body_t](sl-wisun-msg-set-rx-fifo-size-cnf-body-t)

[sl_wisun_msg_set_rx_fifo_size_cnf_t](sl-wisun-msg-set-rx-fifo-size-cnf-t)

[sl_wisun_msg_set_rx_fifo_size_req_body_t](sl-wisun-msg-set-rx-fifo-size-req-body-t)

[sl_wisun_msg_set_rx_fifo_size_req_t](sl-wisun-msg-set-rx-fifo-size-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_rx_fifo_size_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_rx_fifo_size_cnf_body_t sl_wisun_msg_set_rx_fifo_size_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_rx_fifo_size_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_rx_fifo_size_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### size (heading level 8)

```
uint16_t sl_wisun_msg_set_rx_fifo_size_req_body_t::size
```

**Description:** Desired size of the RX FIFO in bytes in [64, 4096] (power of two)

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_rx_fifo_size_req_body_t sl_wisun_msg_set_rx_fifo_size_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_rx_fifo_size_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_register_address

###### Modules

[sl_wisun_msg_register_address_cnf_body_t](sl-wisun-msg-register-address-cnf-body-t)

[sl_wisun_msg_register_address_cnf_t](sl-wisun-msg-register-address-cnf-t)

[sl_wisun_msg_register_address_req_body_t](sl-wisun-msg-register-address-req-body-t)

[sl_wisun_msg_register_address_req_t](sl-wisun-msg-register-address-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_register_address_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_register_address_cnf_body_t sl_wisun_msg_register_address_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_register_address_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### registration_lifetime_m (heading level 8)

```
uint16_t sl_wisun_msg_register_address_req_body_t::registration_lifetime_m
```

**Description:** Registration lifetime in minutes.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_register_address_req_body_t::reserved
```

**Description:** Reserved, set to zero.

###### target_address (heading level 8)

```
in6_addr_t sl_wisun_msg_register_address_req_body_t::target_address
```

**Description:** Target Address.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_register_address_req_body_t sl_wisun_msg_register_address_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_register_address_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_dhcpv6_vendor_data

###### Modules

[sl_wisun_msg_set_dhcpv6_vendor_data_cnf_body_t](sl-wisun-msg-set-dhcpv6-vendor-data-cnf-body-t)

[sl_wisun_msg_set_dhcpv6_vendor_data_cnf_t](sl-wisun-msg-set-dhcpv6-vendor-data-cnf-t)

[sl_wisun_msg_set_dhcpv6_vendor_data_req_body_t](sl-wisun-msg-set-dhcpv6-vendor-data-req-body-t)

[sl_wisun_msg_set_dhcpv6_vendor_data_req_t](sl-wisun-msg-set-dhcpv6-vendor-data-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_dhcpv6_vendor_data_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_dhcpv6_vendor_data_cnf_body_t sl_wisun_msg_set_dhcpv6_vendor_data_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_dhcpv6_vendor_data_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### data_length (heading level 8)

```
uint16_t sl_wisun_msg_set_dhcpv6_vendor_data_req_body_t::data_length
```

**Description:** Vendor-specific data length.

###### enterprise_number (heading level 8)

```
uint32_t sl_wisun_msg_set_dhcpv6_vendor_data_req_body_t::enterprise_number
```

**Description:** IANA enterprise number.

###### reserved (heading level 8)

```
uint16_t sl_wisun_msg_set_dhcpv6_vendor_data_req_body_t::reserved
```

**Description:** Reserved, set to zero.

###### vendor_data (heading level 8)

```
uint8_t sl_wisun_msg_set_dhcpv6_vendor_data_req_body_t::vendor_data[]
```

**Description:** Vendor-specific data.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_dhcpv6_vendor_data_req_body_t sl_wisun_msg_set_dhcpv6_vendor_data_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_dhcpv6_vendor_data_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_last_gasp

###### Modules

[sl_wisun_msg_set_last_gasp_cnf_body_t](sl-wisun-msg-set-last-gasp-cnf-body-t)

[sl_wisun_msg_set_last_gasp_cnf_t](sl-wisun-msg-set-last-gasp-cnf-t)

[sl_wisun_msg_set_last_gasp_req_body_t](sl-wisun-msg-set-last-gasp-req-body-t)

[sl_wisun_msg_set_last_gasp_req_t](sl-wisun-msg-set-last-gasp-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_last_gasp_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_last_gasp_cnf_body_t sl_wisun_msg_set_last_gasp_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_last_gasp_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### enable (heading level 8)

```
uint8_t sl_wisun_msg_set_last_gasp_req_body_t::enable
```

**Description:** Enter (true) or leave (false) Last Gasp mode.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_last_gasp_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_last_gasp_req_body_t sl_wisun_msg_set_last_gasp_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_last_gasp_req_t::header
```

**Description:** Common message header.

##### sl_wisun_msg_set_first_breath

###### Modules

[sl_wisun_msg_set_first_breath_cnf_body_t](sl-wisun-msg-set-first-breath-cnf-body-t)

[sl_wisun_msg_set_first_breath_cnf_t](sl-wisun-msg-set-first-breath-cnf-t)

[sl_wisun_msg_set_first_breath_req_body_t](sl-wisun-msg-set-first-breath-req-body-t)

[sl_wisun_msg_set_first_breath_req_t](sl-wisun-msg-set-first-breath-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_msg_set_first_breath_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_first_breath_cnf_body_t sl_wisun_msg_set_first_breath_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_first_breath_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### enable (heading level 8)

```
uint8_t sl_wisun_msg_set_first_breath_req_body_t::enable
```

**Description:** Enter (true) or leave (false) First Breath mode.

###### reserved (heading level 8)

```
uint8_t sl_wisun_msg_set_first_breath_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_msg_set_first_breath_req_body_t sl_wisun_msg_set_first_breath_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_msg_set_first_breath_req_t::header
```

**Description:** Common message header.

#### Border Router Message API

Wi-SUN Border Router Message API contains messages for Border Router specific functionality for Network Co-Processor (NCP) use-cases. 

The API is functionally equivalent of [Border Router API](sl-wisun-br-api). It's an extension, not a replacement of [Message API](sl-wisun-msg-api). An application implementing Border Router capability may utilize functions from both APIs. See [API availability](api-availability) for further information. 

##### Modules

[sl_wisun_br_msg_header_t](sl-wisun-br-msg-header-t)

[sl_wisun_br_msg_generic](sl-wisun-br-msg-generic)

[sl_wisun_br_msg_start](sl-wisun-br-msg-start)

[sl_wisun_br_msg_stop](sl-wisun-br-msg-stop)

[sl_wisun_br_msg_set_get](sl-wisun-br-msg-set-gtk)

[sl_wisun_br_msg_set_network_size](sl-wisun-br-msg-set-network-size)

[sl_wisun_br_msg_get_ip_address](sl-wisun-br-msg-get-ip-address)

[sl_wisun_br_msg_get_gak](sl-wisun-br-msg-get-gak)

[sl_wisun_br_msg_get_state](sl-wisun-br-msg-get-state)

[sl_wisun_br_msg_set_device_certificate](sl-wisun-br-msg-set-device-certificate)

[sl_wisun_br_msg_set_broadcast_settings](sl-wisun-br-msg-set-broadcast-settings)

[sl_wisun_br_msg_set_connection_params](sl-wisun-br-msg-set-connection-params)

[sl_wisun_br_msg_set_advanced_params](sl-wisun-br-msg-set-advanced-params)

[sl_wisun_br_msg_set_lfn_params](sl-wisun-br-msg-set-lfn-params)

[sl_wisun_br_msg_set_lfn_support](sl-wisun-br-msg-set-lfn-support)

[sl_wisun_br_msg_set_dhcp_vendor_data](sl-wisun-br-msg-set-dhcp-vendor-data)

[sl_wisun_br_msg_pan_defect_advertise](sl-wisun-br-msg-pan-defect-advertise)

[sl_wisun_br_msg_set_ipv6_prefix](sl-wisun-br-msg-set-ipv6-prefix)

[sl_wisun_br_trigger_global_repair](sl-wisun-br-trigger-global-repair)

[sl_wisun_br_msg_get_routing_table_entry_count](sl-wisun-br-msg-get-routing-table-entry-count)

[sl_wisun_br_msg_get_routing_table](sl-wisun-br-msg-get-routing-table)

[sl_wisun_br_msg_get_routing_table_from_index](sl-wisun-br-msg-get-routing-table-from-index)

[sl_wisun_br_msg_revoke_pairwise_keys](sl-wisun-br-msg-revoke-pairwise-keys)

[sl_wisun_br_msg_revoke_gtks](sl-wisun-br-msg-revoke-gtks)

##### Enumerations

###### sl_wisun_br_msg_cnf_id_t

```
enum sl_wisun_br_msg_cnf_id_t {
    SL_WISUN_BR_MSG_START_CNF_ID = 0x7F
    SL_WISUN_BR_MSG_STOP_CNF_ID = 0x7E
    SL_WISUN_BR_MSG_SET_NETWORK_SIZE_CNF_ID = 0x7D
    SL_WISUN_BR_MSG_SET_GTK_CNF_ID = 0x7C
    SL_WISUN_BR_MSG_GET_IP_ADDR_CNF_ID = 0x7B
    SL_WISUN_BR_MSG_GET_GAK_CNF_ID = 0x7A
    SL_WISUN_BR_MSG_GET_STATE_CNF_ID = 0x79
    SL_WISUN_BR_MSG_SET_DEVICE_CERTIFICATE_CNF_ID = 0x78
    SL_WISUN_BR_MSG_SET_BROADCAST_SETTINGS_CNF_ID = 0x77
    SL_WISUN_BR_MSG_SET_CONNECTION_PARAMS_CNF_ID = 0x76
    SL_WISUN_BR_MSG_SET_LFN_PARAMS_CNF_ID = 0x75
    SL_WISUN_BR_MSG_SET_LFN_SUPPORT_CNF_ID = 0x74
    UNUSED_0x73_CNF_ID = 0x73
    SL_WISUN_BR_MSG_PAN_DEFECT_ADVERTISE_CNF_ID = 0x72
    SL_WISUN_BR_MSG_SET_IPV6_PREFIX_CNF_ID = 0x71
    SL_WISUN_BR_MSG_TRIGGER_GLOBAL_REPAIR_CNF_ID = 0x70
    SL_WISUN_BR_MSG_GET_ROUTING_TABLE_ENTRY_COUNT_CNF_ID = 0x6F
    SL_WISUN_BR_MSG_GET_ROUTING_TABLE_CNF_ID = 0x6E
    SL_WISUN_BR_MSG_REVOKE_PAIRWISE_KEYS_CNF_ID = 0x6D
    SL_WISUN_BR_MSG_REVOKE_GTKS_CNF_ID = 0x6C
    SL_WISUN_BR_MSG_GET_ROUTING_TABLE_FROM_INDEX_CNF_ID = 0x6B
    SL_WISUN_BR_MSG_SET_ADVANCED_PARAMS_CNF_ID = 0x6A
}
```

**Description:**

Wi-SUN BR Message API confirmation IDs.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_BR_MSG_START_CNF_ID||
|SL_WISUN_BR_MSG_STOP_CNF_ID||
|SL_WISUN_BR_MSG_SET_NETWORK_SIZE_CNF_ID||
|SL_WISUN_BR_MSG_SET_GTK_CNF_ID||
|SL_WISUN_BR_MSG_GET_IP_ADDR_CNF_ID||
|SL_WISUN_BR_MSG_GET_GAK_CNF_ID||
|SL_WISUN_BR_MSG_GET_STATE_CNF_ID||
|SL_WISUN_BR_MSG_SET_DEVICE_CERTIFICATE_CNF_ID||
|SL_WISUN_BR_MSG_SET_BROADCAST_SETTINGS_CNF_ID||
|SL_WISUN_BR_MSG_SET_CONNECTION_PARAMS_CNF_ID||
|SL_WISUN_BR_MSG_SET_LFN_PARAMS_CNF_ID||
|SL_WISUN_BR_MSG_SET_LFN_SUPPORT_CNF_ID||
|UNUSED_0x73_CNF_ID||
|SL_WISUN_BR_MSG_PAN_DEFECT_ADVERTISE_CNF_ID||
|SL_WISUN_BR_MSG_SET_IPV6_PREFIX_CNF_ID||
|SL_WISUN_BR_MSG_TRIGGER_GLOBAL_REPAIR_CNF_ID||
|SL_WISUN_BR_MSG_GET_ROUTING_TABLE_ENTRY_COUNT_CNF_ID||
|SL_WISUN_BR_MSG_GET_ROUTING_TABLE_CNF_ID||
|SL_WISUN_BR_MSG_REVOKE_PAIRWISE_KEYS_CNF_ID||
|SL_WISUN_BR_MSG_REVOKE_GTKS_CNF_ID||
|SL_WISUN_BR_MSG_GET_ROUTING_TABLE_FROM_INDEX_CNF_ID||
|SL_WISUN_BR_MSG_SET_ADVANCED_PARAMS_CNF_ID||

###### sl_wisun_br_msg_req_id_t

```
enum sl_wisun_br_msg_req_id_t {
    SL_WISUN_BR_MSG_START_REQ_ID = 0x7F
    SL_WISUN_BR_MSG_STOP_REQ_ID = 0x7E
    SL_WISUN_BR_MSG_SET_NETWORK_SIZE_REQ_ID = 0x7D
    SL_WISUN_BR_MSG_SET_GTK_REQ_ID = 0x7C
    SL_WISUN_BR_MSG_GET_IP_ADDR_REQ_ID = 0x7B
    SL_WISUN_BR_MSG_GET_GAK_REQ_ID = 0x7A
    SL_WISUN_BR_MSG_GET_STATE_REQ_ID = 0x79
    SL_WISUN_BR_MSG_SET_DEVICE_CERTIFICATE_REQ_ID = 0x78
    SL_WISUN_BR_MSG_SET_BROADCAST_SETTINGS_REQ_ID = 0x77
    SL_WISUN_BR_MSG_SET_CONNECTION_PARAMS_REQ_ID = 0x76
    SL_WISUN_BR_MSG_SET_LFN_PARAMS_REQ_ID = 0x75
    SL_WISUN_BR_MSG_SET_LFN_SUPPORT_REQ_ID = 0x74
    UNUSED_0x73_REQ_ID = 0x73
    SL_WISUN_BR_MSG_PAN_DEFECT_ADVERTISE_REQ_ID = 0x72
    SL_WISUN_BR_MSG_SET_IPV6_PREFIX_REQ_ID = 0x71
    SL_WISUN_BR_MSG_TRIGGER_GLOBAL_REPAIR_REQ_ID = 0x70
    SL_WISUN_BR_MSG_GET_ROUTING_TABLE_ENTRY_COUNT_REQ_ID = 0x6F
    SL_WISUN_BR_MSG_GET_ROUTING_TABLE_REQ_ID = 0x6E
    SL_WISUN_BR_MSG_REVOKE_PAIRWISE_KEYS_REQ_ID = 0x6D
    SL_WISUN_BR_MSG_REVOKE_GTKS_REQ_ID = 0x6C
    SL_WISUN_BR_MSG_GET_ROUTING_TABLE_FROM_INDEX_REQ_ID = 0x6B
    SL_WISUN_BR_MSG_SET_ADVANCED_PARAMS_REQ_ID = 0x6A
}
```

**Description:**

Wi-SUN BR Message API request IDs.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_BR_MSG_START_REQ_ID||
|SL_WISUN_BR_MSG_STOP_REQ_ID||
|SL_WISUN_BR_MSG_SET_NETWORK_SIZE_REQ_ID||
|SL_WISUN_BR_MSG_SET_GTK_REQ_ID||
|SL_WISUN_BR_MSG_GET_IP_ADDR_REQ_ID||
|SL_WISUN_BR_MSG_GET_GAK_REQ_ID||
|SL_WISUN_BR_MSG_GET_STATE_REQ_ID||
|SL_WISUN_BR_MSG_SET_DEVICE_CERTIFICATE_REQ_ID||
|SL_WISUN_BR_MSG_SET_BROADCAST_SETTINGS_REQ_ID||
|SL_WISUN_BR_MSG_SET_CONNECTION_PARAMS_REQ_ID||
|SL_WISUN_BR_MSG_SET_LFN_PARAMS_REQ_ID||
|SL_WISUN_BR_MSG_SET_LFN_SUPPORT_REQ_ID||
|UNUSED_0x73_REQ_ID||
|SL_WISUN_BR_MSG_PAN_DEFECT_ADVERTISE_REQ_ID||
|SL_WISUN_BR_MSG_SET_IPV6_PREFIX_REQ_ID||
|SL_WISUN_BR_MSG_TRIGGER_GLOBAL_REPAIR_REQ_ID||
|SL_WISUN_BR_MSG_GET_ROUTING_TABLE_ENTRY_COUNT_REQ_ID||
|SL_WISUN_BR_MSG_GET_ROUTING_TABLE_REQ_ID||
|SL_WISUN_BR_MSG_REVOKE_PAIRWISE_KEYS_REQ_ID||
|SL_WISUN_BR_MSG_REVOKE_GTKS_REQ_ID||
|SL_WISUN_BR_MSG_GET_ROUTING_TABLE_FROM_INDEX_REQ_ID||
|SL_WISUN_BR_MSG_SET_ADVANCED_PARAMS_REQ_ID||

Wi-SUN BR Message API common header. 

###### Public Attributes

###### id (heading level 7)

```
uint8_t sl_wisun_br_msg_header_t::id
```

**Description:** ID (request, confirmation, indication) of the message.

###### info (heading level 7)

```
uint8_t sl_wisun_br_msg_header_t::info
```

**Description:** Processing metadata for the message.

###### length (heading level 7)

```
uint16_t sl_wisun_br_msg_header_t::length
```

**Description:** Total length of the message in bytes, this field included.

##### sl_wisun_br_msg_generic

###### Modules

[sl_wisun_br_msg_generic_body_t](sl-wisun-br-msg-generic-body-t)

[sl_wisun_br_msg_generic_cnf_t](sl-wisun-br-msg-generic-cnf-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_generic_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_generic_body_t sl_wisun_br_msg_generic_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_generic_cnf_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_start

###### Modules

[sl_wisun_br_msg_start_cnf_body_t](sl-wisun-br-msg-start-cnf-body-t)

[sl_wisun_br_msg_start_cnf_t](sl-wisun-br-msg-start-cnf-t)

[sl_wisun_br_msg_start_req_body_t](sl-wisun-br-msg-start-req-body-t)

[sl_wisun_br_msg_start_req_t](sl-wisun-br-msg-start-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_start_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_start_cnf_body_t sl_wisun_br_msg_start_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_start_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### name (heading level 8)

```
uint8_t sl_wisun_br_msg_start_req_body_t::name[SL_WISUN_NETWORK_NAME_SIZE]
```

**Description:** Network name as a NULL terminated string.

###### phy_config (heading level 8)

```
sl_wisun_phy_config_t sl_wisun_br_msg_start_req_body_t::phy_config
```

**Description:** PHY configuration.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_start_req_body_t sl_wisun_br_msg_start_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_start_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_stop

###### Modules

[sl_wisun_br_msg_stop_cnf_body_t](sl-wisun-br-msg-stop-cnf-body-t)

[sl_wisun_br_msg_stop_cnf_t](sl-wisun-br-msg-stop-cnf-t)

[sl_wisun_br_msg_stop_req_body_t](sl-wisun-br-msg-stop-req-body-t)

[sl_wisun_br_msg_stop_req_t](sl-wisun-br-msg-stop-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_stop_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_stop_cnf_body_t sl_wisun_br_msg_stop_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_stop_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### non_graceful (heading level 8)

```
uint32_t sl_wisun_br_msg_stop_req_body_t::non_graceful
```

**Description:** 1 for non-graceful stop

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_stop_req_body_t sl_wisun_br_msg_stop_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_stop_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_get

###### Modules

[sl_wisun_br_msg_set_gtk_cnf_body_t](sl-wisun-br-msg-set-gtk-cnf-body-t)

[sl_wisun_br_msg_set_gtk_cnf_t](sl-wisun-br-msg-set-gtk-cnf-t)

[sl_wisun_br_msg_set_gtk_req_body_t](sl-wisun-br-msg-set-gtk-req-body-t)

[sl_wisun_br_msg_set_gtk_req_t](sl-wisun-br-msg-set-gtk-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_gtk_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_gtk_cnf_body_t sl_wisun_br_msg_set_gtk_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_gtk_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### gtk (heading level 8)

```
uint8_t sl_wisun_br_msg_set_gtk_req_body_t::gtk[SL_WISUN_GTK_LEN]
```

**Description:** GTK.

###### index (heading level 8)

```
uint8_t sl_wisun_br_msg_set_gtk_req_body_t::index
```

**Description:** Index.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_set_gtk_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_gtk_req_body_t sl_wisun_br_msg_set_gtk_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_gtk_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_network_size

###### Modules

[sl_wisun_br_msg_set_network_size_cnf_body_t](sl-wisun-br-msg-set-network-size-cnf-body-t)

[sl_wisun_br_msg_set_network_size_cnf_t](sl-wisun-br-msg-set-network-size-cnf-t)

[sl_wisun_br_msg_set_network_size_req_body_t](sl-wisun-br-msg-set-network-size-req-body-t)

[sl_wisun_br_msg_set_network_size_req_t](sl-wisun-br-msg-set-network-size-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_network_size_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_network_size_cnf_body_t sl_wisun_br_msg_set_network_size_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_network_size_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_set_network_size_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

###### size (heading level 8)

```
uint8_t sl_wisun_br_msg_set_network_size_req_body_t::size
```

**Description:** Network size.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_network_size_req_body_t sl_wisun_br_msg_set_network_size_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_network_size_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_get_ip_address

###### Modules

[sl_wisun_br_msg_get_ip_addr_cnf_t](sl-wisun-br-msg-get-ip-addr-cnf-t)

[sl_wisun_br_msg_get_ip_addr_req_t](sl-wisun-br-msg-get-ip-addr-req-t)

[sl_wisun_br_msg_ip_addr_cnf_body_t](sl-wisun-br-msg-ip-addr-cnf-body-t)

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_ip_addr_cnf_body_t sl_wisun_br_msg_get_ip_addr_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_ip_addr_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_ip_addr_req_t::header
```

**Description:** Common message header.

Confirmation message body. 

###### Public Attributes (heading level 7)

###### dodagid (heading level 8)

```
in6_addr_t sl_wisun_br_msg_ip_addr_cnf_body_t::dodagid
```

**Description:** DODAGID.

###### global_address (heading level 8)

```
in6_addr_t sl_wisun_br_msg_ip_addr_cnf_body_t::global_address
```

**Description:** Global Unicast address.

###### link_local_address (heading level 8)

```
in6_addr_t sl_wisun_br_msg_ip_addr_cnf_body_t::link_local_address
```

**Description:** Link-local address.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_ip_addr_cnf_body_t::status
```

**Description:** Status of the request.

##### sl_wisun_br_msg_get_gak

###### Modules

[sl_wisun_br_msg_get_gak_cnf_body_t](sl-wisun-br-msg-get-gak-cnf-body-t)

[sl_wisun_br_msg_get_gak_cnf_t](sl-wisun-br-msg-get-gak-cnf-t)

[sl_wisun_br_msg_get_gak_req_body_t](sl-wisun-br-msg-get-gak-req-body-t)

[sl_wisun_br_msg_get_gak_req_t](sl-wisun-br-msg-get-gak-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### gak (heading level 8)

```
uint8_t sl_wisun_br_msg_get_gak_cnf_body_t::gak[SL_WISUN_GAK_LEN]
```

**Description:** GAK.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_get_gak_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_gak_cnf_body_t sl_wisun_br_msg_get_gak_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_gak_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### index (heading level 8)

```
uint8_t sl_wisun_br_msg_get_gak_req_body_t::index
```

**Description:** Index.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_get_gak_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_gak_req_body_t sl_wisun_br_msg_get_gak_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_gak_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_get_state

###### Modules

[sl_wisun_br_msg_get_state_cnf_body_t](sl-wisun-br-msg-get-state-cnf-body-t)

[sl_wisun_br_msg_get_state_cnf_t](sl-wisun-br-msg-get-state-cnf-t)

[sl_wisun_br_msg_get_state_req_t](sl-wisun-br-msg-get-state-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### state (heading level 8)

```
uint32_t sl_wisun_br_msg_get_state_cnf_body_t::state
```

**Description:** Border router state.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_get_state_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_state_cnf_body_t sl_wisun_br_msg_get_state_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_state_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_state_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_device_certificate

###### Modules

[sl_wisun_br_msg_set_device_certificate_cnf_body_t](sl-wisun-br-msg-set-device-certificate-cnf-body-t)

[sl_wisun_br_msg_set_device_certificate_cnf_t](sl-wisun-br-msg-set-device-certificate-cnf-t)

[sl_wisun_br_msg_set_device_certificate_req_body_t](sl-wisun-br-msg-set-device-certificate-req-body-t)

[sl_wisun_br_msg_set_device_certificate_req_t](sl-wisun-br-msg-set-device-certificate-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_device_certificate_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_device_certificate_cnf_body_t sl_wisun_br_msg_set_device_certificate_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_device_certificate_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### certificate (heading level 8)

```
uint8_t sl_wisun_br_msg_set_device_certificate_req_body_t::certificate[]
```

**Description:** Certificate data.

###### certificate_length (heading level 8)

```
uint16_t sl_wisun_br_msg_set_device_certificate_req_body_t::certificate_length
```

**Description:** Size of the certificate data.

###### certificate_options (heading level 8)

```
uint16_t sl_wisun_br_msg_set_device_certificate_req_body_t::certificate_options
```

**Description:** Options for the certificate.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_device_certificate_req_body_t sl_wisun_br_msg_set_device_certificate_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_device_certificate_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_broadcast_settings

###### Modules

[sl_wisun_br_msg_set_broadcast_settings_cnf_body_t](sl-wisun-br-msg-set-broadcast-settings-cnf-body-t)

[sl_wisun_br_msg_set_broadcast_settings_cnf_t](sl-wisun-br-msg-set-broadcast-settings-cnf-t)

[sl_wisun_br_msg_set_broadcast_settings_req_body_t](sl-wisun-br-msg-set-broadcast-settings-req-body-t)

[sl_wisun_br_msg_set_broadcast_settings_req_t](sl-wisun-br-msg-set-broadcast-settings-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_broadcast_settings_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_broadcast_settings_cnf_body_t sl_wisun_br_msg_set_broadcast_settings_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_broadcast_settings_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### dwell_interval_ms (heading level 8)

```
uint8_t sl_wisun_br_msg_set_broadcast_settings_req_body_t::dwell_interval_ms
```

**Description:** Broadcast dwell interval.

###### interval_ms (heading level 8)

```
uint32_t sl_wisun_br_msg_set_broadcast_settings_req_body_t::interval_ms
```

**Description:** Broadcast interval.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_set_broadcast_settings_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_broadcast_settings_req_body_t sl_wisun_br_msg_set_broadcast_settings_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_broadcast_settings_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_connection_params

###### Modules

[sl_wisun_br_msg_set_connection_params_cnf_body_t](sl-wisun-br-msg-set-connection-params-cnf-body-t)

[sl_wisun_br_msg_set_connection_params_cnf_t](sl-wisun-br-msg-set-connection-params-cnf-t)

[sl_wisun_br_msg_set_connection_params_req_body_t](sl-wisun-br-msg-set-connection-params-req-body-t)

[sl_wisun_br_msg_set_connection_params_req_t](sl-wisun-br-msg-set-connection-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_connection_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_connection_params_cnf_body_t sl_wisun_br_msg_set_connection_params_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_set_connection_params_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### parameters (heading level 8)

```
sl_wisun_br_connection_params_t sl_wisun_br_msg_set_connection_params_req_body_t::parameters
```

**Description:** Connection parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_connection_params_req_body_t sl_wisun_br_msg_set_connection_params_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_set_connection_params_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_advanced_params

###### Modules

[sl_wisun_br_msg_set_advanced_params_cnf_body_t](sl-wisun-br-msg-set-advanced-params-cnf-body-t)

[sl_wisun_br_msg_set_advanced_params_cnf_t](sl-wisun-br-msg-set-advanced-params-cnf-t)

[sl_wisun_br_msg_set_advanced_params_req_body_t](sl-wisun-br-msg-set-advanced-params-req-body-t)

[sl_wisun_br_msg_set_advanced_params_req_t](sl-wisun-br-msg-set-advanced-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_advanced_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_advanced_params_cnf_body_t sl_wisun_br_msg_set_advanced_params_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_advanced_params_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### parameters (heading level 8)

```
sl_wisun_br_advanced_parameters_t sl_wisun_br_msg_set_advanced_params_req_body_t::parameters
```

**Description:** Advanced connection parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_advanced_params_req_body_t sl_wisun_br_msg_set_advanced_params_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_advanced_params_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_lfn_params

###### Modules

[sl_wisun_br_msg_set_lfn_params_cnf_body_t](sl-wisun-br-msg-set-lfn-params-cnf-body-t)

[sl_wisun_br_msg_set_lfn_params_cnf_t](sl-wisun-br-msg-set-lfn-params-cnf-t)

[sl_wisun_br_msg_set_lfn_params_req_body_t](sl-wisun-br-msg-set-lfn-params-req-body-t)

[sl_wisun_br_msg_set_lfn_params_req_t](sl-wisun-br-msg-set-lfn-params-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_lfn_params_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_lfn_params_cnf_body_t sl_wisun_br_msg_set_lfn_params_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_set_lfn_params_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### parameters (heading level 8)

```
sl_wisun_br_lfn_params_t sl_wisun_br_msg_set_lfn_params_req_body_t::parameters
```

**Description:** LFN parenting parameters.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_lfn_params_req_body_t sl_wisun_br_msg_set_lfn_params_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_set_lfn_params_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_lfn_support

###### Modules

[sl_wisun_br_msg_set_lfn_support_cnf_body_t](sl-wisun-br-msg-set-lfn-support-cnf-body-t)

[sl_wisun_br_msg_set_lfn_support_cnf_t](sl-wisun-br-msg-set-lfn-support-cnf-t)

[sl_wisun_br_msg_set_lfn_support_req_body_t](sl-wisun-br-msg-set-lfn-support-req-body-t)

[sl_wisun_br_msg_set_lfn_support_req_t](sl-wisun-br-msg-set-lfn-support-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_lfn_support_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_lfn_support_cnf_body_t sl_wisun_br_msg_set_lfn_support_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_set_lfn_support_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### lfn_limit (heading level 8)

```
uint8_t sl_wisun_br_msg_set_lfn_support_req_body_t::lfn_limit
```

**Description:** Number of LFN supported [0, 10].

###### lfn_support_pan (heading level 8)

```
uint8_t sl_wisun_br_msg_set_lfn_support_req_body_t::lfn_support_pan
```

**Description:** Enable or disable LFN support PAN-wide.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_set_lfn_support_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_lfn_support_req_body_t sl_wisun_br_msg_set_lfn_support_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_set_lfn_support_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_dhcp_vendor_data

###### Modules

[sl_wisun_br_msg_set_dhcp_vendor_data_cnf_body_t](sl-wisun-br-msg-set-dhcp-vendor-data-cnf-body-t)

[sl_wisun_br_msg_set_dhcp_vendor_data_cnf_t](sl-wisun-br-msg-set-dhcp-vendor-data-cnf-t)

[sl_wisun_br_msg_set_dhcp_vendor_data_req_body_t](sl-wisun-br-msg-set-dhcp-vendor-data-req-body-t)

[sl_wisun_br_msg_set_dhcp_vendor_data_req_t](sl-wisun-br-msg-set-dhcp-vendor-data-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_dhcp_vendor_data_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_dhcp_vendor_data_cnf_body_t sl_wisun_br_msg_set_dhcp_vendor_data_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_dhcp_vendor_data_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### data (heading level 8)

```
uint8_t sl_wisun_br_msg_set_dhcp_vendor_data_req_body_t::data[]
```

**Description:** Vendor specific data.

###### data_length (heading level 8)

```
uint16_t sl_wisun_br_msg_set_dhcp_vendor_data_req_body_t::data_length
```

**Description:** Length of Vendor specific data.

###### enterprise_number (heading level 8)

```
uint32_t sl_wisun_br_msg_set_dhcp_vendor_data_req_body_t::enterprise_number
```

**Description:** Vendor Specific Enterprise Number.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_dhcp_vendor_data_req_body_t sl_wisun_br_msg_set_dhcp_vendor_data_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_dhcp_vendor_data_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_pan_defect_advertise

###### Modules

[sl_wisun_br_msg_pan_defect_advertise_cnf_body_t](sl-wisun-br-msg-pan-defect-advertise-cnf-body-t)

[sl_wisun_br_msg_pan_defect_advertise_cnf_t](sl-wisun-br-msg-pan-defect-advertise-cnf-t)

[sl_wisun_br_msg_pan_defect_advertise_req_body_t](sl-wisun-br-msg-pan-defect-advertise-req-body-t)

[sl_wisun_br_msg_pan_defect_advertise_req_t](sl-wisun-br-msg-pan-defect-advertise-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_pan_defect_advertise_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_pan_defect_advertise_cnf_body_t sl_wisun_br_msg_pan_defect_advertise_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_pan_defect_advertise_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### defect_advertise (heading level 8)

```
uint8_t sl_wisun_br_msg_pan_defect_advertise_req_body_t::defect_advertise
```

**Description:** True to start PAN Defect procedure, false to stop it.

###### max_scan_duration_s (heading level 8)

```
uint32_t sl_wisun_br_msg_pan_defect_advertise_req_body_t::max_scan_duration_s
```

**Description:** Duration after which devices should systemically switch to the alternative PAN if one is available.

###### min_scan_duration_s (heading level 8)

```
uint32_t sl_wisun_br_msg_pan_defect_advertise_req_body_t::min_scan_duration_s
```

**Description:** Minimum duration after which devices are allowed to switch their PAN if an alternative one is available.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_pan_defect_advertise_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_pan_defect_advertise_req_body_t sl_wisun_br_msg_pan_defect_advertise_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_msg_header_t sl_wisun_br_msg_pan_defect_advertise_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_set_ipv6_prefix

###### Modules

[sl_wisun_br_msg_set_ipv6_prefix_cnf_body_t](sl-wisun-br-msg-set-ipv6-prefix-cnf-body-t)

[sl_wisun_br_msg_set_ipv6_prefix_cnf_t](sl-wisun-br-msg-set-ipv6-prefix-cnf-t)

[sl_wisun_br_msg_set_ipv6_prefix_req_body_t](sl-wisun-br-msg-set-ipv6-prefix-req-body-t)

[sl_wisun_br_msg_set_ipv6_prefix_req_t](sl-wisun-br-msg-set-ipv6-prefix-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_set_ipv6_prefix_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_ipv6_prefix_cnf_body_t sl_wisun_br_msg_set_ipv6_prefix_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_ipv6_prefix_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### prefix (heading level 8)

```
uint8_t sl_wisun_br_msg_set_ipv6_prefix_req_body_t::prefix[IPV6_ADDR_SIZE]
```

**Description:** New IPv6 prefix.

###### prefix_length (heading level 8)

```
uint8_t sl_wisun_br_msg_set_ipv6_prefix_req_body_t::prefix_length
```

**Description:** IPv6 prefix length.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_set_ipv6_prefix_req_body_t::reserved[3]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_set_ipv6_prefix_req_body_t sl_wisun_br_msg_set_ipv6_prefix_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_set_ipv6_prefix_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_trigger_global_repair

###### Modules

[sl_wisun_br_msg_trigger_global_repair_cnf_body_t](sl-wisun-br-msg-trigger-global-repair-cnf-body-t)

[sl_wisun_br_msg_trigger_global_repair_cnf_t](sl-wisun-br-msg-trigger-global-repair-cnf-t)

[sl_wisun_br_msg_trigger_global_repair_req_t](sl-wisun-br-msg-trigger-global-repair-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_trigger_global_repair_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_trigger_global_repair_cnf_body_t sl_wisun_br_msg_trigger_global_repair_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_trigger_global_repair_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_trigger_global_repair_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_get_routing_table_entry_count

###### Modules

[sl_wisun_br_msg_get_routing_table_entry_count_cnf_body_t](sl-wisun-br-msg-get-routing-table-entry-count-cnf-body-t)

[sl_wisun_br_msg_get_routing_table_entry_count_cnf_t](sl-wisun-br-msg-get-routing-table-entry-count-cnf-t)

[sl_wisun_br_msg_get_routing_table_entry_count_req_t](sl-wisun-br-msg-get-routing-table-entry-count-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### entry_count (heading level 8)

```
uint16_t sl_wisun_br_msg_get_routing_table_entry_count_cnf_body_t::entry_count
```

**Description:** Size of the routing table.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_get_routing_table_entry_count_cnf_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_get_routing_table_entry_count_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_routing_table_entry_count_cnf_body_t sl_wisun_br_msg_get_routing_table_entry_count_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_routing_table_entry_count_cnf_t::header
```

**Description:** Common message header.

Request message. 

###### Public Attributes (heading level 7)

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_routing_table_entry_count_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_get_routing_table

###### Modules

[sl_wisun_br_msg_get_routing_table_cnf_body_t](sl-wisun-br-msg-get-routing-table-cnf-body-t)

[sl_wisun_br_msg_get_routing_table_cnf_t](sl-wisun-br-msg-get-routing-table-cnf-t)

[sl_wisun_br_msg_get_routing_table_req_body_t](sl-wisun-br-msg-get-routing-table-req-body-t)

[sl_wisun_br_msg_get_routing_table_req_t](sl-wisun-br-msg-get-routing-table-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### entries (heading level 8)

```
sl_wisun_br_routing_table_entry_t sl_wisun_br_msg_get_routing_table_cnf_body_t::entries[]
```

**Description:** Routing table entries read.

###### entry_count (heading level 8)

```
uint16_t sl_wisun_br_msg_get_routing_table_cnf_body_t::entry_count
```

**Description:** Number of entries in the routing table.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_get_routing_table_cnf_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_get_routing_table_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_routing_table_cnf_body_t sl_wisun_br_msg_get_routing_table_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_routing_table_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### entry_count (heading level 8)

```
uint16_t sl_wisun_br_msg_get_routing_table_req_body_t::entry_count
```

**Description:** Maximum number of entries to be retrieved.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_get_routing_table_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_routing_table_req_body_t sl_wisun_br_msg_get_routing_table_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_routing_table_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_get_routing_table_from_index

###### Modules

[sl_wisun_br_msg_get_routing_table_from_index_cnf_body_t](sl-wisun-br-msg-get-routing-table-from-index-cnf-body-t)

[sl_wisun_br_msg_get_routing_table_from_index_cnf_t](sl-wisun-br-msg-get-routing-table-from-index-cnf-t)

[sl_wisun_br_msg_get_routing_table_from_index_req_body_t](sl-wisun-br-msg-get-routing-table-from-index-req-body-t)

[sl_wisun_br_msg_get_routing_table_from_index_req_t](sl-wisun-br-msg-get-routing-table-from-index-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### entries (heading level 8)

```
sl_wisun_br_routing_table_entry_t sl_wisun_br_msg_get_routing_table_from_index_cnf_body_t::entries[]
```

**Description:** Routing table entries read.

###### entry_count (heading level 8)

```
uint16_t sl_wisun_br_msg_get_routing_table_from_index_cnf_body_t::entry_count
```

**Description:** Number of entries in the routing table.

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_get_routing_table_from_index_cnf_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_get_routing_table_from_index_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_routing_table_from_index_cnf_body_t sl_wisun_br_msg_get_routing_table_from_index_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_routing_table_from_index_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### entry_count (heading level 8)

```
uint16_t sl_wisun_br_msg_get_routing_table_from_index_req_body_t::entry_count
```

**Description:** Maximum number of entries to retrieve.

###### start_index (heading level 8)

```
uint16_t sl_wisun_br_msg_get_routing_table_from_index_req_body_t::start_index
```

**Description:** Index of the first entry to retrieve.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_get_routing_table_from_index_req_body_t sl_wisun_br_msg_get_routing_table_from_index_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_get_routing_table_from_index_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_revoke_pairwise_keys

###### Modules

[sl_wisun_br_msg_revoke_pairwise_keys_cnf_body_t](sl-wisun-br-msg-revoke-pairwise-keys-cnf-body-t)

[sl_wisun_br_msg_revoke_pairwise_keys_cnf_t](sl-wisun-br-msg-revoke-pairwise-keys-cnf-t)

[sl_wisun_br_msg_revoke_pairwise_keys_req_body_t](sl-wisun-br-msg-revoke-pairwise-keys-req-body-t)

[sl_wisun_br_msg_revoke_pairwise_keys_req_t](sl-wisun-br-msg-revoke-pairwise-keys-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_revoke_pairwise_keys_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_revoke_pairwise_keys_cnf_body_t sl_wisun_br_msg_revoke_pairwise_keys_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_revoke_pairwise_keys_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### address (heading level 8)

```
sl_wisun_mac_address_t sl_wisun_br_msg_revoke_pairwise_keys_req_body_t::address
```

**Description:** EUI-64 of the target node.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_revoke_pairwise_keys_req_body_t sl_wisun_br_msg_revoke_pairwise_keys_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_revoke_pairwise_keys_req_t::header
```

**Description:** Common message header.

##### sl_wisun_br_msg_revoke_gtks

###### Modules

[sl_wisun_br_msg_revoke_gtks_cnf_body_t](sl-wisun-br-msg-revoke-gtks-cnf-body-t)

[sl_wisun_br_msg_revoke_gtks_cnf_t](sl-wisun-br-msg-revoke-gtks-cnf-t)

[sl_wisun_br_msg_revoke_gtks_req_body_t](sl-wisun-br-msg-revoke-gtks-req-body-t)

[sl_wisun_br_msg_revoke_gtks_req_t](sl-wisun-br-msg-revoke-gtks-req-t)

Confirmation message body. 

###### Public Attributes (heading level 7)

###### status (heading level 8)

```
uint32_t sl_wisun_br_msg_revoke_gtks_cnf_body_t::status
```

**Description:** Status of the request.

Confirmation message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_revoke_gtks_cnf_body_t sl_wisun_br_msg_revoke_gtks_cnf_t::body
```

**Description:** Confirmation message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_revoke_gtks_cnf_t::header
```

**Description:** Common message header.

Request message body. 

###### Public Attributes (heading level 7)

###### hardcoded_gtk (heading level 8)

```
uint8_t sl_wisun_br_msg_revoke_gtks_req_body_t::hardcoded_gtk[SL_WISUN_GTK_LEN]
```

**Description:** (L)GTK to install after revocation

###### reserved (heading level 8)

```
uint8_t sl_wisun_br_msg_revoke_gtks_req_body_t::reserved[2]
```

**Description:** Reserved, set to zero.

###### revoke_lgtks (heading level 8)

```
uint8_t sl_wisun_br_msg_revoke_gtks_req_body_t::revoke_lgtks
```

**Description:** Revokes GTKs when set to 0, and LGTKs otherwise.

###### use_hardcoded_gtk (heading level 8)

```
uint8_t sl_wisun_br_msg_revoke_gtks_req_body_t::use_hardcoded_gtk
```

**Description:** True to use hardcoded GTK, false to generate a random one.

Request message. 

###### Public Attributes (heading level 7)

###### body (heading level 8)

```
sl_wisun_br_msg_revoke_gtks_req_body_t sl_wisun_br_msg_revoke_gtks_req_t::body
```

**Description:** Request message body.

###### header (heading level 8)

```
sl_wisun_br_msg_header_t sl_wisun_br_msg_revoke_gtks_req_t::header
```

**Description:** Common message header.

#### Socket API

Socket API provides socket-based networking functions for IPv6 connectivity, closely aligning with the POSIX.1-2024 specification. 

##### Modules

[cmsghdr](cmsghdr)

[in6_addr](in6-addr)

[in6_pktinfo](in6-pktinfo)

[iovec](iovec)

[ip6_mtuinfo](ip6-mtuinfo)

[ipv6_mreq](ipv6-mreq)

[msghdr](msghdr)

[sockaddr](sockaddr)

[sockaddr_in6](sockaddr-in6)

##### IPv6 socket options

IPv6 socket options summaryopt_name   Data type   set/getsockopt   sendmsg   recvmsg    IPV6_TCLASS   int   Set/Get   Yes   No    IPV6_UNICAST_HOPS   int   Set/Get   No   No    IPV6_MULTICAST_HOPS   int   Set/Get   No   No    IPV6_USE_MIN_MTU   int   Set/Get   Yes   No    IPV6_HOPLIMIT   int   None   Yes   Yes    IPV6_RECVHOPLIMIT   int   Set/Get   No   No    IPV6_MULTICAST_LOOP   int   Set/Get   Yes   No    IPV6_JOIN_GROUP   ipv6_mreq_t   Set only   No   No    IPV6_ADD_MEMBERSHIP   ipv6_mreq_t   Set only   No   No    IPV6_LEAVE_GROUP   ipv6_mreq_t   Set only   No   No    IPV6_DROP_MEMBERSHIP   ipv6_mreq_t   Set only   No   No    IPV6_PKTINFO   in6_pktinfo_t   None   Yes   Yes    IPV6_RCVPKTINFO   int   Set/Get   No   No    IPV6_RECVTCLASS   int   Set/Get   No   No    IPV6_DONTFRAG   int   Set/Get   Yes   No

`#define IPV6_TCLASS 1`

**Description**: Sets or reads the full 8-bit IPv6 Traffic Class (RFC 3542 section 6.5), as int.

`#define IPV6_UNICAST_HOPS 2`

**Description**: Set the unicast hop limit for the socket, as int.

`#define IPV6_MULTICAST_HOPS 3`

**Description**: Set the multicast hop limit for the socket, as int.

`#define IPV6_USE_MIN_MTU 5`

**Description**: Specify PMTU preference, as int; Valid values -1 (PMTUD for unicast, default), 0 (PMTUD always), 1 (PMTUD off).

`#define IPV6_HOPLIMIT 8`

**Description**: Ancillary data option on [sendmsg()](sl-wisun-socket-api#sendmsg)/recvmsg(), value to be used for single ongoing packet, as int; Valid values 0-255, -1 for default.

`#define IPV6_RECVHOPLIMIT 11`

**Description**: Ancillary data option on [recvmsg()](sl-wisun-socket-api#recvmsg), specifies hop-limit for the single received ongoing packet, as int; A nonzero value enables the option; a value of 0 disables the option.

`#define IPV6_MULTICAST_LOOP 14`

**Description**: Specify whether outgoing multicast packets are looped back, as int.

`#define IPV6_ADD_MEMBERSHIP 15`

**Description**: Join a multicast group.

`#define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP`

**Description**: Sets or reads the full 8-bit IPv6 Traffic Class (RFC 3542 section 6.5), as int.

`#define IPV6_DROP_MEMBERSHIP 16`

**Description**: Leave a multicast group.

`#define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP`

**Description**: Sets or reads the full 8-bit IPv6 Traffic Class (RFC 3542 section 6.5), as int.

`#define IPV6_PKTINFO 9`

**Description**: Specify control messages packet info for [recvmsg()](sl-wisun-socket-api#recvmsg) as struct [in6_pktinfo](in6-pktinfo).

`#define IPV6_RECVPKTINFO 10`

**Description**: Set delivery of the IPV6_PKTINFO control message on incoming datagrams, as int.

`#define IPV6_RECVTCLASS 12`

**Description**: Enables the application to receive the value of the traffic class field from the IPv6 header, as int; A nonzero value enables the option; a value of 0 disables the option.

`#define IPV6_DONTFRAG 6`

**Description**: Specify not to fragment datagrams, as int; For Wi-SUN, direct neighbors can receive frames up to 1504 bytes, while the other nodes can receive frames up to 1280 bytes.

##### Differentiated Services Code Points (DSCP) — IANA assigned values

These are the raw code-point values; combine with IPV6_TCLASS_FROM_DSCP or IPV6_TCLASS_FROM_DSCP_AND_ECN to obtain a Traffic Class octet suitable for use with IPV6_TCLASS.

`#define IP_DSCP_CS0 0`

**Description**: CS0.

`#define IP_DSCP_CS1 8`

**Description**: CS1.

`#define IP_DSCP_AF11 10`

**Description**: AF11.

`#define IP_DSCP_AF12 12`

**Description**: AF12.

`#define IP_DSCP_AF13 14`

**Description**: AF13.

`#define IP_DSCP_CS2 16`

**Description**: CS2.

`#define IP_DSCP_AF21 18`

**Description**: AF21.

`#define IP_DSCP_AF22 20`

**Description**: AF22.

`#define IP_DSCP_AF23 22`

**Description**: AF23.

`#define IP_DSCP_CS3 24`

**Description**: CS3.

`#define IP_DSCP_AF31 26`

**Description**: AF31.

`#define IP_DSCP_AF32 28`

**Description**: AF32.

`#define IP_DSCP_AF33 30`

**Description**: AF33.

`#define IP_DSCP_CS4 32`

**Description**: CS4.

`#define IP_DSCP_AF41 34`

**Description**: AF41.

`#define IP_DSCP_AF42 36`

**Description**: AF42.

`#define IP_DSCP_AF43 38`

**Description**: AF43.

`#define IP_DSCP_CS5 40`

**Description**: CS5.

`#define IP_DSCP_VOICE_ADMIT 44`

**Description**: VOICE-ADMIT.

`#define IP_DSCP_EF 46`

**Description**: EF.

`#define IP_DSCP_CS6 48`

**Description**: CS6.

`#define IP_DSCP_CS7 56`

**Description**: CS7.

##### Wi-SUN DSCP (Differentiated Services Code Point) QoS supported levels.

`#define DSCP_DEFAULT IP_DSCP_CS0`

**Description**: Standard priority and it is socket default.

`#define DSCP_AF11 IP_DSCP_AF11`

**Description**: Application high priority service: Stack priorities these messages over the default priority messages.

`#define DSCP_EF IP_DSCP_EF`

**Description**: Expedited Forwarding (EF) QoS level enable high priority state: low loss, low delay, and low jitter services.

##### Explicit Congestion Notification (ECN) code points (RFC 3168)

Two-bit ECN values occupying bits 1-0 of the IPv6 Traffic Class octet (and the equivalent IPv4 ToS field).

`#define IP_ECN_NOT_ECT 0`

**Description**: Not ECN-Capable Transport.

`#define IP_ECN_ECT_1 1`

**Description**: ECN-Capable Transport(1)

`#define IP_ECN_ECT_0 2`

**Description**: ECN-Capable Transport(0)

`#define IP_ECN_CE 3`

**Description**: Congestion Experienced.

##### IPv6 Traffic Class byte (RFC 3542 section 6.5)

The IPv6 Traffic Class is an 8-bit field placed in the IPv6 header: DSCP (Differentiated Services Code Point, RFC 2474) occupies bits 7-2 and ECN (Explicit Congestion Notification, RFC 3168) bits 1-0.Use IPV6_TCLASS_FROM_DSCP or IPV6_TCLASS_FROM_DSCP_AND_ECN to build a Traffic Class octet from a DSCP code point (0-63), and IPV6_DSCP_FROM_TCLASS for the inverse.These helpers are a Wi-SUN extension to RFC 3542; they live here because they manipulate the Traffic Class field of the IPv6 header.

`#define IPV6_TCLASS_DSCP_SHIFT 2`

**Description**: Six-bit DSCP code point (0-63).

`#define IPV6_TCLASS_ECN_MASK 0x03u`

**Description**: Six-bit DSCP code point (0-63).

`#define IPV6_DSCP_CODEPOINT_MASK 0x3Fu`

**Description**: Six-bit DSCP code point (0-63).

`#define IPV6_TCLASS_FROM_DSCP_AND_ECN (dscp, ecn)`

**Description**: Traffic Class octet from DSCP code point and ECN Not-ECT.

`#define IPV6_TCLASS_FROM_DSCP (dscp)`

**Description**: Traffic Class octet from DSCP code point (ECN Not-ECT)

`#define IPV6_DSCP_FROM_TCLASS (tclass)`

**Description**: DSCP code point (0-63) from a full RFC 3542 Traffic Class octet (inverse of [IPV6_TCLASS_FROM_DSCP](sl-wisun-socket-api#ipv6-tclass-from-dscp)).

##### Ancillary data object information MACROS

`#define CMSG_ALIGN (len)`

**Description**: Returns the length of the data with the required alignment.

`#define CMSG_SPACE (len)`

**Description**: Returns the number of bytes an ancillary element with payload of the passed data length occupies.

`#define CMSG_LEN (len)`

**Description**: Returns the value to store in the cmsg_len member of the cmsghdr structure.

`#define CMSG_FIRSTHDR (mhdr)`

**Description**: Returns a pointer to the first control message header in the given msghdr structure.

`#define CMSG_NXTHDR (mhdr, cmsg)`

**Description**: Returns a pointer to the next control message header in the ancillary data buffer.

`#define CMSG_DATA (cmsg)`

**Description**: Returns a pointer to the data portion of a cmsghdr.

##### Flags we can use with recv(), recvfrom() and recvmsg()

`#define MSG_TRUNC 0x0001`

**Description**: Normal data truncated, to be used as msg_flags field in the msghdr structure.

`#define MSG_CTRUNC 0x0002`

**Description**: Control data truncated, to be used as msg_flags field in the msghdr structure.

`#define MSG_PEEK 0x0004`

**Description**: Leave received data in queue, to be used as the flags parameter.

##### Protocol levels used for socket_setsockopt.

`#define SOL_SOCKET 0`

**Description**: Socket option level.

`#define SOL_APPLICATION 1`

**Description**: Application socket option level.

##### application level socket options

application level socket options summaryopt_name   data type   set/get   sendmsg   recvmsg    SO_EVENT_MODE   uint32_t   Set only   No   Yes    SO_NONBLOCK   uint32_t   Set only   Yes   Yes

`#define SO_EVENT_MODE 10`

**Description**: Specify event mode of a socket. When set, optval must point to an uint32_t.

Possible values are:

- [SL_WISUN_SOCKET_EVENT_MODE_INDICATION](sl-wisun-socket-api#sl-wisun-socket-event-mode-indication): received data is included in SL_WISUN_MSG_SOCKET_DATA_IND_ID indication
- [SL_WISUN_SOCKET_EVENT_MODE_POLLING](sl-wisun-socket-api#sl-wisun-socket-event-mode-polling): only the amount of received data is included [SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-available-ind-id) indication. [recv()](sl-wisun-socket-api#recv) or [recvfrom()](sl-wisun-socket-api#recvfrom) shouldbe invoked after indication reception to retrieve data

`#define SOCKET_EVENT_MODE SO_EVENT_MODE`

**Description**: Specify event mode of a socket. When set, optval must point to an uint32_t.

Possible values are:

- [SL_WISUN_SOCKET_EVENT_MODE_INDICATION](sl-wisun-socket-api#sl-wisun-socket-event-mode-indication): received data is included in SL_WISUN_MSG_SOCKET_DATA_IND_ID indication
- [SL_WISUN_SOCKET_EVENT_MODE_POLLING](sl-wisun-socket-api#sl-wisun-socket-event-mode-polling): only the amount of received data is included [SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-available-ind-id) indication. [recv()](sl-wisun-socket-api#recv) or [recvfrom()](sl-wisun-socket-api#recvfrom) shouldbe invoked after indication reception to retrieve data

`#define SO_NONBLOCK 11`

**Description**: Enable/disable nonblocking mode.

##### socket level options

socket level options summaryopt_name   data type   set/get   sendmsg   recvmsg    SO_RCVBUF   int32_t   Set/Get   No   Yes    SO_SNDBUF   int32_t   Set/Get   Yes   No    SO_SNDLOWAT   int32_t   Set/Get   Yes   No    SO_WRITABLE   int32_t   Get   No   No    SO_READABLE   int32_t   Get   No   No

`#define SO_RCVBUF 1`

**Description**: Specify receive buffer size in payload bytes. When set, optval must point to an int32_t.

0 means unread data are dropped, unless read in data callback.

`#define SO_SNDBUF 2`

**Description**: Specify send buffer size in payload bytes.

`#define SO_SNDLOWAT 4`

**Description**: Specify send low water mark in payload bytes.

`#define SO_WRITABLE 5`

**Description**: Non-standard POSIX option SO_WRITABLE.

`#define SO_READABLE 6`

**Description**: Non-standard POSIX option SO_READABLE.

##### Socket-level Wi-SUN extensions

`#define SO_EDFE_MODE 0xfb`

**Description**: Enable Extended Directed Frame Exchange mode. When set, optval must point to an uint32_t. When set, all data from the socket will be sent using the EDFE mode even if there is a single fragment. Disabled by default.

`#define SOCKET_EDFE_MODE SO_EDFE_MODE`

**Description**: Enable Extended Directed Frame Exchange mode. When set, optval must point to an uint32_t. When set, all data from the socket will be sent using the EDFE mode even if there is a single fragment. Disabled by default.

##### Enumerations

###### sl_wisun_socket_event_mode_t

```
enum sl_wisun_socket_event_mode_t {
    SL_WISUN_SOCKET_EVENT_MODE_INDICATION = 0
    SL_WISUN_SOCKET_EVENT_MODE_POLLING = 1
}
```

**Description:**

Enumerations for socket event mode.

**Enumerator:**

|   |   |
|---|---|
|SL_WISUN_SOCKET_EVENT_MODE_INDICATION|SL_WISUN_MSG_SOCKET_DATA_IND_ID is sent to the app with the packet contained in the indication.|
|SL_WISUN_SOCKET_EVENT_MODE_POLLING|SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID is sent to the app indicating the amount of data received [recv()](sl-wisun-socket-api#recv) or [recvfrom()](sl-wisun-socket-api#recvfrom) should be invoked after indication reception to retrieve data This is the default socket event mode option.|

###### socket_domain

```
enum socket_domain {
    AF_INET6 = 0
}
```

**Description:**

Supported address families.

**Enumerator:**

|   |   |
|---|---|
|AF_INET6|IP version 6.|

###### socket_protocol

```
enum socket_protocol {
    IPPROTO_IP = 0
    IPPROTO_ICMP = 1
    IPPROTO_TCP = 2
    IPPROTO_UDP = 3
    IPPROTO_IPV6 = 41
}
```

**Description:**

IP protocols (used as `protocol` argument to [socket()](sl-wisun-socket-api#socket) and as `level` argument to [setsockopt()](sl-wisun-socket-api#setsockopt)/getsockopt() for protocol-level options).

**Enumerator:**

|   |   |
|---|---|
|IPPROTO_IP|Dummy protocol.|
|IPPROTO_ICMP|Internet Control Message Protocol.|
|IPPROTO_TCP|Transmission Control Protocol.|
|IPPROTO_UDP|User Datagram Protocol.|
|IPPROTO_IPV6|IPv6 socket option level.|

###### socket_type

```
enum socket_type {
    SOCK_INVALID = 0
    SOCK_STREAM = 1
    SOCK_DGRAM = 2
    SOCK_RAW = 3
}
```

**Description:**

Socket types.

**Enumerator:**

|   |   |
|---|---|
|SOCK_INVALID|invalid socket type|
|SOCK_STREAM|stream (connection) socket (TCP)|
|SOCK_DGRAM|datagram (connectionless) socket (UDP)|
|SOCK_RAW|raw socket|

##### Typedefs

###### cmsghdr_t

`typedef struct cmsghdr cmsghdr_t`

**Description:**

Control messages.

###### in6_addr_t

`typedef struct in6_addr in6_addr_t`

**Description:**

IPv6 Internet address.

###### in6_pktinfo_t

`typedef struct in6_pktinfo in6_pktinfo_t`

**Description:**

Structure to store the IPv6 packet information.

###### in_port_t

`typedef uint16_t in_port_t`

**Description:**

Transport layer port.

###### iovec_t

`typedef struct iovec iovec_t`

**Description:**

Structure to store scatter/gather array elements.

###### ip6_mtuinfo_t

`typedef struct ip6_mtuinfo ip6_mtuinfo_t`

**Description:**

Structure to store the IPv6 MTU (Maximum Transmission Unit) information.

###### ipv6_mreq_t

`typedef struct ipv6_mreq ipv6_mreq_t`

**Description:**

Structure to specify the multicast group and the interface.

###### msghdr_t

`typedef struct msghdr msghdr_t`

**Description:**

The msghdr structure is used by the [recvmsg()](sl-wisun-socket-api#recvmsg) and [sendmsg()](sl-wisun-socket-api#sendmsg) functions.

###### sa_family_t

`typedef uint32_t sa_family_t`

**Description:**

Address family.

###### sl_socket_domain_t

`typedef enum socket_domain sl_socket_domain_t`

**Description:**

Supported address families.

###### sl_socket_protocol_t

`typedef enum socket_protocol sl_socket_protocol_t`

**Description:**

IP protocols (used as `protocol` argument to [socket()](sl-wisun-socket-api#socket) and as `level` argument to [setsockopt()](sl-wisun-socket-api#setsockopt)/getsockopt() for protocol-level options).

###### sl_socket_type_t

`typedef enum socket_type sl_socket_type_t`

**Description:**

Socket types.

###### sl_wisun_socket_id_t

`typedef int sl_wisun_socket_id_t`

**Description:**

Socket id.

###### sockaddr_in6_t

`typedef struct sockaddr_in6 sockaddr_in6_t`

**Description:**

IPv6 address format.

###### socklen_t

`typedef uint32_t socklen_t`

**Description:**

Socket address length type definition.

##### Variables

###### in6addr_any

```
const in6_addr_t in6addr_any
```

**Description:** IPv6 wildcard address.

##### Functions

###### accept

`int accept(int sockid, struct sockaddr *addr, socklen_t *addrlen)`

**Description:** Accept a connection on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket descriptor|
|struct [sockaddr](sockaddr) *|[inout]|addr|A pointer to sockaddr structure filled in with the address of the peer (remote) socket. When addr is NULL, nothing is filled in; in this case, addrlen is not used, and should also be NULL.|
|[socklen_t](sl-wisun-socket-api#socklen-t) *|[inout]|addrlen|The caller must initialize it to contain the size (in bytes) of the structure pointed to by addr. On return it will contain the actual size of the peer address.|

**Returns**

- The socket id of the accepted socket on success, -1 if an error occurred.

Used with connection-based socket types (TCP). It extracts the first connection request on the queue of pending connections for the listening socket. 

###### bind

`int bind(int sockid, const struct sockaddr *addr, socklen_t addrlen)`

**Description:** Bind a name to a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket id|
|const struct [sockaddr](sockaddr) *|[in]|addr|address structure ptr|
|[socklen_t](sl-wisun-socket-api#socklen-t)|[in]|addrlen|address structure size|

**Returns**

- 0 on success, -1 on failure.

Assigns the address to the socket, referred to by the socket ID, as specified by addr. It is normally necessary to assign a local address using [bind()](sl-wisun-socket-api#bind) before a [SOCK_STREAM](sl-wisun-socket-api#sock-stream) socket may receive connections. 

###### close

`int close(int sockid)`

**Description:** Close a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket id|

**Returns**

- 0 on success, -1 on failure.

Close a socket and remove from the socket handler storage. 

###### connect

`int connect(int sockid, const struct sockaddr *addr, socklen_t addrlen)`

**Description:** Initiate a connection on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket descriptor.|
|const struct [sockaddr](sockaddr) *|[in]|addr|If the socket sockid is of type [SOCK_DGRAM](sl-wisun-socket-api#sock-dgram), addr is the address to which datagrams are sent by default and the only address from which datagrams are received. If the socket is of type [SOCK_STREAM](sl-wisun-socket-api#sock-stream), this call attempts to make a connection to the socket that is bound to the address specified by addr.|
|[socklen_t](sl-wisun-socket-api#socklen-t)|[in]|addrlen|length of the supplied sockaddr structure.|

**Returns**

- 0 on connection or binding success, -1 if an error occurred.

Connects the socket referred to by the sockid to the address specified by address. 

###### getpeername

`int getpeername(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len)`

**Description:** Get the address of the peer connected to the socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|socket|The socket file descriptor.|
|struct [sockaddr](sockaddr) *restrict|[out]|address|A pointer to a sockaddr structure where the peer's address will be stored.|
|[socklen_t](sl-wisun-socket-api#socklen-t) *restrict|[inout]|address_len|A pointer to a socklen_t variable that specifies the size of the 'address' structure.|

This function retrieves the address of the peer connected to the specified socket. The peer's address is stored in the provided 'address' structure, and the length of the address is stored in 'address_len'.

**Returns**

- 0 on success, -1 on failure and sets `errno` appropriately.

###### getsockname

`int getsockname(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len)`

**Description:** Retrieves the local address of a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|socket|The socket descriptor.|
|struct [sockaddr](sockaddr) *restrict|[out]|address|A pointer to a `struct sockaddr` where the local address information will be stored.|
|[socklen_t](sl-wisun-socket-api#socklen-t) *restrict|[inout]|address_len|A pointer to a `socklen_t` variable that specifies the size of the `address` structure. Upon successful completion, it contains the actual size of the address data.|

**Returns**

- On success, returns zero. On failure, returns -1 and sets `errno` appropriately.

This function retrieves the local address associated with a socket. It populates the provided `address` structure with the local address information. 

###### getsockopt

`int getsockopt(int sockid, int level, int optname, void *optval, socklen_t *optlen)`

**Description:** Get socket option.

**Parameters:**

<table>
  <thead>
    <th>Type</th>
    <th>Direction</th>
    <th>Argument Name</th>
    <th>Description</th>
  </thead>
  <tbody>
    <tr>
      <td>int</td>
      <td>[in]</td>
      <td>sockid</td>
      <td>socket descriptor.</td>
    </tr>
    <tr>
      <td>int</td>
      <td>[in]</td>
      <td>level</td>
      <td>socket protocol level.</td>
    </tr>
    <tr>
      <td>int</td>
      <td>[in]</td>
      <td>optname</td>
      <td>Option name. Supported options:

- for [SOL_SOCKET](sl-wisun-socket-api#sol-socket) level:  
  - [SO_RCVBUF](sl-wisun-socket-api#so-rcvbuf)  
  - [SO_SNDBUF](sl-wisun-socket-api#so-sndbuf)  
  - [SO_SNDLOWAT](sl-wisun-socket-api#so-sndlowat)
- for [IPPROTO_IPV6](sl-wisun-socket-api#ipproto-ipv6) level:  
  - [IPV6_UNICAST_HOPS](sl-wisun-socket-api#ipv6-unicast-hops)  
  - [IPV6_MULTICAST_HOPS](sl-wisun-socket-api#ipv6-multicast-hops)</td>
    </tr>
    <tr>
      <td>void *</td>
      <td>[out]</td>
      <td>optval</td>
      <td>option value structure pointer.</td>
    </tr>
    <tr>
      <td>[socklen_t](sl-wisun-socket-api#socklen-t) *</td>
      <td>[in]</td>
      <td>optlen</td>
      <td>size of the option value structure.</td>
    </tr>
  </tbody>
</table>

**Returns**

- 0 on success, -1 if an error occurred.

The function gets socket option by optname, and copies option data to optval ptr. 

###### listen

`int listen(int sockid, int backlog)`

**Description:** Listen for connections on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket id|
|int|[in]|backlog|Argument defines the maximum length to which the queue of pending connections for sockid may grow. Not implemented for Wi-SUN, the connection queue size is always 1|

**Returns**

- 0 on success, -1 if an error occurred.

Marks the socket referred to by sockid as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept. 

###### recv

`ssize_t recv(int sockid, void *buf, size_t len, int flags)`

**Description:** Receive a message from a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|descriptor of socket to receive the message from.|
|void *|[out]|buf|pointer to destination data buffer.|
|size_t|[in]|len|length of destination data buffer.|
|int|[in]|flags|flags to select type of message reception. Ignored in our implementation.|

**Returns**

- The number of bytes received on success, -1 if an error occurred.

Should be used for connection-oriented protocol (TCP) 

###### recvfrom

`ssize_t recvfrom(int sockid, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)`

**Description:** Receive messages from a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|descriptor of socket to receive the message from.|
|void *|[out]|buf|pointer to destination data buffer.|
|size_t|[in]|len|length of destination data buffer.|
|int|[in]|flags|flags to select type of message reception. Ignored in our implementation.|
|struct [sockaddr](sockaddr) *|[in]|src_addr|pointer to a sockaddr structure in which the sending address is to be stored.|
|[socklen_t](sl-wisun-socket-api#socklen-t) *|[in]|addrlen|length of the supplied sockaddr structure.|

**Returns**

- The number of bytes received on success, -1 if an error occurred.

Receives data on a socket whether or not it is connection-oriented. 

###### recvmsg

`ssize_t recvmsg(int socket, struct msghdr *message, int flags)`

**Description:** Receive a message from a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|socket|Specifies the socket file descriptor.|
|struct [msghdr](msghdr) *|[inout]|message|Points to a msghdr structure, containing both the buffer to store the source address and the buffers for the incoming message.|
|int|[in]|flags|Specifies the type of message reception.|

**Returns**

- The number of bytes received on success, -1 if an error occurred.

This function is typically used with connectionless-mode sockets because it permits the application to retrieve the source address of received data. 

###### send

`ssize_t send(int sockid, const void *buff, size_t len, int flags)`

**Description:** Send a message on a socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket descriptor.|
|const void *|[in]|buff|pointer to data buffer to send.|
|size_t|[in]|len|length of data buffer to send.|
|int|[in]|flags|flags to select send options. Ignored in our implementation.|

**Returns**

- The number of bytes sent on success, -1 if an error occurred.

Preferred with connection-oriented sockets (TCP). 

###### sendmsg

`ssize_t sendmsg(int socket, const struct msghdr *message, int flags)`

**Description:** Send a message through a connection-mode or connectionless-mode socket.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|socket|Specifies the socket file descriptor.|
|const struct [msghdr](msghdr) *|[in]|message|Points to a msghdr structure, containing both the destination address and the buffers for the outgoing message.|
|int|[in]|flags|Specifies the type of message transmission.|

**Returns**

- The number of bytes received on success, -1 if an error occurred.

###### sendto

`ssize_t sendto(int sockid, const void *buff, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addr_len)`

**Description:** Send a message to a given address.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|sockid|socket descriptor.|
|const void *|[in]|buff|pointer to data buffer to send.|
|size_t|[in]|len|length of data buffer to send.|
|int|[in]|flags|flags to select send options. Ignored in our implementation.|
|const struct [sockaddr](sockaddr) *|[in]|dest_addr|pointer to destination address buffer; Required for datagram sockets.|
|[socklen_t](sl-wisun-socket-api#socklen-t)|[in]|addr_len|length of destination address buffer.|

**Returns**

- The number of bytes sent on success, -1 if an error occurred.

Preferred in datagram mode (UDP). 

###### setsockopt

`int setsockopt(int sockid, int level, int optname, const void *optval, socklen_t optlen)`

**Description:** Set socket option designated by optname at a given protocol level to the value pointed by optval.

**Parameters:**

<table>
  <thead>
    <th>Type</th>
    <th>Direction</th>
    <th>Argument Name</th>
    <th>Description</th>
  </thead>
  <tbody>
    <tr>
      <td>int</td>
      <td>[in]</td>
      <td>sockid</td>
      <td>socket ID</td>
    </tr>
    <tr>
      <td>int</td>
      <td>[in]</td>
      <td>level</td>
      <td>protocol level at which the option resides. it could be:

- [SOL_SOCKET](sl-wisun-socket-api#sol-socket)
- [IPPROTO_IPV6](sl-wisun-socket-api#ipproto-ipv6)
- [SOL_APPLICATION](sl-wisun-socket-api#sol-application)</td>
    </tr>
    <tr>
      <td>int</td>
      <td>[in]</td>
      <td>optname</td>
      <td>option name. it could be:

- for [SOL_SOCKET](sl-wisun-socket-api#sol-socket) level:  
  - [SO_RCVBUF](sl-wisun-socket-api#so-rcvbuf)  
  - [SO_SNDBUF](sl-wisun-socket-api#so-sndbuf)  
  - [SO_SNDLOWAT](sl-wisun-socket-api#so-sndlowat)
- for [IPPROTO_IPV6](sl-wisun-socket-api#ipproto-ipv6) level:  
  - [IPV6_UNICAST_HOPS](sl-wisun-socket-api#ipv6-unicast-hops)  
  - [IPV6_MULTICAST_HOPS](sl-wisun-socket-api#ipv6-multicast-hops)  
  - [IPV6_JOIN_GROUP](sl-wisun-socket-api#ipv6-join-group)  
  - [IPV6_LEAVE_GROUP](sl-wisun-socket-api#ipv6-leave-group)  
  - [SO_EDFE_MODE](sl-wisun-socket-api#so-edfe-mode)
- for [SOL_APPLICATION](sl-wisun-socket-api#sol-application):  
  - [SO_EVENT_MODE](sl-wisun-socket-api#so-event-mode)  
  - [SO_NONBLOCK](sl-wisun-socket-api#so-nonblock)</td>
    </tr>
    <tr>
      <td>const void *</td>
      <td>[in]</td>
      <td>optval</td>
      <td>Pointer to the socket option new value. The type of variable pointed by optval depends level and optname values.</td>
    </tr>
    <tr>
      <td>[socklen_t](sl-wisun-socket-api#socklen-t)</td>
      <td>[in]</td>
      <td>optlen</td>
      <td>Must be the size of the symbol pointed by optval.</td>
    </tr>
  </tbody>
</table>

**Returns**

- 0 on success, -1 if an error occurred.

This function can set socket properties. 

###### socket

`int socket(int domain, int type, int protocol)`

**Description:** Create an endpoint for communication and returns an Id that refers to that endpoint.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|domain|Specifies a communication domain. It selects the protocol family which will be used for communication. Must be set to AF_INET6 (IPv6 network socket)|
|int|[in]|type|The communication semantics It can be:<br/><br/>- [SOCK_STREAM](sl-wisun-socket-api#sock-stream) - TCP stream socket type<br/>- [SOCK_DGRAM](sl-wisun-socket-api#sock-dgram) - UDP datagram socket type<br/>- [SOCK_RAW](sl-wisun-socket-api#sock-raw) - Raw Socket type (ICMP)|
|int|[in]|protocol|Specifies the particular protocol to be used. It can be:<br/><br/>- [IPPROTO_ICMP](sl-wisun-socket-api#ipproto-icmp) - Ping<br/>- [IPPROTO_IP](sl-wisun-socket-api#ipproto-ip) and IPPROTO_TCP - TCP stream sockets<br/>- [IPPROTO_IP](sl-wisun-socket-api#ipproto-ip) and IPPROTO_UDP - UDP datagram sockets|

**Returns**

- The socket's id on success, (-1) on failure.

##### Macros

`#define APP_LEVEL_SOCKET SOL_APPLICATION`

**Description**: For backward compatibility.

`#define IN6ADDR_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }`

**Description**: Initialization value for IPv6 wildcard address.

`#define INET6_ADDRSTRLEN 46`

**Description**: Length of the string form for IPv6.

`#define IPV6_ADDR_SIZE 16`

**Description**: Size of an IPv6 address.

`#define SOCK_NONBLOCK 0X00010000`

**Description**: When bitwise ored with socket's type, it sets the O_NONBLOCK status flag on the opened socket file description.

Control messages. 

###### Public Attributes

###### cmsg_len (heading level 7)

```
socklen_t cmsghdr::cmsg_len
```

**Description:** Message length in bytes, including this header.

###### cmsg_level (heading level 7)

```
int cmsghdr::cmsg_level
```

**Description:** originating protocol

###### cmsg_type (heading level 7)

```
int cmsghdr::cmsg_type
```

**Description:** protocol-specific type

IPv6 Internet address. 

###### Public Attributes

###### address (heading level 7)

```
uint8_t in6_addr::address[IPV6_ADDR_SIZE]
```

**Description:** IPv6 address (network byte order)

Structure to store the IPv6 packet information. 

###### Public Attributes

###### ipi6_addr (heading level 7)

```
in6_addr_t in6_pktinfo::ipi6_addr
```

**Description:** src/dst IPv6 address

###### ipi6_ifindex (heading level 7)

```
int in6_pktinfo::ipi6_ifindex
```

**Description:** arrival interface index

Structure to store scatter/gather array elements. 

###### Public Attributes

###### iov_base (heading level 7)

```
void* iovec::iov_base
```

**Description:** Store the base address of a memory region for input or output.

###### iov_len (heading level 7)

```
size_t iovec::iov_len
```

**Description:** Length of the memory region iov_base points to.

Structure to store the IPv6 MTU (Maximum Transmission Unit) information. 

###### Public Attributes

###### ip6m_addr (heading level 7)

```
struct sockaddr_in6 ip6_mtuinfo::ip6m_addr
```

**Description:** IPv6 address.

###### ip6m_mtu (heading level 7)

```
uint32_t ip6_mtuinfo::ip6m_mtu
```

**Description:** MTU size.

Structure to specify the multicast group and the interface. 

###### Public Attributes

###### ipv6mr_ifindex (heading level 7)

```
int ipv6_mreq::ipv6mr_ifindex
```

**Description:** Local IPv6 address of interface.

###### ipv6mr_multiaddr (heading level 7)

```
struct in6_addr ipv6_mreq::ipv6mr_multiaddr
```

**Description:** IPv6 multicast address of group.

The msghdr structure is used by the [recvmsg()](sl-wisun-socket-api#recvmsg) and [sendmsg()](sl-wisun-socket-api#sendmsg) functions. 

###### Public Attributes

###### msg_control (heading level 7)

```
void* msghdr::msg_control
```

**Description:** ancillary data

###### msg_controllen (heading level 7)

```
socklen_t msghdr::msg_controllen
```

**Description:** ancillary data buffer length

###### msg_flags (heading level 7)

```
int msghdr::msg_flags
```

**Description:** flags on received message

###### msg_iov (heading level 7)

```
struct iovec* msghdr::msg_iov
```

**Description:** scatter/gather array

###### msg_iovlen (heading level 7)

```
int msghdr::msg_iovlen
```

**Details:** # elements in msg_iov

###### msg_name (heading level 7)

```
void* msghdr::msg_name
```

**Description:** ptr to socket address structure

###### msg_namelen (heading level 7)

```
socklen_t msghdr::msg_namelen
```

**Description:** size of socket address structure

Socket address. 

###### Public Attributes

###### sa_data (heading level 7)

```
uint8_t sockaddr::sa_data[26]
```

**Description:** 26 bytes of protocol address (IPv6)

###### sa_family (heading level 7)

```
sa_family_t sockaddr::sa_family
```

**Description:** address family, AF_XXXX

IPv6 address format. 

###### Public Attributes

###### sin6_addr (heading level 7)

```
in6_addr_t sockaddr_in6::sin6_addr
```

**Description:** IPv6 address.

###### sin6_family (heading level 7)

```
sa_family_t sockaddr_in6::sin6_family
```

**Description:** AF_INET6.

###### sin6_flowinfo (heading level 7)

```
uint32_t sockaddr_in6::sin6_flowinfo
```

**Description:** IPv6 flow information.

###### sin6_port (heading level 7)

```
in_port_t sockaddr_in6::sin6_port
```

**Description:** Transport layer port.

###### sin6_scope_id (heading level 7)

```
uint32_t sockaddr_in6::sin6_scope_id
```

**Description:** Scope ID.

#### Select API

Select API provides an implementation of [select()](sl-wisun-select-api#select) function, modeled after POSIX.1-2024 specification. 

In order to utilize the function, the application must utilize **wisun_select** component, and call the componen callbacks [sl_wisun_check_read_sockfd_set()](sl-wisun-select-api#sl-wisun-check-read-sockfd-set) an [sl_wisun_check_write_sockfd_set()](sl-wisun-select-api#sl-wisun-check-write-sockfd-set) from its event handler. 

##### Modules

[fd_set](fd-set)

##### Typedefs

###### fd_mask

`typedef long int fd_mask`

**Description:**

A type representing a set of file descriptors.

##### Functions

###### select

`int select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict timeout)`

**Description:** Monitor multiple file descriptors for readiness.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|int|[in]|nfds|The highest-numbered file descriptor in any of the three sets, plus 1.|
|[fd_set](fd-set) *restrict|[inout]|readfds|An optional pointer to a set of file descriptors to be checked for readability.|
|[fd_set](fd-set) *restrict|[inout]|writefds|An optional pointer to a set of file descriptors to be checked for writability.|
|[fd_set](fd-set) *restrict|[inout]|exceptfds|An optional pointer to a set of file descriptors to be checked for exceptions.|
|struct timeval *restrict|[in]|timeout|An optional timeout. If NULL, [select()](sl-wisun-select-api#select) blocks indefinitely. To specify a non-blocking poll, set the timeout to zero.|

**Returns**

- On success, returns the total number of bits set in readfds, writefds. If the time limit expires, [select()](sl-wisun-select-api#select) returns zero. On error, -1 is returned, and errno is set appropriately.

This function monitors multiple file descriptors, waiting until one or more of the file descriptors are ready for an I/O operation.

**Note**

- This implementation does not handle exceptfds.

###### sl_wisun_check_read_sockfd_set

`void sl_wisun_check_read_sockfd_set(void)`

**Description:** Check the read socket file descriptor set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function notifies select to check the read socket file descriptor set. The function should be called in response to the reception of [SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-available-ind-id). It notifies select to check the read socket file descriptor set for any ready socket to read.

Usage: 

```c
// Application indication handler
void sl_wisun_on_event(void) {
  // Application code here...
  switch (evt->header.id) {
    // When SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID is received
    case SL_WISUN_MSG_SOCKET_DATA_AVAILABLE_IND_ID:
      // Call the function to check the read socket file descriptor set
      sl_wisun_check_read_sockfd_set();
      break;
  }
  // Application code here...
}

```

###### sl_wisun_check_write_sockfd_set

`void sl_wisun_check_write_sockfd_set(void)`

**Description:** Check the write socket file descriptor set.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function notifies select to check the write socket file descriptor set. The function should be called in response to the reception of [SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID](sl-wisun-evt#sl-wisun-msg-socket-data-sent-ind-id). It notifies select to check the write socket file descriptor set for any ready socket to write.

Usage: 

```c
void sl_wisun_on_event(void) {
  // Your code here...
  switch (evt->header.id) {
    // When SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID is received
    case SL_WISUN_MSG_SOCKET_DATA_SENT_IND_ID:
      // Call the function to check the write socket file descriptor set
      sl_wisun_check_write_sockfd_set();
      break;
  }
  // Your code here...
}

```

###### sl_wisun_select_init

`void sl_wisun_select_init(void)`

**Description:** Initialize the select system.

**Parameters:**

|Type|Direction|Argument Name|Description|
|----|---------|-------------|-----------|
|void|N/A|undefined||

This function initializes the select system by creating a new event flag with the specified attributes. The event flag is used to indicate when a file descriptor set is ready to be checked for I/O operations. 

##### Macros

`#define FD_CLR (d, set)`

**Description**: Clear the bit for the file descriptor d in the [fd_set](fd-set).

`#define FD_ELT (d)`

**Description**: Calculate the index in the fds_bits array for the file descriptor d.

`#define FD_ISSET (d, set)`

**Description**: Check whether the bit for the file descriptor d is set in the [fd_set](fd-set).

`#define FD_MASK (d)`

**Description**: Create a mask for the bit position within an fd_mask for the file descriptor d.

`#define FD_SET (d, set)`

**Description**: Set the bit for the file descriptor d in the [fd_set](fd-set).

`#define FD_SETSIZE 64`

**Description**: Maximum number of file descriptors in ‘[fd_set](fd-set)’.

`#define FD_ZERO (set)`

**Description**: Clear all bits in the [fd_set](fd-set).

`#define NFDBITS (8 * (int) sizeof (fd_mask))`

**Description**: The number of bits in an fd_mask.

A structure representing a set of file descriptors for select operations. 

###### Public Attributes

###### fds_bits (heading level 7)

```
fd_mask fd_set::fds_bits[FD_SETSIZE/(8 *(int) sizeof(fd_mask))]
```

**Description:** An array of fd_mask, each bit representing a file descriptor.