1 /* 2 * Copyright (c) 2018 - 2023, Nordic Semiconductor ASA 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright notice, this 11 * list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its 18 * contributors may be used to endorse or promote products derived from this 19 * software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 /** 36 * @brief Module that defines the Radio Scheduler interface. 37 * 38 */ 39 40 #ifndef NRF_802154_RSCH_H_ 41 #define NRF_802154_RSCH_H_ 42 43 #include <stdbool.h> 44 #include <stdint.h> 45 46 #ifdef __cplusplus 47 extern "C" { 48 #endif 49 50 /** 51 * @defgroup nrf_rsch Radio Scheduler 52 * @{ 53 * @ingroup nrf_802154 54 * @brief The Radio Scheduler interface. 55 * 56 * Radio Scheduler is responsible to schedule radio activities and preconditions in time. It is 57 * expected that the Radio Scheduler module manages timings to meet the requirements requested from 58 * the core module. 59 * 60 * Examples of the radio activity preconditions are: High-Frequency Clock running, radio arbiter (RAAL) 61 * granted access to the RADIO peripheral. 62 */ 63 64 /** 65 * @brief Maximum number of DTX delayed timeslots that can be scheduled simultaneously. 66 */ 67 #ifndef NRF_802154_RSCH_DLY_TS_OP_DTX_SLOTS 68 #define NRF_802154_RSCH_DLY_TS_OP_DTX_SLOTS 1 69 #endif 70 71 /** 72 * @brief Maximum number of DRX delayed timeslots that can be scheduled simultaneously. 73 */ 74 #ifndef NRF_802154_RSCH_DLY_TS_OP_DRX_SLOTS 75 #define NRF_802154_RSCH_DLY_TS_OP_DRX_SLOTS 2 76 #endif 77 78 /** 79 * @brief Maximum number of CSMA/CA delayed timeslots that can be scheduled simultaneously. 80 */ 81 #ifndef NRF_802154_RSCH_DLY_TS_OP_CSMACA_SLOTS 82 #define NRF_802154_RSCH_DLY_TS_OP_CSMACA_SLOTS 1 83 #endif 84 85 /** 86 * @brief Number of available slots for all delayed timeslots. 87 */ 88 #define NRF_802154_RSCH_DLY_TS_SLOTS \ 89 NRF_802154_RSCH_DLY_TS_OP_DTX_SLOTS + \ 90 NRF_802154_RSCH_DLY_TS_OP_DRX_SLOTS + \ 91 NRF_802154_RSCH_DLY_TS_OP_CSMACA_SLOTS 92 93 /** 94 * @brief List of the preconditions that have to be met before any radio activity. 95 */ 96 typedef enum 97 { 98 RSCH_PREC_HFCLK, 99 RSCH_PREC_RAAL, 100 RSCH_PREC_COEX, 101 RSCH_PREC_CNT, 102 } rsch_prec_t; 103 104 /** 105 * @brief Priorities of the 802.15.4 radio operations. 106 */ 107 typedef enum 108 { 109 RSCH_PRIO_IDLE, ///< Priority used in the sleep state. With this priority, RSCH releases all preconditions. 110 RSCH_PRIO_IDLE_LISTENING, ///< Priority used during the idle listening procedure. 111 RSCH_PRIO_RX, ///< Priority used when a frame is being received. 112 RSCH_PRIO_DETECT, ///< Priority used to detect channel conditions (CCA, ED). 113 RSCH_PRIO_TX, ///< Priority used to transmit a frame. 114 115 RSCH_PRIO_MIN_APPROVED = RSCH_PRIO_IDLE_LISTENING, ///< Minimal priority indicating that the given precondition is approved. 116 RSCH_PRIO_MAX = RSCH_PRIO_TX, ///< Maximal priority available in the RSCH module. 117 } rsch_prio_t; 118 119 /** 120 * @brief Enumeration of the delayed timeslot operation types. 121 */ 122 typedef enum 123 { 124 RSCH_DLY_TS_OP_DTX, ///< Timeslot for delayed TX operation. 125 RSCH_DLY_TS_OP_DRX, ///< Timeslot for delayed RX operation. 126 RSCH_DLY_TS_OP_CSMACA, ///< Timeslot for CSMA/CA operation. 127 } rsch_dly_ts_op_t; 128 129 /** 130 * @brief Identifier of a delayed timeslot. 131 */ 132 typedef uint32_t rsch_dly_ts_id_t; 133 134 /** 135 * @brief Enumeration of the precondition requesting strategies. 136 */ 137 typedef enum 138 { 139 /** The following delayed timeslot type requires preconditions to be requested immediately 140 * and released only by @ref nrf_802154_rsch_delayed_timeslot_cancel call. It is scheduled 141 * irrespectively of current approved preconditions, which might introduce additional delays. 142 * This delayed timeslot type also supports requests with target time in the past. 143 */ 144 RSCH_DLY_TS_TYPE_RELAXED, 145 146 /** The following delayed timeslot type requires preconditions to be requested as late 147 * as possible to ensure they are ramped up on target time, and released as soon as possible. 148 * This mode of operation does not allow for requests in the past and puts strict conditions 149 * on preconditions that must be approved when the scheduled operation starts. 150 */ 151 RSCH_DLY_TS_TYPE_PRECISE, 152 } rsch_dly_ts_type_t; 153 154 /** 155 * @brief Function pointer used for notifying about delayed timeslot start. 156 * 157 * @param[in] dly_ts_id Identifier of the started delayed timeslot. 158 */ 159 typedef void (* rsch_dly_ts_started_callback_t)(rsch_dly_ts_id_t dly_ts_id); 160 161 /** 162 * @brief Structure that holds parameters of a delayed timeslot request. 163 */ 164 typedef struct 165 { 166 uint64_t trigger_time; ///< Trigger time of the timeslot start, in microseconds. 167 bool ppi_trigger_en; ///< Enable the (D)PPI triggering after the start of the timeslot. 168 uint32_t ppi_trigger_dly; ///< Time delta between @p trigger_time and the moment of (D)PPI triggering. 169 rsch_prio_t prio; ///< Priority level required for the delayed timeslot. 170 rsch_dly_ts_op_t op; ///< Operation to be performed in the requested timeslot. 171 rsch_dly_ts_type_t type; ///< Type of the requested timeslot. 172 rsch_dly_ts_started_callback_t started_callback; ///< Callback called when delayed timeslot starts. 173 rsch_dly_ts_id_t id; ///< Identifier of the timeslot provided by its owner. Its value must be unique, to unambigously map to an active slot. 174 } rsch_dly_ts_param_t; 175 176 /** 177 * @brief Initializes Radio Scheduler. 178 * 179 * @note This function must be called once, before any other function from this module. 180 * 181 * @note Radio Scheduler starts in the inactive mode after the initialization. To start the radio activity, 182 * @ref nrf_802154_rsch_continuous_mode_enter should be called. 183 * 184 */ 185 void nrf_802154_rsch_init(void); 186 187 /** 188 * @brief Deinitializes Radio Scheduler. 189 * 190 */ 191 void nrf_802154_rsch_uninit(void); 192 193 /** 194 * @brief Sets the priority for the continuous radio mode. 195 * 196 * In the continuous mode, Radio Scheduler tries to satisfy all preconditions for as long as 197 * possible to give the radio driver core as much radio time as possible while 198 * disturbing the other activities to the minimum extent. 199 * 200 * @note The start of a timeslot is indicated by the @ref nrf_802154_rsch_prec_is_approved call. 201 * @note To disable the continuous radio mode, the @ref RSCH_PRIO_IDLE should be used. 202 * 203 * @param[in] prio Priority level used in the continuous radio mode. 204 * 205 */ 206 void nrf_802154_rsch_continuous_mode_priority_set(rsch_prio_t prio); 207 208 /** 209 * @brief Confirms that the current part of the continuous timeslot is ended by the core. 210 * 211 * This confirmation is used by the core to synchronize the ending of the continuous timeslot parts with 212 * the RSCH module. 213 * 214 */ 215 void nrf_802154_rsch_continuous_ended(void); 216 217 /** 218 * @brief Immediately requests a timeslot for radio communication. 219 * 220 * This function is to be called only after @ref nrf_802154_rsch_prec_is_approved indicated the 221 * start of a timeslot. 222 * 223 * @param[in] length_us Requested radio timeslot length in microseconds. 224 * 225 * @retval true Radio driver has now exclusive access to the RADIO peripheral for the 226 * full length of the timeslot. 227 * @retval false Slot cannot be assigned due to other activities. 228 * 229 */ 230 bool nrf_802154_rsch_timeslot_request(uint32_t length_us); 231 232 /** 233 * @brief Requests a timeslot in the future. 234 * 235 * Request timeslot that is to be granted in the future. The function parameters provide data when 236 * the timeslot is supposed to start and how long it is to last. When the requested timeslot starts, 237 * @p p_dly_ts_param->started_callback is called. 238 * 239 * For a given type of operation to be performed in the delayed timeslot, @p p_dly_ts_param->op, 240 * there's a limited number of delayed timeslots that can be scheduled at the same time: 241 * - for delayed transmissions it's @ref NRF_802154_RSCH_DLY_TS_OP_DTX_SLOTS; 242 * - for delayed receptions it's @ref NRF_802154_RSCH_DLY_TS_OP_DRX_SLOTS; 243 * - for CSMA/CA it's @ref NRF_802154_RSCH_DLY_TS_OP_CSMACA_SLOTS. 244 * 245 * If the API user requests more delayed timeslots with given @p p_dly_ts_param->op than specified 246 * by these constants, the request will fail unconditionally. It also implies that there can only 247 * be as many delayed timeslots scheduled simultaneously in total as the sum of these constants. 248 * 249 * @note Every call to this function must be paired with a call to 250 * @ref nrf_802154_rsch_delayed_timeslot_cancel so that the assigned slot becomes 251 * available for future requests. 252 * 253 * @note @p p_dly_ts_param->started_callback can be delayed and it is up to 254 * the called module to check the delay and decide if it causes any issues. 255 * 256 * @note The time parameters use the same units that are used in the SL Timer module. 257 * 258 * @param[in] p_dly_ts_param Parameters of the requested delayed timeslot. 259 * 260 * @retval true Requested timeslot has been scheduled. 261 * @retval false Requested timeslot cannot be scheduled and will not be granted. 262 */ 263 bool nrf_802154_rsch_delayed_timeslot_request(const rsch_dly_ts_param_t * p_dly_ts_param); 264 265 /** 266 * @brief Cancels a requested future timeslot. 267 * 268 * The delayed timeslot must be explicitly cancelled from the @p p_dly_ts_param->started_callback 269 * handler function passed to @ref nrf_802154_rsch_delayed_timeslot_request. When timeslot is 270 * released from the handler context, the @p handler flag must be set to @p true. 271 * Otherwise, the timeslot can be cancelled before it starts, which may be earlier than entering the 272 * @p p_dly_ts_param->started_callback handler function. 273 * 274 * Care must be taken when canceling a timeslot from an interrupt context. Delayed timeslots with 275 * type @p RSCH_DLY_TS_TYPE_PRECISE cannot be safely canceled from an interrupt context with higher 276 * priority than delayed timeslot callback context. 277 * 278 * @param[in] dly_ts_id Identifier of the requested timeslot. If the provided value does not refer 279 * to any scheduled delayed timeslot, the function returns false. 280 * @param[in] handler Indicates whether the requested timeslot is released from handler function. 281 * 282 * @retval true Scheduled timeslot has been cancelled. 283 * @retval false No scheduled timeslot has been requested (nothing to cancel). 284 */ 285 bool nrf_802154_rsch_delayed_timeslot_cancel(rsch_dly_ts_id_t dly_ts_id, bool handler); 286 287 /** 288 * @brief Updates the id of (D)PPI channel to be triggered in the current timeslot. 289 * 290 * The update must be done after the start of the timeslot but earlier than @c ppi_trigger_dly. 291 * If updating does not complete on time, (D)PPI triggering may not be performed. 292 * 293 * @retval true (D)PPI channel has been updated and it was done on time, i.e. before 294 * target trigger time. 295 * @retval false Update could not complete or did not complete on time. Nevertheless, 296 * the (D)PPI may have been triggered, but it cannot be stated reliably. 297 */ 298 bool nrf_802154_rsch_delayed_timeslot_ppi_update(uint32_t ppi_channel); 299 300 /** 301 * @brief Updates priority of a requested delayed timeslot. 302 * 303 * @param[in] dly_ts_id Identifier of the requested timeslot. If the provided value does not 304 * refer to any scheduled or active delayed timeslot, the function 305 * returns false. 306 * @param[in] dly_ts_prio Priority to be assigned to the requested timeslot. 307 * 308 * @retval true Scheduled timeslot's priority has been updated. 309 * @retval false Priority of the specified timeslot could not be updated. 310 */ 311 bool nrf_802154_rsch_delayed_timeslot_priority_update(rsch_dly_ts_id_t dly_ts_id, 312 rsch_prio_t dly_ts_prio); 313 314 /** 315 * @brief Retrieves the remaining time until a requested timeslot begins. 316 * 317 * @param[in] dly_ts_id ID of the requested timeslot. 318 * @param[out] p_time_to_start Pointer to a 32-bit variable where time to start will be stored. 319 * 320 * @retval true The given timeslot was scheduled and p_time_to_start contains a valid value. 321 * @retval false The given timeslot was not scheduled and p_time_to_start was not modified. 322 */ 323 bool nrf_802154_rsch_delayed_timeslot_time_to_start_get(rsch_dly_ts_id_t dly_ts_id, 324 uint64_t * p_time_to_start); 325 326 /** 327 * @brief Checks if there is a pending timeslot request. 328 * 329 * @note The delayed timeslot is considered requested once its preconditions are requested 330 * or granted. 331 * 332 * @retval true There is a timeslot request pending. 333 * @retval false There are no pending timeslot requests. 334 */ 335 bool nrf_802154_rsch_timeslot_is_requested(void); 336 337 /** 338 * @brief Checks if the RSCH precondition is satisfied. 339 * 340 * @param[in] prec RSCH precondition to be checked. 341 * @param[in] prio Minimal required priority level of the given precondition. 342 * 343 * @retval true Precondition @p prec is currently granted. 344 * @retval false Precondition @p prec is not currently granted. 345 */ 346 bool nrf_802154_rsch_prec_is_approved(rsch_prec_t prec, rsch_prio_t prio); 347 348 /** 349 * @brief Gets the remaining time of the currently granted timeslot, in microseconds. 350 * 351 * @returns Number of microseconds remaining in the currently granted timeslot. 352 */ 353 uint32_t nrf_802154_rsch_timeslot_us_left_get(void); 354 355 /** 356 * @brief Notifies the core about changes of the approved priority level. 357 * 358 * If @p prio is greater than @ref RSCH_PRIO_IDLE, the radio driver has exclusive access to the 359 * peripherals until this function is called with @p prio equal to @ref RSCH_PRIO_IDLE. 360 * 361 * @note The end of the timeslot is indicated by @p prio equal to @ref RSCH_PRIO_IDLE. 362 * 363 * @param[in] prio Currently approved priority level. 364 */ 365 extern void nrf_802154_rsch_continuous_prio_changed(rsch_prio_t prio); 366 367 #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX) 368 /** 369 * @brief Retrieves time remaining to hardware trigger of a delayed timeslot. 370 * 371 * @note This function exists for testing purposes only. It should not be used in products. 372 */ 373 uint32_t nrf_802154_rsch_delayed_timeslot_time_to_hw_trigger_get(void); 374 #endif /* defined(CONFIG_SOC_SERIES_BSIM_NRFXX) */ 375 376 /** 377 *@} 378 **/ 379 380 #ifdef __cplusplus 381 } 382 #endif 383 384 #endif /* NRF_802154_RSCH_H_ */ 385