mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 18:37:45 +00:00
[mac] ensure MAC operations get started from a tasklet (#2427)
This commit changes how MAC operations (frame tx, active/energy scan, etc.) get started by adding a new tasklet `mOperationTask` which is used to start/perform any pending operation. This ensures that callbacks related to an operation are invoked after the method which initiates the operation returns. For example, when a new `Mac::Sender` is registered with a call to `Mac::SendFrameRequest()`, its callback `FrameRequestHandler` would be invoked after the `SendFrameRequest()` call itself returns. The `mOperationTask` serves two purposes. It's mainly used for starting a new operation. It is also used during Energy Scan to take an RSSI sample.
This commit is contained in:
committed by
Jonathan Hui
parent
debf68dd09
commit
8ef2228ab2
+35
-15
@@ -89,6 +89,7 @@ Mac::Mac(Instance &aInstance):
|
||||
#if OPENTHREAD_CONFIG_STAY_AWAKE_BETWEEN_FRAGMENTS
|
||||
mDelaySleep(false),
|
||||
#endif
|
||||
mOperationTask(aInstance, &Mac::PerformOperation, this),
|
||||
mMacTimer(aInstance, &Mac::HandleMacTimer, this),
|
||||
mBackoffTimer(aInstance, &Mac::HandleBeginTransmit, this),
|
||||
mReceiveTimer(aInstance, &Mac::HandleReceiveTimer, this),
|
||||
@@ -109,7 +110,6 @@ Mac::Mac(Instance &aInstance):
|
||||
mEnergyScanCurrentMaxRssi(kInvalidRssiValue),
|
||||
mScanContext(NULL),
|
||||
mActiveScanHandler(NULL), // Initialize `mActiveScanHandler` and `mEnergyScanHandler` union
|
||||
mEnergyScanSampleRssiTask(aInstance, &Mac::HandleEnergyScanSampleRssi, this),
|
||||
mPcapCallback(NULL),
|
||||
mPcapCallbackContext(NULL),
|
||||
#if OPENTHREAD_ENABLE_MAC_FILTER
|
||||
@@ -273,7 +273,7 @@ void Mac::PerformEnergyScan(void)
|
||||
{
|
||||
RadioReceive(mScanChannel);
|
||||
mEnergyScanCurrentMaxRssi = kInvalidRssiValue;
|
||||
mEnergyScanSampleRssiTask.Post();
|
||||
mOperationTask.Post();
|
||||
|
||||
if (mScanDuration != 0)
|
||||
{
|
||||
@@ -335,17 +335,10 @@ void Mac::EnergyScanDone(int8_t aRssi)
|
||||
PerformEnergyScan();
|
||||
}
|
||||
|
||||
void Mac::HandleEnergyScanSampleRssi(Tasklet &aTasklet)
|
||||
{
|
||||
aTasklet.GetOwner<Mac>().HandleEnergyScanSampleRssi();
|
||||
}
|
||||
|
||||
void Mac::HandleEnergyScanSampleRssi(void)
|
||||
void Mac::SampleRssi(void)
|
||||
{
|
||||
int8_t rssi;
|
||||
|
||||
VerifyOrExit(mOperation == kOperationEnergyScan);
|
||||
|
||||
rssi = otPlatRadioGetRssi(&GetInstance());
|
||||
|
||||
if (rssi != kInvalidRssiValue)
|
||||
@@ -362,11 +355,8 @@ void Mac::HandleEnergyScanSampleRssi(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
mEnergyScanSampleRssiTask.Post();
|
||||
mOperationTask.Post();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
otError Mac::RegisterReceiver(Receiver &aReceiver)
|
||||
@@ -577,6 +567,30 @@ void Mac::StartOperation(Operation aOperation)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mOperation == kOperationIdle)
|
||||
{
|
||||
mOperationTask.Post();
|
||||
}
|
||||
}
|
||||
|
||||
void Mac::PerformOperation(Tasklet &aTasklet)
|
||||
{
|
||||
aTasklet.GetOwner<Mac>().PerformOperation();
|
||||
}
|
||||
|
||||
void Mac::PerformOperation(void)
|
||||
{
|
||||
// The `mOperationTask` tasklet serves two purposes:
|
||||
//
|
||||
// (a) it is used to start a pending operation,
|
||||
// (b) while performing Energy Scan, it is used to take RSSI samples.
|
||||
|
||||
if (mOperation == kOperationEnergyScan)
|
||||
{
|
||||
SampleRssi();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
VerifyOrExit(mOperation == kOperationIdle);
|
||||
|
||||
// `WaitingForData` should be checked before any other pending
|
||||
@@ -634,7 +648,13 @@ void Mac::FinishOperation(void)
|
||||
otLogDebgMac(GetInstance(), "Finishing operation \"%s\"", OperationToString(mOperation));
|
||||
|
||||
mOperation = kOperationIdle;
|
||||
StartOperation(kOperationIdle);
|
||||
|
||||
// Note that we do not want to post the `mOperationTask` here and
|
||||
// instead we do a direct call to `PerformOperation()`. This helps
|
||||
// ensure that if there is no pending operation, the radio is
|
||||
// switched to idle mode immediately.
|
||||
|
||||
PerformOperation();
|
||||
}
|
||||
|
||||
void Mac::GenerateNonce(const ExtAddress &aAddress, uint32_t aFrameCounter, uint8_t aSecurityLevel, uint8_t *aNonce)
|
||||
|
||||
@@ -644,8 +644,8 @@ private:
|
||||
void HandleBeginTransmit(void);
|
||||
static void HandleReceiveTimer(Timer &aTimer);
|
||||
void HandleReceiveTimer(void);
|
||||
static void HandleEnergyScanSampleRssi(Tasklet &aTasklet);
|
||||
void HandleEnergyScanSampleRssi(void);
|
||||
static void PerformOperation(Tasklet &aTasklet);
|
||||
void PerformOperation(void);
|
||||
|
||||
void StartCsmaBackoff(void);
|
||||
|
||||
@@ -654,6 +654,7 @@ private:
|
||||
void PerformActiveScan(void);
|
||||
void PerformEnergyScan(void);
|
||||
void ReportEnergyScanResult(int8_t aRssi);
|
||||
void SampleRssi(void);
|
||||
|
||||
otError RadioTransmit(Frame *aSendFrame);
|
||||
otError RadioReceive(uint8_t aChannel);
|
||||
@@ -674,6 +675,8 @@ private:
|
||||
bool mDelaySleep : 1;
|
||||
#endif
|
||||
|
||||
Tasklet mOperationTask;
|
||||
|
||||
TimerMilli mMacTimer;
|
||||
#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER
|
||||
TimerMicro mBackoffTimer;
|
||||
@@ -708,7 +711,6 @@ private:
|
||||
ActiveScanHandler mActiveScanHandler;
|
||||
EnergyScanHandler mEnergyScanHandler;
|
||||
};
|
||||
Tasklet mEnergyScanSampleRssiTask;
|
||||
|
||||
otLinkPcapCallback mPcapCallback;
|
||||
void *mPcapCallbackContext;
|
||||
|
||||
Reference in New Issue
Block a user