Semtech LoRaMAC implementation

Provides a RIOT adaption of Semtech LoRaMAC implementation. More...

Detailed Description

Provides a RIOT adaption of Semtech LoRaMAC implementation.


This package provides an API built on top of the Semtech LoRaMAC-node reference implementation of a LoRa network.

Importing this package in an application

This package only works with Semtech SX1272 and SX1276 radio devices. Thus, in order to use it properly, the application Makefile must import the corresponding device driver:

USEMODULE += sx1272 # for a SX1272 radio device
USEMODULE += sx1276 # for a SX1276 radio device

In order to use this package in an application, add the following in the application Makefile:

USEPKG += semtech-loramac

Since the LoRa radio depends on regional parameters regarding the access to the physical support, the region where the device is used needs to be set at compile time. Example for EU868:


Using the package API

The package provides a simple API for initializing the MAC, setting/getting parameters, joining a network and sending/receiving packets to/from a LoRa Network.

In your main.c, some header files must be first included:

#include "net/loramac.h" /* core loramac definitions */
#include "semtech_loramac.h" /* package API */

Then define global variables:

semtech_loramac_t loramac; /* The loramac stack device descriptor */
/* define the required keys for OTAA, e.g over-the-air activation (the
null arrays need to be updated with valid LoRa values) */
static const uint8_t deveui[LORAMAC_DEVEUI_LEN] = { 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00 };
static const uint8_t appeui[LORAMAC_APPEUI_LEN] = { 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00 };
static const uint8_t appkey[LORAMAC_APPKEY_LEN] = { 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00 };

Now in the main function:

  1. initialize the LoRaMAC MAC layer
  2. set the LoRa keys
  3. join the network
  4. send some data to the network
int main(void)
/* 1. initialize the LoRaMAC MAC layer */
/* 2. set the keys identifying the device */
semtech_loramac_set_deveui(&loramac, deveui);
semtech_loramac_set_appeui(&loramac, appeui);
semtech_loramac_set_appkey(&loramac, appkey);
/* 3. join the network */
puts("Join procedure failed");
return 1;
puts("Join procedure succeeded");
/* 4. send some data */
char *message = "This is RIOT";
if (semtech_loramac_send(&loramac,
(uint8_t *)message, strlen(message)) != SEMTECH_LORAMAC_TX_DONE) {
printf("Cannot send message '%s'\n", message);
return 1;

To receive downlink messages, enable the semtech_loramac_rx and use a dedicated receiving thread.


If the board CPU provides an internal EEPROM, this package provides a mechanism for storing EUIs, keys and some MAC parameters (frame counter, join status). After a successful join procedure, use semtech_loramac_save function to persist this information and it will be loaded automatically at the next reboot. If the device is already joined to a network, to avoid another OTAA join procedure use semtech_loramac_is_mac_joined function to check the join status of the device.

This mechanism is especially useful when using deep sleep power modes that don't preserve RAM.

Low power considerations

The internal implementation of the required LoRaWAN timings (delay before opening RX windows, duty-cycle delays) automatically achieves the lowest possible power consumption while remaining usable when RIOT's low power modes are not blocked. All timings are managed by the ztimer high level timer abstraction layer running on the low-level RTT peripheral which allows for:

It is not possible to directly call the original LoRaMAC-node API using this package. This package should only be considered as a wrapper around the original LoRaMAC-node API and only the API provided by this package should be used.


The library is using the BSD 3-clause license.

See also


file  timer.h
 Semtech LoRaMAC timer compatibility definitions.
file  semtech_loramac.h
 Public API and definitions of the Semtech LoRaMAC.