Porting LoRaWAN stack and LoRa RF drivers
Mbed OS contains a native LoRaWAN stack (inside the Mbed OS tree) augmented with most commonly used LoRa RF drivers (outside the Mbed OS tree). Arm encourages developers around the globe to contribute to any of the Mbed OS features and functionality, including the LoRaWAN stack and related RF drivers using the general guidelines provided.
The information in this section can be classified in two subsections:
- Porting a LoRa RF driver for the Arm Mbed LoRaWAN stack or any other LoRaWAN stack.
- Porting a third party LoRaWAN stack to Mbed OS .
The idea is to achieve universal application portability. In other words, a single application is compatible with the Arm Mbed LoRaWAN stack and any other third party LoRaWAN stack harnessing Arm Mbed OS.
The whole porting process consists of two key ingredients:
Porting a LoRa RF driver
Arm Mbed OS provides a generic API that serves as a template for any LoRa RF driver. LoRaRadio is a pure virtual class and is an attempt to standardize the APIs across all LoRa radios. Mbed Enabled LoRa radio driver implementations present as a LoRaRadio.
Figure 1. Existing Mbed LoRa RF drivers inherit from the LoRaRadio class.
For a reference implementation, please see the existing LoRa RF drivers. Construction of a LoRaRadio object is a matter of taste. The existing reference drivers allow construction of the LoRaRadio object with full pin definitions to make sure that the driver is usable across platforms with any pin combination. You are free to use any form of construction as long as you provide a LoRaRadio object down to the Arm Mbed LoRaWAN stack. Use of an instance of the
LoRaRadio class for a third party LoRaWAN stack is beyond the scope of this documentation.
For API use cases, details, explanation and meaning, please see the
LoRaRadio class reference below. We carefully planned and designed the data structures provided in LoRaRadio.h. They carry most of what you need to write your LoRa RF driver.
|Public Member Functions|
|virtual void||init_radio (radio_events_t *events)=0|
|Registers radio events with the Mbed LoRaWAN stack and undergoes initialization steps, if any. More...|
|virtual void||radio_reset ()=0|
|Resets the radio module. More...|
|virtual void||sleep (void)=0|
|Put the RF module in sleep mode. More...|
|virtual void||standby (void)=0|
|Sets the radio to standby mode. More...|
|virtual void||set_rx_config (radio_modems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidth_afc, uint16_t preamble_len, uint16_t symb_timeout, bool fix_len, uint8_t payload_len, bool crc_on, bool freq_hop_on, uint8_t hop_period, bool iq_inverted, bool rx_continuous)=0|
|Sets reception parameters. More...|
|virtual void||set_tx_config (radio_modems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preamble_len, bool fix_len, bool crc_on, bool freq_hop_on, uint8_t hop_period, bool iq_inverted, uint32_t timeout)=0|
|Sets the transmission parameters. More...|
|virtual void||send (uint8_t *buffer, uint8_t size)=0|
|Sends the packet. More...|
|virtual void||receive (void)=0|
|Sets the radio to reception mode. More...|
|virtual void||set_channel (uint32_t freq)=0|
|Sets the carrier frequency. More...|
|virtual uint32_t||random (void)=0|
|Generates a 32 bit random value based on RSSI readings. More...|
|virtual uint8_t||get_status (void)=0|
|Gets the radio status. More...|
|virtual void||set_max_payload_length (radio_modems_t modem, uint8_t max)=0|
|Sets the maximum payload length. More...|
|virtual void||set_public_network (bool enable)=0|
|Sets the network to public or private. More...|
|virtual uint32_t||time_on_air (radio_modems_t modem, uint8_t pkt_len)=0|
|Computes the packet time on air for the given payload. More...|
|virtual bool||perform_carrier_sense (radio_modems_t modem, uint32_t freq, int16_t rssi_threshold, uint32_t max_carrier_sense_time)=0|
|Performs carrier sensing. More...|
|virtual void||start_cad (void)=0|
|Sets the radio to CAD mode. More...|
|virtual bool||check_rf_frequency (uint32_t frequency)=0|
|Checks whether the given RF is in range. More...|
|virtual void||set_tx_continuous_wave (uint32_t freq, int8_t power, uint16_t time)=0|
|Sets the radio to continuous wave transmission mode. More...|
|virtual void||lock (void)=0|
|Acquires exclusive access to this radio. More...|
|virtual void||unlock (void)=0|
|Releases exclusive access to this radio. More...|
Porting a third party LoRaWANStack
The vision driving Arm Mbed OS entails one operating system for myriad IoT technologies encompassing a multitude of devices or platforms. However, it does not limit the user to design something specific or tailored to his or her needs. We designed Arm Mbed LoRaWAN APIs in such a way that a developer can totally replace the native Mbed OS LoRaWAN stack with one of his or her own.
This subsection discusses how a third party LoRaWAN stack can seamlessly provide services to existing Mbed OS LoRaWAN applications or can reuse applications with minimal effort in terms of code.
Note: The way a third party LoRaWAN stack harnesses the powers of Arm Mbed OS, in other words, synchronization methods (if using RTOS), timers, HAL and so on is beyond the scope of this documentation.
The LoRaWANBase class is a pure virtual class providing user facing APIs for a LoRaWAN stack.
The native Arm Mbed LoRaWAN stack implements
LoRaWANBase as LoRaWANInterface, which then serves as a network interface for the application. Potentially, any developer or vendor can provide an implementation of
LoRaWANBase, and that particular implementation would serve as a network interface for the application.
Figure 2. Inheriting from LoRaWANBase to provide portable APIs.
There can be many different scenarios when it comes to devices supporting LoRaWAN technology:
Case 1: Design based on a LoRa chipset
This design pattern follows the generic architecture with the LoRa radio part based on the LoRa transceiver and antenna plus associated RF circuitry from any vendor. The developer chooses only the LoRa radio chipset and the LoRaWAN stack, and the application runs on the MCU. In this case, you can use any Mbed compatible LoRaWAN stack, in other words, the native Mbed OS LoRaWAN stack or your ported LoRaWAN stack.
Figure 3. Design based on LoRa RF chipset.
Case 2: Design based on a LoRa module
A LoRa module means that the LoRa transceiver and an MCU are bound together (not in the same silicon package). This can be considered as a unit with all the connections between radio and MCU, plus antenna and other RF circuitry the vendor has already taken care of for the developer. For a developer, it means a board that contains a target MCU and RF transceiver integrated on the board (not on a chip). Arm Mbed OS provides the LoRaWAN stack and application, and the developer can modify the example application for his or her needs.
Case 3: Design based on a LoRa RF-MCU
An RF-MCU is an SoC including an MCU and LoRa transceiver on the same silicon package. From a developer’s point of view, this design is identical to a module-based design described in Case 2.
Figure 4. Design based on LoRa module (both as integrated on board and on chip).
Case 4: Design based on a LoRa modem
A LoRa modem is a component that contains a stack and RF circuitry as a full package, mostly wired to a host MCU. In this case, if the developer wishes to be compliant with the existing applications, he or she may choose to write an adapter layer, which should be an implementation of
LoRaWANBase and under the hood it could be AT commands to control the modem.
Figure 5. Design based on LoRa modem.
Please follow the detailed reference of
LoRaWANBase to understand what these APIs and related data structures mean and why are they designed in this way.
You must implement the
initialize(events::EventQueue *queue) API. Our design philosophy is that we wish to support the tiniest of devices with very little memory, and an event queue shared between the application and network stack is the best option in terms of memory.
|Public Member Functions|
|virtual lorawan_status_t||initialize (events::EventQueue *queue)=0|
|Initialize the LoRa stack. More...|
|virtual lorawan_status_t||connect ()=0|
|Connect OTAA or ABP using the Mbed OS config system. More...|
|virtual lorawan_status_t||connect (const lorawan_connect_t &connect)=0|
|Connect OTAA or ABP with parameters. More...|
|virtual lorawan_status_t||disconnect ()=0|
|Disconnect the current session. More...|
|virtual lorawan_status_t||add_link_check_request ()=0|
|Validate the connectivity with the network. More...|
|virtual void||remove_link_check_request ()=0|
|Removes link check request sticky MAC command. More...|
|virtual lorawan_status_t||set_datarate (uint8_t data_rate)=0|
|Sets up a particular data rate. More...|
|virtual lorawan_status_t||enable_adaptive_datarate ()=0|
|Enables adaptive data rate (ADR) More...|
|virtual lorawan_status_t||disable_adaptive_datarate ()=0|
|Disables adaptive data rate. More...|
|virtual lorawan_status_t||set_confirmed_msg_retries (uint8_t count)=0|
|Sets up the retry counter for confirmed messages. More...|
|virtual lorawan_status_t||set_channel_plan (const lorawan_channelplan_t &channel_plan)=0|
|Sets the channel plan. More...|
|virtual lorawan_status_t||get_channel_plan (lorawan_channelplan_t &channel_plan)=0|
|Gets the channel plans from the LoRa stack. More...|
|virtual lorawan_status_t||remove_channel_plan ()=0|
|Removes an active channel plan. More...|
|virtual lorawan_status_t||remove_channel (uint8_t index)=0|
|Removes a single channel. More...|
|virtual int16_t||send (uint8_t port, const uint8_t *data, uint16_t length, int flags)=0|
|Send message to gateway. More...|
|virtual int16_t||receive (uint8_t port, uint8_t *data, uint16_t length, int flags)=0|
|Receives a message from the Network Server on a specific port. More...|
|virtual int16_t||receive (uint8_t *data, uint16_t length, uint8_t &port, int &flags)=0|
|Receives a message from the Network Server on any port. More...|
|virtual lorawan_status_t||add_app_callbacks (lorawan_app_callbacks_t *callbacks)=0|
|Add application callbacks to the stack. More...|
|virtual lorawan_status_t||set_device_class (device_class_t device_class)=0|
|Change device class. More...|
|virtual lorawan_status_t||get_tx_metadata (lorawan_tx_metadata &metadata)=0|
|Get hold of TX meta-data. More...|
|virtual lorawan_status_t||get_rx_metadata (lorawan_rx_metadata &metadata)=0|
|Get hold of RX meta-data. More...|
|virtual lorawan_status_t||get_backoff_metadata (int &backoff)=0|
|Get hold of backoff time. More...|
|virtual lorawan_status_t||cancel_sending (void)=0|
|Cancel outgoing transmission. More...|
Note: We'll publish automated tests for LoRa soon. For Mbed Partners that want to start porting Lora drivers, please contact your Partner lead.