mirror of
https://github.com/espressif/openthread.git
synced 2026-08-26 12:11:17 +00:00
[radio] refactor Radio::Statistics (#10961)
This commit refactors `Radio::Statistics` to be a nested type within the `Radio` class. It is declared as a `friend` of `Radio` so that its interaction with `Radio` can be defined as `private` methods.
This commit is contained in:
@@ -41,9 +41,9 @@ using namespace ot;
|
||||
|
||||
const otRadioTimeStats *otRadioTimeStatsGet(otInstance *aInstance)
|
||||
{
|
||||
return &AsCoreType(aInstance).Get<RadioStatistics>().GetStats();
|
||||
return &AsCoreType(aInstance).Get<Radio::Statistics>().GetStats();
|
||||
}
|
||||
|
||||
void otRadioTimeStatsReset(otInstance *aInstance) { AsCoreType(aInstance).Get<RadioStatistics>().ResetTime(); }
|
||||
void otRadioTimeStatsReset(otInstance *aInstance) { AsCoreType(aInstance).Get<Radio::Statistics>().ResetTime(); }
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
|
||||
@@ -751,7 +751,7 @@ template <> inline Radio &Instance::Get(void) { return mRadio; }
|
||||
template <> inline Radio::Callbacks &Instance::Get(void) { return mRadio.mCallbacks; }
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
template <> inline RadioStatistics &Instance::Get(void) { return mRadio.mRadioStatistics; }
|
||||
template <> inline Radio::Statistics &Instance::Get(void) { return mRadio.mStatistics; }
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_CONFIG_UPTIME_ENABLE
|
||||
|
||||
+10
-13
@@ -117,19 +117,19 @@ Error Radio::Transmit(Mac::TxFrame &aFrame)
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
inline uint64_t UintSafeMinus(uint64_t aLhs, uint64_t aRhs) { return aLhs > aRhs ? (aLhs - aRhs) : 0; }
|
||||
|
||||
RadioStatistics::RadioStatistics(void)
|
||||
Radio::Statistics::Statistics(void)
|
||||
: mStatus(kDisabled)
|
||||
{
|
||||
ResetTime();
|
||||
}
|
||||
|
||||
void RadioStatistics::RecordStateChange(Status aStatus)
|
||||
void Radio::Statistics::RecordStateChange(Status aStatus)
|
||||
{
|
||||
UpdateTime();
|
||||
mStatus = aStatus;
|
||||
}
|
||||
|
||||
void RadioStatistics::HandleReceiveAt(uint32_t aDurationUs)
|
||||
void Radio::Statistics::HandleReceiveAt(uint32_t aDurationUs)
|
||||
{
|
||||
// The actual rx time of ReceiveAt cannot be obtained from software level. This is a workaround.
|
||||
if (mStatus == kSleep)
|
||||
@@ -138,7 +138,7 @@ void RadioStatistics::HandleReceiveAt(uint32_t aDurationUs)
|
||||
}
|
||||
}
|
||||
|
||||
void RadioStatistics::RecordTxDone(otError aError, uint16_t aPsduLength)
|
||||
void Radio::Statistics::RecordTxDone(otError aError, uint16_t aPsduLength)
|
||||
{
|
||||
if (aError == kErrorNone || aError == kErrorNoAck)
|
||||
{
|
||||
@@ -164,7 +164,7 @@ void RadioStatistics::RecordTxDone(otError aError, uint16_t aPsduLength)
|
||||
}
|
||||
}
|
||||
|
||||
void RadioStatistics::RecordRxDone(otError aError)
|
||||
void Radio::Statistics::RecordRxDone(otError aError)
|
||||
{
|
||||
uint32_t ackTimeUs;
|
||||
|
||||
@@ -183,23 +183,20 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
const otRadioTimeStats &RadioStatistics::GetStats(void)
|
||||
const Radio::Statistics::TimeStats &Radio::Statistics::GetStats(void)
|
||||
{
|
||||
UpdateTime();
|
||||
|
||||
return mTimeStats;
|
||||
}
|
||||
|
||||
void RadioStatistics::ResetTime(void)
|
||||
void Radio::Statistics::ResetTime(void)
|
||||
{
|
||||
mTimeStats.mDisabledTime = 0;
|
||||
mTimeStats.mSleepTime = 0;
|
||||
mTimeStats.mRxTime = 0;
|
||||
mTimeStats.mTxTime = 0;
|
||||
mLastUpdateTime = TimerMicro::GetNow();
|
||||
ClearAllBytes(mTimeStats);
|
||||
mLastUpdateTime = TimerMicro::GetNow();
|
||||
}
|
||||
|
||||
void RadioStatistics::UpdateTime(void)
|
||||
void Radio::Statistics::UpdateTime(void)
|
||||
{
|
||||
TimeMicro nowTime = TimerMicro::GetNow();
|
||||
uint32_t timeElapsed = nowTime - mLastUpdateTime;
|
||||
|
||||
+73
-56
@@ -79,59 +79,11 @@ static constexpr uint32_t kMinWakeupListenDuration = 100;
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements the radio statistics logic.
|
||||
*
|
||||
* The radio statistics are the time when the radio in TX/RX/radio state.
|
||||
* Since this class collects these statistics from pure software level and no platform API is involved, a simplified
|
||||
* model is used to calculate the time of different radio states. The data may not be very accurate, but it's
|
||||
* sufficient to provide a general understanding of the proportion of time a device is in different radio states.
|
||||
*
|
||||
* The simplified model is:
|
||||
* - The RadioStats is only aware of 2 states: RX and sleep.
|
||||
* - Each time `Radio::Receive` or `Radio::Sleep` is called, it will check the current state and add the time since
|
||||
* last time the methods were called. For example, `Sleep` is first called and `Receive` is called after 1 second,
|
||||
* then 1 second will be added to SleepTime and the current state switches to `Receive`.
|
||||
* - The time of TX will be calculated from the callback of TransmitDone. If TX returns OT_ERROR_NONE or
|
||||
* OT_ERROR_NO_ACK, the tx time will be added according to the number of bytes sent. And the SleepTime or RxTime
|
||||
* will be reduced accordingly.
|
||||
* - When `GetStats` is called, an operation will be executed to calcute the time for the last state. And the result
|
||||
* will be returned.
|
||||
*/
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
|
||||
#if !OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD) && \
|
||||
!OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
#error "OPENTHREAD_CONFIG_RADIO_STATS_ENABLE requires OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE".
|
||||
#endif
|
||||
|
||||
class RadioStatistics
|
||||
{
|
||||
public:
|
||||
enum Status : uint8_t
|
||||
{
|
||||
kDisabled,
|
||||
kSleep,
|
||||
kReceive,
|
||||
};
|
||||
|
||||
explicit RadioStatistics(void);
|
||||
|
||||
void RecordStateChange(Status aStatus);
|
||||
void HandleReceiveAt(uint32_t aDurationUs);
|
||||
void RecordTxDone(otError aError, uint16_t aPsduLength);
|
||||
void RecordRxDone(otError aError);
|
||||
const otRadioTimeStats &GetStats(void);
|
||||
void ResetTime(void);
|
||||
|
||||
private:
|
||||
void UpdateTime(void);
|
||||
|
||||
Status mStatus;
|
||||
otRadioTimeStats mTimeStats;
|
||||
TimeMicro mLastUpdateTime;
|
||||
};
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
|
||||
/**
|
||||
* Represents an OpenThread radio abstraction.
|
||||
*/
|
||||
@@ -263,6 +215,71 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
/**
|
||||
* Implements the radio statistics logic.
|
||||
*
|
||||
* The radio statistics are the time when the radio in TX/RX/radio state.
|
||||
* Since this class collects these statistics from pure software level
|
||||
* and no platform API is involved, a simplified model is used to
|
||||
* calculate the time of different radio states. The data may not be very
|
||||
* accurate, but it's sufficient to provide a general understanding of
|
||||
* the proportion of time a device is in different radio states.
|
||||
*
|
||||
* The simplified model is:
|
||||
* - The radio statistics is only aware of 2 states: RX and sleep.
|
||||
* - Each time `Radio::Receive` or `Radio::Sleep` is called, it will check
|
||||
* the current state and add the time since last time the methods were
|
||||
* called. For example, `Sleep` is first called and `Receive` is called
|
||||
* after 1 second, then 1 second will be added to SleepTime and the
|
||||
* current state switches to `Receive`.
|
||||
* - The time of TX will be calculated from the callback of TransmitDone.
|
||||
* If TX returns kErrorNone or kErrorNoAk, the tx time will be added
|
||||
* according to the number of bytes sent. And the SleepTime or RxTime
|
||||
* will be reduced accordingly.
|
||||
* - When `GetStats` is called, an operation will be executed to calculate
|
||||
* the time for the last state. And the result will be returned.
|
||||
*/
|
||||
class Statistics : private NonCopyable
|
||||
{
|
||||
friend class Radio;
|
||||
friend class Callbacks;
|
||||
|
||||
public:
|
||||
using TimeStats = otRadioTimeStats; ///< Radio statistics (time spend in each state).
|
||||
|
||||
/**
|
||||
* Retrieves the current radio statistics.
|
||||
*
|
||||
* @return The current time statistics.
|
||||
*/
|
||||
const TimeStats &GetStats(void);
|
||||
|
||||
/**
|
||||
* Resets the radio statistics.
|
||||
*/
|
||||
void ResetTime(void);
|
||||
|
||||
private:
|
||||
enum Status : uint8_t{
|
||||
kDisabled,
|
||||
kSleep,
|
||||
kReceive,
|
||||
};
|
||||
|
||||
Statistics(void);
|
||||
void RecordStateChange(Status aStatus);
|
||||
void HandleReceiveAt(uint32_t aDurationUs);
|
||||
void RecordTxDone(otError aError, uint16_t aPsduLength);
|
||||
void RecordRxDone(otError aError);
|
||||
void UpdateTime(void);
|
||||
|
||||
Status mStatus;
|
||||
TimeStats mTimeStats;
|
||||
TimeMicro mLastUpdateTime;
|
||||
};
|
||||
#endif // OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
|
||||
/**
|
||||
* Initializes the `Radio` object.
|
||||
*
|
||||
@@ -835,7 +852,7 @@ private:
|
||||
|
||||
Callbacks mCallbacks;
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
RadioStatistics mRadioStatistics;
|
||||
Statistics mStatistics;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -912,7 +929,7 @@ inline otRadioState Radio::GetState(void) { return otPlatRadioGetState(GetInstan
|
||||
inline Error Radio::Enable(void)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
mRadioStatistics.RecordStateChange(RadioStatistics::kSleep);
|
||||
mStatistics.RecordStateChange(Statistics::kSleep);
|
||||
#endif
|
||||
return otPlatRadioEnable(GetInstancePtr());
|
||||
}
|
||||
@@ -920,7 +937,7 @@ inline Error Radio::Enable(void)
|
||||
inline Error Radio::Disable(void)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
mRadioStatistics.RecordStateChange(RadioStatistics::kDisabled);
|
||||
mStatistics.RecordStateChange(Statistics::kDisabled);
|
||||
#endif
|
||||
return otPlatRadioDisable(GetInstancePtr());
|
||||
}
|
||||
@@ -930,7 +947,7 @@ inline bool Radio::IsEnabled(void) { return otPlatRadioIsEnabled(GetInstancePtr(
|
||||
inline Error Radio::Sleep(void)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
mRadioStatistics.RecordStateChange(RadioStatistics::kSleep);
|
||||
mStatistics.RecordStateChange(Statistics::kSleep);
|
||||
#endif
|
||||
return otPlatRadioSleep(GetInstancePtr());
|
||||
}
|
||||
@@ -938,7 +955,7 @@ inline Error Radio::Sleep(void)
|
||||
inline Error Radio::Receive(uint8_t aChannel)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
mRadioStatistics.RecordStateChange(RadioStatistics::kReceive);
|
||||
mStatistics.RecordStateChange(Statistics::kReceive);
|
||||
#endif
|
||||
return otPlatRadioReceive(GetInstancePtr(), aChannel);
|
||||
}
|
||||
@@ -950,7 +967,7 @@ inline Error Radio::ReceiveAt(uint8_t aChannel, uint32_t aStart, uint32_t aDurat
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
mRadioStatistics.HandleReceiveAt(aDuration);
|
||||
mStatistics.HandleReceiveAt(aDuration);
|
||||
}
|
||||
#endif
|
||||
return error;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace ot {
|
||||
void Radio::Callbacks::HandleReceiveDone(Mac::RxFrame *aFrame, Error aError)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
Get<RadioStatistics>().RecordRxDone(aError);
|
||||
Get<Radio::Statistics>().RecordRxDone(aError);
|
||||
#endif
|
||||
Get<Mac::SubMac>().HandleReceiveDone(aFrame, aError);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ void Radio::Callbacks::HandleTransmitStarted(Mac::TxFrame &aFrame) { Get<Mac::Su
|
||||
void Radio::Callbacks::HandleTransmitDone(Mac::TxFrame &aFrame, Mac::RxFrame *aAckFrame, Error aError)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_RADIO_STATS_ENABLE && (OPENTHREAD_FTD || OPENTHREAD_MTD)
|
||||
Get<RadioStatistics>().RecordTxDone(aError, aFrame.GetLength());
|
||||
Get<Radio::Statistics>().RecordTxDone(aError, aFrame.GetLength());
|
||||
#endif
|
||||
Get<Mac::SubMac>().HandleTransmitDone(aFrame, aAckFrame, aError);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user