diff --git a/sys/include/net/gnrc/lorawan.h b/sys/include/net/gnrc/lorawan.h index 0518fd9b16..97f5994853 100644 --- a/sys/include/net/gnrc/lorawan.h +++ b/sys/include/net/gnrc/lorawan.h @@ -188,6 +188,13 @@ void gnrc_lorawan_radio_rx_timeout_cb(gnrc_lorawan_t *mac); */ void gnrc_lorawan_radio_tx_done_cb(gnrc_lorawan_t *mac); +/** + * @brief Indicate the MAC layer that the timer was fired + * + * @param[in] mac pointer to the MAC descriptor + */ +void gnrc_lorawan_timeout_cb(gnrc_lorawan_t *mac); + /** * @brief Init GNRC LoRaWAN * @@ -296,6 +303,23 @@ netdev_t *gnrc_lorawan_get_netdev(gnrc_lorawan_t *mac); */ int gnrc_lorawan_phy_set_channel_mask(gnrc_lorawan_t *mac, uint16_t channel_mask); +/** + * @brief Set a timer with the given time + * @note Supposed to be implemented by the user of GNRC LoRaWAN + * + * @param[in] mac pointer to the MAC descriptor + * @param us timeout microseconds + */ +void gnrc_lorawan_set_timer(gnrc_lorawan_t *mac, uint32_t us); + +/** + * @brief Remove the current timer + * @note Supposed to be implemented by the user of GNRC LoRaWAN + * + * @param[in] mac pointer to the MAC descriptor + */ +void gnrc_lorawan_remove_timer(gnrc_lorawan_t *mac); + #ifdef __cplusplus } #endif diff --git a/sys/include/net/gnrc/netif/lorawan.h b/sys/include/net/gnrc/netif/lorawan.h index ed7647cf6f..610a805857 100644 --- a/sys/include/net/gnrc/netif/lorawan.h +++ b/sys/include/net/gnrc/netif/lorawan.h @@ -20,6 +20,8 @@ #include "net/gnrc/lorawan.h" +#include "xtimer.h" + #ifdef __cplusplus extern "C" { #endif @@ -39,6 +41,8 @@ typedef struct { uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< Device EUI buffer */ uint8_t appeui[LORAMAC_APPEUI_LEN]; /**< App EUI buffer */ gnrc_lorawan_t mac; /**< gnrc lorawan mac descriptor */ + xtimer_t timer; /**< General purpose timer */ + xtimer_t backoff_timer; /**< Backoff timer */ uint8_t flags; /**< flags for the LoRaWAN interface */ uint8_t demod_margin; /**< value of last demodulation margin */ uint8_t num_gateways; /**< number of gateways of last link check */ diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c index 6749feb75f..efeab23dd7 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c @@ -27,16 +27,11 @@ #include "net/lorawan/hdr.h" #include "net/loramac.h" #include "net/gnrc/lorawan/region.h" +#include "timex.h" #define ENABLE_DEBUG 0 #include "debug.h" -/* This factor is used for converting "real" seconds into microcontroller - * microseconds. This is done in order to correct timer drift. - */ -#define _DRIFT_FACTOR (int)(US_PER_SEC * 100 / \ - (100 + (CONFIG_GNRC_LORAWAN_TIMER_DRIFT / 10.0))) - #define GNRC_LORAWAN_DL_RX2_DR_MASK (0x0F) /**< DL Settings DR Offset mask */ #define GNRC_LORAWAN_DL_RX2_DR_POS (0) /**< DL Settings DR Offset pos */ #define GNRC_LORAWAN_DL_DR_OFFSET_MASK (0x70) /**< DL Settings RX2 DR mask */ @@ -52,10 +47,9 @@ static inline void gnrc_lorawan_mlme_reset(gnrc_lorawan_t *mac) static inline void gnrc_lorawan_mlme_backoff_init(gnrc_lorawan_t *mac) { - mac->mlme.backoff_msg.type = MSG_TYPE_MLME_BACKOFF_EXPIRE; mac->mlme.backoff_state = 0; - gnrc_lorawan_mlme_backoff_expire(mac); + gnrc_lorawan_mlme_backoff_expire_cb(mac); } static inline void gnrc_lorawan_mcps_reset(gnrc_lorawan_t *mac) @@ -151,19 +145,33 @@ void gnrc_lorawan_open_rx_window(gnrc_lorawan_t *mac) { netdev_t *dev = gnrc_lorawan_get_netdev(mac); - mac->msg.type = MSG_TYPE_TIMEOUT; /* Switch to RX state */ if (mac->state == LORAWAN_STATE_RX_1) { - xtimer_set_msg(&mac->rx, _DRIFT_FACTOR, &mac->msg, thread_getpid()); + gnrc_lorawan_set_timer(mac, US_PER_SEC); } netopt_state_t state = NETOPT_STATE_RX; dev->driver->set(dev, NETOPT_STATE, &state, sizeof(state)); } +void gnrc_lorawan_timeout_cb(gnrc_lorawan_t *mac) +{ + switch(mac->state) { + case LORAWAN_STATE_RX_1: + case LORAWAN_STATE_RX_2: + gnrc_lorawan_open_rx_window(mac); + break; + case LORAWAN_STATE_JOIN: + gnrc_lorawan_trigger_join(mac); + break; + default: + gnrc_lorawan_event_ack_timeout(mac); + break; + } +} + void gnrc_lorawan_radio_tx_done_cb(gnrc_lorawan_t *mac) { - mac->msg.type = MSG_TYPE_TIMEOUT; mac->state = LORAWAN_STATE_RX_1; int rx_1; @@ -172,7 +180,7 @@ void gnrc_lorawan_radio_tx_done_cb(gnrc_lorawan_t *mac) rx_1 = mac->mlme.activation == MLME_ACTIVATION_NONE ? CONFIG_LORAMAC_DEFAULT_JOIN_DELAY1 : mac->rx_delay; - xtimer_set_msg(&mac->rx, rx_1 * _DRIFT_FACTOR, &mac->msg, thread_getpid()); + gnrc_lorawan_set_timer(mac, rx_1 * US_PER_SEC); uint8_t dr_offset = (mac->dl_settings & GNRC_LORAWAN_DL_DR_OFFSET_MASK) >> GNRC_LORAWAN_DL_DR_OFFSET_POS; @@ -239,7 +247,7 @@ void gnrc_lorawan_radio_rx_done_cb(gnrc_lorawan_t *mac, uint8_t *psdu, return; } mac->state = LORAWAN_STATE_IDLE; - xtimer_remove(&mac->rx); + gnrc_lorawan_remove_timer(mac); uint8_t mtype = (*psdu & MTYPE_MASK) >> 5; diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c index ff6e2b1b49..c889191795 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c @@ -335,12 +335,8 @@ static void _handle_retransmissions(gnrc_lorawan_t *mac) { if (mac->mcps.nb_trials-- == 0) { _end_of_tx(mac, MCPS_CONFIRMED, -ETIMEDOUT); - } - else { - mac->msg.type = MSG_TYPE_MCPS_ACK_TIMEOUT; - xtimer_set_msg(&mac->rx, 1000000 + random_uint32_range(0, - 2000000), &mac->msg, - thread_getpid()); + } else { + gnrc_lorawan_set_timer(mac, 1000000 + random_uint32_range(0, 2000000)); } } diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c index dc43267807..774837c867 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c @@ -54,6 +54,13 @@ static void _build_join_req_pkt(uint8_t *appeui, uint8_t *deveui, &hdr->mic); } +void gnrc_lorawan_trigger_join(gnrc_lorawan_t *mac) +{ + iolist_t pkt = {.iol_base = mac->mcps.mhdr_mic, .iol_len = + sizeof(lorawan_join_request_t), .iol_next = NULL}; + gnrc_lorawan_send_pkt(mac, &pkt, mac->last_dr); +} + static int gnrc_lorawan_send_join_request(gnrc_lorawan_t *mac, uint8_t *deveui, uint8_t *appeui, uint8_t *appkey, uint8_t dr) @@ -68,18 +75,15 @@ static int gnrc_lorawan_send_join_request(gnrc_lorawan_t *mac, uint8_t *deveui, mac->mlme.dev_nonce[0] = random_number & 0xFF; mac->mlme.dev_nonce[1] = (random_number >> 8) & 0xFF; - /* build join request */ - uint8_t psdu[sizeof(lorawan_join_request_t)]; + mac->last_dr = dr; + mac->state = LORAWAN_STATE_JOIN; - iolist_t pkt = - { .iol_base = &psdu, .iol_len = sizeof(psdu), .iol_next = NULL }; - - _build_join_req_pkt(appeui, deveui, appkey, mac->mlme.dev_nonce, psdu); + /* Use the buffer for MHDR */ + _build_join_req_pkt(appeui, deveui, appkey, mac->mlme.dev_nonce, (uint8_t*) mac->mcps.mhdr_mic); /* We need a random delay for join request. Otherwise there might be * network congestion if a group of nodes start at the same time */ - xtimer_usleep(random_uint32() & GNRC_LORAWAN_JOIN_DELAY_U32_MASK); - gnrc_lorawan_send_pkt(mac, &pkt, dr); + gnrc_lorawan_set_timer(mac, random_uint32() & GNRC_LORAWAN_JOIN_DELAY_U32_MASK); mac->mlme.backoff_budget -= mac->toa; @@ -156,7 +160,7 @@ out: gnrc_lorawan_mlme_confirm(mac, &mlme_confirm); } -void gnrc_lorawan_mlme_backoff_expire(gnrc_lorawan_t *mac) +void gnrc_lorawan_mlme_backoff_expire_cb(gnrc_lorawan_t *mac) { uint8_t counter = mac->mlme.backoff_state & 0x1F; uint8_t state = mac->mlme.backoff_state >> 5; @@ -183,9 +187,6 @@ void gnrc_lorawan_mlme_backoff_expire(gnrc_lorawan_t *mac) counter--; mac->mlme.backoff_state = state << 5 | (counter & 0x1F); - xtimer_set_msg(&mac->mlme.backoff_timer, - GNRC_LORAWAN_BACKOFF_WINDOW_TICK, - &mac->mlme.backoff_msg, thread_getpid()); } static void _mlme_set(gnrc_lorawan_t *mac, const mlme_request_t *mlme_request, diff --git a/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h b/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h index d4afdf6170..afa0f4af9d 100644 --- a/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h +++ b/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h @@ -24,8 +24,6 @@ #include "net/lora.h" #include "net/lorawan/hdr.h" #include "net/gnrc/pktbuf.h" -#include "xtimer.h" -#include "msg.h" #include "net/netdev.h" #include "net/netdev/layer.h" #include "net/loramac.h" @@ -35,8 +33,6 @@ extern "C" { #endif #define MSG_TYPE_TIMEOUT (0x3457) /**< Timeout message type */ -#define MSG_TYPE_MCPS_ACK_TIMEOUT (0x3458) /**< ACK timeout message type */ -#define MSG_TYPE_MLME_BACKOFF_EXPIRE (0x3459) /**< Backoff timer expiration message type */ #define MTYPE_MASK 0xE0 /**< MHDR mtype mask */ #define MTYPE_JOIN_REQUEST 0x0 /**< Join Request type */ @@ -61,6 +57,7 @@ extern "C" { #define LORAWAN_STATE_RX_1 (1) /**< MAC state machine in RX1 */ #define LORAWAN_STATE_RX_2 (2) /**< MAC state machine in RX2 */ #define LORAWAN_STATE_TX (3) /**< MAC state machine in TX */ +#define LORAWAN_STATE_JOIN (4) /**< MAC state machine in Join */ #define GNRC_LORAWAN_DIR_UPLINK (0U) /**< uplink frame direction */ #define GNRC_LORAWAN_DIR_DOWNLINK (1U) /**< downlink frame direction */ @@ -163,8 +160,6 @@ typedef struct { * @brief MLME service access point descriptor */ typedef struct { - xtimer_t backoff_timer; /**< timer used for backoff expiration */ - msg_t backoff_msg; /**< msg for backoff expiration */ uint8_t activation; /**< Activation mechanism of the MAC layer */ int pending_mlme_opts; /**< holds pending mlme opts */ uint32_t nid; /**< current Network ID */ @@ -176,8 +171,6 @@ typedef struct { /** * @brief GNRC LoRaWAN mac descriptor */ typedef struct { - xtimer_t rx; /**< RX timer */ - msg_t msg; /**< MAC layer message descriptor */ gnrc_lorawan_mcps_t mcps; /**< MCPS descriptor */ gnrc_lorawan_mlme_t mlme; /**< MLME descriptor */ void *mlme_buf; /**< pointer to MLME buffer */ @@ -420,11 +413,12 @@ uint8_t gnrc_lorawan_region_mac_payload_max(uint8_t datarate); /** * @brief MLME Backoff expiration tick * - * Should be called every hour in order to maintain the Time On Air budget. + * Must be called once an hour (right after calling @ref + * gnrc_lorawan_init) in order to maintain the Time On Air budget. * * @param[in] mac pointer to the MAC descriptor */ -void gnrc_lorawan_mlme_backoff_expire(gnrc_lorawan_t *mac); +void gnrc_lorawan_mlme_backoff_expire_cb(gnrc_lorawan_t *mac); /** * @brief Process and dispatch a full LoRaWAN packet @@ -487,6 +481,13 @@ static inline void gnrc_lorawan_mac_release(gnrc_lorawan_t *mac) */ void gnrc_lorawan_set_rx2_dr(gnrc_lorawan_t *mac, uint8_t rx2_dr); +/** + * @brief Trigger the transmission of the Join Request packet. + * + * @param[in] mac pointer to the MAC descriptor + */ +void gnrc_lorawan_trigger_join(gnrc_lorawan_t *mac); + #ifdef __cplusplus } #endif diff --git a/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c b/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c index 6dabb4a474..8a16feb79d 100644 --- a/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c +++ b/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c @@ -27,9 +27,16 @@ #include "net/gnrc/lorawan/region.h" #include "net/gnrc/netreg.h" -#define ENABLE_DEBUG 0 +#define ENABLE_DEBUG (0) #include "debug.h" +#define MSG_TYPE_MLME_BACKOFF_EXPIRE (0x3458) /**< Backoff timer expiration message type */ + +/* This factor is used for converting "real" seconds into microcontroller + * microseconds. This is done in order to correct timer drift. + */ +#define ADJUST_DRIFT(us) (int) (us * 100 / (100 + (CONFIG_GNRC_LORAWAN_TIMER_DRIFT / 10.0))) + static uint8_t _nwkskey[LORAMAC_NWKSKEY_LEN]; static uint8_t _appskey[LORAMAC_APPSKEY_LEN]; static uint8_t _appkey[LORAMAC_APPKEY_LEN]; @@ -37,6 +44,9 @@ static uint8_t _deveui[LORAMAC_DEVEUI_LEN]; static uint8_t _appeui[LORAMAC_APPEUI_LEN]; static uint8_t _devaddr[LORAMAC_DEVADDR_LEN]; +static msg_t timeout_msg = {.type = MSG_TYPE_TIMEOUT}; +static msg_t backoff_msg = {.type = MSG_TYPE_MLME_BACKOFF_EXPIRE}; + static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt); static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif); static void _msg_handler(gnrc_netif_t *netif, msg_t *msg); @@ -73,6 +83,18 @@ void gnrc_lorawan_mlme_confirm(gnrc_lorawan_t *mac, mlme_confirm_t *confirm) } } +void gnrc_lorawan_set_timer(gnrc_lorawan_t *mac, uint32_t us) +{ + gnrc_netif_lorawan_t *lw_netif = container_of(mac, gnrc_netif_lorawan_t, mac); + xtimer_set_msg(&lw_netif->timer, ADJUST_DRIFT(us), &timeout_msg, thread_getpid()); +} + +void gnrc_lorawan_remove_timer(gnrc_lorawan_t *mac) +{ + gnrc_netif_lorawan_t *lw_netif = container_of(mac, gnrc_netif_lorawan_t, mac); + xtimer_remove(&lw_netif->timer); +} + static inline void _set_be_addr(gnrc_lorawan_t *mac, uint8_t *be_addr) { uint32_t tmp = byteorder_bebuftohl(be_addr); @@ -228,8 +250,11 @@ static void _init(gnrc_netif_t *netif) _memcpy_reversed(netif->lorawan.appeui, _appeui, sizeof(_appeui)); _set_be_addr(&netif->lorawan.mac, _devaddr); - gnrc_lorawan_init(&netif->lorawan.mac, netif->lorawan.nwkskey, - netif->lorawan.appskey); + gnrc_lorawan_init(&netif->lorawan.mac, netif->lorawan.nwkskey, netif->lorawan.appskey); + + xtimer_set_msg(&netif->lorawan.backoff_timer, + GNRC_LORAWAN_BACKOFF_WINDOW_TICK, + &backoff_msg, thread_getpid()); } int gnrc_netif_lorawan_create(gnrc_netif_t *netif, char *stack, int stacksize, @@ -276,13 +301,13 @@ static void _msg_handler(gnrc_netif_t *netif, msg_t *msg) (void)msg; switch (msg->type) { case MSG_TYPE_TIMEOUT: - gnrc_lorawan_open_rx_window(&netif->lorawan.mac); - break; - case MSG_TYPE_MCPS_ACK_TIMEOUT: - gnrc_lorawan_event_ack_timeout(&netif->lorawan.mac); + gnrc_lorawan_timeout_cb(&netif->lorawan.mac); break; case MSG_TYPE_MLME_BACKOFF_EXPIRE: - gnrc_lorawan_mlme_backoff_expire(&netif->lorawan.mac); + gnrc_lorawan_mlme_backoff_expire_cb(&netif->lorawan.mac); + xtimer_set_msg(&netif->lorawan.backoff_timer, + GNRC_LORAWAN_BACKOFF_WINDOW_TICK, + &backoff_msg, thread_getpid()); default: break; }