1 /* 2 * Copyright (c) 2021, 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 Low Power Timer Abstraction Layer for the nrf_802154_sl_timer service 37 * 38 * @details 39 * Design claims: 40 * 1. lptimer works in @c lpticks (Low Power Timer Ticks), it is not aware of other timer units with 41 * exception to convenience functions for calculating lpticks to other units. 42 * 2. One @c lptick is at least 1 microsecond, but can be greater. 43 * 3. lptimer can rarely fire spurious "timer fired" callout as well as rarely perform spurious (D)PPI 44 * triggering (if connections have been made). This phenomena should be avoided, but modules relying 45 * on lptimer must be immune to such behavior. 46 * 4. lptimer counts @c lpticks as @c uint64_t type, handling (and hiding from higher layers) any 47 * underlying RTC overflow events. 48 */ 49 50 #ifndef NRF_802154_PLATFORM_SL_LPTIMER_H_ 51 #define NRF_802154_PLATFORM_SL_LPTIMER_H_ 52 53 #include <stdint.h> 54 #include <stdbool.h> 55 56 #ifdef __cplusplus 57 extern "C" { 58 #endif 59 60 /**@brief Special value to use when no (D)PPI configuration is requested. */ 61 #define NRF_802154_SL_HW_TASK_PPI_INVALID UINT32_MAX 62 63 /**@brief Type of result returned by LPTIMER platform functions. */ 64 typedef uint32_t nrf_802154_sl_lptimer_platform_result_t; 65 66 /**@brief Operation performed successfully. */ 67 #define NRF_802154_SL_LPTIMER_PLATFORM_SUCCESS 0 68 69 /**@brief The timer was scheduled too early in the future. */ 70 #define NRF_802154_SL_LPTIMER_PLATFORM_TOO_LATE 1 71 72 /**@brief The timer was scheduled too far in the future. */ 73 #define NRF_802154_SL_LPTIMER_PLATFORM_TOO_DISTANT 2 74 75 /**@brief No free hardware resources available to perform the operation. */ 76 #define NRF_802154_SL_LPTIMER_PLATFORM_NO_RESOURCES 3 77 78 /**@brief Operation could not be completed due to a wrong state. */ 79 #define NRF_802154_SL_LPTIMER_PLATFORM_WRONG_STATE 4 80 81 /** @brief Initializes the Timer. 82 */ 83 void nrf_802154_platform_sl_lp_timer_init(void); 84 85 /** @brief Deinitializes the Timer. 86 */ 87 void nrf_802154_platform_sl_lp_timer_deinit(void); 88 89 /**@brief Returns current state of the lptimer in @c lpticks . 90 */ 91 uint64_t nrf_802154_platform_sl_lptimer_current_lpticks_get(void); 92 93 /**@brief Converts time in microseconds to @c lpticks 94 * 95 * @param[in] us Number of microseconds to convert. 96 * @param[in] round_up @c true, to force rounding up. @c false to round down. 97 * 98 * @return Time corresponding to @p us in @c lpticks. 99 */ 100 uint64_t nrf_802154_platform_sl_lptimer_us_to_lpticks_convert(uint64_t us, bool round_up); 101 102 /**@brief Converts time in @c lpticks to microseconds. 103 * 104 * @param[in] lpticks Number of lpticks to convert. 105 * 106 * @return Time corresponding to @p lpticks in microseconds. 107 */ 108 uint64_t nrf_802154_platform_sl_lptimer_lpticks_to_us_convert(uint64_t lpticks); 109 110 /**@brief Schedules a lptimer event to happen at given time. 111 * 112 * @param[in] fire_lpticks Timer state (in @c lpticks) at which timer event should fire. 113 * If @p fire_lpticks are in the past, the lptimer event will be triggered 114 * asap, but still from the context of an lptimer's ISR. If 115 * @ref nrf_802154_platform_sl_lptimer_critical_section_enter is 116 * in effect, processing will be delayed until pending interrupt 117 * can be processed. 118 */ 119 void nrf_802154_platform_sl_lptimer_schedule_at(uint64_t fire_lpticks); 120 121 /**@brief Disables generation of any event scheduled by @ref nrf_802154_platform_sl_lptimer_schedule_at 122 * 123 * @note If called from ISR priority higher than the priority from which 124 * @ref nrf_802154_sl_timer_handler is called, the @ref nrf_802154_sl_timer_handler function 125 * may be still called after @ref nrf_802154_platform_sl_lptimer_disable. It is due to the fact 126 * that ISR can be preempted in such way, that decision to call @ref nrf_802154_sl_timer_handler 127 * has already been taken and the call is inevitable (or is already in process of execution) 128 */ 129 void nrf_802154_platform_sl_lptimer_disable(void); 130 131 /**@brief Enters into critical section of the lptimer module. 132 * @note Critical section can be nested 133 * 134 * Inside critical section calls to @ref nrf_802154_sl_timer_handler do not happen. This 135 * includes indirect effect of calling @ref nrf_802154_platform_sl_lptimer_schedule_at. If necessary 136 * the interrupt calling the @ref nrf_802154_sl_timer_handler function it will remain pending 137 * at least until a corresponding call to @ref nrf_802154_platform_sl_lptimer_critical_section_exit. 138 */ 139 void nrf_802154_platform_sl_lptimer_critical_section_enter(void); 140 141 /**@brief Exits out of critical section of the lptimer module. 142 */ 143 void nrf_802154_platform_sl_lptimer_critical_section_exit(void); 144 145 /**@brief Prepares hardware bindings for triggering hardware task. 146 * 147 * This function configures timer compare channel to fire at a specified time and publish 148 * the signal to a specific PPI channel. The PPI channel may initially be set to 149 * @ref NRF_802154_SL_HW_TASK_PPI_INVALID and later updated with 150 * @ref nrf_802154_platform_sl_lptimer_hw_task_update_ppi. 151 * 152 * @param[in] fire_lpticks Timer state (in @c lpticks) at which timer event should fire. 153 * @param[in] ppi_channel (D)PPI channel that compare event will be published to. 154 * 155 * @retval NRF_802154_SL_LPTIMER_PLATFORM_SUCCESS 156 * The timer was started successfuly and (D)PPI channel was connected, if requested. 157 * @retval NRF_802154_SL_LPTIMER_PLATFORM_TOO_LATE 158 * The timer was scheduled too early in the future. The (D)PPI channel was not connected. 159 * @retval NRF_802154_SL_LPTIMER_PLATFORM_TOO_DISTANT 160 * The timer was scheduled too far in the future. The (D)PPI channel was not connected. 161 * @retval NRF_802154_SL_LPTIMER_PLATFORM_NO_RESOURCES 162 * No available compare channels to schedule a timer. The (D)PPI channel was not connected. 163 */ 164 nrf_802154_sl_lptimer_platform_result_t nrf_802154_platform_sl_lptimer_hw_task_prepare( 165 uint64_t fire_lpticks, 166 uint32_t ppi_channel); 167 168 /**@brief Removes hardware bindings created for hardware task and stops the timer. 169 * 170 * @retval NRF_802154_SL_LPTIMER_PLATFORM_SUCCESS 171 * The cleaning was successful. 172 * @retval NRF_802154_SL_LPTIMER_PLATFORM_WRONG_STATE 173 * Cleaning was not performed because the module is in an unsuitable state. 174 */ 175 nrf_802154_sl_lptimer_platform_result_t nrf_802154_platform_sl_lptimer_hw_task_cleanup(void); 176 177 /**@brief Updates the hardware bindings for triggering hardware task. 178 * 179 * If the timer was started with @ref nrf_802154_platform_sl_lptimer_hw_task_prepare 180 * without specifying a valid (D)PPI channel (@ref NRF_802154_SL_HW_TASK_PPI_INVALID) 181 * it is possible to use this function to update the (D)PPI channel to a valid one. 182 * 183 * @param[in] ppi_channel (D)PPI channel that compare event will be published to. 184 * 185 * @retval NRF_802154_SL_LPTIMER_PLATFORM_SUCCESS 186 * The (D)PPI channel was connected and it was done on time, i.e. before specified 187 * fire time. 188 * @retval NRF_802154_SL_LPTIMER_PLATFORM_TOO_LATE 189 * The (D)PPI channel was connected, but it is not sure if it was done in time: 190 * it has been detected that the timer has already fired. 191 * @retval NRF_802154_SL_LPTIMER_PLATFORM_WRONG_STATE 192 * The (D)PPI channel was not connected, because the timer is not properly configured. 193 */ 194 nrf_802154_sl_lptimer_platform_result_t nrf_802154_platform_sl_lptimer_hw_task_update_ppi( 195 uint32_t ppi_channel); 196 197 /** 198 * @brief Starts a one-shot synchronization timer that expires at the nearest possible timepoint. 199 * 200 * On timer expiration, the @ref nrf_802154_sl_timestamper_synchronized function is called and the 201 * event returned by @ref nrf_802154_platform_sl_lptimer_sync_event_get is triggered. 202 * 203 * @note @ref nrf_802154_sl_timestamper_synchronized may be called multiple times. 204 */ 205 void nrf_802154_platform_sl_lptimer_sync_schedule_now(void); 206 207 /** 208 * @brief Starts a one-shot synchronization timer that expires at the specified time. 209 * 210 * This function starts a one-shot synchronization timer that expires at @p fire_lpticks. 211 * 212 * On timer expiration, @ref nrf_802154_sl_timestamper_synchronized function is called and 213 * the event returned by @ref nrf_802154_platform_sl_lptimer_sync_event_get is triggered. 214 * 215 * @param[in] fire_lpticks Timer state (in @c lpticks) at which timer event should fire. 216 */ 217 void nrf_802154_platform_sl_lptimer_sync_schedule_at(uint64_t fire_lpticks); 218 219 /** 220 * @brief Stops the currently running synchronization timer. 221 */ 222 void nrf_802154_platform_sl_lptimer_sync_abort(void); 223 224 /** 225 * @brief Gets the event used to synchronize this timer with the HP Timer. 226 * 227 * @returns Address of the peripheral register corresponding to the event 228 * to be used for the timer synchronization. 229 * 230 */ 231 uint32_t nrf_802154_platform_sl_lptimer_sync_event_get(void); 232 233 /** 234 * @brief Gets the timestamp of the synchronization event. 235 * 236 * @returns Timestamp of the synchronization event. 237 */ 238 uint64_t nrf_802154_platform_sl_lptimer_sync_lpticks_get(void); 239 240 /** 241 * @brief Gets the granularity of the timer. 242 * 243 * This function can be used to round up or round down the time calculations. 244 * 245 * @returns Timer granularity in microseconds. 246 */ 247 uint32_t nrf_802154_platform_sl_lptimer_granularity_get(void); 248 249 /**@brief Handler called from an ISR of lptimer. 250 * 251 * @param now_lpticks Specifies moment in time at which the handler is triggered. 252 */ 253 extern void nrf_802154_sl_timer_handler(uint64_t now_lpticks); 254 255 /** 256 * @brief Callback function executed when the synchronization timer expires. 257 */ 258 extern void nrf_802154_sl_timestamper_synchronized(void); 259 260 #ifdef __cplusplus 261 } 262 #endif 263 264 #endif // NRF_802154_PLATFORM_SL_LPTIMER_H_ 265