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-LoRaWAN
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;23status = LoRaWAN_Init( LORAMAC_REGION_US915 );45if( status == LORAMAC_STATUS_OK )6{7 /* Continue with LoRaWAN Activation. */8}9else10{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()
The APIs
LoRaWAN_GetNetworkParams()
LoRaWAN_SetNetworkParams()
Activitation
Two types of activation are supported: Over The Air Activation (OTAA) or Activation By Personalization (ABP).
The
LoRaWAN_Join()
1LoRaMacStatus_t status;23status = LoRaWAN_Join();45if( status == LORAMAC_STATUS_OK )6{7 /* Send or receive data with LoRaWAN. */8}9else10{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}56void getJoinEUI( uint8_t * param )7{8 /* Copy the 8 byte join EUI into param here. */9}1011void 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()
1LoRaMacStatus_t status;23status = LoRaWAN_ActivateByPersonalization();45if( status == LORAMAC_STATUS_OK )6{7 /* Send or receive data with LoRaWAN. */8}9else10{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}56void getJoinEUI( uint8_t * param )7{8 /* Copy the 8 byte join EUI into param here. */9}1011uint32_t getDeviceAddress( void )12{13 /* Return the 24 bit network id of the address. */14}1516void getGetAppSessionKey( uint8_t * param )17{18 /* Copy the 16 byte app session key into param here. */19}2021void getGetNwkSessionKey( uint8_t * param )22{23 /* Copy the 16 byte network session key into param here. */2425}
Send Uplink Data
The
LoRaWAN_Send()
1LoRaWANMessage_t uplink;23uplink.port = LORAWAN_APP_PORT;4memcpy( uplink.data, &data, bytesToSend );5uplink.length = bytesToSend;6uplink.dataRate = dataRateToSend; /* Set to zero if using adaptive data rate. */78status = LoRaWAN_Send( &uplink, IS_CONFIRMED );910if( status == LORAMAC_STATUS_OK )11{12 /*13 * Successfully sent uplink data.14 * Wait for receive windows to receive any downlink data.15 */16}17else18{19 /* Failed to send data uplink, Check end-device and gateway connectivity. */20}21
Receive Downlink Data
The
LoRaWAN_Receive()
lorawanConfigDOWNLINK_QUEUE_SIZE
demos/classA/Nordic_NRF52/config/LoRaWANConfig.h
1LoRaWANMessage_t downlink;23status = LoRaWAN_Receive( &downlink, CLASSA_RECEIVE_WINDOW_DURATION_MS );45if( status == pdTRUE )6{7 /* Successfully received downlink data. */8 decodeData( &downlink.data, downlink.length; downlink.port );9}10else11{12 /* No data downlink. Do Nothing. */13}14
Poll for LoRaWAN Events
The
LoRaWAN_PollEvent()
1typedef enum LoRaWANEventType2{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_REPLY12/**< @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;34for (;;)5{6 status = LoRaWAN_PollEvent( &event, 0 );78 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;1920 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;2425 ....2627 ....2829 default:30 break;3132 }33 }34 else35 {36 break;37 }38}39
Cleanup
The
LoRaWAN_Cleanup()