[radio] delayed transmission support (#1976)

* [radio] Add call from radio to MAC layer to indicate transmission start.

This call is used to start ACK timer. When transmission requested by the MAC
layer is delayed by the radio layer (e.g. due to BLE activity) ACK timer should
not be started when MAC requests transmission but when tranmission is started.
This commit provides required functions.

* [nRF52840] Queue transmission in radio platform to allow delayed transmission after BLE activity.

* Add note that otPlatRadioTxStarted() should be called by main OpenThread thread.
This commit is contained in:
Hubert Miś
2017-07-12 11:22:05 -07:00
committed by Jonathan Hui
parent 502c6ca5d6
commit f4fbac1254
12 changed files with 76 additions and 10 deletions
+2
View File
@@ -369,6 +369,8 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
// begin transmit
HWREG(RFCORE_SFR_RFST) = RFCORE_SFR_RFST_INSTR_TXON;
otPlatRadioTxStarted(aInstance, aFrame);
while (HWREG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE);
otLogDebgPlat(sInstance, "Transmitted %d bytes", aFrame->mLength);
+2
View File
@@ -1353,6 +1353,8 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
otEXPECT_ACTION(rfCoreSendTransmitCmd(aFrame->mPsdu, aFrame->mLength - 2) == CMDSTA_Done,
error = OT_ERROR_FAILED);
error = OT_ERROR_NONE;
otPlatRadioTxStarted(aInstance, aFrame);
}
}
+2
View File
@@ -411,6 +411,8 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
ad_ftdf_send_frame_simple(aFrame->mLength, aFrame->mPsdu, aFrame->mChannel, 0, csmaSuppress); //Prio 0 for all.
sRadioState = OT_RADIO_STATE_TRANSMIT;
otPlatRadioTxStarted(aInstance, aFrame);
exit:
return error;
}
+2
View File
@@ -345,6 +345,8 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
otEXPECT_ACTION(RAIL_TxStartWithOptions(aFrame->mChannel, &txOption, RAIL_CcaCsma, &csmaConfig) == RAIL_STATUS_NO_ERROR,
error = OT_ERROR_FAILED);
otPlatRadioTxStarted(aInstance, aFrame);
exit:
CORE_EXIT_CRITICAL();
return error;
+2 -1
View File
@@ -473,7 +473,6 @@ exit:
void radioTransmitMessage(otInstance *aInstance)
{
(void)aInstance;
uint8_t header_len = 0;
sTransmitError = OT_ERROR_NONE;
@@ -506,6 +505,8 @@ void radioTransmitMessage(otInstance *aInstance)
mrf24j40_write_short_ctrl_reg(MRF24J40_TXNCON, reg | MRF24J40_TXNTRIG);
otPlatRadioTxStarted(aInstance, &sTransmitFrame);
int16_t tx_timeout = 500;
Mrf24StatusTx = 0;
+2 -2
View File
@@ -335,8 +335,6 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
otError status = OT_ERROR_NONE;
uint32_t timeout;
(void) aInstance;
otEXPECT_ACTION(((sState != OT_RADIO_STATE_TRANSMIT) &&
(sState != OT_RADIO_STATE_DISABLED)), status = OT_ERROR_INVALID_STATE);
@@ -379,6 +377,8 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
/* Unmask SEQ interrupt */
ZLL->PHY_CTRL &= ~ZLL_PHY_CTRL_SEQMSK_MASK;
otPlatRadioTxStarted(aInstance, aFrame);
exit:
return status;
}
+19 -1
View File
@@ -92,6 +92,7 @@ static int8_t sEnergyDetected;
typedef enum
{
kPendingEventSleep, // Requested to enter Sleep state.
kPendingEventTransmit, // Frame is queued for transmission.
kPendingEventFrameTransmitted, // Transmitted frame and received ACK (if requested).
kPendingEventChannelAccessFailure, // Failed to transmit frame (channel busy).
kPendingEventEnergyDetectionStart, // Requested to start Energy Detection procedure.
@@ -327,11 +328,12 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame)
if (nrf_drv_radio802154_transmit(&aFrame->mPsdu[-1], aFrame->mChannel, aFrame->mPower, true))
{
clearPendingEvents();
otPlatRadioTxStarted(aInstance, aFrame);
}
else
{
clearPendingEvents();
setPendingEvent(kPendingEventChannelAccessFailure);
setPendingEvent(kPendingEventTransmit);
}
return OT_ERROR_NONE;
@@ -523,6 +525,15 @@ void nrf5RadioProcess(otInstance *aInstance)
}
}
if (isPendingEventSet(kPendingEventTransmit))
{
if (nrf_drv_radio802154_transmit(sTransmitPsdu, sTransmitFrame.mChannel, sTransmitFrame.mPower, true))
{
resetPendingEvent(kPendingEventTransmit);
otPlatRadioTxStarted(aInstance, &sTransmitFrame);
}
}
if (isPendingEventSet(kPendingEventFrameTransmitted))
{
#if OPENTHREAD_ENABLE_DIAG
@@ -592,6 +603,13 @@ void nrf_drv_radio802154_received(uint8_t *p_data, int8_t power, int8_t lqi)
{
otRadioFrame *receivedFrame = NULL;
if (isPendingEventSet(kPendingEventTransmit))
{
nrf_drv_radio802154_buffer_free(p_data);
return;
}
for (uint32_t i = 0; i < RADIO_RX_BUFFERS; i++)
{
if (sReceivedFrames[i].mPsdu == NULL)
+1
View File
@@ -508,6 +508,7 @@ void radioSendMessage(otInstance *aInstance)
{
sTransmitMessage.mChannel = sTransmitFrame.mChannel;
otPlatRadioTxStarted(aInstance, &sTransmitFrame);
radioTransmit(&sTransmitMessage, &sTransmitFrame);
sAckWait = isAckRequested(sTransmitFrame.mPsdu);
+12
View File
@@ -388,6 +388,18 @@ otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance);
*/
otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame);
/**
* The radio driver calls this method to notify OpenThread that the transmission has started.
*
* @note This function should be called by the same thread that executes all of the other OpenThread code. It should
* not be called by ISR or any other task.
*
* @param[in] aInstance A pointer to the OpenThread instance structure.
* @param[in] aFrame A pointer to the frame that is being transmitted.
*
*/
extern void otPlatRadioTxStarted(otInstance *aInstance, otRadioFrame *aFrame);
/**
* The radio driver calls this method to notify OpenThread that the transmission has completed,
* this callback pass up the ACK frame, new add platforms should use this callback function.
+20 -6
View File
@@ -832,12 +832,6 @@ void Mac::HandleBeginTransmit(void)
assert(error == OT_ERROR_NONE);
if (sendFrame.GetAckRequest() && !(otPlatRadioGetCaps(GetInstance()) & OT_RADIO_CAPS_ACK_TIMEOUT))
{
mMacTimer.Start(kAckTimeout);
otLogDebgMac(GetInstance(), "Ack timer start");
}
if (mPcapCallback)
{
sendFrame.mDidTX = true;
@@ -856,6 +850,26 @@ exit:
}
}
extern "C" void otPlatRadioTxStarted(otInstance *aInstance, otRadioFrame *aFrame)
{
otLogFuncEntry();
aInstance->mThreadNetif.GetMac().TransmitStartedTask(aFrame);
otLogFuncExit();
}
void Mac::TransmitStartedTask(otRadioFrame *aFrame)
{
Frame *frame = static_cast<Frame *>(aFrame);
if (frame->GetAckRequest() && !(otPlatRadioGetCaps(GetInstance()) & OT_RADIO_CAPS_ACK_TIMEOUT))
{
mMacTimer.Start(kAckTimeout);
otLogDebgMac(GetInstance(), "Ack timer start");
}
}
#if OPENTHREAD_CONFIG_LEGACY_TRANSMIT_DONE
extern "C" void otPlatRadioTransmitDone(otInstance *aInstance, otRadioFrame *aFrame, bool aRxPending,
otError aError)
+7
View File
@@ -501,6 +501,13 @@ public:
*/
void ReceiveDoneTask(Frame *aFrame, otError aError);
/**
* This method is called to handle transmission start events.
*
* @param[in] aFrame A pointer to the frame that is transmitted.
*/
void TransmitStartedTask(otRadioFrame *aFrame);
#if OPENTHREAD_CONFIG_LEGACY_TRANSMIT_DONE
/**
* This method is called to handle transmit events.
+5
View File
@@ -70,6 +70,11 @@ extern "C" void otPlatRadioReceiveDone(otInstance *, otRadioFrame *aFrame, otErr
(void)aError;
}
extern "C" void otPlatRadioTxStarted(otInstance *, otRadioFrame *aFrame)
{
(void) aFrame;
}
/**
* diagnostics module tests