LoRaWAN end device MAC layer for SX1272 and SX1276. Supports LoRaWAN-1.0 and LoRaWAN-1.1

Dependencies:   sx12xx_hal

Dependents:   LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more

radio chip selection

Radio chip driver is not included, because two options are available.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.

application project requirements

This library requires mbed TLS to be enabled.
The file mbed_app.json must be present in the project using this library:

{
    "macros": [ "MBEDTLS_CMAC_C" ]
}

regional PHY selection

All end device configuration is done in Commissioning.h, define desired radio frequency band of operation in this header file.
Commissioning.h is located in the application using this library.

end device provisioning

End device is provisioned by editing Commissioning.h in the application which is using this library
To use LoRaWAN-1.0 OTA: make sure LORAWAN_ROOT_APPKEY is undefined.
To use LoRaWAN-1.1 OTA, define LORAWAN_ROOT_APPKEY.
To select OTA operation, define LORAWAN_JOIN_EUI, then LORAWAN_DEVICE_EUI must be defined, along with root key(s).
To select ABP operation, undefine LORAWAN_JOIN_EUI: then define session keys

LoRaWAN 1.0 nameLoRaWAN 1.1 nameComissioning.h defnedescription
OTADevEUIDevEUILORAWAN_DEVICE_EUIuniquely identifies end device
OTAAppEUIJoinEUILORAWAN_JOIN_EUI
OTAAppKeyNwkKeyLORAWAN_ROOT_NWKKEYroot key for network server
OTA(note 1)AppKeyLORAWAN_ROOT_APPKEYroot key for application server
ABPNwkSKey(note 3)LORAWAN_FNwkSIntKeynetwork session key
ABP(note 2)SNwkSIntKeyLORAWAN_SNwkSIntKeymac layer network integrity key
ABP(note 2)NwkSEncKeyLORAWAN_NwkSEncKeynetwork session encryption key
ABP(note 2)FNwkSIntKeyLORAWAN_FNwkSIntKeyforwarding network session integrity key
ABPAppSKeyAppSKeyLORAWAN_APPSKEYapplication session encryption key

(note 1): LoRaWAN-1.0 OTA uses a single root key for both network server and application server.

In LoRaWAN-1.0 OTA: the single root AppKey is used to generate NwkSkey and AppSKey.
(note 2): In LoRaWAN-1.0 (both OTA and ABP) SNwkSIntKey, NwkSEncKey. FNwkSIntKey are of same value and are collectively known as NwkSKey.
(note 3): LoRaWAN-1.0 uses single network session key, LoRaWAN-1.1 uses 3 network session keys. Both use a unique application session key.


In LoRaWAN-1.1 OTA: the root NwkKey is used to generate SNwkSIntKey, NwkSEncKey, FNwkSIntKey
In LoRaWAN-1.1 OTA: the root AppKey is used to generate AppSKey


in ABP mode, the DevAddr, and session keys are fixed (never change), and frame counters never reset to zero.
ABP operation has no concept of: root keys, or DevEUI or JoinEUI/AppEUI.
in OTA mode, the DevAddr and session keys are assigned at join procedure, and frame counters reset at join.

eeprom

This library includes eeprom driver to support non-volatile storage required by LoRaWAN specification.
Currently eeprom is implemented for STM32L1 family and STM32L0 family.
Writing of values are wear-leveled to increase endurance; each write operation circulates across several memory locations. A read operation returns the highest value found. This simple method is used for sequence numbers which only increase.

value nameused in
DevNonceOTAfor Join request (note 1)
RJcount1OTAfor ReJoin Type 1 request
FCntUpABPuplink frame counter
NFCntDownABPdownlink frame counter
AFCntDownABPdownlink frame counter

AFCntDown is only used in LoRaWAN-1.1 when application payload is present in downlink and FPort > 0.
NFCntDown is used in LoRaWAN-1.1 when FPort is zero in downlink or application payload not present.
NFCntDown is the only downlink frame counter used in LoRaWAN-1.0
(note 1) OTA DevNonce is random number in LoRaWAN-1.0, therefore not stored in eeprom. DevNonce in LoRaWAN-1.1 is forever increasing (non-volatile) number upon each join request,.
RJcount0 is only stored in RAM because the value resets upon new session from JoinAccept, therefore not stored in eeprom.
Frame counters in OTA mode reset upon new session in join request, therefore are stored in RAM instead of eeprom for OTA.

radio driver support

When SX127x driver is used, both SX1272 and SX1276 are supported without defining at compile time. The chip is detected at start-up.
Supported radio platforms:


Alternately, when SX126x driver is imported, the SX126xDVK1xAS board is used.

low-speed clock oscillator selection

LoRaWAN uses 32768Hz crystal to permit low-power operation.
However, some mbed targets might revert to low-speed internal oscillator, which is not accurate enough for LoRaWAN operation.
An oscillator check is performed at initialization; program will not start if internal oscillator is used.
To force LSE watch crystal, add to mbed_app.json

{
    "macros": [ "MBEDTLS_CMAC_C" ],
    "target_overrides": {
        "<your-target>": {
            "target.lse_available": true
        }
    }
}
Committer:
Wayne Roberts
Date:
Mon Aug 20 14:09:49 2018 -0700
Revision:
12:0f28f2e7c35e
Parent:
11:ce1317758488
add 8 hybrid channel sets for us915 band

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 11:ce1317758488 1 #include <stdint.h>
Wayne Roberts 11:ce1317758488 2 #include "eeprom.h"
Wayne Roberts 11:ce1317758488 3
Wayne Roberts 11:ce1317758488 4 /* TODO: use non-volatile memory */
Wayne Roberts 11:ce1317758488 5 uint16_t devNonce;
Wayne Roberts 11:ce1317758488 6 uint16_t rjCount1;
Wayne Roberts 11:ce1317758488 7 uint16_t joinNonce;
Wayne Roberts 11:ce1317758488 8
Wayne Roberts 11:ce1317758488 9 uint32_t fcntUp;
Wayne Roberts 11:ce1317758488 10 uint32_t nfcntDown;
Wayne Roberts 11:ce1317758488 11 uint32_t afcntDown;
Wayne Roberts 11:ce1317758488 12
Wayne Roberts 11:ce1317758488 13 uint32_t eeprom_read(eeprom_value_e ev)
Wayne Roberts 11:ce1317758488 14 {
Wayne Roberts 11:ce1317758488 15 switch (ev) {
Wayne Roberts 11:ce1317758488 16 #ifdef LORAWAN_JOIN_EUI
Wayne Roberts 11:ce1317758488 17 case EEPROM_DEVNONCE:
Wayne Roberts 11:ce1317758488 18 return devNonce;
Wayne Roberts 11:ce1317758488 19 case EEPROM_RJCOUNT1:
Wayne Roberts 11:ce1317758488 20 return rjCount1;
Wayne Roberts 11:ce1317758488 21 #ifdef LORAWAN_ROOT_APPKEY
Wayne Roberts 11:ce1317758488 22 case EEPROM_JOINNONCE:
Wayne Roberts 11:ce1317758488 23 return joinNonce;
Wayne Roberts 11:ce1317758488 24 #endif /* LORAWAN_ROOT_APPKEY */
Wayne Roberts 11:ce1317758488 25 #else
Wayne Roberts 11:ce1317758488 26 case EEPROM_FCNTUP:
Wayne Roberts 11:ce1317758488 27 return fcntUp;
Wayne Roberts 11:ce1317758488 28 case EEPROM_NFCNTDWN:
Wayne Roberts 11:ce1317758488 29 return nfcntDown;
Wayne Roberts 11:ce1317758488 30 case EEPROM_AFCNTDWN:
Wayne Roberts 11:ce1317758488 31 return afcntDown;
Wayne Roberts 11:ce1317758488 32 #endif /* !LORAWAN_JOIN_EUI */
Wayne Roberts 11:ce1317758488 33 default: return 0;
Wayne Roberts 11:ce1317758488 34 }
Wayne Roberts 11:ce1317758488 35 }
Wayne Roberts 11:ce1317758488 36
Wayne Roberts 11:ce1317758488 37 int eeprom_increment_value(eeprom_value_e ev)
Wayne Roberts 11:ce1317758488 38 {
Wayne Roberts 11:ce1317758488 39 switch (ev) {
Wayne Roberts 11:ce1317758488 40 #ifdef LORAWAN_JOIN_EUI
Wayne Roberts 11:ce1317758488 41 case EEPROM_DEVNONCE:
Wayne Roberts 11:ce1317758488 42 devNonce++;
Wayne Roberts 11:ce1317758488 43 return 0;
Wayne Roberts 11:ce1317758488 44 case EEPROM_RJCOUNT1:
Wayne Roberts 11:ce1317758488 45 rjCount1++;
Wayne Roberts 11:ce1317758488 46 return 0;
Wayne Roberts 11:ce1317758488 47 #ifdef LORAWAN_ROOT_APPKEY
Wayne Roberts 11:ce1317758488 48 case EEPROM_JOINNONCE:
Wayne Roberts 11:ce1317758488 49 joinNonce++;
Wayne Roberts 11:ce1317758488 50 return 0;
Wayne Roberts 11:ce1317758488 51 #endif /* LORAWAN_ROOT_APPKEY */
Wayne Roberts 11:ce1317758488 52 #else
Wayne Roberts 11:ce1317758488 53 case EEPROM_FCNTUP:
Wayne Roberts 11:ce1317758488 54 fcntUp++;
Wayne Roberts 11:ce1317758488 55 return 0;
Wayne Roberts 11:ce1317758488 56 case EEPROM_NFCNTDWN:
Wayne Roberts 11:ce1317758488 57 nfcntDown++;
Wayne Roberts 11:ce1317758488 58 return 0;
Wayne Roberts 11:ce1317758488 59 case EEPROM_AFCNTDWN:
Wayne Roberts 11:ce1317758488 60 afcntDown++;
Wayne Roberts 11:ce1317758488 61 return 0;
Wayne Roberts 11:ce1317758488 62 #endif /* !LORAWAN_JOIN_EUI */
Wayne Roberts 11:ce1317758488 63 default:
Wayne Roberts 11:ce1317758488 64 return -1;
Wayne Roberts 11:ce1317758488 65 }
Wayne Roberts 11:ce1317758488 66 }
Wayne Roberts 11:ce1317758488 67
Wayne Roberts 11:ce1317758488 68 int eeprom_clear(eeprom_value_e ev)
Wayne Roberts 11:ce1317758488 69 {
Wayne Roberts 11:ce1317758488 70 switch (ev) {
Wayne Roberts 11:ce1317758488 71 #ifdef LORAWAN_JOIN_EUI
Wayne Roberts 11:ce1317758488 72 case EEPROM_DEVNONCE:
Wayne Roberts 11:ce1317758488 73 devNonce++;
Wayne Roberts 11:ce1317758488 74 return 0;
Wayne Roberts 11:ce1317758488 75 case EEPROM_RJCOUNT1:
Wayne Roberts 11:ce1317758488 76 rjCount1++;
Wayne Roberts 11:ce1317758488 77 return 0;
Wayne Roberts 11:ce1317758488 78 #ifdef LORAWAN_ROOT_APPKEY
Wayne Roberts 11:ce1317758488 79 case EEPROM_JOINNONCE:
Wayne Roberts 11:ce1317758488 80 joinNonce++;
Wayne Roberts 11:ce1317758488 81 return 0;
Wayne Roberts 11:ce1317758488 82 #endif /* LORAWAN_ROOT_APPKEY */
Wayne Roberts 11:ce1317758488 83 #else
Wayne Roberts 11:ce1317758488 84 case EEPROM_FCNTUP:
Wayne Roberts 11:ce1317758488 85 fcntUp++;
Wayne Roberts 11:ce1317758488 86 return 0;
Wayne Roberts 11:ce1317758488 87 case EEPROM_NFCNTDWN:
Wayne Roberts 11:ce1317758488 88 nfcntDown++;
Wayne Roberts 11:ce1317758488 89 return 0;
Wayne Roberts 11:ce1317758488 90 case EEPROM_AFCNTDWN:
Wayne Roberts 11:ce1317758488 91 afcntDown++;
Wayne Roberts 11:ce1317758488 92 return 0;
Wayne Roberts 11:ce1317758488 93 #endif /* !LORAWAN_JOIN_EUI */
Wayne Roberts 11:ce1317758488 94 default: return 0;
Wayne Roberts 11:ce1317758488 95 }
Wayne Roberts 11:ce1317758488 96 }
Wayne Roberts 11:ce1317758488 97
Wayne Roberts 11:ce1317758488 98 int eeprom_write_word(eeprom_value_e ev, uint32_t value)
Wayne Roberts 11:ce1317758488 99 {
Wayne Roberts 11:ce1317758488 100 switch (ev) {
Wayne Roberts 11:ce1317758488 101 #ifdef LORAWAN_JOIN_EUI
Wayne Roberts 11:ce1317758488 102 case EEPROM_DEVNONCE:
Wayne Roberts 11:ce1317758488 103 case EEPROM_RJCOUNT1:
Wayne Roberts 11:ce1317758488 104 return -1;
Wayne Roberts 11:ce1317758488 105 #ifdef LORAWAN_ROOT_APPKEY
Wayne Roberts 11:ce1317758488 106 case EEPROM_JOINNONCE:
Wayne Roberts 11:ce1317758488 107 joinNonce = value;
Wayne Roberts 11:ce1317758488 108 return 0;
Wayne Roberts 11:ce1317758488 109 #endif /* LORAWAN_ROOT_APPKEY */
Wayne Roberts 11:ce1317758488 110 #else
Wayne Roberts 11:ce1317758488 111 case EEPROM_FCNTUP:
Wayne Roberts 11:ce1317758488 112 fcntUp = value;
Wayne Roberts 11:ce1317758488 113 return 0;
Wayne Roberts 11:ce1317758488 114 case EEPROM_NFCNTDWN:
Wayne Roberts 11:ce1317758488 115 nfcntDown = value;
Wayne Roberts 11:ce1317758488 116 return 0;
Wayne Roberts 11:ce1317758488 117 case EEPROM_AFCNTDWN:
Wayne Roberts 11:ce1317758488 118 afcntDown = value;
Wayne Roberts 11:ce1317758488 119 return 0;
Wayne Roberts 11:ce1317758488 120 #endif /* !LORAWAN_JOIN_EUI */
Wayne Roberts 11:ce1317758488 121 default:
Wayne Roberts 11:ce1317758488 122 return -1;
Wayne Roberts 11:ce1317758488 123 }
Wayne Roberts 11:ce1317758488 124 }
Wayne Roberts 11:ce1317758488 125