[mac] apply RxChannelAfterTxDone only if RxOnWhenIdle (#10826)

This commit updates the implementation to apply RxChannelAfterTxDone
only if RxOnWhenIdle.
This commit is contained in:
Yakun Xu
2024-10-28 14:19:44 -07:00
committed by GitHub
parent fb3b26553b
commit 005c5cefc2
7 changed files with 80 additions and 13 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ extern "C" {
*
* @note This number versions both OpenThread platform and user APIs.
*/
#define OPENTHREAD_API_VERSION (457)
#define OPENTHREAD_API_VERSION (458)
/**
* @addtogroup api-instance
+11
View File
@@ -1180,6 +1180,17 @@ void otLinkGetWakeupListenParameters(otInstance *aInstance, uint32_t *aInterval,
*/
otError otLinkSetWakeupListenParameters(otInstance *aInstance, uint32_t aInterval, uint32_t aDuration);
/**
* Sets the rx-on-when-idle state.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aRxOnWhenIdle TRUE to keep radio in Receive state, FALSE to put to Sleep state during idle periods.
*
* @retval OT_ERROR_NONE If successful.
* @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
*/
otError otLinkSetRxOnWhenIdle(otInstance *aInstance, bool aRxOnWhenIdle);
/**
* @}
*/
+20 -2
View File
@@ -33,14 +33,14 @@
#include "openthread-core-config.h"
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
#include <openthread/platform/time.h>
#include "instance/instance.hpp"
using namespace ot;
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
otError otLinkRawSetReceiveDone(otInstance *aInstance, otLinkRawReceiveDone aCallback)
{
return AsCoreType(aInstance).Get<Mac::LinkRaw>().SetReceiveDone(aCallback);
@@ -276,3 +276,21 @@ void otLinkGetFactoryAssignedIeeeEui64(otInstance *aInstance, otExtAddress *aEui
#endif // OPENTHREAD_RADIO
#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
otError otLinkSetRxOnWhenIdle(otInstance *aInstance, bool aRxOnWhenIdle)
{
Error error = OT_ERROR_NONE;
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
VerifyOrExit(AsCoreType(aInstance).Get<Mac::LinkRaw>().IsEnabled(), error = kErrorInvalidState);
#else
VerifyOrExit(AsCoreType(aInstance).Get<Mac::Mac>().IsEnabled() &&
AsCoreType(aInstance).Get<Mle::Mle>().IsDisabled(),
error = kErrorInvalidState);
#endif
AsCoreType(aInstance).Get<Mac::SubMac>().SetRxOnWhenIdle(aRxOnWhenIdle);
exit:
return error;
}
+1 -1
View File
@@ -591,7 +591,7 @@ void SubMac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aErro
SetState(kStateReceive);
#if OPENTHREAD_RADIO
if (aFrame.GetChannel() != aFrame.GetRxChannelAfterTxDone())
if (aFrame.GetChannel() != aFrame.GetRxChannelAfterTxDone() && mRxOnWhenIdle)
{
// On RCP build, we switch immediately to the specified RX
// channel if it is different from the channel on which frame
+5 -8
View File
@@ -85,12 +85,6 @@ extern "C" void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, o
Instance &instance = AsCoreType(aInstance);
Mac::TxFrame &txFrame = *static_cast<Mac::TxFrame *>(aFrame);
Mac::RxFrame *ackFrame = static_cast<Mac::RxFrame *>(aAckFrame);
#if OPENTHREAD_RADIO
uint8_t channel = txFrame.mInfo.mTxInfo.mRxChannelAfterTxDone;
OT_ASSERT((otPlatRadioGetSupportedChannelMask(aInstance) & (1UL << channel)) != 0);
IgnoreError(otPlatRadioReceive(aInstance, channel));
#endif
VerifyOrExit(instance.IsInitialized());
@@ -152,8 +146,11 @@ extern "C" void otPlatDiagRadioTransmitDone(otInstance *aInstance, otRadioFrame
#if OPENTHREAD_RADIO
uint8_t channel = txFrame.mInfo.mTxInfo.mRxChannelAfterTxDone;
OT_ASSERT((otPlatRadioGetSupportedChannelMask(aInstance) & (1UL << channel)) != 0);
IgnoreError(otPlatRadioReceive(aInstance, channel));
if (channel != aFrame->mChannel)
{
OT_ASSERT((otPlatRadioGetSupportedChannelMask(aInstance) & (1UL << channel)) != 0);
IgnoreError(otPlatRadioReceive(aInstance, channel));
}
#endif
#if OPENTHREAD_CONFIG_MULTI_RADIO
txFrame.SetRadioType(Mac::kRadioTypeIeee802154);
+1 -1
View File
@@ -1599,7 +1599,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_RX_ON_WHEN_IDLE_M
otError error = OT_ERROR_NONE;
SuccessOrExit(error = mDecoder.ReadBool(enabled));
otPlatRadioSetRxOnWhenIdle(mInstance, enabled);
SuccessOrExit(error = otLinkSetRxOnWhenIdle(mInstance, enabled));
exit:
return error;
+41
View File
@@ -244,3 +244,44 @@ TEST(RadioSpinelTransmit, shouldPerformCsmaCaWhenEnabled)
platform.GoInMs(1000);
}
TEST(RadioSpinelTransmit, shouldNotCauseSwitchingToRxAfterTxDoneIfNotRxOnWhenIdle)
{
FakeCoprocessorPlatform platform;
constexpr Mac::PanId kSrcPanId = 0x1234;
constexpr Mac::PanId kDstPanId = 0x4321;
constexpr uint8_t kDstAddr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88};
constexpr uint16_t kSrcAddr = 0xac00;
constexpr int8_t kTxPower = 100;
uint8_t frameBuffer[OT_RADIO_FRAME_MAX_SIZE];
Mac::TxFrame txFrame;
txFrame.mPsdu = frameBuffer;
{
Mac::TxFrame::Info frameInfo;
frameInfo.mType = Mac::Frame::kTypeData;
frameInfo.mVersion = Mac::Frame::kVersion2006;
frameInfo.mAddrs.mSource.SetShort(kSrcAddr);
frameInfo.mAddrs.mDestination.SetExtended(kDstAddr);
frameInfo.mPanIds.SetSource(kSrcPanId);
frameInfo.mPanIds.SetDestination(kDstPanId);
frameInfo.mSecurityLevel = Mac::Frame::kSecurityEncMic32;
frameInfo.PrepareHeadersIn(txFrame);
}
txFrame.mInfo.mTxInfo.mTxPower = kTxPower;
txFrame.mChannel = 11;
txFrame.mInfo.mTxInfo.mRxChannelAfterTxDone = 25;
ASSERT_EQ(platform.mRadioSpinel.Enable(FakePlatform::CurrentInstance()), kErrorNone);
ASSERT_EQ(platform.mRadioSpinel.Receive(11), kErrorNone);
ASSERT_EQ(platform.mRadioSpinel.SetRxOnWhenIdle(false), kErrorNone);
ASSERT_EQ(platform.mRadioSpinel.Transmit(txFrame), kErrorNone);
platform.GoInMs(1000);
EXPECT_EQ(platform.GetReceiveChannel(), 11);
}