1 /* 2 * Copyright (c) 2020 - 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 provides the timer service for the 802.15.4 driver. 37 * 38 * The @b timer module allows scheduling future actions to happen. Object of type 39 * @ref nrf_802154_sl_timer_t (and related functions) is responsible for this feature. 40 */ 41 42 #ifndef NRF_802154_SL_TIMER_H_ 43 #define NRF_802154_SL_TIMER_H_ 44 45 #include <stdint.h> 46 #include <stdbool.h> 47 48 #ifdef __cplusplus 49 extern "C" { 50 #endif 51 52 /** 53 * @defgroup nrf_802154_sl_timer Timer Service 54 * @{ 55 * @ingroup nrf_802154_sl_timer 56 * @brief The Timer Service for the 802.15.4 driver. 57 * 58 */ 59 60 /**@brief Number of array elements required by @ref nrf_802154_sl_timer_priv_placeholder_t. */ 61 #define NRF_802154_SL_TIMER_PRIV_SIZE 2U 62 63 /**@brief Type of result returned by timer-related functions. 64 * 65 * Possible values: 66 * @ref NRF_802154_SL_TIMER_RET_SUCCESS 67 * @ref NRF_802154_SL_TIMER_RET_TOO_LATE 68 * @ref NRF_802154_SL_TIMER_RET_TOO_DISTANT 69 * @ref NRF_802154_SL_TIMER_RET_NO_RESOURCES 70 * @ref NRF_802154_SL_TIMER_RET_INACTIVE 71 * @ref NRF_802154_SL_TIMER_RET_BAD_REQUEST 72 */ 73 typedef uint32_t nrf_802154_sl_timer_ret_t; 74 75 /**@brief Operation performed successfully. */ 76 #define NRF_802154_SL_TIMER_RET_SUCCESS 0U 77 78 /**@brief Passed invalid parameters to a call. 79 * This result may occur if the user filled incorrect values in the request 80 * object or given feature is not supported yet 81 */ 82 #define NRF_802154_SL_TIMER_RET_BAD_REQUEST 1U 83 84 /**@brief Operation was requested too late to be performed in requested time. */ 85 #define NRF_802154_SL_TIMER_RET_TOO_LATE 2U 86 87 /**@brief The trigger time for the requested operation is too distant. 88 * 89 * Some platforms have a limitation to how far in the future operation can be 90 * scheduled. This result may happen for @ref nrf_802154_sl_timer_add with 91 * @ref nrf_802154_sl_timer_t::trigger_time containing a value too far from `now`. 92 */ 93 #define NRF_802154_SL_TIMER_RET_TOO_DISTANT 3U 94 95 /**@brief There were no available resources required to schedule requested activity. 96 * 97 * This result may happen for @ref nrf_802154_sl_timer_add with 98 * @ref nrf_802154_sl_timer_t::action_type containing 99 * @ref NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE. To trigger hardware task by the timer, 100 * some hardware resources like PPI/DPPI channels, EGU channels, timer compare channels 101 * (implementation dependent) were needed, but they were unavailable. 102 */ 103 #define NRF_802154_SL_TIMER_RET_NO_RESOURCES 4U 104 105 /**@brief The timer was inactive at the moment of requested operation. */ 106 #define NRF_802154_SL_TIMER_RET_INACTIVE 5U 107 108 /**@brief Type representing a timer. */ 109 typedef struct nrf_802154_sl_timer_s nrf_802154_sl_timer_t; 110 111 /**@brief Type of callback function pointer to be called when timer triggers. */ 112 typedef void (* nrf_802154_sl_timer_callback_t)(nrf_802154_sl_timer_t * p_timer); 113 114 /**@brief Action types to be performed when a timer triggers. 115 * 116 * This is a bitmask with possible masks: 117 * @ref NRF_802154_SL_TIMER_ACTION_TYPE_CALLBACK 118 * @ref NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE 119 */ 120 typedef uint8_t nrf_802154_sl_timer_action_type_t; 121 122 /**@brief Timer action type mask allowing a callback to be called. */ 123 #define NRF_802154_SL_TIMER_ACTION_TYPE_CALLBACK (1U << 0) 124 /**@brief Timer action type mask allowing triggering a hardware task. */ 125 #define NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE (1U << 1) 126 127 /** 128 * @brief Special value that indicates that (D)PPI configuration is incomplete. 129 */ 130 #define NRF_802154_SL_TIMER_INVALID_PPI_CHANNEL UINT32_MAX 131 132 /**@brief Structure that represents private fields of a timer required by the implementation. */ 133 typedef struct 134 { 135 uint64_t placeholder[NRF_802154_SL_TIMER_PRIV_SIZE]; 136 } nrf_802154_sl_timer_priv_placeholder_t; 137 138 struct nrf_802154_sl_timer_s 139 { 140 /**@brief Private fields required by the implementation. 141 * 142 * Must be at the beginning of the structure. 143 */ 144 nrf_802154_sl_timer_priv_placeholder_t priv; 145 146 /**@brief The timestamp in microseconds at which the timer should be triggered. 147 * 148 * The callback will be called no earlier than at given @p trigger_time, but may be delayed 149 * due to processing time taken by other ISRs. 150 */ 151 uint64_t trigger_time; 152 153 /**@brief User-provided data. 154 * 155 * User preparing a timer can store any data within this field. Timer module does not 156 * process this data. 157 */ 158 union 159 { 160 void * p_pointer; 161 const void * p_cpointer; 162 } user_data; 163 164 /**@brief Action type to be performed when the timer triggers. 165 * 166 * Depending on value bits set in this bitmask, appropriate fields of @c action is valid. 167 */ 168 nrf_802154_sl_timer_action_type_t action_type; 169 170 struct 171 { 172 /**@brief Parameters applicable when @c action_type contains 173 * @ref NRF_802154_SL_TIMER_ACTION_TYPE_CALLBACK */ 174 struct 175 { 176 /**@brief Callback to be called when the timer triggers. 177 * 178 * The callback is called within an ISR. Please take into account possible 179 * latency between moment of trigger and moment when the callback gets called. 180 */ 181 nrf_802154_sl_timer_callback_t callback; 182 } callback; 183 184 /**@brief Parameters applicable when @c action_type contains 185 * @ref NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE */ 186 struct 187 { 188 /**@brief Identifier of (D)PPI channel to be triggered at @c trigger_time. 189 * 190 * The API user is responsible for creating all necessary hardware bindings between 191 * provided (D)PPI channel and the requested task, as well as necessary configuration 192 * of these resources. Moreover, the API user must keep the hardware bindings enabled 193 * and functional until the requested hardware task is triggered or until the timer 194 * is successfully removed. 195 * 196 * A special value of @ref NRF_802154_SL_TIMER_INVALID_PPI_CHANNEL can be set. In this 197 * case, the binding creation is postponed and the user is required to use the 198 * @ref nrf_802154_sl_timer_update_ppi to complete the configuration. Must do so 199 * before @c trigger_time expires. 200 */ 201 uint32_t ppi_channel; 202 } hardware; 203 } action; 204 }; 205 206 /**@brief Initializes the timer module. */ 207 void nrf_802154_sl_timer_module_init(void); 208 209 /**@brief Uninitializes the timer module. */ 210 void nrf_802154_sl_timer_module_uninit(void); 211 212 /**@brief Gets current time. 213 * 214 * @return Time in microseconds. 215 */ 216 uint64_t nrf_802154_sl_timer_current_time_get(void); 217 218 /**@brief Initializes a timer instance. 219 * 220 * This function plays a role of a constructor. It should be called once 221 * per timer instance before any other API call related to given 222 * timer instance. Calling any other API related to a timer 223 * instance before call to @ref nrf_802154_sl_timer_init or 224 * calling @ref nrf_802154_sl_timer_init more than once is an 225 * undefined behavior. 226 * 227 * @param p_timer Pointer to a timer instance to be initialized. 228 */ 229 void nrf_802154_sl_timer_init(nrf_802154_sl_timer_t * p_timer); 230 231 /**@brief De-initializes a timer instance. 232 * 233 * This function plays a role of a destructor. 234 * 235 * @param p_timer Pointer to a timer instance to be de-initialized. 236 */ 237 void nrf_802154_sl_timer_deinit(nrf_802154_sl_timer_t * p_timer); 238 239 /**@brief Adds a timer to the active timers list. 240 * 241 * This function adds the timer pointed by @p p_timer parameter to an active timers 242 * list. Before call to @ref nrf_802154_sl_timer_add the timer must fill 243 * public fields of timer object instance in the following way: 244 * - @ref nrf_802154_sl_timer_t::trigger_time is set up to the moment when the timer 245 * is expected to trigger 246 * - Optionally @ref nrf_802154_sl_timer_t::user_data may be set, to user-dependent value. 247 * - @ref nrf_802154_sl_timer_t::action_type is set according to requested action. 248 * - Depending on value written to @ref nrf_802154_sl_timer_t::action_type 249 * matching fields of @ref nrf_802154_sl_timer_t::action must be filled. 250 * 251 * When this function succeeds the timer module takes ownership of the timer instance. 252 * A user is forbidden to modify the structure until the callback is called or 253 * @ref nrf_802154_sl_timer_remove is successfully called. Modification of timer owned by the 254 * timer service results in an undefined behavior. In particular the user 255 * is forbidden to set a new value of @ref nrf_802154_sl_timer_t::trigger_time as long as the 256 * timer is owned by the timer service. 257 * 258 * Please note that if @ref nrf_802154_sl_timer_t::trigger_time is in the past or very near in 259 * the future, the timer is scheduled and will fire as soon as possible but not earlier than 260 * given by @ref nrf_802154_sl_timer_t::trigger_time. 261 * 262 * @param p_timer Pointer to a timer instance to add to active timers list. 263 * 264 * @retval NRF_802154_SL_TIMER_RET_SUCCESS 265 * Function succeeded. The timer is sussessfully added. The requested action is 266 * scheduled to happen. 267 * @retval NRF_802154_SL_TIMER_RET_NO_RESOURCES 268 * The requested hardware task can't be bound to the timer due to lack of hardware resources. 269 * @retval NRF_802154_SL_TIMER_RET_BAD_REQUEST 270 * A user passed unsupported or invalid parameters in @p p_timer. 271 */ 272 nrf_802154_sl_timer_ret_t nrf_802154_sl_timer_add(nrf_802154_sl_timer_t * p_timer); 273 274 /**@brief Removes a timer from the active timers list. 275 * 276 * @param p_timer Pointer to a timer instance to be removed from the active timers list. 277 * 278 * @retval NRF_802154_SL_TIMER_RET_SUCCESS 279 * The timer was running and it has been successfully removed from active timers list. 280 * The requested action (either callback or hardware task trigger) will not happen. 281 * @retval NRF_802154_SL_TIMER_RET_INACTIVE 282 * The timer was not running at the moment of the call and is not in the active timers list. 283 * Nothing can be implied about the completion of the timer's requested action, without 284 * checking external conditions. It is up to the caller to detect if requested action 285 * (either callback, hardware task or both) has already been executed, is currently 286 * in progress or yet remains to be executed. 287 */ 288 nrf_802154_sl_timer_ret_t nrf_802154_sl_timer_remove(nrf_802154_sl_timer_t * p_timer); 289 290 /**@brief Updates the (D)PPI channel to be triggered. 291 * 292 * @param p_timer Pointer to a timer instance to be updated. 293 * @param ppi_chn Identifier of (D)PPI channel to be triggered at @c trigger_time. 294 * 295 * @retval NRF_802154_SL_TIMER_RET_SUCCESS 296 * The (D)PPI channel was updated and it was done on time, i.e. before specified 297 * trigger time. 298 * @retval NRF_802154_SL_TIMER_RET_TOO_LATE 299 * It has been detected that the timer has already fired and because of this the update 300 * could not complete at all or did not complete on time. Nevertheless, the (D)PPI may 301 * have been triggered, but it cannot be stated reliably. 302 * @retval NRF_802154_SL_TIMER_RET_BAD_REQUEST 303 * A user passed invalid parameters in @p p_timer, e.g. @c action_type does not contain 304 * @ref NRF_802154_SL_TIMER_ACTION_TYPE_HARDWARE. 305 */ 306 nrf_802154_sl_timer_ret_t nrf_802154_sl_timer_update_ppi(nrf_802154_sl_timer_t * p_timer, 307 uint32_t ppi_chn); 308 309 /** 310 *@} 311 **/ 312 313 #ifdef __cplusplus 314 } 315 #endif 316 317 #endif /* NRF_802154_SL_TIMER_H_ */ 318