No Matches
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 works with Semtech SX1261, SX1262, SX1268, SX1272 and SX1276 radio devices. Thus, in order to use it properly, the application Makefile must import the corresponding device driver:

USEMODULE += sx1261 # for a SX1261 radio device
USEMODULE += sx1262 # for a SX1262 radio device
USEMODULE += sx1268 # for a SX1268 radio device
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 */
LoRaMAC header definitions.
Public API and definitions of the Semtech LoRaMAC.

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 };
Application key length in bytes.
Definition loramac.h:570
Application EUI length in bytes.
Definition loramac.h:560
Device EUI length in bytes.
Definition loramac.h:550
Semtech LoRaMAC descriptor.

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;
#define printf(...)
A wrapper for the printf() function that passes arguments through unmodified, but fails to compile if...
Definition stdio.h:60
Other-the-air activation.
Definition loramac.h:673
uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type)
Starts a LoRaWAN network join procedure.
void semtech_loramac_set_deveui(semtech_loramac_t *mac, const uint8_t *eui)
Sets the device EUI.
uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len)
Sends data to the LoRaWAN network.
void semtech_loramac_set_appeui(semtech_loramac_t *mac, const uint8_t *eui)
Sets the application EUI.
void semtech_loramac_set_appkey(semtech_loramac_t *mac, const uint8_t *key)
Sets the application key.
int semtech_loramac_init(semtech_loramac_t *mac)
Initializes the semtech loramac mac.
Transmission completed.
Join procedure succeeded.

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.