Skip to content

Commit 5e4b872

Browse files
authored
Merge pull request #8393 from cmonr/unittest-fix
Revert "Merge pull request #8183 from hasnainvirk/QOS_impl"
2 parents 19190d6 + dd8e9bb commit 5e4b872

File tree

11 files changed

+148
-269
lines changed

11 files changed

+148
-269
lines changed

features/lorawan/LoRaWANStack.cpp

Lines changed: 86 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ SPDX-License-Identifier: BSD-3-Clause
4040
* Control flags for transient states
4141
*/
4242
#define IDLE_FLAG 0x00000000
43-
#define RETRY_EXHAUSTED_FLAG 0x00000001
43+
#define TX_ONGOING_FLAG 0x00000001
4444
#define MSG_RECVD_FLAG 0x00000002
4545
#define CONNECTED_FLAG 0x00000004
4646
#define USING_OTAA_FLAG 0x00000008
@@ -68,7 +68,6 @@ LoRaWANStack::LoRaWANStack()
6868
_tx_metadata(),
6969
_rx_metadata(),
7070
_num_retry(1),
71-
_qos_cnt(1),
7271
_ctrl_flags(IDLE_FLAG),
7372
_app_port(INVALID_PORT),
7473
_link_check_requested(false),
@@ -275,6 +274,7 @@ lorawan_status_t LoRaWANStack::stop_sending(void)
275274

276275
if (_loramac.clear_tx_pipe() == LORAWAN_STATUS_OK) {
277276
_ctrl_flags &= ~TX_DONE_FLAG;
277+
_ctrl_flags &= ~TX_ONGOING_FLAG;
278278
_loramac.set_tx_ongoing(false);
279279
_device_current_state = DEVICE_STATE_IDLE;
280280
return LORAWAN_STATUS_OK;
@@ -449,8 +449,7 @@ lorawan_status_t LoRaWANStack::set_device_class(const device_class_t &device_cla
449449
if (device_class == CLASS_B) {
450450
return LORAWAN_STATUS_UNSUPPORTED;
451451
}
452-
_loramac.set_device_class(device_class,
453-
mbed::callback(this, &LoRaWANStack::post_process_tx_no_reception));
452+
_loramac.set_device_class(device_class, mbed::callback(this, &LoRaWANStack::handle_ack_expiry_for_class_c));
454453
return LORAWAN_STATUS_OK;
455454
}
456455

@@ -560,6 +559,7 @@ void LoRaWANStack::process_transmission_timeout()
560559
// this is a fatal error and should not happen
561560
tr_debug("TX Timeout");
562561
_loramac.on_radio_tx_timeout();
562+
_ctrl_flags &= ~TX_ONGOING_FLAG;
563563
_ctrl_flags &= ~TX_DONE_FLAG;
564564
if (_device_current_state == DEVICE_STATE_JOINING) {
565565
mlme_confirm_handler();
@@ -573,110 +573,41 @@ void LoRaWANStack::process_transmission_timeout()
573573
void LoRaWANStack::process_transmission(void)
574574
{
575575
tr_debug("Transmission completed");
576+
_loramac.on_radio_tx_done(_tx_timestamp);
577+
578+
make_tx_metadata_available();
576579

577580
if (_device_current_state == DEVICE_STATE_JOINING) {
578581
_device_current_state = DEVICE_STATE_AWAITING_JOIN_ACCEPT;
579582
}
580583

581584
if (_device_current_state == DEVICE_STATE_SENDING) {
582585
if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) {
586+
_ctrl_flags |= TX_ONGOING_FLAG;
587+
_ctrl_flags &= ~TX_DONE_FLAG;
583588
tr_debug("Awaiting ACK");
584589
_device_current_state = DEVICE_STATE_AWAITING_ACK;
585-
}
586-
}
587-
588-
_loramac.on_radio_tx_done(_tx_timestamp);
589-
}
590-
591-
void LoRaWANStack::post_process_tx_with_reception()
592-
{
593-
if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) {
594-
// if ack was not received, we will try retransmission after
595-
// ACK_TIMEOUT. handle_data_frame() already disables ACK_TIMEOUT timer
596-
// if ack was received. Otherwise, following method will be called in
597-
// LoRaMac.cpp, on_ack_timeout_timer_event().
598-
if (_loramac.get_mcps_indication()->is_ack_recvd) {
590+
} else if (_loramac.get_device_class() == CLASS_A) {
591+
// Class A unconfirmed message sent, TX_DONE event will be sent to
592+
// application when RX2 windows is elapsed, i.e., in process_reception_timeout()
593+
_ctrl_flags &= ~TX_ONGOING_FLAG;
599594
_ctrl_flags |= TX_DONE_FLAG;
600-
_ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
601-
tr_debug("Ack=OK, NbTrials=%d",
602-
_loramac.get_mcps_confirmation()->nb_retries);
603-
_loramac.post_process_mcps_req();
604-
make_tx_metadata_available();
605-
state_controller(DEVICE_STATE_STATUS_CHECK);
606-
} else {
607-
if (!_loramac.continue_sending_process()
608-
&& _loramac.get_current_slot() != RX_SLOT_WIN_1) {
609-
tr_error("Retries exhausted for Class %s device",
610-
_loramac.get_device_class() == CLASS_A ? "A" : "C");
611-
_ctrl_flags &= ~TX_DONE_FLAG;
612-
_ctrl_flags |= RETRY_EXHAUSTED_FLAG;
613-
state_controller(DEVICE_STATE_STATUS_CHECK);
614-
}
615-
}
616-
} else {
617-
// handle UNCONFIRMED case here, RX slots were turned off due to
618-
// valid packet reception.
619-
uint8_t prev_QOS_level = _loramac.get_prev_QOS_level();
620-
uint8_t QOS_level = _loramac.get_QOS_level();
621-
622-
// We will not apply QOS on the post-processing of the previous
623-
// outgoing message as we would have received QOS instruction in response
624-
// to that particular message
625-
if (QOS_level > LORAWAN_DEFAULT_QOS && _qos_cnt < QOS_level
626-
&& (prev_QOS_level == QOS_level)) {
627-
_ctrl_flags &= ~TX_DONE_FLAG;
628-
const int ret = _queue->call(this, &LoRaWANStack::state_controller,
629-
DEVICE_STATE_SCHEDULING);
630-
MBED_ASSERT(ret != 0);
631-
(void) ret;
632-
_qos_cnt++;
633-
tr_info("QOS: repeated transmission #%d queued", _qos_cnt);
634-
} else {
595+
} else if (_loramac.get_device_class() == CLASS_C) {
596+
// In Class C, reception timeout never happens, so we handle the state
597+
// progression for TX_DONE in UNCONFIRMED case here
635598
_loramac.post_process_mcps_req();
636-
_ctrl_flags |= TX_DONE_FLAG;
637-
make_tx_metadata_available();
638599
state_controller(DEVICE_STATE_STATUS_CHECK);
600+
state_machine_run_to_completion();
639601
}
640602
}
641603
}
642604

643-
void LoRaWANStack::post_process_tx_no_reception()
605+
void LoRaWANStack::handle_ack_expiry_for_class_c(void)
644606
{
645-
if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) {
646-
if (_loramac.continue_sending_process()) {
647-
_ctrl_flags &= ~TX_DONE_FLAG;
648-
_ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
649-
return;
650-
}
651-
652-
tr_error("Retries exhausted for Class %s device",
653-
_loramac.get_device_class() == CLASS_A ? "A" : "C");
654-
_ctrl_flags &= ~TX_DONE_FLAG;
655-
_ctrl_flags |= RETRY_EXHAUSTED_FLAG;
656-
} else {
657-
_ctrl_flags |= TX_DONE_FLAG;
658-
659-
uint8_t prev_QOS_level = _loramac.get_prev_QOS_level();
660-
uint8_t QOS_level = _loramac.get_QOS_level();
661-
662-
if (QOS_level > LORAWAN_DEFAULT_QOS && (prev_QOS_level == QOS_level)) {
663-
if (_qos_cnt < QOS_level) {
664-
const int ret = _queue->call(this, &LoRaWANStack::state_controller,
665-
DEVICE_STATE_SCHEDULING);
666-
MBED_ASSERT(ret != 0);
667-
(void)ret;
668-
_qos_cnt++;
669-
tr_info("QOS: repeated transmission #%d queued", _qos_cnt);
670-
state_machine_run_to_completion();
671-
return;
672-
}
673-
}
674-
}
675-
676-
_loramac.post_process_mcps_req();
677-
make_tx_metadata_available();
607+
_ctrl_flags &= ~TX_DONE_FLAG;
608+
_ctrl_flags |= TX_ONGOING_FLAG;
609+
tr_error("Retries exhausted for Class C device");
678610
state_controller(DEVICE_STATE_STATUS_CHECK);
679-
state_machine_run_to_completion();
680611
}
681612

682613
void LoRaWANStack::handle_scheduling_failure(void)
@@ -686,18 +617,16 @@ void LoRaWANStack::handle_scheduling_failure(void)
686617
state_machine_run_to_completion();
687618
}
688619

689-
690620
void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size,
691621
int16_t rssi, int8_t snr)
692622
{
693623
_device_current_state = DEVICE_STATE_RECEIVING;
694-
695624
_ctrl_flags &= ~MSG_RECVD_FLAG;
696-
_ctrl_flags &= ~TX_DONE_FLAG;
697-
_ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
698625

699626
_loramac.on_radio_rx_done(payload, size, rssi, snr);
700627

628+
make_rx_metadata_available();
629+
701630
if (_loramac.get_mlme_confirmation()->pending) {
702631
_loramac.post_process_mlme_request();
703632
mlme_confirm_handler();
@@ -713,10 +642,36 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size
713642
return;
714643
}
715644

716-
make_rx_metadata_available();
717-
718-
// Post process transmission in response to the reception
719-
post_process_tx_with_reception();
645+
// if the outgoing message was of CONFIRMED type
646+
if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) {
647+
// if ack was not received, we will try retransmission after
648+
// ACK_TIMEOUT. handle_data_frame() already disables ACK_TIMEOUT timer
649+
// if ack was received. Otherwise, following method will be called in
650+
// LoRaMac.cpp, on_ack_timeout_timer_event().
651+
if (_loramac.get_mcps_indication()->is_ack_recvd) {
652+
tr_debug("Ack=OK, NbTrials=%d",
653+
_loramac.get_mcps_confirmation()->nb_retries);
654+
_loramac.post_process_mcps_req();
655+
_ctrl_flags |= TX_DONE_FLAG;
656+
_ctrl_flags &= ~TX_ONGOING_FLAG;
657+
state_controller(DEVICE_STATE_STATUS_CHECK);
658+
} else {
659+
if (!_loramac.continue_sending_process() &&
660+
_loramac.get_current_slot() != RX_SLOT_WIN_1) {
661+
tr_error("Retries exhausted for Class A device");
662+
_ctrl_flags &= ~TX_DONE_FLAG;
663+
_ctrl_flags |= TX_ONGOING_FLAG;
664+
state_controller(DEVICE_STATE_STATUS_CHECK);
665+
}
666+
}
667+
} else if (_loramac.get_device_class() == CLASS_A) {
668+
// handle UNCONFIRMED case here, RX slots were turned off due to
669+
// valid packet reception. For Class C, an outgoing UNCONFIRMED message
670+
// gets its handling in process_transmission.
671+
_loramac.post_process_mcps_req();
672+
_ctrl_flags |= TX_DONE_FLAG;
673+
state_controller(DEVICE_STATE_STATUS_CHECK);
674+
}
720675

721676
// handle any pending MCPS indication
722677
if (_loramac.get_mcps_indication()->pending) {
@@ -725,13 +680,15 @@ void LoRaWANStack::process_reception(const uint8_t *const payload, uint16_t size
725680
state_controller(DEVICE_STATE_STATUS_CHECK);
726681
}
727682

728-
// complete the cycle only if TX_DONE_FLAG is set
729-
if (_ctrl_flags & TX_DONE_FLAG) {
683+
// change the state only if a TX cycle completes for Class A
684+
// For class C it's not needed as it will already be in receiving
685+
// state, no matter if the TX cycle completed or not.
686+
if (!(_ctrl_flags & TX_ONGOING_FLAG)) {
687+
// we are done here, update the state
730688
state_machine_run_to_completion();
731689
}
732690

733-
// suppress auto uplink if another auto-uplink is in AWAITING_ACK state
734-
if (_loramac.get_mlme_indication()->pending && !_automatic_uplink_ongoing) {
691+
if (_loramac.get_mlme_indication()->pending) {
735692
tr_debug("MLME Indication pending");
736693
_loramac.post_process_mlme_ind();
737694
tr_debug("Immediate Uplink requested");
@@ -767,7 +724,18 @@ void LoRaWANStack::process_reception_timeout(bool is_timeout)
767724
* never occurs.
768725
*/
769726
if (slot == RX_SLOT_WIN_2) {
770-
post_process_tx_no_reception();
727+
_loramac.post_process_mcps_req();
728+
729+
if (_loramac.get_mcps_confirmation()->req_type == MCPS_CONFIRMED) {
730+
if (_loramac.continue_sending_process()) {
731+
return;
732+
} else {
733+
tr_error("Retries exhausted for Class A device");
734+
}
735+
}
736+
737+
state_controller(DEVICE_STATE_STATUS_CHECK);
738+
state_machine_run_to_completion();
771739
}
772740
}
773741

@@ -1056,15 +1024,11 @@ void LoRaWANStack::mcps_indication_handler()
10561024
|| (_loramac.get_device_class() == CLASS_C
10571025
&& mcps_indication->type == MCPS_CONFIRMED)) {
10581026
#if (MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE)
1059-
// Do not queue an automatic uplink of there is one already outgoing
1060-
// This means we have not received an ack for the previous automatic uplink
1061-
if (!_automatic_uplink_ongoing) {
1062-
tr_debug("Sending empty uplink message...");
1063-
_automatic_uplink_ongoing = true;
1064-
const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port);
1065-
MBED_ASSERT(ret != 0);
1066-
(void)ret;
1067-
}
1027+
tr_debug("Sending empty uplink message...");
1028+
_automatic_uplink_ongoing = true;
1029+
const int ret = _queue->call(this, &LoRaWANStack::send_automatic_uplink_message, mcps_indication->port);
1030+
MBED_ASSERT(ret != 0);
1031+
(void)ret;
10681032
#else
10691033
send_event_to_application(UPLINK_REQUIRED);
10701034
#endif
@@ -1118,7 +1082,8 @@ void LoRaWANStack::process_shutdown_state(lorawan_status_t &op_status)
11181082
_lw_session.active = false;
11191083
_device_current_state = DEVICE_STATE_SHUTDOWN;
11201084
op_status = LORAWAN_STATUS_DEVICE_OFF;
1121-
_ctrl_flags = 0;
1085+
_ctrl_flags &= ~CONNECTED_FLAG;
1086+
_ctrl_flags &= ~CONN_IN_PROGRESS_FLAG;
11221087
send_event_to_application(DISCONNECTED);
11231088
}
11241089

@@ -1134,15 +1099,20 @@ void LoRaWANStack::process_status_check_state()
11341099
// Another possibility is the case when the stack fails to schedule a
11351100
// deferred transmission and a scheduling failure handler is invoked.
11361101
_ctrl_flags &= ~TX_DONE_FLAG;
1102+
_ctrl_flags &= ~TX_ONGOING_FLAG;
11371103
_loramac.set_tx_ongoing(false);
11381104
_loramac.reset_ongoing_tx();
11391105
mcps_confirm_handler();
11401106

11411107
} else if (_device_current_state == DEVICE_STATE_RECEIVING) {
11421108

1143-
if ((_ctrl_flags & TX_DONE_FLAG) || (_ctrl_flags & RETRY_EXHAUSTED_FLAG)) {
1109+
if ((_ctrl_flags & TX_DONE_FLAG) || (_ctrl_flags & TX_ONGOING_FLAG)) {
1110+
// for CONFIRMED case, ack validity is already checked
1111+
// If it was a successful transmission, TX_ONGOING_FLAG will not be set.
1112+
// If it was indeed set, that means the device was in Class C mode and
1113+
// CONFIRMED transmission was in place and the ack retries maxed out.
11441114
_ctrl_flags &= ~TX_DONE_FLAG;
1145-
_ctrl_flags &= ~RETRY_EXHAUSTED_FLAG;
1115+
_ctrl_flags &= ~TX_ONGOING_FLAG;
11461116
_loramac.set_tx_ongoing(false);
11471117
_loramac.reset_ongoing_tx();
11481118
// if an automatic uplink is ongoing, we should not send a TX_DONE
@@ -1174,6 +1144,7 @@ void LoRaWANStack::process_scheduling_state(lorawan_status_t &op_status)
11741144

11751145
op_status = _loramac.send_ongoing_tx();
11761146
if (op_status == LORAWAN_STATUS_OK) {
1147+
_ctrl_flags |= TX_ONGOING_FLAG;
11771148
_ctrl_flags &= ~TX_DONE_FLAG;
11781149
_loramac.set_tx_ongoing(true);
11791150
_device_current_state = DEVICE_STATE_SENDING;

features/lorawan/LoRaWANStack.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,9 @@ class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> {
483483
void make_tx_metadata_available(void);
484484
void make_rx_metadata_available(void);
485485

486+
void handle_ack_expiry_for_class_c(void);
486487
void handle_scheduling_failure(void);
487488

488-
void post_process_tx_with_reception(void);
489-
void post_process_tx_no_reception(void);
490-
491489
private:
492490
LoRaMac _loramac;
493491
radio_events_t radio_events;
@@ -499,7 +497,6 @@ class LoRaWANStack: private mbed::NonCopyable<LoRaWANStack> {
499497
lorawan_tx_metadata _tx_metadata;
500498
lorawan_rx_metadata _rx_metadata;
501499
uint8_t _num_retry;
502-
uint8_t _qos_cnt;
503500
uint32_t _ctrl_flags;
504501
uint8_t _app_port;
505502
bool _link_check_requested;

0 commit comments

Comments
 (0)