From d1798375e0aac8b6325374549a9ce9159bf655d9 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Fri, 17 May 2019 11:21:08 +0200 Subject: [PATCH 1/8] pkg/semtech-loramac: reduce MAC thread message queue --- pkg/semtech-loramac/contrib/semtech_loramac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c index 530873312233..51af9addde4b 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac.c @@ -50,7 +50,7 @@ #define ENABLE_DEBUG (0) #include "debug.h" -#define SEMTECH_LORAMAC_MSG_QUEUE (16U) +#define SEMTECH_LORAMAC_MSG_QUEUE (4U) #define SEMTECH_LORAMAC_LORAMAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) static msg_t _semtech_loramac_msg_queue[SEMTECH_LORAMAC_MSG_QUEUE]; static char _semtech_loramac_stack[SEMTECH_LORAMAC_LORAMAC_STACKSIZE]; From b7890b3031a653bde2d33afb54b9aa819e29af53 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Fri, 17 May 2019 11:32:30 +0200 Subject: [PATCH 2/8] pkg/semtech-loramac: refactor send and recv interactions with the MAC Now TX notification messages are only sent after mcps confirm event. RX message notification message is sent after mcps indication --- pkg/semtech-loramac/contrib/semtech_loramac.c | 410 +++++++++--------- pkg/semtech-loramac/include/semtech_loramac.h | 33 +- 2 files changed, 217 insertions(+), 226 deletions(-) diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c index 51af9addde4b..722e09be9029 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac.c @@ -146,105 +146,19 @@ static uint8_t _semtech_loramac_send(semtech_loramac_t *mac, static void mcps_confirm(McpsConfirm_t *confirm) { DEBUG("[semtech-loramac] MCPS confirm event\n"); - if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { - DEBUG("[semtech-loramac] MCPS confirm event OK\n"); - - switch (confirm->McpsRequest) { - case MCPS_UNCONFIRMED: - { - /* Check Datarate - Check TxPower */ - DEBUG("[semtech-loramac] MCPS confirm event: UNCONFIRMED\n"); - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = SEMTECH_LORAMAC_TX_DONE; - msg_send(&msg, semtech_loramac_pid); - break; - } - - case MCPS_CONFIRMED: - /* Check Datarate - Check TxPower - Check AckReceived - Check NbTrials */ - DEBUG("[semtech-loramac] MCPS confirm event: CONFIRMED\n"); - break; - - case MCPS_PROPRIETARY: - DEBUG("[semtech-loramac] MCPS confirm event: PROPRIETARY\n"); - break; - - default: - DEBUG("[semtech-loramac] MCPS confirm event: UNKNOWN\n"); - break; - } - } - else { - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = SEMTECH_LORAMAC_TX_CNF_FAILED; - msg_send(&msg, semtech_loramac_pid); - } + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_MCPS_CONFIRM; + msg.content.ptr = confirm; + msg_send(&msg, semtech_loramac_pid); } /* MCPS-Indication event function */ static void mcps_indication(McpsIndication_t *indication) { DEBUG("[semtech-loramac] MCPS indication event\n"); - if (indication->Status != LORAMAC_EVENT_INFO_STATUS_OK) { - DEBUG("[semtech-loramac] MCPS indication no OK\n"); - return; - } - - if (ENABLE_DEBUG) { - switch (indication->McpsIndication) { - case MCPS_UNCONFIRMED: - DEBUG("[semtech-loramac] MCPS indication Unconfirmed\n"); - break; - - case MCPS_CONFIRMED: - DEBUG("[semtech-loramac] MCPS indication Confirmed\n"); - break; - - case MCPS_PROPRIETARY: - DEBUG("[semtech-loramac] MCPS indication Proprietary\n"); - break; - - case MCPS_MULTICAST: - DEBUG("[semtech-loramac] MCPS indication Multicast\n"); - break; - - default: - break; - } - } - - /* Check Multicast - Check Port - Check Datarate - Check FramePending */ - if (indication->FramePending == true) { - /* The server signals that it has pending data to be sent. - We schedule an uplink as soon as possible to flush the server. */ - DEBUG("[semtech-loramac] MCPS indication: pending data, schedule an " - "uplink\n"); - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = SEMTECH_LORAMAC_TX_SCHEDULE; - msg_send(&msg, semtech_loramac_pid); - } - msg_t msg; - if (indication->RxData) { - DEBUG("[semtech-loramac] MCPS indication: data received\n"); - msg.type = MSG_TYPE_LORAMAC_RX; - msg.content.ptr = indication; - } - else { - DEBUG("[semtech-loramac] MCPS indication: TX done\n"); - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = SEMTECH_LORAMAC_TX_DONE; - } + msg.type = MSG_TYPE_LORAMAC_MCPS_INDICATION; + msg.content.ptr = indication; msg_send(&msg, semtech_loramac_pid); } @@ -252,56 +166,20 @@ static void mcps_indication(McpsIndication_t *indication) static void mlme_confirm(MlmeConfirm_t *confirm) { DEBUG("[semtech-loramac] MLME confirm event\n"); - switch (confirm->MlmeRequest) { - case MLME_JOIN: - if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { - /* Status is OK, node has joined the network */ - DEBUG("[semtech-loramac] join succeeded\n"); - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_JOIN; - msg.content.value = SEMTECH_LORAMAC_JOIN_SUCCEEDED; - msg_send(&msg, semtech_loramac_pid); - } - else { - DEBUG("[semtech-loramac] join not successful\n"); - /* Join was not successful. */ - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_JOIN; - msg.content.value = SEMTECH_LORAMAC_JOIN_FAILED; - msg_send(&msg, semtech_loramac_pid); - } - break; - - case MLME_LINK_CHECK: - if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { - DEBUG("[semtech-loramac] link check received\n"); - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_LINK_CHECK; - msg.content.ptr = confirm; - msg_send(&msg, semtech_loramac_pid); - } - - default: - break; - } + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_MLME_CONFIRM; + msg.content.ptr = confirm; + msg_send(&msg, semtech_loramac_pid); } /* MLME-Indication event function */ static void mlme_indication(MlmeIndication_t *indication) { - switch (indication->MlmeIndication) { - case MLME_SCHEDULE_UPLINK: - /* The MAC signals that we shall provide an uplink - as soon as possible */ - DEBUG("[semtech-loramac] MLME indication: schedule an uplink\n"); - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = SEMTECH_LORAMAC_TX_SCHEDULE; - msg_send(&msg, semtech_loramac_pid); - break; - default: - break; - } + DEBUG("[semtech-loramac] MLME indication event\n"); + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_MLME_INDICATION; + msg.content.ptr = indication; + msg_send(&msg, semtech_loramac_pid); } #ifdef MODULE_PERIPH_EEPROM @@ -442,7 +320,6 @@ void _init_loramac(semtech_loramac_t *mac, semtech_loramac_set_system_max_rx_error(mac, LORAMAC_DEFAULT_SYSTEM_MAX_RX_ERROR); semtech_loramac_set_min_rx_symbols(mac, LORAMAC_DEFAULT_MIN_RX_SYMBOLS); - mac->link_chk.available = false; #ifdef MODULE_PERIPH_EEPROM _read_loramac_config(mac); #endif @@ -478,7 +355,7 @@ static void _join_otaa(semtech_loramac_t *mac) DEBUG("[semtech-loramac] join otaa: duty cycle restricted\n"); /* Cannot join. */ msg_t msg; - msg.type = MSG_TYPE_LORAMAC_JOIN; + msg.type = MSG_TYPE_LORAMAC_JOIN_STATUS; msg.content.value = SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED; msg_send(&msg, semtech_loramac_pid); return; @@ -488,7 +365,7 @@ static void _join_otaa(semtech_loramac_t *mac) DEBUG("[semtech-loramac] join otaa: mac is busy\n"); /* Cannot join. */ msg_t msg; - msg.type = MSG_TYPE_LORAMAC_JOIN; + msg.type = MSG_TYPE_LORAMAC_JOIN_STATUS; msg.content.value = SEMTECH_LORAMAC_BUSY; msg_send(&msg, semtech_loramac_pid); return; @@ -498,7 +375,7 @@ static void _join_otaa(semtech_loramac_t *mac) DEBUG("[semtech-loramac] join otaa: failed with status %d\n", ret); /* Cannot join. */ msg_t msg; - msg.type = MSG_TYPE_LORAMAC_JOIN; + msg.type = MSG_TYPE_LORAMAC_JOIN_STATUS; msg.content.value = SEMTECH_LORAMAC_JOIN_FAILED; msg_send(&msg, semtech_loramac_pid); return; @@ -558,16 +435,12 @@ static void _send(semtech_loramac_t *mac, void *arg) { loramac_send_params_t params = *(loramac_send_params_t *)arg; uint8_t status = _semtech_loramac_send(mac, params.payload, params.len); -#ifdef MODULE_PERIPH_EEPROM - if (status == SEMTECH_LORAMAC_TX_OK) { - /* save the uplink counter */ - _save_uplink_counter(mac); + if (status != SEMTECH_LORAMAC_TX_OK) { + msg_t msg; + msg.type = MSG_TYPE_LORAMAC_TX_STATUS; + msg.content.value = (uint8_t)status; + msg_send(&msg, semtech_loramac_pid); } -#endif - msg_t msg; - msg.type = MSG_TYPE_LORAMAC_TX_STATUS; - msg.content.value = (uint8_t)status; - msg_send(&msg, semtech_loramac_pid); } static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg) @@ -695,63 +568,194 @@ void *_semtech_loramac_event_loop(void *arg) msg_reply(&msg, &msg_resp); break; } - case MSG_TYPE_LORAMAC_JOIN: + case MSG_TYPE_LORAMAC_JOIN_STATUS: { - DEBUG("[semtech-loramac] loramac join notification msg\n"); + DEBUG("[semtech-loramac] join status msg received\n"); msg_t msg_ret; msg_ret.content.value = msg.content.value; - msg_send(&msg_ret, mac->caller_pid); + msg_send(&msg_ret, mac->tx_pid); break; } - case MSG_TYPE_LORAMAC_LINK_CHECK: + case MSG_TYPE_LORAMAC_TX_STATUS: { + DEBUG("[semtech-loramac] TX status msg received\n"); + msg_t msg_ret; + msg_ret.content.value = msg.content.value; + msg_send(&msg_ret, mac->tx_pid); + break; + } + case MSG_TYPE_LORAMAC_MLME_CONFIRM: + { + DEBUG("[semtech-loramac] MLME confirm msg received\n"); MlmeConfirm_t *confirm = (MlmeConfirm_t *)msg.content.ptr; - mac->link_chk.demod_margin = confirm->DemodMargin; - mac->link_chk.nb_gateways = confirm->NbGateways; - mac->link_chk.available = true; - DEBUG("[semtech-loramac] link check info received:\n" - " - Demodulation marging: %d\n" - " - Number of gateways: %d\n", - mac->link_chk.demod_margin, - mac->link_chk.nb_gateways); + switch (confirm->MlmeRequest) { + case MLME_JOIN: + { + msg_t msg_ret; + msg_ret.type = MSG_TYPE_LORAMAC_JOIN_STATUS; + if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { + /* Status is OK, node has joined the network */ + DEBUG("[semtech-loramac] join succeeded\n"); + msg_ret.content.value = SEMTECH_LORAMAC_JOIN_SUCCEEDED; + } + else { + DEBUG("[semtech-loramac] join not successful\n"); + /* Join was not successful. */ + msg_ret.content.value = SEMTECH_LORAMAC_JOIN_FAILED; + } + msg_send(&msg_ret, mac->tx_pid); + break; + } + case MLME_LINK_CHECK: + if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { + mac->link_chk.demod_margin = confirm->DemodMargin; + mac->link_chk.nb_gateways = confirm->NbGateways; + DEBUG("[semtech-loramac] link check info received:\n" + " - Demodulation marging: %d\n" + " - Number of gateways: %d\n", + mac->link_chk.demod_margin, + mac->link_chk.nb_gateways); + msg_t msg_ret; + msg_ret.content.value = SEMTECH_LORAMAC_RX_LINK_CHECK; + msg_send(&msg_ret, mac->rx_pid); + } + default: + break; + } + break; } - case MSG_TYPE_LORAMAC_TX_STATUS: + case MSG_TYPE_LORAMAC_MLME_INDICATION: { - DEBUG("[semtech-loramac] received TX status\n"); - if (msg.content.value == SEMTECH_LORAMAC_TX_SCHEDULE) { - DEBUG("[semtech-loramac] schedule immediate TX\n"); + DEBUG("[semtech-loramac] MLME indication msg received\n"); + MlmeIndication_t *indication = (MlmeIndication_t *)msg.content.ptr; + if (indication->MlmeIndication == MLME_SCHEDULE_UPLINK) { + DEBUG("[semtech-loramac] MLME indication: schedule an uplink\n"); uint8_t prev_port = mac->port; mac->port = 0; _semtech_loramac_send(mac, NULL, 0); mac->port = prev_port; } - else { - DEBUG("[semtech-loramac] forward TX status to caller thread\n"); - msg_t msg_ret; - msg_ret.type = msg.type; - msg_ret.content.value = msg.content.value; - msg_send(&msg_ret, mac->caller_pid); - } break; } - case MSG_TYPE_LORAMAC_RX: + case MSG_TYPE_LORAMAC_MCPS_CONFIRM: { + DEBUG("[semtech-loramac] MCPS confirm msg received\n"); + McpsConfirm_t *confirm = (McpsConfirm_t *)msg.content.ptr; msg_t msg_ret; - msg_ret.type = MSG_TYPE_LORAMAC_RX; + msg_ret.type = MSG_TYPE_LORAMAC_TX_STATUS; + uint8_t status = SEMTECH_LORAMAC_TX_CNF_FAILED; + if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { + DEBUG("[semtech-loramac] MCPS confirm event OK\n"); + status = SEMTECH_LORAMAC_TX_DONE; +#ifdef MODULE_PERIPH_EEPROM + /* save the uplink counter */ + _save_uplink_counter(mac); +#endif + if (ENABLE_DEBUG) { + switch (confirm->McpsRequest) { + case MCPS_UNCONFIRMED: + { + /* Check Datarate + Check TxPower */ + DEBUG("[semtech-loramac] MCPS confirm event: UNCONFIRMED\n"); + break; + } + + case MCPS_CONFIRMED: + /* Check Datarate + Check TxPower + Check AckReceived + Check NbTrials */ + DEBUG("[semtech-loramac] MCPS confirm event: CONFIRMED\n"); + break; + + case MCPS_PROPRIETARY: + DEBUG("[semtech-loramac] MCPS confirm event: PROPRIETARY\n"); + break; + + default: + DEBUG("[semtech-loramac] MCPS confirm event: UNKNOWN\n"); + break; + } + } + } + + DEBUG("[semtech-loramac] forward TX status to sender thread\n"); + msg_ret.content.value = status; + msg_send(&msg_ret, mac->tx_pid); + break; + } + case MSG_TYPE_LORAMAC_MCPS_INDICATION: + { + DEBUG("[semtech-loramac] MCPS indication msg received\n"); McpsIndication_t *indication = (McpsIndication_t *)msg.content.ptr; - memcpy(mac->rx_data.payload, - indication->Buffer, indication->BufferSize); - mac->rx_data.payload_len = indication->BufferSize; - mac->rx_data.port = indication->Port; - DEBUG("[semtech-loramac] loramac RX data:\n" - " - Payload: %s\n" - " - Size: %d\n" - " - Port: %d\n", - (char *)mac->rx_data.payload, - mac->rx_data.payload_len, - mac->rx_data.port); - msg_send(&msg_ret, mac->caller_pid); + if (indication->Status != LORAMAC_EVENT_INFO_STATUS_OK) { + DEBUG("[semtech-loramac] MCPS indication no OK\n"); + break; + } + + if (ENABLE_DEBUG) { + switch (indication->McpsIndication) { + case MCPS_UNCONFIRMED: + DEBUG("[semtech-loramac] MCPS indication Unconfirmed\n"); + break; + + case MCPS_CONFIRMED: + DEBUG("[semtech-loramac] MCPS indication Confirmed\n"); + break; + + case MCPS_PROPRIETARY: + DEBUG("[semtech-loramac] MCPS indication Proprietary\n"); + break; + + case MCPS_MULTICAST: + DEBUG("[semtech-loramac] MCPS indication Multicast\n"); + break; + + default: + break; + } + } + + /* Check Multicast + Check Port + Check Datarate + Check FramePending */ + if (indication->FramePending) { + /* The server signals that it has pending data to be sent. + We schedule an uplink as soon as possible to flush the server. */ + DEBUG("[semtech-loramac] MCPS indication: pending data, schedule an " + "uplink\n"); + uint8_t prev_port = mac->port; + mac->port = 0; + _semtech_loramac_send(mac, NULL, 0); + mac->port = prev_port; + } + if (indication->RxData) { + DEBUG("[semtech-loramac] MCPS indication: data received\n"); + memcpy(mac->rx_data.payload, + indication->Buffer, indication->BufferSize); + mac->rx_data.payload_len = indication->BufferSize; + mac->rx_data.port = indication->Port; + DEBUG("[semtech-loramac] loramac RX data:\n" + " - Payload: %s\n" + " - Size: %d\n" + " - Port: %d\n", + (char *)mac->rx_data.payload, + mac->rx_data.payload_len, + mac->rx_data.port); + msg_t msg_ret; + msg_ret.content.value = SEMTECH_LORAMAC_RX_DATA; + msg_send(&msg_ret, mac->rx_pid); + } + if (indication->AckReceived) { + DEBUG("[semtech-loramac] MCPS indication: ACK received\n"); + msg_t msg_ret; + msg_ret.content.value = SEMTECH_LORAMAC_RX_CONFIRMED; + msg_send(&msg_ret, mac->rx_pid); + } + break; } default: @@ -806,7 +810,7 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type) return SEMTECH_LORAMAC_ALREADY_JOINED; } - mac->caller_pid = thread_getpid(); + mac->tx_pid = thread_getpid(); _semtech_loramac_call(_join, &type); @@ -824,7 +828,6 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type) void semtech_loramac_request_link_check(semtech_loramac_t *mac) { mutex_lock(&mac->lock); - mac->link_chk.available = false; MlmeReq_t mlmeReq; mlmeReq.Type = MLME_LINK_CHECK; LoRaMacMlmeRequest(&mlmeReq); @@ -833,14 +836,13 @@ 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) { - mac->link_chk.available = false; if (!_is_mac_joined(mac)) { DEBUG("[semtech-loramac] network is not joined\n"); return SEMTECH_LORAMAC_NOT_JOINED; } - /* Correctly set the caller pid */ - mac->caller_pid = thread_getpid(); + /* Correctly set the sender thread pid */ + mac->tx_pid = thread_getpid(); loramac_send_params_t params; params.payload = data; @@ -851,34 +853,18 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) /* Wait for TX status information from the MAC */ msg_t msg; msg_receive(&msg); - if (msg.type != MSG_TYPE_LORAMAC_TX_STATUS) { - return SEMTECH_LORAMAC_TX_ERROR; - } - return (uint8_t)msg.content.value; } uint8_t semtech_loramac_recv(semtech_loramac_t *mac) { - mac->caller_pid = thread_getpid(); + /* Correctly set the receiver thread pid */ + mac->rx_pid = thread_getpid(); /* Wait until the mac receive some information */ msg_t msg; msg_receive(&msg); - uint8_t ret; - switch (msg.type) { - case MSG_TYPE_LORAMAC_RX: - ret = SEMTECH_LORAMAC_DATA_RECEIVED; - break; - case MSG_TYPE_LORAMAC_TX_STATUS: - ret = (uint8_t)msg.content.value; - break; - default: - ret = SEMTECH_LORAMAC_TX_ERROR; - break; - } + DEBUG("[semtech-loramac] received something\n"); - DEBUG("[semtech-loramac] MAC reply received: %d\n", ret); - - return ret; + return (uint8_t)msg.content.value; } diff --git a/pkg/semtech-loramac/include/semtech_loramac.h b/pkg/semtech-loramac/include/semtech_loramac.h index 69c7ad398d13..479b9c7e03d7 100644 --- a/pkg/semtech-loramac/include/semtech_loramac.h +++ b/pkg/semtech-loramac/include/semtech_loramac.h @@ -36,15 +36,17 @@ extern "C" { * @name Definitions for messages exchanged between the MAC and call threads * @{ */ -#define MSG_TYPE_ISR (0x3456) /**< radio device ISR */ -#define MSG_TYPE_RX_TIMEOUT (0x3457) /**< radio driver RX timeout */ -#define MSG_TYPE_TX_TIMEOUT (0x3458) /**< radio driver TX timeout */ -#define MSG_TYPE_MAC_TIMEOUT (0x3459) /**< MAC timers timeout */ -#define MSG_TYPE_LORAMAC_CMD (0x3460) /**< Command sent to the MAC */ -#define MSG_TYPE_LORAMAC_JOIN (0x3461) /**< MAC join event */ -#define MSG_TYPE_LORAMAC_TX_STATUS (0x3462) /**< MAC TX status */ -#define MSG_TYPE_LORAMAC_RX (0x3463) /**< Some data received */ -#define MSG_TYPE_LORAMAC_LINK_CHECK (0x3464) /**< Link check info received */ +#define MSG_TYPE_ISR (0x3456) /**< radio device ISR */ +#define MSG_TYPE_RX_TIMEOUT (0x3457) /**< radio driver RX timeout */ +#define MSG_TYPE_TX_TIMEOUT (0x3458) /**< radio driver TX timeout */ +#define MSG_TYPE_MAC_TIMEOUT (0x3459) /**< MAC timers timeout */ +#define MSG_TYPE_LORAMAC_CMD (0x3460) /**< Command sent to the MAC */ +#define MSG_TYPE_LORAMAC_JOIN_STATUS (0x3461) /**< Join status */ +#define MSG_TYPE_LORAMAC_TX_STATUS (0x3462) /**< Uplink status */ +#define MSG_TYPE_LORAMAC_MLME_CONFIRM (0x3463) /**< MAC MLME confirm event */ +#define MSG_TYPE_LORAMAC_MLME_INDICATION (0x3464) /**< MAC MLME indication event */ +#define MSG_TYPE_LORAMAC_MCPS_CONFIRM (0x3465) /**< MAC MCPS confirm event */ +#define MSG_TYPE_LORAMAC_MCPS_INDICATION (0x3466) /**< MAC MCPS indication event */ /** @} */ /** @@ -65,7 +67,9 @@ enum { SEMTECH_LORAMAC_TX_DONE, /**< Transmission completed */ SEMTECH_LORAMAC_TX_CNF_FAILED, /**< Confirmable transmission failed */ SEMTECH_LORAMAC_TX_ERROR, /**< Error in TX (invalid param, unknown service) */ - SEMTECH_LORAMAC_DATA_RECEIVED, /**< Data received */ + SEMTECH_LORAMAC_RX_DATA, /**< Data received */ + SEMTECH_LORAMAC_RX_LINK_CHECK, /**< Link check info received */ + SEMTECH_LORAMAC_RX_CONFIRMED, /**< Confirmed ACK received */ SEMTECH_LORAMAC_BUSY, /**< Internal MAC is busy */ SEMTECH_LORAMAC_DUTYCYCLE_RESTRICTED /**< Restricted access to channels */ }; @@ -101,7 +105,6 @@ typedef struct { typedef struct { uint8_t demod_margin; /**< Demodulation margin */ uint8_t nb_gateways; /**< number of LoRa gateways found */ - bool available; /**< new link check information avalable */ } semtech_loramac_link_check_info_t; /** @@ -109,7 +112,8 @@ typedef struct { */ typedef struct { mutex_t lock; /**< loramac access lock */ - uint8_t caller_pid; /**< pid of caller thread */ + uint8_t tx_pid; /**< pid of sender thread */ + uint8_t rx_pid; /**< pid of receiver thread */ uint8_t port; /**< application TX port */ uint8_t cnf; /**< enable/disable confirmable messages */ uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< device EUI */ @@ -184,8 +188,9 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) * * @param[in] mac Pointer to the mac * - * @return SEMTECH_LORAMAC_TX_DONE when TX has completed, no data received - * @return SEMTECH_LORAMAC_DATA_RECEIVED when TX has completed and data is received + * @return SEMTECH_LORAMAC_RX_DATA when data is received + * @return SEMTECH_LORAMAC_RX_LINK_CHECK when link check information is received + * @return SEMTECH_LORAMAC_RX_CONFIRMED when an ACK is received from the network */ uint8_t semtech_loramac_recv(semtech_loramac_t *mac); From 0838cf99bb04f888c8b61f0f1c7fea93839873bc Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Fri, 17 May 2019 11:33:17 +0200 Subject: [PATCH 3/8] tests/pkg_semtech-loramac: add RX thread for downlink messages --- tests/pkg_semtech-loramac/main.c | 76 ++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/tests/pkg_semtech-loramac/main.c b/tests/pkg_semtech-loramac/main.c index 52547aabc2d6..235bc0d99a08 100644 --- a/tests/pkg_semtech-loramac/main.c +++ b/tests/pkg_semtech-loramac/main.c @@ -20,6 +20,7 @@ #include #include +#include "thread.h" #include "msg.h" #include "shell.h" #include "fmt.h" @@ -27,12 +28,50 @@ #include "net/loramac.h" #include "semtech_loramac.h" +#define LORAMAC_RECV_MSG_QUEUE (4U) +static msg_t _loramac_recv_queue[LORAMAC_RECV_MSG_QUEUE]; + semtech_loramac_t loramac; /* Application key is 16 bytes long (e.g. 32 hex chars), and thus the longest possible size (with application session and network session keys) */ static char print_buf[LORAMAC_APPKEY_LEN * 2 + 1]; +static char _recv_stack[THREAD_STACKSIZE_DEFAULT]; + +static void *_wait_recv(void *arg) +{ + msg_init_queue(_loramac_recv_queue, LORAMAC_RECV_MSG_QUEUE); + + (void)arg; + while (1) { + /* blocks until something is received */ + switch (semtech_loramac_recv(&loramac)) { + case SEMTECH_LORAMAC_RX_DATA: + loramac.rx_data.payload[loramac.rx_data.payload_len] = 0; + printf("Data received: %s, port: %d\n", + (char *)loramac.rx_data.payload, loramac.rx_data.port); + break; + + case SEMTECH_LORAMAC_RX_LINK_CHECK: + printf("Link check information:\n" + " - Demodulation margin: %d\n" + " - Number of gateways: %d\n", + loramac.link_chk.demod_margin, + loramac.link_chk.nb_gateways); + break; + + case SEMTECH_LORAMAC_RX_CONFIRMED: + puts("Received ACK from network"); + break; + + default: + break; + } + } + return NULL; +} + static void _loramac_usage(void) { puts("Usage: loramac Date: Fri, 17 May 2019 11:35:57 +0200 Subject: [PATCH 4/8] pkg-semtech-loramac: update/simplify doxygen documentation --- pkg/semtech-loramac/doc.txt | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/pkg/semtech-loramac/doc.txt b/pkg/semtech-loramac/doc.txt index b9a0245e58a6..1ef4e0ca6a1a 100644 --- a/pkg/semtech-loramac/doc.txt +++ b/pkg/semtech-loramac/doc.txt @@ -66,7 +66,6 @@ * 2. set the LoRa keys * 3. join the network * 4. send some data to the network - * 5. wait for any potentially received data * * ```c * int main(void) @@ -94,14 +93,46 @@ * return 1; * } * - * /* 5. wait for any potentially received data */ - * if (semtech_loramac_recv(&loramac) == SEMTECH_LORAMAC_DATA_RECEIVED) { + * } + * ``` + * + * To receive downlink messages, use a dedicated receiving thread. + * - At the beginning of the application source file, add the necessary + * includes and declare the message queue and stack arrays: + * ```c + * #include "thread.h" + * + * #define RECV_MSG_QUEUE (4U) + * static msg_t _recv_queue[RECV_MSG_QUEUE]; + * + * static char _recv_stack[THREAD_STACKSIZE_DEFAULT]; + * ``` + * - Implement the thread: it initializes its message queue and then + * simply calls the blocking `semtech_loramac_recv` function in a loop: + * ```c + * static void *_recv(void *arg) + * { + * msg_init_queue(_recv_queue, RECV_MSG_QUEUE); + * + * (void)arg; + * while (1) { + * /* blocks until some data is received */ + * semtech_loramac_recv(&loramac); * loramac.rx_data.payload[loramac.rx_data.payload_len] = 0; * printf("Data received: %s, port: %d\n", * (char *)loramac.rx_data.payload, loramac.rx_data.port); + * } + * * } + * return NULL; * } * ``` + * - Finally, this thread can be started after the join procedure + * succeeds: + * ```c + * thread_create(_recv_stack, sizeof(_recv_stack), + * THREAD_PRIORITY_MAIN - 1, 0, _recv, NULL, "recv thread"); + * ``` * * @warning It is not possible to directly call the original LoRaMAC-node API * using this package. This package should only be considered as a From f2c63c86fdb49cb8fe85e52ac4521899e035e785 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Fri, 17 May 2019 11:36:59 +0200 Subject: [PATCH 5/8] examples/lorawan: remove recv call to avoid endless lock This can highly happen when no message is received from the network after a send --- examples/lorawan/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/lorawan/main.c b/examples/lorawan/main.c index da2e43212d39..f323e5212422 100644 --- a/examples/lorawan/main.c +++ b/examples/lorawan/main.c @@ -74,9 +74,6 @@ static void _send_message(void) printf("Cannot send message '%s', ret code: %d\n", message, ret); return; } - /* The send was successfully scheduled, now wait until the send cycle has - completed and a reply is received from the MAC */ - semtech_loramac_recv(&loramac); } static void *sender(void *arg) From b5c48ef04ee62b7a332b160735507fbb69f065e8 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Wed, 29 May 2019 10:10:16 +0200 Subject: [PATCH 6/8] pkg/semtech-loramac: make RX optional --- makefiles/pseudomodules.inc.mk | 1 + pkg/semtech-loramac/contrib/semtech_loramac.c | 8 ++++++++ pkg/semtech-loramac/doc.txt | 7 ++++++- pkg/semtech-loramac/include/semtech_loramac.h | 16 ++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index b4b6abd897fd..1bbc7c0e431d 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -68,6 +68,7 @@ PSEUDOMODULES += saul_gpio PSEUDOMODULES += saul_nrf_temperature PSEUDOMODULES += scanf_float PSEUDOMODULES += schedstatistics +PSEUDOMODULES += semtech_loramac_rx PSEUDOMODULES += sock PSEUDOMODULES += sock_ip PSEUDOMODULES += sock_tcp diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c index 722e09be9029..97f9bf559d41 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac.c @@ -606,6 +606,7 @@ void *_semtech_loramac_event_loop(void *arg) msg_send(&msg_ret, mac->tx_pid); break; } +#ifdef MODULE_SEMTECH_LORAMAC_RX case MLME_LINK_CHECK: if (confirm->Status == LORAMAC_EVENT_INFO_STATUS_OK) { mac->link_chk.demod_margin = confirm->DemodMargin; @@ -619,6 +620,7 @@ void *_semtech_loramac_event_loop(void *arg) msg_ret.content.value = SEMTECH_LORAMAC_RX_LINK_CHECK; msg_send(&msg_ret, mac->rx_pid); } +#endif default: break; } @@ -732,6 +734,7 @@ void *_semtech_loramac_event_loop(void *arg) _semtech_loramac_send(mac, NULL, 0); mac->port = prev_port; } +#ifdef MODULE_SEMTECH_LORAMAC_RX if (indication->RxData) { DEBUG("[semtech-loramac] MCPS indication: data received\n"); memcpy(mac->rx_data.payload, @@ -755,6 +758,7 @@ void *_semtech_loramac_event_loop(void *arg) msg_ret.content.value = SEMTECH_LORAMAC_RX_CONFIRMED; msg_send(&msg_ret, mac->rx_pid); } +#endif break; } @@ -825,6 +829,7 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type) return SEMTECH_LORAMAC_JOIN_SUCCEEDED; } +#ifdef MODULE_SEMTECH_LORAMAC_RX void semtech_loramac_request_link_check(semtech_loramac_t *mac) { mutex_lock(&mac->lock); @@ -833,6 +838,7 @@ void semtech_loramac_request_link_check(semtech_loramac_t *mac) LoRaMacMlmeRequest(&mlmeReq); mutex_unlock(&mac->lock); } +#endif uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) { @@ -856,6 +862,7 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) return (uint8_t)msg.content.value; } +#ifdef MODULE_SEMTECH_LORAMAC_RX uint8_t semtech_loramac_recv(semtech_loramac_t *mac) { /* Correctly set the receiver thread pid */ @@ -868,3 +875,4 @@ uint8_t semtech_loramac_recv(semtech_loramac_t *mac) return (uint8_t)msg.content.value; } +#endif diff --git a/pkg/semtech-loramac/doc.txt b/pkg/semtech-loramac/doc.txt index 1ef4e0ca6a1a..9660698aa0d0 100644 --- a/pkg/semtech-loramac/doc.txt +++ b/pkg/semtech-loramac/doc.txt @@ -96,7 +96,12 @@ * } * ``` * - * To receive downlink messages, use a dedicated receiving thread. + * To receive downlink messages, enable the `semtech_loramac_rx` and use a + * dedicated receiving thread. + * - In the application Makefile, add + * ```mk + * USEMODULE += semtech_loramac_rx + * ``` * - At the beginning of the application source file, add the necessary * includes and declare the message queue and stack arrays: * ```c diff --git a/pkg/semtech-loramac/include/semtech_loramac.h b/pkg/semtech-loramac/include/semtech_loramac.h index 479b9c7e03d7..976ecc3660af 100644 --- a/pkg/semtech-loramac/include/semtech_loramac.h +++ b/pkg/semtech-loramac/include/semtech_loramac.h @@ -99,6 +99,7 @@ typedef struct { uint8_t port; /**< RX port */ } semtech_loramac_rx_data_t; +#if defined(MODULE_SEMTECH_LORAMAC_RX) || DOXYGEN /** * @brief LoRaMAC link check information */ @@ -106,6 +107,7 @@ typedef struct { uint8_t demod_margin; /**< Demodulation margin */ uint8_t nb_gateways; /**< number of LoRa gateways found */ } semtech_loramac_link_check_info_t; +#endif /** * @brief Semtech LoRaMAC descriptor @@ -113,7 +115,9 @@ typedef struct { typedef struct { mutex_t lock; /**< loramac access lock */ uint8_t tx_pid; /**< pid of sender thread */ +#if defined(MODULE_SEMTECH_LORAMAC_RX) || DOXYGEN uint8_t rx_pid; /**< pid of receiver thread */ +#endif uint8_t port; /**< application TX port */ uint8_t cnf; /**< enable/disable confirmable messages */ uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< device EUI */ @@ -122,8 +126,10 @@ typedef struct { 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 */ +#endif } semtech_loramac_t; /** @@ -172,6 +178,7 @@ uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type); */ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len); +#if defined(MODULE_SEMTECH_LORAMAC_RX) || DOXYGEN /** * @brief Wait for a message sent by the LoRaWAN network * @@ -184,6 +191,9 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) * Be sure to call this function before the end of the RX windows otherwise it * may block the calling thread. * + * By default this feature is not available to the user application, enable it + * by adding `USEMODULE += semtech_loramac_rx` to the application Makefile. + * * @see semtech_loramac_send * * @param[in] mac Pointer to the mac @@ -193,13 +203,19 @@ uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) * @return SEMTECH_LORAMAC_RX_CONFIRMED when an ACK is received from the network */ uint8_t semtech_loramac_recv(semtech_loramac_t *mac); +#endif +#if defined(MODULE_SEMTECH_LORAMAC_RX) || DOXYGEN /** * @brief Requests a LoRaWAN link check * + * By default this feature is not available to the user application, enable it + * by adding `USEMODULE += semtech_loramac_rx` to the application Makefile. + * * @param[in] mac Pointer to the mac */ void semtech_loramac_request_link_check(semtech_loramac_t *mac); +#endif /** * @brief Sets the device EUI From 14a4db137c4a7c7b644d7a3e858a2c9607d2624a Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Wed, 29 May 2019 10:11:39 +0200 Subject: [PATCH 7/8] tests/pkg_semtech-loramac: conditionally build RX related code --- tests/pkg_semtech-loramac/main.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tests/pkg_semtech-loramac/main.c b/tests/pkg_semtech-loramac/main.c index 235bc0d99a08..e5a068f43a7e 100644 --- a/tests/pkg_semtech-loramac/main.c +++ b/tests/pkg_semtech-loramac/main.c @@ -20,23 +20,26 @@ #include #include +#ifdef MODULE_SEMTECH_LORAMAC_RX #include "thread.h" #include "msg.h" +#endif + #include "shell.h" #include "fmt.h" #include "net/loramac.h" #include "semtech_loramac.h" -#define LORAMAC_RECV_MSG_QUEUE (4U) -static msg_t _loramac_recv_queue[LORAMAC_RECV_MSG_QUEUE]; - semtech_loramac_t loramac; /* Application key is 16 bytes long (e.g. 32 hex chars), and thus the longest possible size (with application session and network session keys) */ static char print_buf[LORAMAC_APPKEY_LEN * 2 + 1]; +#ifdef MODULE_SEMTECH_LORAMAC_RX +#define LORAMAC_RECV_MSG_QUEUE (4U) +static msg_t _loramac_recv_queue[LORAMAC_RECV_MSG_QUEUE]; static char _recv_stack[THREAD_STACKSIZE_DEFAULT]; static void *_wait_recv(void *arg) @@ -71,10 +74,14 @@ static void *_wait_recv(void *arg) } return NULL; } +#endif static void _loramac_usage(void) { - puts("Usage: loramac 2) { _loramac_usage(); @@ -481,6 +489,7 @@ static int _cmd_loramac(int argc, char **argv) semtech_loramac_request_link_check(&loramac); puts("Link check request scheduled"); } +#endif #ifdef MODULE_PERIPH_EEPROM else if (strcmp(argv[1], "save") == 0) { if (argc > 2) { @@ -516,8 +525,10 @@ int main(void) { semtech_loramac_init(&loramac); +#ifdef MODULE_SEMTECH_LORAMAC_RX thread_create(_recv_stack, sizeof(_recv_stack), THREAD_PRIORITY_MAIN - 1, 0, _wait_recv, NULL, "recv thread"); +#endif puts("All up, running the shell now"); char line_buf[SHELL_DEFAULT_BUFSIZE]; From 56fb2578bfe94f1e7acff0910ce684afdf498f49 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Tue, 21 May 2019 08:58:35 +0200 Subject: [PATCH 8/8] tests/pkg_semtech-loramac: use semtech_loramac_rx with supported boards --- tests/pkg_semtech-loramac/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/pkg_semtech-loramac/Makefile b/tests/pkg_semtech-loramac/Makefile index 256c8ab0d2c1..af4ead186eb7 100644 --- a/tests/pkg_semtech-loramac/Makefile +++ b/tests/pkg_semtech-loramac/Makefile @@ -9,12 +9,21 @@ BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-leonardo arduino-nano \ BOARD_BLACKLIST := msb-430 msb-430h pic32-clicker pic32-wifire \ telosb wsn430-v1_3b wsn430-v1_4 z1 +# waspmote-pro doesn't have enough RAM to support another thread dedicated to +# RX messages +BOARD_WITHOUT_LORAMAC_RX := waspmote-pro + LORA_DRIVER ?= sx1276 LORA_REGION ?= EU868 USEPKG += semtech-loramac USEMODULE += $(LORA_DRIVER) +# load loramac RX if board supports it +ifeq (,$(filter $(BOARD),$(BOARD_WITHOUT_LORAMAC_RX))) + USEMODULE += semtech_loramac_rx +endif + USEMODULE += shell USEMODULE += shell_commands USEMODULE += fmt