Skip to content

Commit

Permalink
drivers: ieee802154: improve CSL standard conformance
Browse files Browse the repository at this point in the history
This change slightly simplifies the configuration of a CSL receiver and
generalized CSL_RX_TIME to EXPECTED_RX_TIME as a re-usable primitive
across several timing-sensitive IEEE 802.15.4 standard sub-protocols
(namely BE-PANs/DSME/CSL/RIT/TSCH).

This API change is based on the rules outlined in RFC zephyrproject-rtos#61227.

Fixes: zephyrproject-rtos#62918

Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
  • Loading branch information
fgrandel committed Oct 8, 2023
1 parent 6552e05 commit 56fe356
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 63 deletions.
5 changes: 3 additions & 2 deletions drivers/ieee802154/ieee802154_nrf5.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,8 +905,9 @@ static int nrf5_configure(const struct device *dev,
} break;

#if defined(CONFIG_IEEE802154_CSL_ENDPOINT)
case IEEE802154_CONFIG_CSL_RX_TIME: {
nrf_802154_csl_writer_anchor_time_set(config->csl_rx_time / NSEC_PER_USEC);
case IEEE802154_CONFIG_EXPECTED_RX_TIME: {
nrf_802154_csl_writer_anchor_time_set(nrf_802154_timestamp_phr_to_mhr_convert(
config->expected_rx_time / NSEC_PER_USEC));
} break;

case IEEE802154_CONFIG_RX_SLOT: {
Expand Down
224 changes: 168 additions & 56 deletions include/zephyr/net/ieee802154_radio.h
Original file line number Diff line number Diff line change
Expand Up @@ -757,61 +757,181 @@ enum ieee802154_config_type {
IEEE802154_CONFIG_RX_SLOT,

/**
* Configure CSL receiver (Endpoint) period.
*
* @details In order to configure a CSL receiver the upper layer should combine several
* configuration options in the following way:
* 1. Use @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE once to inform the driver of the
* short and extended addresses of the peer to which it should inject CSL IEs.
* 2. Use @ref IEEE802154_CONFIG_CSL_RX_TIME periodically, before each use of
* @ref IEEE802154_CONFIG_CSL_PERIOD setting parameters of the nearest CSL RX window,
* and before each use of IEEE_CONFIG_RX_SLOT setting parameters of the following (not
* the nearest one) CSL RX window, to allow the driver to calculate the proper
* CSL phase to the nearest CSL window to inject in the CSL IEs for both transmitted
* data and ACK frames.
* 3. Use @ref IEEE802154_CONFIG_CSL_PERIOD on each value change to update the current
* CSL period value which will be injected in the CSL IEs together with the CSL phase
* based on @ref IEEE802154_CONFIG_CSL_RX_TIME.
* 4. Use @ref IEEE802154_CONFIG_RX_SLOT periodically to schedule the immediate receive
* window early enough before the expected window start time, taking into account
* possible clock drifts and scheduling uncertainties.
*
* This diagram shows the usage of the four options over time:
*
* Start CSL Schedule CSL window
*
* ENH_ACK_HEADER_IE CSL_RX_TIME (following window)
* | |
* | CSL_RX_TIME (nearest window) | RX_SLOT (nearest window)
* | | | |
* | | CSL_PERIOD | |
* | | | | |
* v v v v v
* ----------------------------------------------------------[ CSL window ]-----+
* ^ |
* | |
* +--------------------- loop ---------+
* Enables or disables a device as a CSL receiver and configures its CSL
* period.
*
* @details Configures the CSL period in units of 10 symbol periods.
* Values greater than zero enable CSL if the driver supports it and the
* device starts to operate as a CSL receiver. Setting this to zero
* disables CSL on the device. If the driver does not support CSL, the
* configuration call SHALL return -ENOTSUP.
*
* See section 7.4.2.3 and section 8.4.3.6, table 8-104, macCslPeriod.
*
* @note Confusingly the standard calls the CSL receiver "CSL
* coordinator" (i.e. "coordinating the CSL protocol timing", see
* section 6.12.2.2), although, typically, a CSL coordinator is NOT also
* an IEEE 802.15.4 FFD coordinator or PAN coordintor but a simple RFD
* end device (compare the device roles outlined in sections 5.1, 5.3,
* 5.5 and 6.1). To avoid confusion we therefore prefer calling CSL
* coordinators (typically an RFD end device) "CSL receivers" and CSL
* peer devices (typically FFD coordinators or PAN coordinators) "CSL
* transmitters". Also note that at this time, we do NOT support
* unsynchronized transmission with CSL wake up frames as specified in
* section 6.12.2.4.4.
*
* To offload CSL receiver timing to the driver the upper layer SHALL
* combine several configuration options in the following way:
*
* 1. Use @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE once with an
* appropriate pre-filled CSL IE and the CSL phase set to an
* arbitrary value or left uninitialized. The CSL phase SHALL be
* injected on-the-fly by the driver at runtime as outlined in 2.
* below. Adding a short and extended address will inform the driver
* of the specific CSL receiver to which it SHALL inject CSL IEs. If
* no addresses are given then the CSL IE will be injected into all
* enhanced ACK frames as soon as CSL is enabled. This configuration
* SHALL be done before enabling CSL by setting a CSL period greater
* than zero.
*
* 2. Configure @ref IEEE802154_CONFIG_EXPECTED_RX_TIME immediately
* followed by @ref IEEE802154_CONFIG_CSL_PERIOD. To prevent race
* conditions, the upper layer SHALL ensure that the receiver is not
* enabled during or between the two calls (e.g. by a previously
* configured RX slot) nor SHALL a frame be transmitted concurrently.
*
* The expected RX time SHALL point to the end of SFD of an ideally
* timed RX frame in an arbitrary past or future CSL channel sample,
* i.e. whose "end of SFD" arrives exactly at the locally predicted
* time inside the CSL channel sample.
*
* The driver SHALL derive CSL anchor points and the CSL phase from
* the given expected RX time as follows:
*
* cslAnchorPointNs = last expected RX time
* + PHY-specific PHR duration in ns
*
* startOfMhrNs = start of MHR of the frame containing the
* CSL IE relative to the local network clock
*
* cslPhase = (startOfMhrNs - cslAnchorPointNs)
* / (10 * PHY specific symbol period in ns)
* % cslPeriod
*
* The driver SHALL set the CSL phase in the IE configured in 1. and
* inject that IE on-the-fly into outgoing enhanced ACK frames if the
* destination address conforms to the IE's address filter.
*
* 3. Use @ref IEEE802154_CONFIG_RX_SLOT periodically to schedule
* each CSL channel sample early enough before its start time. The
* size of the CSL channel sample SHALL take relative clock drift and
* scheduling uncertainties with respect to CSL transmitters into
* account as specified by the standard such that at least the full
* SHR of a legitimate RX frame is guaranteed to land inside the
* channel sample.
*
* To this avail, the last configured expected RX time plus an
* integer number of CSL periods SHALL point exactly to the center of
* each CSL channel sample:
*
* rxSlotCenterNs_N = last expected RX time
* + N * (cslPeriod * 10 * PHY-specific symbol period in ns)
*
* While the configured CSL period is greater than zero, drivers
* SHOULD validate the center of each RX slot accordingly. If
* validation fails, drivers SHOULD log the error but SHALL
* nevertheless accept and schedule the RX slot with a zero success
* value to work around minor implementation or rounding errors in
* upper layers.
*
* Configure and start a CSL receiver:
*
* ENH_ACK_HEADER_IE
* |
* | EXPECTED_RX_TIME (end of SFD of a perfectly timed RX
* | | frame in the first channel sample)
* | |
* | | CSL_PERIOD (>0) RX_SLOT
* | | | |
* v v v v
* -----------------------------------------------[-CSL channel sample ]----+
* ^ |
* | |
* +--------------------- loop ---------+
*
* Disable CSL on the receiver:
*
* CSL_PERIOD (=0)
* |
* v
* ---------------------
*
* Update the CSL period to a new value:
*
* EXPECTED_RX_TIME (based on updated period)
* |
* | CSL_PERIOD (>0, updated) RX_SLOT
* | | |
* v v v
* -----------------------------------------------[-CSL channel sample ]----+
* ^ |
* | |
* +--------------------- loop ---------+
*
* @note Available in any interface operational state.
*
* @warning This configuration option does not conform to the
* requirements specified in #61227 as it is incompatible with standard
* primitives and may therefore be deprecated in the future.
*/
IEEE802154_CONFIG_CSL_PERIOD,

/**
* @brief Configure the next CSL receive window (i.e. "channel sample")
* center, in units of nanoseconds relative to the network subsystem's
* local clock.
* Configure a timepoint at which an RX frame is expected to arrive.
*
* @details Configure the nanosecond resolution timepoint relative to
* the network subsystem's local clock at which an RX frame's end of SFD
* (i.e. equivalently its end of SHR, start of PHR, or in the case of
* PHYs with RDEV or ERDEV capability the RMARKER) is expected to arrive
* at the local antenna assuming perfectly synchronized local and remote
* network clocks and zero distance between antennas.
*
* This parameter MAY be used to offload parts of timing sensitive TDMA
* (e.g. TSCH, beacon-enabled PAN including DSME), low-energy (e.g.
* CSL, RIT) or ranging (TDoA) protocols to the driver. In these
* protocols, medium access is tightly controlled such that the expected
* arrival time of a frame can be predicted within a well-defined time
* window. This feature will typically be combined with @ref
* IEEE802154_CONFIG_RX_SLOT although this is not a hard requirement.
*
* The "expected RX time" MAY be interpreted slightly differently
* depending on the protocol context:
* - CSL phase (i.e. time to the next expected CSL transmission) or anchor
* time (i.e. any arbitrary timepoint with "zero CSL phase") SHALL be
* derived by adding the PHY header duration to the expected RX time
* to calculate the "start of MHR" ("first symbol of MAC", see section
* 6.12.2.1) required by the CSL protocol, compare @ref
* IEEE802154_CONFIG_CSL_PERIOD.
* - In TSCH the expected RX time MAY be set to macTsRxOffset +
* macTsRxWait / 2. Then the time correction SHALL be calculated as
* the expected RX time minus actual arrival timestamp, see section
* 6.5.4.3.
* - In ranging applications, time difference of arrival (TDOA) MAY be
* calculated inside the driver comparing actual RMARKER timestamps
* against the assumed synchronized time at which the ranging frame
* was sent, see IEEE 802.15.4z.
*
* In case of periodic protocols (e.g. CSL channel samples, periodic
* beacons of a single PAN, periodic ranging "blinks"), a single
* timestamp at any time in the past or in the future may be given from
* which other expected timestamps can be derived by adding or
* substracting multiples of the RX period. See e.g. the CSL
* documentation in this API.
*
* Additionally this parameter MAY be used by drivers to discipline
* their local representation of a distributed network clock by deriving
* synchronization instants related to a remote representation of the
* same clock (as in PTP).
*
* @note Available in any interface operational state.
*
* @warning This configuration option does not conform to the
* requirements specified in #61227 as it is incompatible with standard
* primitives and may therefore be deprecated in the future.
*/
IEEE802154_CONFIG_CSL_RX_TIME,
IEEE802154_CONFIG_EXPECTED_RX_TIME,

/**
* Indicates whether to inject IE into ENH ACK Frame for specific address
Expand Down Expand Up @@ -927,22 +1047,14 @@ struct ieee802154_config {
/**
* see @ref IEEE802154_CONFIG_CSL_PERIOD
*
* The CSL period in units of 10 symbol periods,
* see section 7.4.2.3.
*
* in CPU byte order
*/
uint32_t csl_period;

/**
* see @ref IEEE802154_CONFIG_CSL_RX_TIME
*
* Nanosecond resolution timestamp relative to the network
* subsystem's local clock defining the center of the CSL RX window
* at which the receiver is expected to be fully started up
* (i.e. not including any startup times).
* see @ref IEEE802154_CONFIG_EXPECTED_RX_TIME
*/
net_time_t csl_rx_time;
net_time_t expected_rx_time;

/** see @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE */
struct {
Expand Down
14 changes: 12 additions & 2 deletions modules/openthread/platform/radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL);

#define CHANNEL_COUNT OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MAX - OT_RADIO_2P4GHZ_OQPSK_CHANNEL_MIN + 1

/* PHY header duration in us (i.e. 2 symbol periods @ 62.5k symbol rate), see
* IEEE 802.15.4, sections 12.1.3.1, 12.2.5 and 12.3.3.
*/
#define PHR_DURATION_US 32U

enum pending_events {
PENDING_EVENT_FRAME_TO_SEND, /* There is a tx frame to send */
PENDING_EVENT_FRAME_RECEIVED, /* Radio has received new frame */
Expand Down Expand Up @@ -1265,10 +1270,15 @@ void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTi
{
ARG_UNUSED(aInstance);

/* CSL sample time points to "start of MAC" while the expected RX time
* refers to "end of SFD".
*/
struct ieee802154_config config = {
.csl_rx_time = convert_32bit_us_wrapped_to_64bit_ns(aCslSampleTime)};
.expected_rx_time =
convert_32bit_us_wrapped_to_64bit_ns(aCslSampleTime - PHR_DURATION_US),
};

(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_RX_TIME, &config);
(void)radio_api->configure(radio_dev, IEEE802154_CONFIG_EXPECTED_RX_TIME, &config);
}
#endif /* CONFIG_OPENTHREAD_CSL_RECEIVER */

Expand Down
8 changes: 5 additions & 3 deletions tests/subsys/openthread/radio_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,20 +901,22 @@ static int custom_configure_csl_rx_time(const struct device *dev,
const struct ieee802154_config *config)
{
zassert_equal(dev, radio, "Device handle incorrect.");
zassert_equal(type, IEEE802154_CONFIG_CSL_RX_TIME, "Config type incorrect.");
custom_configure_csl_rx_time_mock_csl_rx_time = config->csl_rx_time;
zassert_equal(type, IEEE802154_CONFIG_EXPECTED_RX_TIME, "Config type incorrect.");
custom_configure_csl_rx_time_mock_csl_rx_time = config->expected_rx_time;

return 0;
}

ZTEST(openthread_radio, test_csl_receiver_sample_time)
{
uint32_t sample_time = 50U;
uint32_t phr_duration = 32U;

configure_mock_fake.custom_fake = custom_configure_csl_rx_time;
otPlatRadioUpdateCslSampleTime(NULL, sample_time);
zassert_equal(1, configure_mock_fake.call_count);
zassert_equal(sample_time * NSEC_PER_USEC, custom_configure_csl_rx_time_mock_csl_rx_time);
zassert_equal((sample_time - phr_duration) * NSEC_PER_USEC,
custom_configure_csl_rx_time_mock_csl_rx_time);
}


Expand Down

0 comments on commit 56fe356

Please sign in to comment.