diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 31f36a7ab..4b5b9d15e 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (346) +#define OPENTHREAD_API_VERSION (347) /** * @addtogroup api-instance diff --git a/include/openthread/link.h b/include/openthread/link.h index 933098c77..5c920db9e 100644 --- a/include/openthread/link.h +++ b/include/openthread/link.h @@ -1031,7 +1031,7 @@ otError otLinkSetPromiscuous(otInstance *aInstance, bool aPromiscuous); * @returns The CSL channel. * */ -uint8_t otLinkCslGetChannel(otInstance *aInstance); +uint8_t otLinkGetCslChannel(otInstance *aInstance); /** * Sets the CSL channel. @@ -1044,29 +1044,40 @@ uint8_t otLinkCslGetChannel(otInstance *aInstance); * @retval OT_ERROR_INVALID_ARGS Invalid @p aChannel. * */ -otError otLinkCslSetChannel(otInstance *aInstance, uint8_t aChannel); +otError otLinkSetCslChannel(otInstance *aInstance, uint8_t aChannel); /** - * Gets the CSL period. + * Represents CSL period ten symbols unit in microseconds. * - * @param[in] aInstance A pointer to an OpenThread instance. - * - * @returns The CSL period in units of 10 symbols. + * The CSL period (in micro seconds) MUST be a multiple of this value. * */ -uint16_t otLinkCslGetPeriod(otInstance *aInstance); +#define OT_LINK_CSL_PERIOD_TEN_SYMBOLS_UNIT_IN_USEC (160) /** - * Sets the CSL period in units of 10 symbols. Disable CSL by setting this parameter to `0`. + * Gets the CSL period in microseconds * * @param[in] aInstance A pointer to an OpenThread instance. - * @param[in] aPeriod The CSL period in units of 10 symbols. + * + * @returns The CSL period in microseconds. + * + */ +uint32_t otLinkGetCslPeriod(otInstance *aInstance); + +/** + * Sets the CSL period in microseconds. Disable CSL by setting this parameter to `0`. + * + * The CSL period MUST be a multiple of `OT_LINK_CSL_PERIOD_TEN_SYMBOLS_UNIT_IN_USEC`, otherwise `OT_ERROR_INVALID_ARGS` + * is returned. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aPeriod The CSL period in microseconds. * * @retval OT_ERROR_NONE Successfully set the CSL period. - * @retval OT_ERROR_INVALID_ARGS Invalid CSL period. + * @retval OT_ERROR_INVALID_ARGS Invalid CSL period * */ -otError otLinkCslSetPeriod(otInstance *aInstance, uint16_t aPeriod); +otError otLinkSetCslPeriod(otInstance *aInstance, uint32_t aPeriod); /** * Gets the CSL timeout. @@ -1076,7 +1087,7 @@ otError otLinkCslSetPeriod(otInstance *aInstance, uint16_t aPeriod); * @returns The CSL timeout in seconds. * */ -uint32_t otLinkCslGetTimeout(otInstance *aInstance); +uint32_t otLinkGetCslTimeout(otInstance *aInstance); /** * Sets the CSL timeout in seconds. @@ -1088,7 +1099,7 @@ uint32_t otLinkCslGetTimeout(otInstance *aInstance); * @retval OT_ERROR_INVALID_ARGS Invalid CSL timeout. * */ -otError otLinkCslSetTimeout(otInstance *aInstance, uint32_t aTimeout); +otError otLinkSetCslTimeout(otInstance *aInstance, uint32_t aTimeout); /** * Returns the current CCA (Clear Channel Assessment) failure rate. diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index bb7ef0c3d..35dd46496 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -1059,7 +1059,7 @@ otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCo * Enable or disable CSL receiver. * * @param[in] aInstance The OpenThread instance structure. - * @param[in] aCslPeriod CSL period, 0 for disabling CSL. + * @param[in] aCslPeriod CSL period, 0 for disabling CSL. CSL period is in unit of 10 symbols. * @param[in] aShortAddr The short source address of CSL receiver's peer. * @param[in] aExtAddr The extended source address of CSL receiver's peer. * diff --git a/src/cli/README.md b/src/cli/README.md index 3ad8e6c20..c0b9217ff 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -983,10 +983,12 @@ Done Get the CSL configuration. +CSL period is shown in microseconds. + ```bash > csl Channel: 11 -Period: 1000 (in units of 10 symbols), 160ms +Period: 160000us Timeout: 1000s Done ``` @@ -1002,10 +1004,12 @@ Done ### csl period \ -Set CSL period in units of 10 symbols. Disable CSL by setting this parameter to `0`. +Set CSL period in microseconds. Disable CSL by setting this parameter to `0`. + +The CSL period MUST be a multiple 160 microseconds which is 802.15.4 "ten symbols time". ```bash -> csl period 3000 +> csl period 30000000 Done ``` diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 05da53569..e7775fd25 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -2327,23 +2327,22 @@ template <> otError Interpreter::Process(Arg aArgs[]) * @code * csl * Channel: 11 - * Period: 1000 (in units of 10 symbols), 160ms + * Period: 160000us * Timeout: 1000s * Done * @endcode * @par * Gets the CSL configuration. - * @sa otLinkCslGetChannel - * @sa otLinkCslGetPeriod - * @sa otLinkCslGetPeriod - * @sa otLinkCslGetTimeout + * @sa otLinkGetCslChannel + * @sa otLinkGetCslPeriod + * @sa otLinkGetCslPeriod + * @sa otLinkGetCslTimeout */ if (aArgs[0].IsEmpty()) { - OutputLine("Channel: %u", otLinkCslGetChannel(GetInstancePtr())); - OutputLine("Period: %u(in units of 10 symbols), %lums", otLinkCslGetPeriod(GetInstancePtr()), - ToUlong(otLinkCslGetPeriod(GetInstancePtr()) * kUsPerTenSymbols / 1000)); - OutputLine("Timeout: %lus", ToUlong(otLinkCslGetTimeout(GetInstancePtr()))); + OutputLine("Channel: %u", otLinkGetCslChannel(GetInstancePtr())); + OutputLine("Period: %luus", ToUlong(otLinkGetCslPeriod(GetInstancePtr()))); + OutputLine("Timeout: %lus", ToUlong(otLinkGetCslTimeout(GetInstancePtr()))); } /** * @cli csl channel @@ -2353,25 +2352,25 @@ template <> otError Interpreter::Process(Arg aArgs[]) * @endcode * @cparam csl channel @ca{channel} * @par api_copy - * #otLinkCslSetChannel + * #otLinkSetCslChannel */ else if (aArgs[0] == "channel") { - error = ProcessSet(aArgs + 1, otLinkCslSetChannel); + error = ProcessSet(aArgs + 1, otLinkSetCslChannel); } /** * @cli csl period * @code - * csl period 3000 + * csl period 3000000 * Done * @endcode * @cparam csl period @ca{period} * @par api_copy - * #otLinkCslSetPeriod + * #otLinkSetCslPeriod */ else if (aArgs[0] == "period") { - error = ProcessSet(aArgs + 1, otLinkCslSetPeriod); + error = ProcessSet(aArgs + 1, otLinkSetCslPeriod); } /** * @cli csl timeout @@ -2381,11 +2380,11 @@ template <> otError Interpreter::Process(Arg aArgs[]) * @endcode * @cparam csl timeout @ca{timeout} * @par api_copy - * #otLinkCslSetTimeout + * #otLinkSetCslTimeout */ else if (aArgs[0] == "timeout") { - error = ProcessSet(aArgs + 1, otLinkCslSetTimeout); + error = ProcessSet(aArgs + 1, otLinkSetCslTimeout); } else { diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp index 7a97d4ce0..f342627a9 100644 --- a/src/core/api/link_api.cpp +++ b/src/core/api/link_api.cpp @@ -395,9 +395,9 @@ bool otLinkIsCslEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Ge bool otLinkIsCslSupported(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsCslSupported(); } -uint8_t otLinkCslGetChannel(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslChannel(); } +uint8_t otLinkGetCslChannel(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslChannel(); } -otError otLinkCslSetChannel(otInstance *aInstance, uint8_t aChannel) +otError otLinkSetCslChannel(otInstance *aInstance, uint8_t aChannel) { Error error = kErrorNone; @@ -409,25 +409,39 @@ exit: return error; } -uint16_t otLinkCslGetPeriod(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslPeriod(); } - -otError otLinkCslSetPeriod(otInstance *aInstance, uint16_t aPeriod) +uint32_t otLinkGetCslPeriod(otInstance *aInstance) { - Error error = kErrorNone; + return Mac::Mac::CslPeriodToUsec(AsCoreType(aInstance).Get().GetCslPeriod()); +} - VerifyOrExit((aPeriod == 0 || kMinCslPeriod <= aPeriod), error = kErrorInvalidArgs); - AsCoreType(aInstance).Get().SetCslPeriod(aPeriod); +otError otLinkSetCslPeriod(otInstance *aInstance, uint32_t aPeriod) +{ + Error error = kErrorNone; + uint16_t periodInTenSymbolsUnit; + + if (aPeriod == 0) + { + periodInTenSymbolsUnit = 0; + } + else + { + VerifyOrExit((aPeriod % kUsPerTenSymbols) == 0, error = kErrorInvalidArgs); + periodInTenSymbolsUnit = ClampToUint16(aPeriod / kUsPerTenSymbols); + VerifyOrExit(periodInTenSymbolsUnit >= kMinCslPeriod, error = kErrorInvalidArgs); + } + + AsCoreType(aInstance).Get().SetCslPeriod(periodInTenSymbolsUnit); exit: return error; } -uint32_t otLinkCslGetTimeout(otInstance *aInstance) +uint32_t otLinkGetCslTimeout(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslTimeout(); } -otError otLinkCslSetTimeout(otInstance *aInstance, uint32_t aTimeout) +otError otLinkSetCslTimeout(otInstance *aInstance, uint32_t aTimeout) { Error error = kErrorNone; diff --git a/src/core/common/time.hpp b/src/core/common/time.hpp index 89c22c239..e1e564161 100644 --- a/src/core/common/time.hpp +++ b/src/core/common/time.hpp @@ -65,6 +65,7 @@ public: static constexpr uint32_t kOneMinuteInMsec = kOneSecondInMsec * 60; ///< One minute interval in msec. static constexpr uint32_t kOneHourInMsec = kOneMinuteInMsec * 60; ///< One hour interval in msec. static constexpr uint32_t kOneDayInMsec = kOneHourInMsec * 24; ///< One day interval in msec. + static constexpr uint32_t kOneMsecInUsec = 1000u; ///< One millisecond in microseconds. /** * This constant defines a maximum time duration ensured to be longer than any other duration. diff --git a/src/core/mac/data_poll_sender.cpp b/src/core/mac/data_poll_sender.cpp index 4f1aaead6..e11f1c82b 100644 --- a/src/core/mac/data_poll_sender.cpp +++ b/src/core/mac/data_poll_sender.cpp @@ -504,9 +504,9 @@ uint32_t DataPollSender::CalculatePollPeriod(void) const period = Min(period, kRetxPollPeriod); #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (Get().GetCslPeriodMs() > 0) + if (Get().GetCslPeriodInMsec() > 0) { - period = Min(period, Get().GetCslPeriodMs()); + period = Min(period, Get().GetCslPeriodInMsec()); } #endif } diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 4131b2754..f0c3951c7 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -2291,6 +2291,16 @@ void Mac::SetCslPeriod(uint16_t aPeriod) UpdateCsl(); } +uint32_t Mac::GetCslPeriodInMsec(void) const +{ + return DivideAndRoundToClosest(CslPeriodToUsec(GetCslPeriod()), 1000u); +} + +uint32_t Mac::CslPeriodToUsec(uint16_t aPeriodInTenSymbols) +{ + return static_cast(aPeriodInTenSymbols) * kUsPerTenSymbols; +} + bool Mac::IsCslEnabled(void) const { return !Get().IsRxOnWhenIdle() && IsCslCapable(); } bool Mac::IsCslCapable(void) const { return (GetCslPeriod() > 0) && IsCslSupported(); } diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 26c9320eb..8e218553f 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -620,12 +620,15 @@ public: uint16_t GetCslPeriod(void) const { return mCslPeriod; } /** - * Gets the CSL period. + * Gets the CSL period in milliseconds. + * + * If the CSL period cannot be represented exactly in milliseconds, return the rounded value to the nearest + * millisecond. * * @returns CSL period in milliseconds. * */ - uint32_t GetCslPeriodMs(void) const { return mCslPeriod * kUsPerTenSymbols / 1000; } + uint32_t GetCslPeriodInMsec(void) const; /** * Sets the CSL period. @@ -635,6 +638,16 @@ public: */ void SetCslPeriod(uint16_t aPeriod); + /** + * This method converts a given CSL period in units of 10 symbols to microseconds. + * + * @param[in] aPeriodInTenSymbols The CSL period in unit of 10 symbols. + * + * @returns The converted CSL period value in microseconds corresponding to @p aPeriodInTenSymbols. + * + */ + static uint32_t CslPeriodToUsec(uint16_t aPeriodInTenSymbols); + /** * Indicates whether CSL is started at the moment. * @@ -680,7 +693,6 @@ public: { mLinks.GetSubMac().SetCslParentAccuracy(aCslAccuracy); } - #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE && OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index bbdb88485..7d85683b6 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -395,7 +395,7 @@ public: /** * Configures CSL parameters in 'SubMac'. * - * @param[in] aPeriod The CSL period. + * @param[in] aPeriod The CSL period (in unit of 10 symbols). * @param[in] aChannel The CSL channel. * @param[in] aShortAddr The short source address of CSL receiver's peer. * @param[in] aExtAddr The extended source address of CSL receiver's peer. diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index e64483b36..f33cf451c 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1948,7 +1948,7 @@ void Mle::ScheduleMessageTransmissionTimer(void) #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE if (Get().IsCslEnabled()) { - ExitNow(interval = Get().GetCslPeriodMs() + static_cast(kUnicastRetransmissionDelay)); + ExitNow(interval = Get().GetCslPeriodInMsec() + kUnicastRetransmissionDelay); } else #endif diff --git a/src/lib/spinel/spinel.h b/src/lib/spinel/spinel.h index c251eb1db..ffa370786 100644 --- a/src/lib/spinel/spinel.h +++ b/src/lib/spinel/spinel.h @@ -3055,10 +3055,13 @@ enum SPINEL_PROP_THREAD_NEW_DATASET = SPINEL_PROP_THREAD_EXT__BEGIN + 40, /// MAC CSL Period - /** Format: `S` + /** Format: `L` * Required capability: `SPINEL_CAP_THREAD_CSL_RECEIVER` * - * The CSL period in units of 10 symbols. Value of 0 indicates that CSL should be disabled. + * The CSL period in microseconds. Value of 0 indicates that CSL should be disabled. + * + * The CSL period MUST be a multiple of 160 (which is 802.15 "ten symbols time"). + * */ SPINEL_PROP_THREAD_CSL_PERIOD = SPINEL_PROP_THREAD_EXT__BEGIN + 41, diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 78141dbfc..867d3cefd 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -261,12 +261,12 @@ exit: #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE template <> otError NcpBase::HandlePropertySet(void) { - uint16_t cslPeriod; + uint32_t cslPeriod; otError error = OT_ERROR_NONE; - SuccessOrExit(error = mDecoder.ReadUint16(cslPeriod)); + SuccessOrExit(error = mDecoder.ReadUint32(cslPeriod)); - error = otLinkCslSetPeriod(mInstance, cslPeriod); + error = otLinkSetCslPeriod(mInstance, cslPeriod); exit: return error; @@ -274,7 +274,7 @@ exit: template <> otError NcpBase::HandlePropertyGet(void) { - return mEncoder.WriteUint16(otLinkCslGetPeriod(mInstance)); + return mEncoder.WriteUint32(otLinkGetCslPeriod(mInstance)); } template <> otError NcpBase::HandlePropertySet(void) @@ -284,7 +284,7 @@ template <> otError NcpBase::HandlePropertySet(v SuccessOrExit(error = mDecoder.ReadUint32(cslTimeout)); - error = otLinkCslSetTimeout(mInstance, cslTimeout); + error = otLinkSetCslTimeout(mInstance, cslTimeout); exit: return error; @@ -292,7 +292,7 @@ exit: template <> otError NcpBase::HandlePropertyGet(void) { - return mEncoder.WriteUint32(otLinkCslGetTimeout(mInstance)); + return mEncoder.WriteUint32(otLinkGetCslTimeout(mInstance)); } template <> otError NcpBase::HandlePropertySet(void) @@ -302,7 +302,7 @@ template <> otError NcpBase::HandlePropertySet(v SuccessOrExit(error = mDecoder.ReadUint8(cslChannel)); - error = otLinkCslSetChannel(mInstance, cslChannel); + error = otLinkSetCslChannel(mInstance, cslChannel); exit: return error; @@ -310,7 +310,7 @@ exit: template <> otError NcpBase::HandlePropertyGet(void) { - return mEncoder.WriteUint8(otLinkCslGetChannel(mInstance)); + return mEncoder.WriteUint8(otLinkGetCslChannel(mInstance)); } #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE diff --git a/tests/scripts/expect/cli-discover.exp b/tests/scripts/expect/cli-discover.exp index 6c769f735..420ba93b3 100755 --- a/tests/scripts/expect/cli-discover.exp +++ b/tests/scripts/expect/cli-discover.exp @@ -101,7 +101,7 @@ for {set i 3} {$i <= 4} {incr i} { if {$::env(THREAD_VERSION) != "1.1" && $::env(OT_NODE_TYPE) == "cli"} { send "csl channel 12\n" expect_line "Done" - send "csl period 3125\n" + send "csl period 500000\n" expect_line "Done" sleep 1 diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py index 7bf3c6ae1..69b245a58 100644 --- a/tests/scripts/thread-cert/pktverify/consts.py +++ b/tests/scripts/thread-cert/pktverify/consts.py @@ -383,8 +383,8 @@ MAC_FRAME_TYPE_ACK = 0x2 MAC_FRAME_TYPE_MAC_CMD = 0x3 # CSL -CSL_DEFAULT_PERIOD = 3125 # 0.5s, 3125 in units of ten symbols CSL_DEFAULT_PERIOD_IN_SECOND = 0.5 +CSL_DEFAULT_PERIOD = CSL_DEFAULT_PERIOD_IN_SECOND * 1000 * 1000 # in usec US_PER_TEN_SYMBOLS = 160 CSL_IE_ID = 0x1a CSL_DEFAULT_TIMEOUT = 30 diff --git a/tests/scripts/thread-cert/v1_2_test_single_probe.py b/tests/scripts/thread-cert/v1_2_test_single_probe.py index 93a8f67fe..5b29aaac8 100755 --- a/tests/scripts/thread-cert/v1_2_test_single_probe.py +++ b/tests/scripts/thread-cert/v1_2_test_single_probe.py @@ -36,7 +36,7 @@ import config LEADER = 1 SSED_1 = 2 -CSL_PERIOD = 500 * 6.25 # 500ms +CSL_PERIOD = 500 * 1000 # 0.5 in usec CSL_TIMEOUT = 30 # 30s diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py index 7bff870fa..47e83479e 100644 --- a/tools/harness-thci/OpenThread.py +++ b/tools/harness-thci/OpenThread.py @@ -2923,11 +2923,8 @@ class OpenThreadTHCI(object): Args: period: csl period in ms - note: OT command 'csl period' accepts parameter in unit of 10 symbols, - period is converted from unit ms to ten symbols (160us per 10 symbols). - """ - cmd = 'csl period %u' % (period * 6.25) + cmd = 'csl period %u' % (period * 1000) return self.__executeCommand(cmd)[-1] == 'Done' @staticmethod diff --git a/tools/otci/otci/otci.py b/tools/otci/otci/otci.py index 7df5930fd..e60acf8ee 100644 --- a/tools/otci/otci/otci.py +++ b/tools/otci/otci/otci.py @@ -1369,7 +1369,7 @@ class OTCI(object): # TODO: csl period # TODO: csl timeout - _CSL_PERIOD_PATTERN = re.compile(r'(\d+)\(in units of 10 symbols\), \d+ms') + _CSL_PERIOD_PATTERN = re.compile(r'(\d+)us') _CSL_TIMEOUT_PATTERN = re.compile(r'(\d+)s') def get_csl_config(self) -> Dict[str, int]: @@ -1398,7 +1398,7 @@ class OTCI(object): """Configure CSL parameters. :param channel: Set CSL channel. - :param period: Set CSL period in units of 10 symbols. Disable CSL by setting this parameter to 0. + :param period: Set CSL period in usec. Disable CSL by setting this parameter to 0. :param timeout: Set the CSL timeout in seconds. """ diff --git a/tools/otci/tests/test_otci.py b/tools/otci/tests/test_otci.py index 736647069..8e5a598c5 100644 --- a/tools/otci/tests/test_otci.py +++ b/tools/otci/tests/test_otci.py @@ -252,7 +252,7 @@ class TestOTCI(unittest.TestCase): self.assertTrue(all(x == 0 for name, x in leader.get_counter(counter_name).items() if "Time" not in name)) logging.info("CSL config: %r", leader.get_csl_config()) - leader.config_csl(channel=13, period=100, timeout=200) + leader.config_csl(channel=13, period=16000, timeout=200) logging.info("CSL config: %r", leader.get_csl_config()) logging.info("EID-to-RLOC cache: %r", leader.get_eidcache())