Skip to content

Commit 35e8141

Browse files
[low-power] enhance mCslFrameRequestAheadUs calculation for RCP
Implement `otPlatRadioGetBusLatency` and `otPlatRadioSetBusLatency` APIs, add optional latency arguments to ot-daemon and `rcp latency` CLI commands. Add APIs to update frame request ahead from runtime, which recalculate `mCslFrameRequestAheadUs` value. Changes allow setting a bus latency while starting a new session between host and RCP device. This way, one host can be connected to different devices and vice versa, ensuring that the latency will be added to `mCslFrameRequestAheadUs` calculations and CSL tx requests will not be sent too late. Signed-off-by: Maciej Baczmanski <maciej.baczmanski@nordicsemi.no>
1 parent 78ecafb commit 35e8141

File tree

13 files changed

+158
-6
lines changed

13 files changed

+158
-6
lines changed

include/openthread/instance.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ extern "C" {
5353
* @note This number versions both OpenThread platform and user APIs.
5454
*
5555
*/
56-
#define OPENTHREAD_API_VERSION (427)
56+
#define OPENTHREAD_API_VERSION (428)
5757

5858
/**
5959
* @addtogroup api-instance

include/openthread/platform/radio.h

+22
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,28 @@ uint64_t otPlatRadioGetNow(otInstance *aInstance);
757757
*/
758758
uint32_t otPlatRadioGetBusSpeed(otInstance *aInstance);
759759

760+
/**
761+
* Get the bus latency in microseconds between the host and the radio chip.
762+
*
763+
* @param[in] aInstance A pointer to an OpenThread instance.
764+
*
765+
* @returns The bus latency in microseconds between the host and the radio chip.
766+
* Return 0 when the MAC and above layer and Radio layer resides on the same chip.
767+
*
768+
*/
769+
uint32_t otPlatRadioGetBusLatency(otInstance *aInstance);
770+
771+
/**
772+
* Set the bus latency in microseconds between the host and the radio chip.
773+
*
774+
* @note This function does not do anything when the MAC and above layer and Radio layer resides on the same chip.
775+
*
776+
* @param[in] aInstance A pointer to an OpenThread instance.
777+
* @param[in] aLatency Bus latency in microseconds.
778+
*
779+
*/
780+
void otPlatRadioSetBusLatency(otInstance *aInstance, uint32_t aLatency);
781+
760782
/**
761783
* @}
762784
*

include/openthread/thread_ftd.h

+9
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,15 @@ void otThreadGetNextHopAndPathCost(otInstance *aInstance,
953953
uint16_t *aNextHopRloc16,
954954
uint8_t *aPathCost);
955955

956+
/**
957+
* Calculates and updates value of CSL Frame Request Ahead, based on bus speed, bus latency and
958+
* `OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US`.
959+
*
960+
* @param[in] aInstance A pointer to an OpenThread instance.
961+
*
962+
*/
963+
void otThreaUpdateFrameRequestAhead(otInstance *aInstance);
964+
956965
/**
957966
* @}
958967
*

src/cli/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -3218,6 +3218,25 @@ OPENTHREAD/20191113-00825-g82053cc9d-dirty; SIMULATION; Jun 4 2020 17:53:16
32183218
Done
32193219
```
32203220
3221+
### rcp latency
3222+
3223+
Get the bus latency in microseconds between the host and the radio chip.
3224+
3225+
```bash
3226+
> rcp latency
3227+
0
3228+
Done
3229+
```
3230+
3231+
### rcp latency \<latency\>
3232+
3233+
Set the bus latency in microseconds between the host and the radio chip.
3234+
3235+
```bash
3236+
> rcp latency 1000
3237+
Done
3238+
```
3239+
32213240
### releaserouterid \<routerid\>
32223241
32233242
Release a Router ID that has been allocated by the device in the Leader role.

src/cli/cli.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -5928,7 +5928,29 @@ template <> otError Interpreter::Process<Cmd("rcp")>(Arg aArgs[])
59285928
{
59295929
OutputLine("%s", version);
59305930
}
5931-
5931+
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
5932+
/**
5933+
* @cli rcp latency (get,set)
5934+
* @code
5935+
* rcp latency
5936+
* 0
5937+
* Done
5938+
* @endcode
5939+
* @code
5940+
* rcp latency 1000
5941+
* Done
5942+
* @endcode
5943+
* @cparam rcp latency [@ca{latency}]
5944+
* @par
5945+
* Gets or sets the bus latency in microseconds between the host and the radio chip.
5946+
* @sa otPlatRadioGetBusLatency
5947+
* @sa otPlatRadioSetBusLatency
5948+
*/
5949+
else if (aArgs[0] == "latency")
5950+
{
5951+
SuccessOrExit(error = ProcessGetSet(aArgs + 1, otPlatRadioGetBusLatency, otPlatRadioSetBusLatency));
5952+
}
5953+
#endif
59325954
else
59335955
{
59345956
error = OT_ERROR_INVALID_ARGS;

src/core/api/thread_ftd_api.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,12 @@ void otThreadGetNextHopAndPathCost(otInstance *aInstance,
428428
(aPathCost != nullptr) ? *aPathCost : pathcost);
429429
}
430430

431+
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
432+
void otThreaUpdateFrameRequestAhead(otInstance *aInstance)
433+
{
434+
AsCoreType(aInstance).Get<CslTxScheduler>().UpdateFrameRequestAhead();
435+
}
436+
437+
#endif // OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
438+
431439
#endif // OPENTHREAD_FTD

src/core/radio/radio_platform.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,19 @@ OT_TOOL_WEAK uint32_t otPlatRadioGetBusSpeed(otInstance *aInstance)
250250
return 0;
251251
}
252252

253+
OT_TOOL_WEAK uint32_t otPlatRadioGetBusLatency(otInstance *aInstance)
254+
{
255+
OT_UNUSED_VARIABLE(aInstance);
256+
257+
return 0;
258+
}
259+
260+
OT_TOOL_WEAK void otPlatRadioSetBusLatency(otInstance *aInstance, uint32_t aLatency)
261+
{
262+
OT_UNUSED_VARIABLE(aInstance);
263+
OT_UNUSED_VARIABLE(aLatency);
264+
}
265+
253266
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
254267
OT_TOOL_WEAK otError otPlatRadioResetCsl(otInstance *aInstance)
255268
{

src/core/thread/csl_tx_scheduler.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include "common/locator_getters.hpp"
3434
#include "common/log.hpp"
35+
#include "common/num_utils.hpp"
3536
#include "common/time.hpp"
3637
#include "mac/mac.hpp"
3738

@@ -68,16 +69,20 @@ CslTxScheduler::CslTxScheduler(Instance &aInstance)
6869
, mFrameContext()
6970
, mCallbacks(aInstance)
7071
{
71-
InitFrameRequestAhead();
72+
UpdateFrameRequestAhead();
7273
}
7374

74-
void CslTxScheduler::InitFrameRequestAhead(void)
75+
void CslTxScheduler::UpdateFrameRequestAhead(void)
7576
{
7677
uint32_t busSpeedHz = otPlatRadioGetBusSpeed(&GetInstance());
78+
uint32_t busLatency = otPlatRadioGetBusLatency(&GetInstance());
79+
7780
// longest frame on bus is 127 bytes with some metadata, use 150 bytes for bus Tx time estimation
7881
uint32_t busTxTimeUs = ((busSpeedHz == 0) ? 0 : (150 * 8 * 1000000 + busSpeedHz - 1) / busSpeedHz);
7982

80-
mCslFrameRequestAheadUs = OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + busTxTimeUs;
83+
mCslFrameRequestAheadUs = OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US + busTxTimeUs + busLatency;
84+
LogInfo("Bus TX Time: %lu usec, Latency: %lu usec. Calculated CSL Frame Request Ahead: %lu usec",
85+
ToUlong(busTxTimeUs), ToUlong(busLatency), ToUlong(mCslFrameRequestAheadUs));
8186
}
8287

8388
void CslTxScheduler::Update(void)

src/core/thread/csl_tx_scheduler.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,17 @@ class CslTxScheduler : public InstanceLocator, private NonCopyable
231231
*/
232232
void Clear(void);
233233

234+
/**
235+
* Updates the value of `mCslFrameRequestAheadUs`, based on bus speed, bus latency
236+
* and `OPENTHREAD_CONFIG_MAC_CSL_REQUEST_AHEAD_US`.
237+
*
238+
*/
239+
void UpdateFrameRequestAhead(void);
240+
234241
private:
235242
// Guard time in usec to add when checking delay while preparing the CSL frame for tx.
236243
static constexpr uint32_t kFramePreparationGuardInterval = 1500;
237244

238-
void InitFrameRequestAhead(void);
239245
void RescheduleCslTx(void);
240246

241247
uint32_t GetNextCslTransmissionDelay(const Child &aChild, uint32_t &aDelayFromLastRx, uint32_t aAheadUs) const;

src/lib/spinel/radio_spinel.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ RadioSpinel::RadioSpinel(void)
7878
, mPanId(0xffff)
7979
, mChannel(0)
8080
, mRxSensitivity(0)
81+
, mBusLatency(0)
8182
, mState(kStateDisabled)
8283
, mIsPromiscuous(false)
8384
, mRxOnWhenIdle(true)
@@ -1903,6 +1904,10 @@ uint64_t RadioSpinel::GetNow(void) { return (mIsTimeSynced) ? (otPlatTimeGet() +
19031904

19041905
uint32_t RadioSpinel::GetBusSpeed(void) const { return GetSpinelDriver().GetSpinelInterface()->GetBusSpeed(); }
19051906

1907+
uint32_t RadioSpinel::GetBusLatency(void) const { return mBusLatency; }
1908+
1909+
void RadioSpinel::SetBusLatency(uint32_t aLatency) { mBusLatency = aLatency; }
1910+
19061911
void RadioSpinel::HandleRcpUnexpectedReset(spinel_status_t aStatus)
19071912
{
19081913
OT_UNUSED_VARIABLE(aStatus);

src/lib/spinel/radio_spinel.hpp

+18
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,22 @@ class RadioSpinel : private Logger
857857
*/
858858
uint32_t GetBusSpeed(void) const;
859859

860+
/**
861+
* Returns the bus latency between the host and the radio.
862+
*
863+
* @returns Bus latency in microseconds.
864+
*
865+
*/
866+
uint32_t GetBusLatency(void) const;
867+
868+
/**
869+
* Sets the bus latency between the host and the radio.
870+
*
871+
* @param[in] aLatency Bus latency in microseconds.
872+
*
873+
*/
874+
void SetBusLatency(uint32_t aLatency);
875+
860876
/**
861877
* Returns the co-processor sw version string.
862878
*
@@ -1254,6 +1270,8 @@ class RadioSpinel : private Logger
12541270
static otExtAddress sIeeeEui64;
12551271
static otRadioCaps sRadioCaps;
12561272

1273+
uint32_t mBusLatency;
1274+
12571275
State mState;
12581276
bool mIsPromiscuous : 1; ///< Promiscuous mode.
12591277
bool mRxOnWhenIdle : 1; ///< RxOnWhenIdle mode.

src/posix/platform/radio.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <string.h>
3737

3838
#include <openthread/logging.h>
39+
#include <openthread/thread_ftd.h>
3940
#include <openthread/platform/diag.h>
4041

4142
#include "common/code_utils.hpp"
@@ -130,6 +131,13 @@ void Radio::ProcessRadioUrl(const RadioUrl &aRadioUrl)
130131
SuccessOrDie(otPlatRadioSetRegion(gInstance, regionCode));
131132
}
132133

134+
if (aRadioUrl.HasParam("bus-latency"))
135+
{
136+
uint32_t busLatency;
137+
SuccessOrDie(aRadioUrl.ParseUint32("bus-latency", busLatency));
138+
mRadioSpinel.SetBusLatency(busLatency);
139+
}
140+
133141
ProcessMaxPowerTable(aRadioUrl);
134142

135143
#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE
@@ -900,6 +908,22 @@ uint32_t otPlatRadioGetBusSpeed(otInstance *aInstance)
900908
return GetRadioSpinel().GetBusSpeed();
901909
}
902910

911+
uint32_t otPlatRadioGetBusLatency(otInstance *aInstance)
912+
{
913+
OT_UNUSED_VARIABLE(aInstance);
914+
return GetRadioSpinel().GetBusLatency();
915+
}
916+
917+
void otPlatRadioSetBusLatency(otInstance *aInstance, uint32_t aLatency)
918+
{
919+
GetRadioSpinel().SetBusLatency(aLatency);
920+
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
921+
otThreaUpdateFrameRequestAhead(aInstance);
922+
#else
923+
OT_UNUSED_VARIABLE(aInstance);
924+
#endif
925+
}
926+
903927
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
904928
uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance)
905929
{

src/posix/platform/radio_url.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ const char *otSysGetRadioUrlHelpString(void)
121121
" fem-lnagain[=dbm] Set the Rx LNA gain in dBm of the external FEM.\n"
122122
" no-reset Do not send Spinel reset command to RCP on initialization.\n"
123123
" skip-rcp-compatibility-check Skip checking RCP API version and capabilities during initialization.\n"
124+
" bus-latency[=usec] Communication latency in usec, default is 0.\n"
124125
#if OPENTHREAD_CONFIG_MULTIPAN_RCP_ENABLE
125126
" iid Set the Spinel Interface ID for this process. Valid values are 0-3.\n"
126127
" iid-list List of IIDs a host can subscribe to receive spinel frames other than \n"

0 commit comments

Comments
 (0)