[link-raw] fix radio with multiple transmit buffers (#3239)

This commit is contained in:
Yakun Xu
2018-11-01 21:34:51 -07:00
committed by Jonathan Hui
parent 706b393a7b
commit 92bcf61a8e
10 changed files with 228 additions and 175 deletions
@@ -244,4 +244,12 @@ void otSimSendEvent(const struct Event *aEvent);
*/
void otSimSendUartWriteEvent(const uint8_t *aData, uint16_t aLength);
/**
* This function checks if radio transmitting is pending.
*
* @returns Whether radio transmitting is pending.
*
*/
bool platformRadioIsTransmitPending(void);
#endif // PLATFORM_POSIX_H_
+1 -1
View File
@@ -281,7 +281,7 @@ void otSysProcessDrivers(otInstance *aInstance)
platformUartUpdateFdSet(&read_fds, &write_fds, &error_fds, &max_fd);
#endif
if (!otTaskletsArePending(aInstance) && platformAlarmGetNext() > 0)
if (!otTaskletsArePending(aInstance) && platformAlarmGetNext() > 0 && !platformRadioIsTransmitPending())
{
platformSendSleepEvent();
+6 -1
View File
@@ -540,9 +540,14 @@ void radioSendMessage(otInstance *aInstance)
sAckWait = true;
}
bool platformRadioIsTransmitPending(void)
{
return sState == OT_RADIO_STATE_TRANSMIT && !sAckWait;
}
void platformRadioProcess(otInstance *aInstance)
{
if (sState == OT_RADIO_STATE_TRANSMIT && !sAckWait)
if (platformRadioIsTransmitPending())
{
radioSendMessage(aInstance);
}
+1 -2
View File
@@ -177,14 +177,13 @@ typedef void (*otLinkRawTransmitDone)(otInstance * aInstance,
* 2. Transmits the PSDU on the given channel and at the given transmit power.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aFrame A pointer to the frame that was transmitted.
* @param[in] aCallback A pointer to a function called on completion of the transmission.
*
* @retval OT_ERROR_NONE Successfully transitioned to Transmit.
* @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state.
*
*/
otError otLinkRawTransmit(otInstance *aInstance, otRadioFrame *aFrame, otLinkRawTransmitDone aCallback);
otError otLinkRawTransmit(otInstance *aInstance, otLinkRawTransmitDone aCallback);
/**
* Get the most recent RSSI measurement.
+4 -11
View File
@@ -105,20 +105,13 @@ otError otLinkRawReceive(otInstance *aInstance, otLinkRawReceiveDone aCallback)
otRadioFrame *otLinkRawGetTransmitBuffer(otInstance *aInstance)
{
otRadioFrame *buffer = NULL;
VerifyOrExit(static_cast<Instance *>(aInstance)->GetLinkRaw().IsEnabled());
buffer = otPlatRadioGetTransmitBuffer(aInstance);
exit:
return buffer;
return static_cast<Instance *>(aInstance)->GetLinkRaw().GetTransmitFrame();
}
otError otLinkRawTransmit(otInstance *aInstance, otRadioFrame *aFrame, otLinkRawTransmitDone aCallback)
otError otLinkRawTransmit(otInstance *aInstance, otLinkRawTransmitDone aCallback)
{
otLogInfoPlat("LinkRaw Transmit (%d bytes on channel %d)", aFrame->mLength, aFrame->mChannel);
return static_cast<Instance *>(aInstance)->GetLinkRaw().Transmit(aFrame, aCallback);
otLogInfoPlat("LinkRaw Transmit");
return static_cast<Instance *>(aInstance)->GetLinkRaw().Transmit(aCallback);
}
int8_t otLinkRawGetRssi(otInstance *aInstance)
+3 -3
View File
@@ -407,7 +407,7 @@ public:
* @returns A reference to the LinkRaw object.
*
*/
LinkRaw &GetLinkRaw(void) { return mLinkRaw; }
Mac::LinkRaw &GetLinkRaw(void) { return mLinkRaw; }
#endif
private:
@@ -460,7 +460,7 @@ private:
MessagePool mMessagePool;
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
LinkRaw mLinkRaw;
Mac::LinkRaw mLinkRaw;
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
#if OPENTHREAD_CONFIG_ENABLE_DYNAMIC_LOG_LEVEL
@@ -689,7 +689,7 @@ template <> inline AnnounceSender &Instance::Get(void)
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
template <> inline LinkRaw &Instance::Get(void)
template <> inline Mac::LinkRaw &Instance::Get(void)
{
return GetLinkRaw();
}
+163 -143
View File
@@ -49,8 +49,12 @@
namespace ot {
namespace Mac {
LinkRaw::LinkRaw(Instance &aInstance)
: mInstance(aInstance)
: InstanceLocator(aInstance)
, mOperationTask(aInstance, &LinkRaw::HandleOperationTask, this)
, mPendingTransmitData(false)
#if OPENTHREAD_LINKRAW_TIMER_REQUIRED
, mTimer(aInstance, &LinkRaw::HandleTimer, this)
, mTimerReason(kTimerReasonNone)
@@ -60,17 +64,33 @@ LinkRaw::LinkRaw(Instance &aInstance)
, mEnergyScanTimer(aInstance, &LinkRaw::HandleTimer, this)
#endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER
#endif // OPENTHREAD_LINKRAW_TIMER_REQUIRED
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
, mCsmaBackoffs(0)
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
, mTransmitRetries(0)
, mCsmaBackoffs(0)
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
, mReceiveChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL)
, mReceiveDoneCallback(NULL)
, mTransmitDoneCallback(NULL)
, mEnergyScanDoneCallback(NULL)
, mTransmitFrame(static_cast<Frame *>(otPlatRadioGetTransmitBuffer(&aInstance)))
, mRadioCaps(otPlatRadioGetCaps(&aInstance))
{
// Query the capabilities to check asserts
(void)GetCaps();
}
void LinkRaw::HandleOperationTask(Tasklet &aTasklet)
{
aTasklet.GetOwner<LinkRaw>().HandleOperationTask();
}
void LinkRaw::HandleOperationTask(void)
{
if (mPendingTransmitData)
{
mPendingTransmitData = false;
TransmitNow();
}
}
otError LinkRaw::SetEnabled(bool aEnabled)
@@ -80,16 +100,16 @@ otError LinkRaw::SetEnabled(bool aEnabled)
otLogInfoPlat("LinkRaw Enabled=%d", aEnabled ? 1 : 0);
#if OPENTHREAD_MTD || OPENTHREAD_FTD
VerifyOrExit(!static_cast<Instance &>(mInstance).GetThreadNetif().IsUp(), error = OT_ERROR_INVALID_STATE);
VerifyOrExit(!GetInstance().GetThreadNetif().IsUp(), error = OT_ERROR_INVALID_STATE);
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
if (aEnabled)
{
otPlatRadioEnable(&mInstance);
otPlatRadioEnable(&GetInstance());
}
else
{
otPlatRadioDisable(&mInstance);
otPlatRadioDisable(&GetInstance());
}
mEnabled = aEnabled;
@@ -106,7 +126,7 @@ otError LinkRaw::SetPanId(uint16_t aPanId)
VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
otPlatRadioSetPanId(&mInstance, aPanId);
otPlatRadioSetPanId(&GetInstance(), aPanId);
mPanId = aPanId;
exit:
@@ -137,7 +157,7 @@ otError LinkRaw::SetExtAddress(const otExtAddress &aExtAddress)
addr.m8[i] = aExtAddress.m8[7 - i];
}
otPlatRadioSetExtendedAddress(&mInstance, &addr);
otPlatRadioSetExtendedAddress(&GetInstance(), &addr);
mExtAddress = aExtAddress;
exit:
@@ -150,7 +170,7 @@ otError LinkRaw::SetShortAddress(uint16_t aShortAddress)
VerifyOrExit(IsEnabled(), error = OT_ERROR_INVALID_STATE);
otPlatRadioSetShortAddress(&mInstance, aShortAddress);
otPlatRadioSetShortAddress(&GetInstance(), aShortAddress);
mShortAddress = aShortAddress;
exit:
@@ -159,40 +179,25 @@ exit:
otRadioCaps LinkRaw::GetCaps(void) const
{
otRadioCaps RadioCaps = otPlatRadioGetCaps(&mInstance);
// The radio shouldn't support a capability if it is being compile
// time included into the raw link-layer code.
otRadioCaps radioCaps = mRadioCaps;
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
if ((RadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) == 0)
{
RadioCaps = static_cast<otRadioCaps>(RadioCaps | OT_RADIO_CAPS_ACK_TIMEOUT);
}
radioCaps |= OT_RADIO_CAPS_ACK_TIMEOUT;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
if ((RadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) == 0)
{
RadioCaps = static_cast<otRadioCaps>(RadioCaps | OT_RADIO_CAPS_TRANSMIT_RETRIES);
}
radioCaps |= OT_RADIO_CAPS_TRANSMIT_RETRIES;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
if ((RadioCaps & OT_RADIO_CAPS_CSMA_BACKOFF) == 0)
{
RadioCaps = static_cast<otRadioCaps>(RadioCaps | OT_RADIO_CAPS_CSMA_BACKOFF);
}
radioCaps |= OT_RADIO_CAPS_CSMA_BACKOFF;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN
if ((RadioCaps & OT_RADIO_CAPS_ENERGY_SCAN) == 0)
{
RadioCaps = static_cast<otRadioCaps>(RadioCaps | OT_RADIO_CAPS_ENERGY_SCAN);
}
radioCaps |= OT_RADIO_CAPS_ENERGY_SCAN;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN
return RadioCaps;
return radioCaps;
}
otError LinkRaw::Receive(otLinkRawReceiveDone aCallback)
@@ -202,7 +207,7 @@ otError LinkRaw::Receive(otLinkRawReceiveDone aCallback)
if (mEnabled)
{
mReceiveDoneCallback = aCallback;
error = otPlatRadioReceive(&mInstance, mReceiveChannel);
error = otPlatRadioReceive(&GetInstance(), mReceiveChannel);
}
return error;
@@ -215,7 +220,7 @@ void LinkRaw::InvokeReceiveDone(otRadioFrame *aFrame, otError aError)
if (aError == OT_ERROR_NONE)
{
otLogInfoPlat("LinkRaw Invoke Receive Done (%d bytes)", aFrame->mLength);
mReceiveDoneCallback(&mInstance, aFrame, aError);
mReceiveDoneCallback(&GetInstance(), aFrame, aError);
}
else
{
@@ -224,117 +229,141 @@ void LinkRaw::InvokeReceiveDone(otRadioFrame *aFrame, otError aError)
}
}
otError LinkRaw::Transmit(otRadioFrame *aFrame, otLinkRawTransmitDone aCallback)
void LinkRaw::StartTransmit(void)
{
otError error = OT_ERROR_INVALID_STATE;
if (mEnabled)
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
if ((mRadioCaps & OT_RADIO_CAPS_CSMA_BACKOFF) == 0 && mTransmitFrame->IsCsmaCaEnabled())
{
mTransmitDoneCallback = aCallback;
StartCsmaBackoff();
}
else
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
{
mPendingTransmitData = true;
mOperationTask.Post();
}
}
void LinkRaw::TransmitNow(void)
{
otError error = otPlatRadioTransmit(&GetInstance(), mTransmitFrame);
if (error != OT_ERROR_NONE)
{
InvokeTransmitDone(mTransmitFrame, NULL, error);
}
}
otError LinkRaw::Transmit(otLinkRawTransmitDone aCallback)
{
otError error = OT_ERROR_NONE;
VerifyOrExit(mEnabled, error = OT_ERROR_INVALID_STATE);
mTransmitDoneCallback = aCallback;
mTransmitFrame->SetCsmaCaEnabled(true);
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
if ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) == 0)
{
mCsmaBackoffs = 0;
}
#endif
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
if ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) == 0)
{
mTransmitRetries = 0;
mCsmaBackoffs = 0;
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled)
{
// Start the transmission backoff logic
StartCsmaBackoff();
error = OT_ERROR_NONE;
}
else
{
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
error = otPlatRadioTransmit(&mInstance, aFrame);
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
}
StartTransmit();
exit:
return error;
}
void LinkRaw::InvokeTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
{
otLogDebgPlat("LinkRaw Transmit Done (err=0x%x)", aError);
assert(aFrame == mTransmitFrame);
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
mTimer.Stop();
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
if (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE)
if (aError == OT_ERROR_NONE)
{
mCsmaBackoffs++;
if (mCsmaBackoffs < aFrame->mInfo.mTxInfo.mMaxCsmaBackoffs)
{
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
StartCsmaBackoff();
#else
// Start the transmit now
otError error = otPlatRadioTransmit(&mInstance, aFrame);
if (error != OT_ERROR_NONE)
{
InvokeTransmitDone(aFrame, NULL, error);
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
ExitNow();
}
otLogDebgPlat("LinkRaw Transmit Done: %s", otThreadErrorToString(aError));
}
else
{
mCsmaBackoffs = 0;
otLogWarnPlat("LinkRaw Transmit Done: %s", otThreadErrorToString(aError));
}
if (aError != OT_ERROR_NONE)
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
if ((mRadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) == 0)
{
if (mTransmitRetries < aFrame->mInfo.mTxInfo.mMaxFrameRetries)
{
mTransmitRetries++;
mTimer.Stop();
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
StartCsmaBackoff();
#else
// Start the transmit now
otError error = otPlatRadioTransmit(&mInstance, aFrame);
if (error != OT_ERROR_NONE)
{
InvokeTransmitDone(aFrame, NULL, error);
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
ExitNow();
}
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
// Transition back to receive state on previous channel
otPlatRadioReceive(&mInstance, mReceiveChannel);
if (mTransmitDoneCallback)
if ((mRadioCaps & OT_RADIO_CAPS_CSMA_BACKOFF) == 0)
{
if (aError == OT_ERROR_NONE)
if (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE)
{
otLogInfoPlat("LinkRaw Invoke Transmit Done");
mCsmaBackoffs++;
if (mCsmaBackoffs < aFrame->mInfo.mTxInfo.mMaxCsmaBackoffs)
{
ExitNow(StartTransmit());
}
}
else
{
otLogWarnPlat("LinkRaw Invoke Transmit Failed (err=0x%x)", aError);
mCsmaBackoffs = 0;
}
mTransmitDoneCallback(&mInstance, aFrame, aAckFrame, aError);
mTransmitDoneCallback = NULL;
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
if ((mRadioCaps & OT_RADIO_CAPS_TRANSMIT_RETRIES) == 0)
{
if (aError != OT_ERROR_NONE)
{
if (mTransmitRetries < aFrame->mInfo.mTxInfo.mMaxFrameRetries)
{
mTransmitRetries++;
#if OPENTHREAD_CONFIG_DISABLE_CSMA_CA_ON_LAST_ATTEMPT
if ((mTransmitFrame->GetMaxFrameRetries() > 0) &&
(mTransmitFrame->GetMaxFrameRetries() <= mTransmitRetries))
{
mTransmitFrame->SetCsmaCaEnabled(false);
}
#endif
ExitNow(StartTransmit());
}
}
}
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
// Transition back to receive state on previous channel
otPlatRadioReceive(&GetInstance(), mReceiveChannel);
VerifyOrExit(mTransmitDoneCallback != NULL);
switch (aError)
{
case OT_ERROR_NONE:
case OT_ERROR_NO_ACK:
case OT_ERROR_CHANNEL_ACCESS_FAILURE:
case OT_ERROR_ABORT:
break;
default:
aError = OT_ERROR_ABORT;
break;
}
mTransmitDoneCallback(&GetInstance(), aFrame, aAckFrame, aError);
exit:
return;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
}
otError LinkRaw::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLinkRawEnergyScanDone aCallback)
@@ -345,16 +374,16 @@ otError LinkRaw::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLink
{
mEnergyScanDoneCallback = aCallback;
if (otPlatRadioGetCaps(&mInstance) & OT_RADIO_CAPS_ENERGY_SCAN)
if (otPlatRadioGetCaps(&GetInstance()) & OT_RADIO_CAPS_ENERGY_SCAN)
{
// Do the HW offloaded energy scan
error = otPlatRadioEnergyScan(&mInstance, aScanChannel, aScanDuration);
error = otPlatRadioEnergyScan(&GetInstance(), aScanChannel, aScanDuration);
}
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN
else
{
// Start listening on the scan channel
otPlatRadioReceive(&mInstance, aScanChannel);
otPlatRadioReceive(&GetInstance(), aScanChannel);
// Reset the RSSI value and start scanning
mEnergyScanRssi = kInvalidRssiValue;
@@ -376,7 +405,7 @@ void LinkRaw::InvokeEnergyScanDone(int8_t aEnergyScanMaxRssi)
{
if (IsEnabled() && mEnergyScanDoneCallback)
{
mEnergyScanDoneCallback(&mInstance, aEnergyScanMaxRssi);
mEnergyScanDoneCallback(&GetInstance(), aEnergyScanMaxRssi);
mEnergyScanDoneCallback = NULL;
}
}
@@ -384,17 +413,14 @@ void LinkRaw::InvokeEnergyScanDone(int8_t aEnergyScanMaxRssi)
void LinkRaw::TransmitStarted(otRadioFrame *aFrame)
{
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
// If we are implementing the ACK timeout logic, start a timer here (if ACK request)
// to fire if we don't get a transmit done callback in time.
if (static_cast<Mac::Frame *>(aFrame)->GetAckRequest() &&
!(otPlatRadioGetCaps(&mInstance) & OT_RADIO_CAPS_ACK_TIMEOUT))
if ((mRadioCaps & OT_RADIO_CAPS_ACK_TIMEOUT) == 0 && static_cast<Frame *>(aFrame)->GetAckRequest())
{
otLogDebgPlat("LinkRaw Starting AckTimeout Timer");
mTimerReason = kTimerReasonAckTimeout;
mTimer.Start(Mac::kAckTimeout);
mTimer.Start(kAckTimeout);
}
#else
OT_UNUSED_VARIABLE(aFrame);
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT
@@ -431,10 +457,10 @@ void LinkRaw::HandleTimer(void)
case kTimerReasonAckTimeout:
{
// Transition back to receive state on previous channel
otPlatRadioReceive(&mInstance, mReceiveChannel);
otPlatRadioReceive(&GetInstance(), mReceiveChannel);
// Invoke completion callback for transmit
InvokeTransmitDone(otPlatRadioGetTransmitBuffer(&mInstance), NULL, OT_ERROR_NO_ACK);
InvokeTransmitDone(mTransmitFrame, NULL, OT_ERROR_NO_ACK);
break;
}
@@ -444,16 +470,7 @@ void LinkRaw::HandleTimer(void)
case kTimerReasonCsmaBackoffComplete:
{
otRadioFrame *aFrame = otPlatRadioGetTransmitBuffer(&mInstance);
// Start the transmit now
otError error = otPlatRadioTransmit(&mInstance, aFrame);
if (error != OT_ERROR_NONE)
{
InvokeTransmitDone(aFrame, NULL, error);
}
TransmitNow();
break;
}
@@ -472,6 +489,7 @@ void LinkRaw::HandleTimer(void)
default:
assert(false);
break;
}
}
@@ -481,16 +499,16 @@ void LinkRaw::HandleTimer(void)
void LinkRaw::StartCsmaBackoff(void)
{
uint32_t backoffExponent = Mac::kMinBE + mTransmitRetries + mCsmaBackoffs;
uint32_t backoffExponent = kMinBE + mTransmitRetries + mCsmaBackoffs;
uint32_t backoff;
if (backoffExponent > Mac::kMaxBE)
if (backoffExponent > kMaxBE)
{
backoffExponent = Mac::kMaxBE;
backoffExponent = kMaxBE;
}
backoff = Random::GetUint32InRange(0, 1U << backoffExponent);
backoff *= (static_cast<uint32_t>(Mac::kUnitBackoffPeriod) * OT_RADIO_SYMBOL_TIME);
backoff *= (static_cast<uint32_t>(kUnitBackoffPeriod) * OT_RADIO_SYMBOL_TIME);
otLogDebgPlat("LinkRaw Starting RetransmitTimeout Timer (%d ms)", backoff);
mTimerReason = kTimerReasonCsmaBackoffComplete;
@@ -511,7 +529,7 @@ void LinkRaw::HandleEnergyScanTimer(void)
// Only process if we are still energy scanning
if (mTimer.IsRunning() && mTimerReason == kTimerReasonEnergyScanComplete)
{
int8_t rssi = otPlatRadioGetRssi(&mInstance);
int8_t rssi = otPlatRadioGetRssi(&GetInstance());
// Only apply the RSSI if it was a valid value
if (rssi != kInvalidRssiValue)
@@ -532,27 +550,31 @@ void LinkRaw::HandleEnergyScanTimer(void)
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN
} // namespace Mac
} // namespace ot
#if OPENTHREAD_RADIO
extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame, otError aError)
{
static_cast<Instance *>(aInstance)->GetLinkRaw().InvokeReceiveDone(aFrame, aError);
static_cast<ot::Instance *>(aInstance)->GetLinkRaw().InvokeReceiveDone(aFrame, aError);
}
extern "C" void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
{
static_cast<Instance *>(aInstance)->GetLinkRaw().InvokeTransmitDone(aFrame, aAckFrame, aError);
static_cast<ot::Instance *>(aInstance)->GetLinkRaw().InvokeTransmitDone(aFrame, aAckFrame, aError);
}
extern "C" void otPlatRadioTxStarted(otInstance *aInstance, otRadioFrame *aFrame)
{
static_cast<Instance *>(aInstance)->GetLinkRaw().TransmitStarted(aFrame);
static_cast<ot::Instance *>(aInstance)->GetLinkRaw().TransmitStarted(aFrame);
}
extern "C" void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi)
{
VerifyOrExit(otInstanceIsInitialized(aInstance));
static_cast<Instance *>(aInstance)->GetLinkRaw().InvokeEnergyScanDone(aEnergyScanMaxRssi);
static_cast<ot::Instance *>(aInstance)->GetLinkRaw().InvokeEnergyScanDone(aEnergyScanMaxRssi);
exit:
return;
@@ -569,6 +591,4 @@ extern "C" void otPlatRadioFrameUpdated(otInstance *aInstance, otRadioFrame *aFr
#endif // OPENTHREAD_RADIO
} // namespace ot
#endif // OPENTHREAD_RADIO || OPENTHREAD_ENABLE_RAW_LINK_API
+33 -13
View File
@@ -38,7 +38,9 @@
#include <openthread/link_raw.h>
#include "common/locator.hpp"
#include "common/timer.hpp"
#include "mac/mac_frame.hpp"
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT || OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF || \
OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN
@@ -49,7 +51,9 @@
namespace ot {
class LinkRaw
namespace Mac {
class LinkRaw : public InstanceLocator
{
public:
/**
@@ -112,14 +116,15 @@ public:
/**
* This method starts a (single) Transmit on the link-layer.
*
* @param[in] aFrame A pointer to the frame that was transmitted.
* @note The callback @p aCallback will not be called if this call does not return OT_ERROR_NONE.
*
* @param[in] aCallback A pointer to a function called on completion of the transmission.
*
* @retval OT_ERROR_NONE Successfully transitioned to Transmit.
* @retval OT_ERROR_INVALID_STATE The radio was not in the Receive state.
*
*/
otError Transmit(otRadioFrame *aFrame, otLinkRawTransmitDone aCallback);
otError Transmit(otLinkRawTransmitDone aCallback);
/**
* This method invokes the mTransmitDoneCallback, if set.
@@ -237,10 +242,22 @@ public:
*/
otError SetExtAddress(const otExtAddress &aExtAddress);
private:
otInstance &mInstance;
/**
* This method gets the transmit frame.
*
* @returns A pointer to the transmit frame.
*
*/
otRadioFrame *GetTransmitFrame(void) { return mTransmitFrame; }
#if OPENTHREAD_LINKRAW_TIMER_REQUIRED
private:
void TransmitNow(void);
void StartTransmit(void);
static void HandleOperationTask(Tasklet &aTasklet);
void HandleOperationTask(void);
Tasklet mOperationTask;
bool mPendingTransmitData : 1;
enum TimerReason
{
@@ -250,6 +267,7 @@ private:
kTimerReasonEnergyScanComplete,
};
#if OPENTHREAD_LINKRAW_TIMER_REQUIRED
TimerMilli mTimer;
TimerReason mTimerReason;
#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER
@@ -263,19 +281,18 @@ private:
#endif // OPENTHREAD_LINKRAW_TIMER_REQUIRED
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
void StartCsmaBackoff(void);
uint8_t mCsmaBackoffs;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
uint8_t mTransmitRetries;
uint8_t mCsmaBackoffs;
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
void StartCsmaBackoff(void);
#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF
#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN
enum
@@ -310,8 +327,11 @@ private:
otLinkRawReceiveDone mReceiveDoneCallback;
otLinkRawTransmitDone mTransmitDoneCallback;
otLinkRawEnergyScanDone mEnergyScanDoneCallback;
Frame * mTransmitFrame;
otRadioCaps mRadioCaps;
};
} // namespace Mac
} // namespace ot
#endif // LINK_RAW_HPP_
+8
View File
@@ -1071,6 +1071,14 @@ public:
*/
void SetCsmaCaEnabled(bool aCsmaCaEnabled) { mInfo.mTxInfo.mCsmaCaEnabled = aCsmaCaEnabled; }
/**
* This method gets the CSMA-CA enabled attribute.
*
* @returns TRUE if CSMA-CA must be enabled for this packet, FALSE otherwise.
*
*/
bool IsCsmaCaEnabled(void) const { return mInfo.mTxInfo.mCsmaCaEnabled; }
/**
* This method returns the key used for frame encryption and authentication (AES CCM).
*
+1 -1
View File
@@ -369,7 +369,7 @@ otError NcpBase::HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader)
// Pass frame to the radio layer. Note, this fails if we
// haven't enabled raw stream or are already transmitting.
error = otLinkRawTransmit(mInstance, frame, &NcpBase::LinkRawTransmitDone);
error = otLinkRawTransmit(mInstance, &NcpBase::LinkRawTransmitDone);
exit: