RAIL Library#

  Silicon Labs Radio Abstraction Interface Layer (RAIL) is a library that can be used as a generic interface for all Silicon Labs radio parts. By programming against this API, you can write code that easily ports across different radio parts while having access to hardware acceleration wherever possible.

Introduction#

The RAIL library is mostly standalone with a few external dependencies. Simplicity Studio application builder is not required but is recommended because it simplifies building applications using RAIL. Depending on the hardware platform that you're using, you may be required to provide certain HAL functionality for the library to work properly. These functions are described in hardware-specific documentation sections and valid implementations can be found as a part of the provided emlib/emdrv HAL layers. It is recommended that you use these versions for maximum support, but you're free to re-implement them if necessary.

Using RAIL#

Features#

At a high level, the functionality supported by RAIL is shown below. For more specifics on the APIs and how to use them, see the module documentation.

  • General

    • Initialize the RAIL API layer.

    • Collect entropy from the radio (if available).

  • Radio Configuration

    • Configure the radio frequency, packet format, channel configuration and other PHY parameters.

    • Query current PHY data rates and parameters like current channel.

  • State Transitions

    • Configure automatic radio state transitions and transition timings.

  • Auto-Ack

    • Configure the radio for automatic acknowledgments.

    • Load the auto ACK payload.

  • System Timing

    • Get the current time in the RAIL timebase.

    • Configure a timer to trigger an event callback after an absolute or relative delay.

    • Specify where within a packet its timestamp is desired.

  • Sleep

    • Configure RAIL behavior and timekeeping for low power modes.

  • Events

    • Configure which radio or RAIL events the application wants to be told about via callback.

  • Data Management

    • Allows the application to choose the type of data and the method of data interaction through RAIL.

  • Receive

    • Configure receive options like CRC checking.

    • Start or schedule when to receive.

    • Enable and configure Address Filtering for each packet.

    • Enable and configure RX Channel Hopping for receiving packets across several channels.

  • Transmit

    • Configure the power amplifier (Power Amplifier (PA)) and set transmit power output.

    • Load and send packet data, either immediately, scheduled, or using CSMA or LBT.

    • Control per-transmit options like CRC generation, ACK waiting, etc.

  • Antenna Control

    • Configuring multi-antenna selection.

  • Multiprotocol

    • Manage time-sharing of the radio among different protocols.

  • Series 3 Scheduler

    • Control scheduled transaction requests between internal and external radio requestors.

  • Calibration

    • APIs for handling various radio calibrations for optimal performance.

  • RF Sense

    • Enable RF energy sensing of specified duration across the 2.4 GHz and/or Sub-GHz bands (supported only on certain EFR32 chips).

  • PTI Packet Trace

    • Configure Packet Trace pins and serial protocol.

    • Specify the stack protocol to aid network analyzer packet decoding.

  • Front End Module Voltage Detection

    • Configure RAIL to measure the voltage on a Front End Module during the transmit packet.

  • Assertions

    • Detecting and handling fatal runtime errors detected by RAIL.

  • Diagnostic

    • Output debug signals like an unmodulated tone and a continuously modulated stream of data.

    • Configure crystal tuning for your radio.

    • Fine-tune the radio tuner frequency.

  • Features

    • Macros to indicate which features exist on which chip families.

Protocol-specific hardware acceleration (each only on supported chips):

  • BLE

    • Configure the Bluetooth Low Energy PHYs available for your device (1 Mbps, 2 Mbps, Coded PHY).

    • Preamble, sync word and whitening adjustment function for connections.

  • IEEE 802.15.4

    • Configure the IEEE802.15.4 2.4 GHz PHY.

    • Configure node address and address filtering for IEEE 802.15.4.

    • Configure auto ACK for IEEE 802.15.4.

  • Sidewalk Radio Configurations

    • Configure 2GFSK 50 kbps Sidewalk PHY.

  • Wireless M-Bus

    • Configure simultaneous M2O RX of T and C modes feature.

  • Z-Wave

    • Configure the Z-Wave PHY appropriate for your region.

    • Configure your NodeId and HomeId for receive filtering and wakeup beam filtering.

Getting Started Example#

Below is a simple example to show you how to initialize the RAIL library in your application. Notice that this requires the channel configurations, which can be generated from the radio calculator in Simplicity Studio. By default, RAIL interacts with data on a per-packet basis. For more information, see Data Management.

_Note: Before the radio can transmit, PA power conversion tables or curves must be established for your platform, which is described in the Hardware-specific Configuration section below but in general should use the RAIL 3 Power Amplifier (PA) Utility plugin._

#include <assert.h>
#include "sl_rail.h"
#include "sl_rail_util_pa_conversions.h" // in sl_rail_util_pa plugin
#include "rail_config.h" // Generated by radio calculator

#define TX_FIFO_BYTES (128)  // Any power of 2 from [64, 4096] on the EFR32

static sl_rail_handle_t rail_handle = SL_RAIL_EFR32_HANDLE;
static sl_rail_tx_power_t tx_power_ddbm = 200; // Default to 20 dBm
static SL_RAIL_DECLARE_FIFO_BUFFER(aligned_tx_fifo, TX_FIFO_BYTES);
static uint8_t *tx_fifo = (uint8_t *)aligned_tx_fifo; // For byte access

static void radio_event_handler(sl_rail_handle_t rail_handle,
                                sl_rail_events_t events)
{
  // ... handle RAIL events, e.g., receive and transmit completion
}

// Initializes the radio out of startup so that it's ready to receive.
void radio_initialize(void)
{
  sl_rail_status_t status;
  sl_rail_config_t rail_config = {
    .events_callback = &radio_event_handler,
  //.p_opaque_handle_0 = ... // app-specific if desired
  //.p_opaque_handle_1 = ... // app-specific if desired
  //.opaque_value = ... // app-specific if desired
    .rx_packet_queue_entries = SL_RAIL_BUILTIN_RX_PACKET_QUEUE_ENTRIES,
    .rx_fifo_bytes = SL_RAIL_BUILTIN_RX_FIFO_BYTES,
    .tx_fifo_bytes = TX_FIFO_BYTES,
    .tx_fifo_init_bytes = 0U,
    .p_rx_packet_queue = sl_rail_builtin_rx_packet_queue_ptr,
    .p_rx_fifo_buffer = sl_rail_builtin_rx_fifo_ptr,
    .p_tx_fifo_buffer = aligned_tx_fifo,
  };

  sl_rail_util_pa_init(); // Establish PA conversion table(s)

  // Initialize the RAIL library and any internal state it requires.
  status = sl_rail_init(&rail_handle, &rail_config, NULL);
  assert(status == SL_RAIL_STATUS_NO_ERROR);
  // Here rail_handle has been converted to a real protocol instance handle

  // Configure calibration settings.
  status = sl_rail_config_cal(rail_handle, SL_RAIL_CAL_ALL);
  assert(status == SL_RAIL_STATUS_NO_ERROR);

  // Configure radio according to the generated radio settings.
  // channelConfigs[] comes from calculator-generated rail_config.c/.h files.
  status = sl_rail_config_channels(rail_handle, channelConfigs[0],
                                   &sl_rail_util_pa_on_channel_config_change);
  assert(status == SL_RAIL_STATUS_NO_ERROR);
  status = sl_rail_set_tx_power_dbm(rail_handle, tx_power_ddbm);
  assert(status == SL_RAIL_STATUS_NO_ERROR);

  // Configure the most useful callbacks and catch a few errors.
  status = sl_rail_config_events(rail_handle,
                                 SL_RAIL_EVENTS_ALL,
                                 (SL_RAIL_EVENT_TX_PACKET_SENT
                                  | SL_RAIL_EVENT_RX_PACKET_RECEIVED
                                  | SL_RAIL_EVENT_RX_FRAME_ERROR));
  assert(status == SL_RAIL_STATUS_NO_ERROR);

  // Set automatic transitions to always receive once started.
  sl_rail_state_transitions_t state_transitions = {
    .success = SL_RAIL_RF_STATE_RX,
    .error   = SL_RAIL_RF_STATE_RX,
  };
  status = sl_rail_set_rx_transitions(rail_handle, &state_transitions);
  assert(status == SL_RAIL_STATUS_NO_ERROR);
  status = sl_rail_set_tx_transitions(rail_handle, &state_transitions);
  assert(status == SL_RAIL_STATUS_NO_ERROR);
}

Hardware-Specific Configuration#

For hardware-specific configuration and setup information, see subsequent sections.

EFR32