@@ -67,7 +67,8 @@ static struct nrf5_802154_data nrf5_data;
6767static const struct device * nrf5_dev ;
6868#endif
6969
70- #define DRX_SLOT_RX 0 /* Delayed reception window ID */
70+ #define DRX_SLOT_RX_PRIMARY 0 /* Primary delayed reception window ID */
71+ #define DRX_SLOT_RX_SECONDARY 1 /* Secondary delayed reception window ID */
7172
7273#define NSEC_PER_TEN_SYMBOLS (10 * IEEE802154_PHY_OQPSK_780_TO_2450MHZ_SYMBOL_PERIOD_NS)
7374
@@ -855,6 +856,38 @@ static void nrf5_config_mac_keys(struct ieee802154_key *mac_keys)
855856}
856857#endif /* CONFIG_NRF_802154_ENCRYPTION */
857858
859+ #if defined(CONFIG_IEEE802154_CSL_ENDPOINT )
860+
861+ static void nrf5_receive_at (const struct ieee802154_config * config )
862+ {
863+ bool primary_cancel = nrf_802154_receive_at_scheduled_cancel (DRX_SLOT_RX_PRIMARY );
864+ bool secondary_cancel = nrf_802154_receive_at_scheduled_cancel (DRX_SLOT_RX_SECONDARY );
865+
866+ if (!primary_cancel && !secondary_cancel ) {
867+ /* Edge case: In between the primary and secondary slot cancellation
868+ * the secondary RX slot might have started. Due to ordering
869+ * of the above two cancellations we can assume that the primary
870+ * slot is already free.
871+ */
872+ primary_cancel = true;
873+ }
874+
875+ uint32_t slot_id = primary_cancel ? DRX_SLOT_RX_PRIMARY : DRX_SLOT_RX_SECONDARY ;
876+
877+ /* Note that even if the nrf_802154_receive_at function is not called in time
878+ * (for example due to the call being blocked by higher priority threads) and
879+ * the delayed reception window is not scheduled, the CSL phase will still be
880+ * calculated as if the following reception windows were at times
881+ * anchor_time + n * csl_period. The previously set
882+ * anchor_time will be used for calculations.
883+ */
884+ nrf_802154_receive_at (config -> rx_slot .start / NSEC_PER_USEC ,
885+ config -> rx_slot .duration / NSEC_PER_USEC ,
886+ config -> rx_slot .channel , slot_id );
887+ }
888+
889+ #endif /* CONFIG_IEEE802154_CSL_ENDPOINT */
890+
858891static int nrf5_configure (const struct device * dev ,
859892 enum ieee802154_config_type type ,
860893 const struct ieee802154_config * config )
@@ -1011,16 +1044,7 @@ static int nrf5_configure(const struct device *dev,
10111044 } break ;
10121045
10131046 case IEEE802154_CONFIG_RX_SLOT : {
1014- /* Note that even if the nrf_802154_receive_at function is not called in time
1015- * (for example due to the call being blocked by higher priority threads) and
1016- * the delayed reception window is not scheduled, the CSL phase will still be
1017- * calculated as if the following reception windows were at times
1018- * anchor_time + n * csl_period. The previously set
1019- * anchor_time will be used for calculations.
1020- */
1021- nrf_802154_receive_at (config -> rx_slot .start / NSEC_PER_USEC ,
1022- config -> rx_slot .duration / NSEC_PER_USEC ,
1023- config -> rx_slot .channel , DRX_SLOT_RX );
1047+ nrf5_receive_at (config );
10241048 } break ;
10251049
10261050 case IEEE802154_CONFIG_CSL_PERIOD : {
@@ -1136,7 +1160,8 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id)
11361160 const struct device * dev = nrf5_get_device ();
11371161
11381162#if defined(CONFIG_IEEE802154_CSL_ENDPOINT )
1139- if (id == DRX_SLOT_RX && error == NRF_802154_RX_ERROR_DELAYED_TIMEOUT ) {
1163+ if ((id == DRX_SLOT_RX_PRIMARY || id == DRX_SLOT_RX_SECONDARY )
1164+ && error == NRF_802154_RX_ERROR_DELAYED_TIMEOUT ) {
11401165 if (!nrf5_data .rx_on_when_idle ) {
11411166 /* Transition to RxOff done automatically by the driver */
11421167 return ;
0 commit comments