1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-24 22:13:52 +01:00

pkg/semtech-loramac: persist OTAA join information in eeprom

This allows to continue sending data even after a reboot of a device that provide non volatile storage, e.g. eeprom
This commit is contained in:
Alexandre Abadie 2019-05-20 15:17:50 +02:00
parent d1f06bd9c7
commit b4d905471f
No known key found for this signature in database
GPG Key ID: 1C919A403CAE1405
3 changed files with 123 additions and 58 deletions

View File

@ -190,7 +190,7 @@ static inline void _set_uplink_counter(semtech_loramac_t *mac, uint8_t *counter)
(uint32_t)counter[2] << 8 |
counter[3]);
DEBUG("[semtech-loramac] uplink counter: %" PRIu32 " \n", counter4);
DEBUG("[semtech-loramac] reading uplink counter: %" PRIu32 " \n", counter4);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
@ -200,6 +200,18 @@ static inline void _set_uplink_counter(semtech_loramac_t *mac, uint8_t *counter)
mutex_unlock(&mac->lock);
}
static inline void _set_join_state(semtech_loramac_t *mac, bool joined)
{
DEBUG("[semtech-loramac] set join state ? %d\n", joined);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = joined;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
static inline void _read_loramac_config(semtech_loramac_t *mac)
{
DEBUG("[semtech-loramac] reading configuration from EEPROM\n");
@ -214,21 +226,33 @@ static inline void _read_loramac_config(semtech_loramac_t *mac)
return;
}
uint8_t tmp_buf[LORAMAC_APPSKEY_LEN] = { 0 };
/* LoRaWAN EUIs, Keys and device address */
pos += eeprom_read(pos, mac->deveui, LORAMAC_DEVEUI_LEN);
pos += eeprom_read(pos, mac->appeui, LORAMAC_APPEUI_LEN);
pos += eeprom_read(pos, mac->appkey, LORAMAC_APPKEY_LEN);
pos += eeprom_read(pos, mac->appskey, LORAMAC_APPSKEY_LEN);
pos += eeprom_read(pos, mac->nwkskey, LORAMAC_NWKSKEY_LEN);
pos += eeprom_read(pos, mac->devaddr, LORAMAC_DEVADDR_LEN);
pos += eeprom_read(pos, tmp_buf, LORAMAC_APPSKEY_LEN);
semtech_loramac_set_appskey(mac, tmp_buf);
pos += eeprom_read(pos, tmp_buf, LORAMAC_NWKSKEY_LEN);
semtech_loramac_set_nwkskey(mac, tmp_buf);
/* uplink counter, mainly used for ABP activation */
/* Read and set device address */
uint8_t devaddr[LORAMAC_DEVADDR_LEN];
pos += eeprom_read(pos, devaddr, LORAMAC_DEVADDR_LEN);
semtech_loramac_set_devaddr(mac, devaddr);
/* uplink counter */
uint8_t counter[4] = { 0 };
pos += eeprom_read(pos, counter, 4);
_set_uplink_counter(mac, counter);
uint8_t joined = eeprom_read_byte(pos);
_set_join_state(mac, (bool)joined);
}
static inline void _save_uplink_counter(semtech_loramac_t *mac)
static inline size_t _save_uplink_counter(semtech_loramac_t *mac)
{
size_t pos = SEMTECH_LORAMAC_EEPROM_START +
SEMTECH_LORAMAC_EEPROM_MAGIC_LEN +
@ -236,17 +260,19 @@ static inline void _save_uplink_counter(semtech_loramac_t *mac)
LORAMAC_APPKEY_LEN + LORAMAC_APPSKEY_LEN +
LORAMAC_NWKSKEY_LEN + LORAMAC_DEVADDR_LEN;
uint8_t counter[4];
uint8_t counter[LORAMAC_DEVADDR_LEN];
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_UPLINK_COUNTER;
LoRaMacMibGetRequestConfirm(&mibReq);
DEBUG("[semtech-loramac] saving uplink counter: %" PRIu32 " \n",
mibReq.Param.UpLinkCounter);
counter[0] = (uint8_t)(mibReq.Param.UpLinkCounter >> 24);
counter[1] = (uint8_t)(mibReq.Param.UpLinkCounter >> 16);
counter[2] = (uint8_t)(mibReq.Param.UpLinkCounter >> 8);
counter[3] = (uint8_t)(mibReq.Param.UpLinkCounter);
mutex_unlock(&mac->lock);
pos += eeprom_write(pos, counter, 4);
return eeprom_write(pos, counter, LORAMAC_DEVADDR_LEN);
}
void semtech_loramac_save_config(semtech_loramac_t *mac)
@ -258,15 +284,27 @@ void semtech_loramac_save_config(semtech_loramac_t *mac)
pos += eeprom_write(pos, magic, SEMTECH_LORAMAC_EEPROM_MAGIC_LEN);
/* Store EUIs, Keys and device address */
uint8_t tmp_buf[LORAMAC_APPSKEY_LEN] = { 0 };
pos += eeprom_write(pos, mac->deveui, LORAMAC_DEVEUI_LEN);
pos += eeprom_write(pos, mac->appeui, LORAMAC_APPEUI_LEN);
pos += eeprom_write(pos, mac->appkey, LORAMAC_APPKEY_LEN);
pos += eeprom_write(pos, mac->appskey, LORAMAC_APPSKEY_LEN);
pos += eeprom_write(pos, mac->nwkskey, LORAMAC_NWKSKEY_LEN);
pos += eeprom_write(pos, mac->devaddr, LORAMAC_DEVADDR_LEN);
semtech_loramac_get_appskey(mac, tmp_buf);
pos += eeprom_write(pos, tmp_buf, LORAMAC_APPSKEY_LEN);
semtech_loramac_get_nwkskey(mac, tmp_buf);
pos += eeprom_write(pos, tmp_buf, LORAMAC_NWKSKEY_LEN);
uint8_t devaddr[LORAMAC_DEVADDR_LEN];
semtech_loramac_get_devaddr(mac, devaddr);
pos += eeprom_write(pos, devaddr, LORAMAC_DEVADDR_LEN);
/* save uplink counter, mainly used for ABP activation */
_save_uplink_counter(mac);
pos += _save_uplink_counter(mac);
/* save join state */
uint8_t joined = (uint8_t)semtech_loramac_is_mac_joined(mac);
eeprom_write_byte(pos, joined);
}
void semtech_loramac_erase_config(void)
@ -283,12 +321,13 @@ void semtech_loramac_erase_config(void)
MibRequestConfirm_t mibReq;
size_t uplink_counter_len = sizeof(mibReq.Param.UpLinkCounter);
size_t joined_state_len = sizeof(mibReq.Param.IsNetworkJoined);
size_t end = (pos + SEMTECH_LORAMAC_EEPROM_MAGIC_LEN +
LORAMAC_DEVEUI_LEN + LORAMAC_APPEUI_LEN +
LORAMAC_APPKEY_LEN + LORAMAC_APPSKEY_LEN +
LORAMAC_NWKSKEY_LEN + LORAMAC_DEVADDR_LEN +
uplink_counter_len);
uplink_counter_len + joined_state_len);
for (size_t p = pos; p < end; p++) {
eeprom_write_byte(p, 0);
}
@ -391,29 +430,16 @@ static void _join_abp(semtech_loramac_t *mac)
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = false;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_DEV_ADDR;
mibReq.Param.DevAddr = ((uint32_t)mac->devaddr[0] << 24 |
(uint32_t)mac->devaddr[1] << 16 |
(uint32_t)mac->devaddr[2] << 8 |
(uint32_t)mac->devaddr[3]);
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NWK_SKEY;
mibReq.Param.NwkSKey = mac->nwkskey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_APP_SKEY;
mibReq.Param.AppSKey = mac->appskey;
LoRaMacMibSetRequestConfirm(&mibReq);
mibReq.Type = MIB_NETWORK_JOINED;
mibReq.Param.IsNetworkJoined = true;
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
/* ABP join procedure always works */
msg_t msg;
msg.type = MSG_TYPE_LORAMAC_JOIN_STATUS;
msg.content.value = SEMTECH_LORAMAC_JOIN_SUCCEEDED;
msg_send(&msg, semtech_loramac_pid);
}
static void _join(semtech_loramac_t *mac, void *arg)
@ -793,7 +819,7 @@ int semtech_loramac_init(semtech_loramac_t *mac)
return 0;
}
static bool _is_mac_joined(semtech_loramac_t *mac)
bool semtech_loramac_is_mac_joined(semtech_loramac_t *mac)
{
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
@ -809,7 +835,7 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type)
{
DEBUG("[semtech-loramac] Starting join procedure: %d\n", type);
if (_is_mac_joined(mac)) {
if (semtech_loramac_is_mac_joined(mac)) {
DEBUG("[semtech-loramac] network is already joined\n");
return SEMTECH_LORAMAC_ALREADY_JOINED;
}
@ -818,15 +844,11 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type)
_semtech_loramac_call(_join, &type);
if (type == LORAMAC_JOIN_OTAA) {
/* Wait until the MAC replies about OTAA join procedure */
msg_t msg;
msg_receive(&msg);
return (uint8_t)msg.content.value;
}
/* Wait until the MAC replies about join procedure */
msg_t msg;
msg_receive(&msg);
/* ABP join procedure always works */
return SEMTECH_LORAMAC_JOIN_SUCCEEDED;
return (uint8_t)msg.content.value;
}
#ifdef MODULE_SEMTECH_LORAMAC_RX
@ -842,7 +864,7 @@ void semtech_loramac_request_link_check(semtech_loramac_t *mac)
uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len)
{
if (!_is_mac_joined(mac)) {
if (!semtech_loramac_is_mac_joined(mac)) {
DEBUG("[semtech-loramac] network is not joined\n");
return SEMTECH_LORAMAC_NOT_JOINED;
}

View File

@ -61,32 +61,69 @@ void semtech_loramac_get_appkey(const semtech_loramac_t *mac, uint8_t *key)
void semtech_loramac_set_appskey(semtech_loramac_t *mac, const uint8_t *skey)
{
memcpy(mac->appskey, skey, LORAMAC_APPSKEY_LEN);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_APP_SKEY;
memcpy(mibReq.Param.AppSKey, skey, LORAMAC_APPSKEY_LEN);
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
void semtech_loramac_get_appskey(const semtech_loramac_t *mac, uint8_t *skey)
void semtech_loramac_get_appskey(semtech_loramac_t *mac, uint8_t *skey)
{
memcpy(skey, mac->appskey, LORAMAC_APPSKEY_LEN);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_APP_SKEY;
LoRaMacMibGetRequestConfirm(&mibReq);
memcpy(skey, mibReq.Param.AppSKey, LORAMAC_APPSKEY_LEN);
mutex_unlock(&mac->lock);
}
void semtech_loramac_set_nwkskey(semtech_loramac_t *mac, const uint8_t *skey)
{
memcpy(mac->nwkskey, skey, LORAMAC_NWKSKEY_LEN);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NWK_SKEY;
memcpy(mibReq.Param.NwkSKey, skey, LORAMAC_NWKSKEY_LEN);
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
void semtech_loramac_get_nwkskey(const semtech_loramac_t *mac, uint8_t *skey)
void semtech_loramac_get_nwkskey(semtech_loramac_t *mac, uint8_t *skey)
{
memcpy(skey, mac->nwkskey, LORAMAC_NWKSKEY_LEN);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NWK_SKEY;
LoRaMacMibGetRequestConfirm(&mibReq);
memcpy(skey, mibReq.Param.NwkSKey, LORAMAC_NWKSKEY_LEN);
mutex_unlock(&mac->lock);
}
void semtech_loramac_set_devaddr(semtech_loramac_t *mac, const uint8_t *addr)
{
memcpy(mac->devaddr, addr, LORAMAC_DEVADDR_LEN);
mutex_lock(&mac->lock);
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEV_ADDR;
mibReq.Param.DevAddr = ((uint32_t)addr[0] << 24 |
(uint32_t)addr[1] << 16 |
(uint32_t)addr[2] << 8 |
(uint32_t)addr[3]);
LoRaMacMibSetRequestConfirm(&mibReq);
mutex_unlock(&mac->lock);
}
void semtech_loramac_get_devaddr(const semtech_loramac_t *mac, uint8_t *addr)
void semtech_loramac_get_devaddr(semtech_loramac_t *mac, uint8_t *addr)
{
memcpy(addr, mac->devaddr, LORAMAC_DEVADDR_LEN);
mutex_lock(&mac->lock);
DEBUG("[semtech-loramac] get device address\n");
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_DEV_ADDR;
LoRaMacMibGetRequestConfirm(&mibReq);
addr[0] = (uint8_t)(mibReq.Param.DevAddr >> 24);
addr[1] = (uint8_t)(mibReq.Param.DevAddr >> 16);
addr[2] = (uint8_t)(mibReq.Param.DevAddr >> 8);
addr[3] = (uint8_t)(mibReq.Param.DevAddr);
mutex_unlock(&mac->lock);
}
void semtech_loramac_set_class(semtech_loramac_t *mac, loramac_class_t cls)

View File

@ -123,9 +123,6 @@ typedef struct {
uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< device EUI */
uint8_t appeui[LORAMAC_APPEUI_LEN]; /**< application EUI */
uint8_t appkey[LORAMAC_APPKEY_LEN]; /**< application key */
uint8_t appskey[LORAMAC_APPSKEY_LEN]; /**< application session key */
uint8_t nwkskey[LORAMAC_NWKSKEY_LEN]; /**< network session key */
uint8_t devaddr[LORAMAC_DEVADDR_LEN]; /**< device address */
#if defined(MODULE_SEMTECH_LORAMAC_RX) || DOXYGEN
semtech_loramac_rx_data_t rx_data; /**< struct handling the RX data */
semtech_loramac_link_check_info_t link_chk; /**< link check information */
@ -205,6 +202,15 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len)
uint8_t semtech_loramac_recv(semtech_loramac_t *mac);
#endif
/**
* @brief Check if network is already joined
*
* @param[in] mac Pointer to the mac
*
* @return true when network is joined, false otherwise
*/
bool semtech_loramac_is_mac_joined(semtech_loramac_t *mac);
#if defined(MODULE_SEMTECH_LORAMAC_RX) || DOXYGEN
/**
* @brief Requests a LoRaWAN link check
@ -279,7 +285,7 @@ void semtech_loramac_set_appskey(semtech_loramac_t *mac, const uint8_t *skey);
* @param[in] mac Pointer to the mac
* @param[in] skey The application session key
*/
void semtech_loramac_get_appskey(const semtech_loramac_t *mac, uint8_t *skey);
void semtech_loramac_get_appskey(semtech_loramac_t *mac, uint8_t *skey);
/**
* @brief Sets the network session key
@ -295,7 +301,7 @@ void semtech_loramac_set_nwkskey(semtech_loramac_t *mac, const uint8_t *skey);
* @param[in] mac Pointer to the mac
* @param[in] skey The network session key
*/
void semtech_loramac_get_nwkskey(const semtech_loramac_t *mac, uint8_t *skey);
void semtech_loramac_get_nwkskey(semtech_loramac_t *mac, uint8_t *skey);
/**
* @brief Sets the device address
@ -311,7 +317,7 @@ void semtech_loramac_set_devaddr(semtech_loramac_t *mac, const uint8_t *addr);
* @param[in] mac Pointer to the mac
* @param[in] addr The device address
*/
void semtech_loramac_get_devaddr(const semtech_loramac_t *mac, uint8_t *addr);
void semtech_loramac_get_devaddr(semtech_loramac_t *mac, uint8_t *addr);
/**
* @brief Sets the device class