mirror of https://github.com/ARMmbed/mbed-os.git
Fix an issue with sequence calls.
This issue is only present for a device in class c mode, which has perform unconfirmed uplinks. https://github.com/Lora-net/LoRaMac-node/issues/327pull/6411/head
parent
e206c1ee54
commit
6114f2b3d5
|
@ -299,7 +299,6 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
loramac_mhdr_t mac_hdr;
|
loramac_mhdr_t mac_hdr;
|
||||||
loramac_frame_ctrl_t fctrl;
|
loramac_frame_ctrl_t fctrl;
|
||||||
cflist_params_t cflist;
|
cflist_params_t cflist;
|
||||||
bool skip_indication = false;
|
|
||||||
|
|
||||||
uint8_t pkt_header_len = 0;
|
uint8_t pkt_header_len = 0;
|
||||||
uint32_t address = 0;
|
uint32_t address = 0;
|
||||||
|
@ -549,8 +548,8 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
// In this case, the MAC layer shall accept the MAC commands
|
// In this case, the MAC layer shall accept the MAC commands
|
||||||
// which are included in the downlink retransmission.
|
// which are included in the downlink retransmission.
|
||||||
// It should not provide the same frame to the application
|
// It should not provide the same frame to the application
|
||||||
// layer again.
|
// layer again. The MAC layer accepts the acknowledgement.
|
||||||
skip_indication = true;
|
_params.flags.bits.mcps_ind_skip = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_params.is_srv_ack_requested = false;
|
_params.is_srv_ack_requested = false;
|
||||||
|
@ -575,6 +574,9 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
if (fctrl.bits.ack == 1) {
|
if (fctrl.bits.ack == 1) {
|
||||||
// Reset MacCommandsBufferIndex when we have received an ACK.
|
// Reset MacCommandsBufferIndex when we have received an ACK.
|
||||||
mac_commands.clear_command_buffer();
|
mac_commands.clear_command_buffer();
|
||||||
|
// Update aknowledgement information
|
||||||
|
mcps.get_confirmation().ack_received = fctrl.bits.ack;
|
||||||
|
mcps.get_indication().is_ack_recvd = fctrl.bits.ack;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Reset the variable if we have received any valid frame.
|
// Reset the variable if we have received any valid frame.
|
||||||
|
@ -611,7 +613,10 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
mac_commands.clear_sticky_mac_cmd();
|
mac_commands.clear_sticky_mac_cmd();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
skip_indication = true;
|
_params.flags.bits.mcps_ind_skip = 1;
|
||||||
|
// This is not a valid frame. Drop it and reset the ACK bits
|
||||||
|
mcps.get_confirmation().ack_received = false;
|
||||||
|
mcps.get_indication().is_ack_recvd = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fctrl.bits.fopts_len > 0) {
|
if (fctrl.bits.fopts_len > 0) {
|
||||||
|
@ -636,11 +641,9 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
|
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip_indication == false) {
|
mcps.get_indication().buffer = _params.payload;
|
||||||
mcps.get_indication().buffer = _params.payload;
|
mcps.get_indication().buffer_size = frame_len;
|
||||||
mcps.get_indication().buffer_size = frame_len;
|
mcps.get_indication().is_data_recvd = true;
|
||||||
mcps.get_indication().is_data_recvd = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fctrl.bits.fopts_len > 0) {
|
if (fctrl.bits.fopts_len > 0) {
|
||||||
|
@ -657,29 +660,9 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skip_indication == false) {
|
|
||||||
// Check if the frame is an acknowledgement
|
|
||||||
if (fctrl.bits.ack == 1) {
|
|
||||||
mcps.get_confirmation().ack_received = true;
|
|
||||||
mcps.get_indication().is_ack_recvd = true;
|
|
||||||
|
|
||||||
// Stop the AckTimeout timer as no more retransmissions
|
|
||||||
// are needed.
|
|
||||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
|
||||||
} else {
|
|
||||||
mcps.get_confirmation().ack_received = false;
|
|
||||||
|
|
||||||
if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
|
|
||||||
// Stop the AckTimeout timer as no more retransmissions
|
|
||||||
// are needed.
|
|
||||||
_lora_time.stop( _params.timers.ack_timeout_timer );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Provide always an indication, skip the callback to the user application,
|
// Provide always an indication, skip the callback to the user application,
|
||||||
// in case of a confirmed downlink retransmission.
|
// in case of a confirmed downlink retransmission.
|
||||||
_params.flags.bits.mcps_ind = 1;
|
_params.flags.bits.mcps_ind = 1;
|
||||||
_params.flags.bits.mcps_ind_skip = skip_indication;
|
|
||||||
} else {
|
} else {
|
||||||
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
|
mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
|
||||||
|
|
||||||
|
@ -687,7 +670,6 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FRAME_TYPE_PROPRIETARY:
|
case FRAME_TYPE_PROPRIETARY:
|
||||||
|
@ -707,9 +689,16 @@ void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
|
||||||
prepare_rx_done_abort();
|
prepare_rx_done_abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_params.flags.bits.mac_done = 1;
|
|
||||||
|
|
||||||
_lora_time.start(_params.timers.mac_state_check_timer, 1);
|
// Verify if we need to disable the AckTimeoutTimer
|
||||||
|
check_to_disable_ack_timeout(_params.is_node_ack_requested, _params.dev_class, mcps.get_confirmation().ack_received,
|
||||||
|
_params.ack_timeout_retry_counter, _params.max_ack_timeout_retries );
|
||||||
|
|
||||||
|
if(_params.timers.ack_timeout_timer.timer_id == 0) {
|
||||||
|
_params.flags.bits.mac_done = 1;
|
||||||
|
|
||||||
|
_lora_time.start(_params.timers.mac_state_check_timer, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoRaMac::on_radio_tx_timeout( void )
|
void LoRaMac::on_radio_tx_timeout( void )
|
||||||
|
@ -1072,6 +1061,39 @@ void LoRaMac::on_rx_window2_timer_event(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoRaMac::check_to_disable_ack_timeout(bool node_ack_requested,
|
||||||
|
device_class_t dev_class,
|
||||||
|
bool ack_received,
|
||||||
|
uint8_t ack_timeout_retries_counter,
|
||||||
|
uint8_t ack_timeout_retries)
|
||||||
|
{
|
||||||
|
// There are three cases where we need to stop the AckTimeoutTimer:
|
||||||
|
if( node_ack_requested == false ) {
|
||||||
|
if( dev_class == CLASS_C ) {
|
||||||
|
// FIRST CASE
|
||||||
|
// We have performed an unconfirmed uplink in class c mode
|
||||||
|
// and have received a downlink in RX1 or RX2.
|
||||||
|
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if( ack_received == 1 ) {
|
||||||
|
// SECOND CASE
|
||||||
|
// We have performed a confirmed uplink and have received a
|
||||||
|
// downlink with a valid ACK.
|
||||||
|
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||||
|
} else {
|
||||||
|
// THIRD CASE
|
||||||
|
if( ack_timeout_retries_counter > ack_timeout_retries ) {
|
||||||
|
// We have performed a confirmed uplink and have not
|
||||||
|
// received a downlink with a valid ACK. In this case
|
||||||
|
// we need to verify if the maximum retries have been
|
||||||
|
// elapsed. If so, stop the timer.
|
||||||
|
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LoRaMac::on_ack_timeout_timer_event(void)
|
void LoRaMac::on_ack_timeout_timer_event(void)
|
||||||
{
|
{
|
||||||
_lora_time.stop(_params.timers.ack_timeout_timer);
|
_lora_time.stop(_params.timers.ack_timeout_timer);
|
||||||
|
|
|
@ -482,6 +482,23 @@ private:
|
||||||
*/
|
*/
|
||||||
void on_rx_window2_timer_event(void);
|
void on_rx_window2_timer_event(void);
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check if the OnAckTimeoutTimer has do be disabled. If so, the
|
||||||
|
* function disables it.
|
||||||
|
*
|
||||||
|
* \param [in] node_ack_requested Set to true, if the node has requested an ACK
|
||||||
|
* \param [in] dev_class The device class
|
||||||
|
* \param [in] ack_received Set to true, if the node has received an ACK
|
||||||
|
* \param [in] ack_timeout_retries_counter Retries counter for confirmed uplinks
|
||||||
|
* \param [in] ack_timeout_retries Maximum retries for confirmed uplinks
|
||||||
|
*/
|
||||||
|
void check_to_disable_ack_timeout(bool node_ack_requested,
|
||||||
|
device_class_t dev_class,
|
||||||
|
bool ack_received,
|
||||||
|
uint8_t ack_timeout_retries_counter,
|
||||||
|
uint8_t ack_timeout_retries);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function executed on AckTimeout timer event
|
* Function executed on AckTimeout timer event
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue