diff --git a/examples/platforms/posix/openthread-core-posix-config.h b/examples/platforms/posix/openthread-core-posix-config.h index cf813d228..f8c5b5c53 100644 --- a/examples/platforms/posix/openthread-core-posix-config.h +++ b/examples/platforms/posix/openthread-core-posix-config.h @@ -41,7 +41,7 @@ * The platform-specific string to insert into the OpenThread version string. * */ -#define OPENTHREAD_CONFIG_PLATFORM_INFO "POSIX" +#define OPENTHREAD_CONFIG_PLATFORM_INFO "POSIX" /** * @def OPENTHREAD_CONFIG_LOG_OUTPUT @@ -50,7 +50,7 @@ * */ #ifndef OPENTHREAD_CONFIG_LOG_OUTPUT /* allow command line override */ -#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED +#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED #endif #if OPENTHREAD_RADIO @@ -60,7 +60,21 @@ * Define to 1 if you want to enable software ACK timeout logic. * */ +#ifndef OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT #define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ACK_TIMEOUT 1 +#endif + +/** + * @def OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN + * + * Define to 1 if you want to enable software energy scanning logic. + * + * Applicable only if raw link layer API is enabled (i.e., `OPENTHREAD_ENABLE_RAW_LINK_API` is set). + * + */ +#ifndef OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN +#define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN 1 +#endif /** * @def OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT @@ -70,7 +84,9 @@ * Applicable only if raw link layer API is enabled (i.e., `OPENTHREAD_ENABLE_RAW_LINK_API` is set). * */ +#ifndef OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT #define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT 1 +#endif /** * @def OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF @@ -80,7 +96,9 @@ * Applicable only if raw link layer API is enabled (i.e., `OPENTHREAD_ENABLE_RAW_LINK_API` is set). * */ -#define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF 1 +#ifndef OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF +#define OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF 1 +#endif #endif // OPENTHREAD_RADIO /** @@ -89,6 +107,6 @@ * Define to 1 if you want to support microsecond timer in platform. * */ -#define OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER 1 +#define OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER 1 -#endif // OPENTHREAD_CORE_POSIX_CONFIG_H_ +#endif // OPENTHREAD_CORE_POSIX_CONFIG_H_ diff --git a/src/core/api/link_raw.hpp b/src/core/api/link_raw.hpp index 2a4c42fbd..0b87ebeae 100644 --- a/src/core/api/link_raw.hpp +++ b/src/core/api/link_raw.hpp @@ -254,6 +254,8 @@ private: TimerReason mTimerReason; #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER TimerMicro mTimerMicro; +#else + TimerMilli mEnergyScanTimer; #endif static void HandleTimer(Timer &aTimer); @@ -278,14 +280,25 @@ private: enum { - kInvalidRssiValue = 127 + kInvalidRssiValue = 127, + /** + * Interval between RSSI samples when performing Energy Scan. + * + * `mTimerMicro` or `mEnergyScanTimer` is used for adding delay between RSSI samples. If microsecond timer is + * supported, 128 usec time between samples is used, otherwise with the millisecond timer `mEnergyScanTimer` the + * minimum value of 1 msec is used. + * + */ +#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER + kEnergyScanRssiSampleInterval = 128, +#else + kEnergyScanRssiSampleInterval = 1, +#endif }; - Tasklet mEnergyScanTask; - int8_t mEnergyScanRssi; + int8_t mEnergyScanRssi; - static void HandleEnergyScanTask(Tasklet &aTasklet); - void HandleEnergyScanTask(void); + void HandleEnergyScanTimer(void); #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN diff --git a/src/core/api/link_raw_api.cpp b/src/core/api/link_raw_api.cpp index 6f6fc551a..6ec0faa15 100644 --- a/src/core/api/link_raw_api.cpp +++ b/src/core/api/link_raw_api.cpp @@ -56,15 +56,14 @@ LinkRaw::LinkRaw(Instance &aInstance) , mTimerReason(kTimerReasonNone) #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER , mTimerMicro(aInstance, &LinkRaw::HandleTimer, this) +#else + , mEnergyScanTimer(aInstance, &LinkRaw::HandleTimer, this) #endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER #endif // OPENTHREAD_LINKRAW_TIMER_REQUIRED #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT , mTransmitRetries(0) , mCsmaBackoffs(0) #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_RETRANSMIT -#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN - , mEnergyScanTask(aInstance, &LinkRaw::HandleEnergyScanTask, this) -#endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN , mReceiveChannel(OPENTHREAD_CONFIG_DEFAULT_CHANNEL) , mReceiveDoneCallback(NULL) , mTransmitDoneCallback(NULL) @@ -284,7 +283,7 @@ void LinkRaw::InvokeTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, InvokeTransmitDone(aFrame, NULL, error); } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF - goto exit; + ExitNow(); } } else @@ -308,7 +307,7 @@ void LinkRaw::InvokeTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, InvokeTransmitDone(aFrame, NULL, error); } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_CSMA_BACKOFF - goto exit; + ExitNow(); } } @@ -346,18 +345,27 @@ otError LinkRaw::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration, otLink { mEnergyScanDoneCallback = aCallback; + if (otPlatRadioGetCaps(&mInstance) & OT_RADIO_CAPS_ENERGY_SCAN) + { + // Do the HW offloaded energy scan + error = otPlatRadioEnergyScan(&mInstance, aScanChannel, aScanDuration); + } #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN - // Start listening on the scan channel - otPlatRadioReceive(&mInstance, aScanChannel); + else + { + // Start listening on the scan channel + otPlatRadioReceive(&mInstance, aScanChannel); - // Reset the RSSI value and start scanning - mEnergyScanRssi = kInvalidRssiValue; - mTimerReason = kTimerReasonEnergyScanComplete; - mTimer.Start(aScanDuration); - mEnergyScanTask.Post(); + // Reset the RSSI value and start scanning + mEnergyScanRssi = kInvalidRssiValue; + mTimerReason = kTimerReasonEnergyScanComplete; +#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER + mTimerMicro.Start(0); #else - // Do the HW offloaded energy scan - error = otPlatRadioEnergyScan(&mInstance, aScanChannel, aScanDuration); + mEnergyScanTimer.Start(0); +#endif + mTimer.Start(aScanDuration); + } #endif // OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN } @@ -396,7 +404,19 @@ void LinkRaw::TransmitStarted(otRadioFrame *aFrame) void LinkRaw::HandleTimer(Timer &aTimer) { - aTimer.GetOwner().HandleTimer(); + LinkRaw &linkRaw = aTimer.GetOwner(); + +#if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN + // Energy scan uses a different timer for adding delay between RSSI samples. + if (&aTimer != &linkRaw.mTimer && linkRaw.mTimerReason == kTimerReasonEnergyScanComplete) + { + linkRaw.HandleEnergyScanTimer(); + } + else +#endif + { + linkRaw.HandleTimer(); + } } void LinkRaw::HandleTimer(void) @@ -486,15 +506,10 @@ void LinkRaw::StartCsmaBackoff(void) #if OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN -void LinkRaw::HandleEnergyScanTask(Tasklet &aTasklet) +void LinkRaw::HandleEnergyScanTimer(void) { - aTasklet.GetOwner().HandleEnergyScanTask(); -} - -void LinkRaw::HandleEnergyScanTask(void) -{ - // Only process task if we are still energy scanning - if (mTimerReason == kTimerReasonEnergyScanComplete) + // Only process if we are still energy scanning + if (mTimer.IsRunning() && mTimerReason == kTimerReasonEnergyScanComplete) { int8_t rssi = otPlatRadioGetRssi(&mInstance); @@ -507,9 +522,11 @@ void LinkRaw::HandleEnergyScanTask(void) } } - // Post another instance of tha task, since we are - // still doing the energy scan. - mEnergyScanTask.Post(); +#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER + mTimerMicro.Start(kEnergyScanRssiSampleInterval); +#else + mEnergyScanTimer.Start(kEnergyScanRssiSampleInterval); +#endif } } diff --git a/src/posix/platform/radio_spinel.cpp b/src/posix/platform/radio_spinel.cpp index 94a13ebce..38faa18d2 100644 --- a/src/posix/platform/radio_spinel.cpp +++ b/src/posix/platform/radio_spinel.cpp @@ -954,6 +954,8 @@ otError RadioSpinel::EnergyScan(uint8_t aScanChannel, uint16_t aScanDuration) { otError error; + VerifyOrExit(mRadioCaps & OT_RADIO_CAPS_ENERGY_SCAN, error = OT_ERROR_NOT_CAPABLE); + SuccessOrExit(error = Set(SPINEL_PROP_MAC_SCAN_MASK, SPINEL_DATATYPE_DATA_S, &aScanChannel, sizeof(uint8_t))); SuccessOrExit(error = Set(SPINEL_PROP_MAC_SCAN_PERIOD, SPINEL_DATATYPE_UINT16_S, aScanDuration)); SuccessOrExit(error = Set(SPINEL_PROP_MAC_SCAN_STATE, SPINEL_DATATYPE_UINT8_S, SPINEL_SCAN_STATE_ENERGY));