mirror of
https://github.com/espressif/openthread.git
synced 2026-08-17 16:09:51 +00:00
[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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -508,6 +508,7 @@ void radioSendMessage(otInstance *aInstance)
|
||||
{
|
||||
sTransmitMessage.mChannel = sTransmitFrame.mChannel;
|
||||
|
||||
otPlatRadioTxStarted(aInstance, &sTransmitFrame);
|
||||
radioTransmit(&sTransmitMessage, &sTransmitFrame);
|
||||
|
||||
sAckWait = isAckRequested(sTransmitFrame.mPsdu);
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user