RAIL is short for Radio Abstraction Interface Layer, and is the most direct interface available for EFR32 radios. You can think of it as a radio driver. While this sounds like a restriction, this actually makes software development for proprietary wireless much simpler:
EFR32 has a very flexible radio, which also makes it quite complex. RAIL (and the radio configurator) provides an easy-to-use interface of EFR32's features.
The various generations of the different EFR32s are slightly different, but the RAIL API is the same (except maybe the chip specific updates), which makes hardware updates almost seamless.
We plan to add RAIL support to all of our future radio MCUs.
RAIL application development is currently possible in the Flex SDK in Simplicity Studio. To progress further with this tutorial, please remember to open the RAIL API documentation.
When to Use RAIL?
If you have an existing protocol, and you must be compatible with it, you'd probably have to use RAIL (as all of our stacks use a standardized frame format). If you want to use sub-GHz communication, you can use RAIL or Connect (and Z-Wave, in the near future), but for simple point to point communication, it's probably simpler to use RAIL.
What is covered by RAIL?
RAIL only supports what the radio hardware supports. For example, auto ACK and address filter is available, but FHSS is not. It can be written quite easily in application, but we (currently) have no hardware acceleration for it. While security is important for wireless communication, it's also not a task for RAIL. The crypto engine is an independent peripheral that can be used to encrypt payloads before giving them to RAIL and the radio hardware.
RAIL Dependencies
To link the RAIL library, you'll need the following emlibs:
em_cmu.c
em_core.c
em_sytem.c
em_emu.c (not a direct requirement but a requirement for em_cmu.c)
Before initializing RAIL, you have to initialize a few things first:
DCDC converter should be initialized for the hardware
HFXO clock should be running and should be used as the main oscillator
RAIL's timer can be set up to work seamlessly in EM2, even though it uses the HFPER clock tree. For that, you'll also need the following:
LFRCO or LFXO running
PRS clock running, PRS channel 7 left unused
On EFR32xG1 and EFR32xG12, RTCC running, and compare channel 0 left unused
Supported Energy Modes
EM1 or higher is required for the radio to be operational (i.e., Transmitting, receiving, or waiting for packets).
EM2 or higher is required for RAIL scheduling or timers (This needs configuration, a topic in Tutorial 5).
EM3 or higher is required for RAIL to work without re-initialization.
Writing Code from Scratch
We do not recommend writing code from scratch because it is much simpler to have something existing that sets up the include paths and linker settings correctly. The best way to start is the example Simple RAIL with HAL. In the next chapter, we'll go through the init code of that project.
RAIL Initialization
RAIL requires some peripherals to work. The simplest way to set them up is to use the RAIL-hal plugin, and call halInit(). If you don't want to use the RAIL-hal plugin, see how the Simple RAIL without HAL example initializes the peripherals.
This will initialize RAIL, set up the railHandle to be used in almost all APIs and configures the event handler function. Note that railCfg is not allocated in stack: It has a member (RAIL_StateBuffer_t buffer) that's used by RAIL to store state variables.
Once RAIL is running, we'll load the configuration we generated: RAIL_ConfigChannels(railHandle, channelConfigs[0], NULL);
Finally, we set up the PA (Power Amplifier, required for transmissions):
RAIL_TxPowerConfig_t txPowerConfig = {
#if HAL_PA_2P4_LOWPOWER
.mode = RAIL_TX_POWER_MODE_2P4_LP,
#else
.mode = RAIL_TX_POWER_MODE_2P4_HP,
#endif
.voltage = BSP_PA_VOLTAGE,
.rampTime = HAL_PA_RAMP,
};
if (channelConfigs[0]->configs[0].baseFrequency < 1000000000UL) {
// Use the Sub-GHz PA if required
txPowerConfig.mode = RAIL_TX_POWER_MODE_SUBGIG;
}
RAIL_ConfigTxPower(railHandle, &txPowerConfig);
RAIL_SetTxPower(railHandle, HAL_PA_POWER);
Note the BSP_ and HAL_ macros: those are generated by the Hardware Configurator (see AN1115 for details). Also, there are simpler ways to select the mode (i.e., you don't have to check the configuration if you only ever need the Sub-GHz mode).
Actually, there are only 2 API calls to be noticed above after a long preparation:
The first configures the PA, the second sets up the output power of the device.
The project also enables calibrations, however, it's a bit more difficult to use them, so we'll return to that topic in its own tutorial.
Conclusion
This project is ready to send out frames. We're going to do that in the next part. You can also find other tutorials from the table of content site.
Please remember to check out the Silicon Labs RAIL API Reference Guide in Studio, for a detailed description on the functions and types discussed in this chapter!
RAIL Tutorial 1: Introduction and Initialization
What is RAIL?
RAIL is short for Radio Abstraction Interface Layer, and is the most direct interface available for EFR32 radios. You can think of it as a radio driver. While this sounds like a restriction, this actually makes software development for proprietary wireless much simpler:
See this KBA for more details.
RAIL application development is currently possible in the Flex SDK in Simplicity Studio. To progress further with this tutorial, please remember to open the RAIL API documentation.
When to Use RAIL?
If you have an existing protocol, and you must be compatible with it, you'd probably have to use RAIL (as all of our stacks use a standardized frame format). If you want to use sub-GHz communication, you can use RAIL or Connect (and Z-Wave, in the near future), but for simple point to point communication, it's probably simpler to use RAIL.
What is covered by RAIL?
RAIL only supports what the radio hardware supports. For example, auto ACK and address filter is available, but FHSS is not. It can be written quite easily in application, but we (currently) have no hardware acceleration for it. While security is important for wireless communication, it's also not a task for RAIL. The crypto engine is an independent peripheral that can be used to encrypt payloads before giving them to RAIL and the radio hardware.
RAIL Dependencies
To link the RAIL library, you'll need the following emlibs:
Before initializing RAIL, you have to initialize a few things first:
RAIL's timer can be set up to work seamlessly in EM2, even though it uses the HFPER clock tree. For that, you'll also need the following:
Supported Energy Modes
EM1 or higher is required for the radio to be operational (i.e., Transmitting, receiving, or waiting for packets).
EM2 or higher is required for RAIL scheduling or timers (This needs configuration, a topic in Tutorial 5).
EM3 or higher is required for RAIL to work without re-initialization.
Writing Code from Scratch
We do not recommend writing code from scratch because it is much simpler to have something existing that sets up the include paths and linker settings correctly. The best way to start is the example Simple RAIL with HAL. In the next chapter, we'll go through the init code of that project.
RAIL Initialization
RAIL requires some peripherals to work. The simplest way to set them up is to use the RAIL-hal plugin, and call
halInit()
. If you don't want to use the RAIL-hal plugin, see how the Simple RAIL without HAL example initializes the peripherals.Next, we'll need to initialize RAIL:
This will initialize RAIL, set up the
railHandle
to be used in almost all APIs and configures the event handler function. Note thatrailCfg
is not allocated in stack: It has a member (RAIL_StateBuffer_t buffer
) that's used by RAIL to store state variables.Once RAIL is running, we'll load the configuration we generated:
RAIL_ConfigChannels(railHandle, channelConfigs[0], NULL);
Finally, we set up the PA (Power Amplifier, required for transmissions):
Note the BSP_ and HAL_ macros: those are generated by the Hardware Configurator (see AN1115 for details). Also, there are simpler ways to select the mode (i.e., you don't have to check the configuration if you only ever need the Sub-GHz mode).
Actually, there are only 2 API calls to be noticed above after a long preparation:
The first configures the PA, the second sets up the output power of the device.
The project also enables calibrations, however, it's a bit more difficult to use them, so we'll return to that topic in its own tutorial.
Conclusion
This project is ready to send out frames. We're going to do that in the next part. You can also find other tutorials from the table of content site.
Please remember to check out the Silicon Labs RAIL API Reference Guide in Studio, for a detailed description on the functions and types discussed in this chapter!
API Introduced in this Tutorial
Functions
Types and enums
Update on 11/27/2018: