Updated Jul 2025

LoRaWAN API References

NOTE: The FreeRTOS LoRaWAN demo project is in the FreeRTOS-Labs. It is fully functional, but undergoing optimizations or refactoring to improve memory usage, modularity, documentation, demo usability, or test coverage. It is available in the Lab-Project-FreeRTOS-LoRaWANexternal_link repository on GitHub separately from the main Labs Project Download.

The following section provides detailed description and usage samples for LoRaWAN APIs in FreeRTOS.

Setup

LoRaWAN_Init() can be used to initialize the LoRaWAN stack for a region. It takes a region parameter as input and initializes the LoRaMAC stack with the default parameters for that region. This API also creates a background LoRaMAC task which loops and processes events from the radio and MAC layers. The API is not re-entrant or thread safe.

1LoRaMacStatus_t status;
2
3status = LoRaWAN_Init( LORAMAC_REGION_US915 );
4
5if( status == LORAMAC_STATUS_OK )
6{
7 /* Continue with LoRaWAN Activation. */
8}
9else
10{
11 /* Exit the program with the appropriate error code. */
12}
13

Configure network parameters for LoRaWAN

The following APIs can be used to configure the network parameters for LoRAWAN.

LoRaWAN_SetAdaptiveDataRate()
can be used to turn on or off adaptive data rates for the end-device. This API can be invoked anytime after the LoRaWAN has been initialized. Turning on adaptive data rates will allow the network server to calculate an optimized data rate for the end-device based on its location and other factors.

The APIs

LoRaWAN_GetNetworkParams()
and
LoRaWAN_SetNetworkParams()
can be used to modify other network parameters, such as channel frequency and data rate, for the second receive window of the device and TX power. If you are using Over the Air Activation (OTAA), a join should be initiated for the new parameters to take effect.

Activitation

Two types of activation are supported: Over The Air Activation (OTAA) or Activation By Personalization (ABP).

The

LoRaWAN_Join()
API is used for OTAA. Example:

1LoRaMacStatus_t status;
2
3status = LoRaWAN_Join();
4
5if( status == LORAMAC_STATUS_OK )
6{
7 /* Send or receive data with LoRaWAN. */
8}
9else
10{
11 /*All JOIN attempts are exhausted. Report this to end user. */
12}
13

The API is a blocking call until join handshake is completed or all the retries are exhausted. The credentials required for Over the Air Activation should be provided using the getter functions below, or pre-provisioned using a secure element.

1void getDeviceEUI( uint8_t * param )
2{
3 /* Copy the 8 byte device EUI into param here. */
4}
5
6void getJoinEUI( uint8_t * param )
7{
8 /* Copy the 8 byte join EUI into param here. */
9}
10
11void getAppKey( uint8_t * param )
12{
13 /* Copy the 16 byte app key into param here. */
14}
15

The API does Join attempts for a configured number of times. Retries are performed at random intervals and under different frequency bands, as recommended by the LoRaWAN specification. The number of retries and the retry intervals can be tuned using the following configs in

demos/classA/Nordic_NRF52/config/LoRaWANConfig.h
:

1#define lorawanConfigMAX_JOIN_ATTEMPTS ( 1000 )
2#define lorawanConfigJOIN_RETRY_INTERVAL_MS ( 2000 )
3#define lorawanConfigMAX_JITTER_MS ( 500 )
4

(2)

LoRaWAN_ActivateByPersonalization()
API can be used for activating a device using ABP method.

1LoRaMacStatus_t status;
2
3status = LoRaWAN_ActivateByPersonalization();
4
5if( status == LORAMAC_STATUS_OK )
6{
7 /* Send or receive data with LoRaWAN. */
8}
9else
10{
11 /* ABP activation failed. Report this to end user. */
12}
13

In the ABP method, an end-device uses its pre-provisioned credentials and does not perform a handshake with the Network Server. The credentials for ABP can be provided using the following getter functions:

1void getDeviceEUI( uint8_t * param )
2{
3 /* Copy the 8 byte device EUI into param here. */
4}
5
6void getJoinEUI( uint8_t * param )
7{
8 /* Copy the 8 byte join EUI into param here. */
9}
10
11uint32_t getDeviceAddress( void )
12{
13 /* Return the 24 bit network id of the address. */
14}
15
16void getGetAppSessionKey( uint8_t * param )
17{
18 /* Copy the 16 byte app session key into param here. */
19}
20
21void getGetNwkSessionKey( uint8_t * param )
22{
23 /* Copy the 16 byte network session key into param here. */
24
25}

The

LoRaWAN_Send()
API can be used to send uplink data to a LoRa Network Server. Uplink data can be confirmed or unconfirmed. For confirmed messages, the API blocks until an acknowledgment is received from the Network Server. This API also performs a configured number of retries, with different data rates, until it receives an acknowledgment. For unconfirmed messages, the API returns as soon as a message is sent out of the radio.

1LoRaWANMessage_t uplink;
2
3uplink.port = LORAWAN_APP_PORT;
4memcpy( uplink.data, &data, bytesToSend );
5uplink.length = bytesToSend;
6uplink.dataRate = dataRateToSend; /* Set to zero if using adaptive data rate. */
7
8status = LoRaWAN_Send( &uplink, IS_CONFIRMED );
9
10if( status == LORAMAC_STATUS_OK )
11{
12 /*
13 * Successfully sent uplink data.
14 * Wait for receive windows to receive any downlink data.
15 */
16}
17else
18{
19 /* Failed to send data uplink, Check end-device and gateway connectivity. */
20}
21

The

LoRaWAN_Receive()
API can be used to block for a specified time until data is received. Applications can choose to wait for downlink data for any period of time by giving a timeout parameter in milliseconds. For example, for class A use cases, an application can wait for the receive window’s duration after sending an uplink message. The downlink queue size can be adjusted based on application needs through the config
lorawanConfigDOWNLINK_QUEUE_SIZE
in
demos/classA/Nordic_NRF52/config/LoRaWANConfig.h

1LoRaWANMessage_t downlink;
2
3status = LoRaWAN_Receive( &downlink, CLASSA_RECEIVE_WINDOW_DURATION_MS );
4
5if( status == pdTRUE )
6{
7 /* Successfully received downlink data. */
8 decodeData( &downlink.data, downlink.length; downlink.port );
9}
10else
11{
12 /* No data downlink. Do Nothing. */
13}
14

Poll for LoRaWAN Events

The

LoRaWAN_PollEvent()
API can be used to poll for any events received from the LoRaWAN network. The network supports receiving the following events at the application layer.

1typedef enum LoRaWANEventType
2{
3 LORAWAN_EVENT_UNKNOWN = 0,
4/**< @brief Type to denote an unexpected event type. */
5 LORAWAN_EVENT_DOWNLINK_PENDING,
6/**< @brief Indicates that server has to send more downlink data or waiting for a mac command uplink. */
7 LORAWAN_EVENT_TOO_MANY_FRAME_LOSS,
8/**< @brief Indicates too many frames are missed between end device and LoRa network server. */
9 LORAWAN_EVENT_DEVICE_TIME_UPDATED,
10/**< @brief Indicates the device time has been synchronized with LoRa network server. */
11 LORAWAN_EVENT_LINK_CHECK_REPLY
12/**< @brief Reply for a link check request from end device. */
13}
14

Applications can poll for any events by optionally blocking for them and then take appropriate actions. The example below shows the application behavior for two such events.

1BaseType_t status;
2LoRaWANEventInfo_t event;
3
4for (;;)
5{
6 status = LoRaWAN_PollEvent( &event, 0 );
7
8 if( status == pdTRUE )
9 {
10 switch( event.type)
11 {
12 case LORAWAN_EVENT_DOWNLINK_PENDING:
13 /*
14 * MAC layer indicated a pending downlink event or an uplink command to be flushed.
15 * Send an empty uplink to fetch the downlink packet.
16 */
17 prvFetchDownlinkPacket();
18 break;
19
20 case LORAWAN_EVENT_TOO_MANY_FRAME_LOSS:
21 /* Too many frame loss between end-device and Network server. Trigger a re-join. */
22 LoRaWAN\_Join();
23 break;
24
25 ....
26
27 ....
28
29 default:
30 break;
31
32 }
33 }
34 else
35 {
36 break;
37 }
38}
39

Cleanup

The

LoRaWAN_Cleanup()
API is used to stop and de-initialize the LoRaMac stack, and delete the LoRaMac task and associated resources.