1 /*
2 * Copyright (c) 2022-2023, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #ifndef ti_drivers_RCL_Scheduler_h__include
34 #define ti_drivers_RCL_Scheduler_h__include
35
36 #include <stdint.h>
37 #include <stddef.h>
38
39 #include <ti/drivers/rcl/RCL_Command.h>
40 #include <ti/drivers/rcl/hal/hal.h>
41
42 /**
43 * Number of ticks in the given number of microseconds
44 */
45 #define RCL_SCHEDULER_SYSTIM_US(x) (((uint32_t) (x)) * 4U)
46 /**
47 * Number of ticks in the given number of milliseconds
48 */
49 #define RCL_SCHEDULER_SYSTIM_MS(x) (((uint32_t) (x)) * 4U * 1000U)
50
51
52 /* Timing constants */
53 #define ABS_START_TIME_OFFSET RCL_SCHEDULER_SYSTIM_US(100U) /*!< Delay from scheduled start to start trigger to LRF */
54 #define IMM_START_TIME_OFFSET RCL_SCHEDULER_SYSTIM_US(90U) /*!< Delay from immediate start to start trigger to LRF */
55 #define RCL_SCHEDULER_MARGIN_ARM RCL_SCHEDULER_SYSTIM_US(40U) /*!< Time to prepare FIFO + PBE */
56 #define RCL_SCHEDULER_MARGIN_CONFIGURE RCL_SCHEDULER_SYSTIM_US(76U) /*!< Time to reload REGBANKs */
57 #define RCL_SCHEDULER_MARGIN_LOAD RCL_SCHEDULER_SYSTIM_US(460U) /*!< Time to load TOPsm images */
58 #define RCL_SCHEDULER_SLEEP_CUTOFF RCL_SCHEDULER_SYSTIM_MS(10U) /*!< Time margin when not to arm LRF immediately */
59 #define RCL_SCHEDULER_TRIG_NOW_DELAY RCL_SCHEDULER_SYSTIM_US(50U) /*!< Delay to add to current time to allow start to be in the future */
60 #if defined(DeviceFamily_CC23X0R5) || defined(DeviceFamily_CC23X0R2) || defined(DeviceFamily_CC23X0R22) || defined(DeviceFamily_CC2340R53)
61 #define RCL_SCHEDULER_WAKEUP_MARGIN RCL_SCHEDULER_SYSTIM_US(390U) /*!< Wakeup margin to allow for varying command and setup time */
62 #else
63 #define RCL_SCHEDULER_WAKEUP_MARGIN RCL_SCHEDULER_SYSTIM_US(1000U)/*!< Wakeup margin to allow for varying command and setup time */
64 #endif
65
66 typedef enum {
67 RCL_SchedulerStopReason_None = 0, /*!< No stop active */
68 RCL_SchedulerStopReason_Timeout = 1, /*!< Command stop time is active */
69 RCL_SchedulerStopReason_Scheduling = 2, /*!< Scheduler stop is active */
70 RCL_SchedulerStopReason_Api = 3, /*!< API stop has been sent and will take precedence */
71 } RCL_SchedulerStopReason;
72
73 typedef enum {
74 RCL_SchedulerStopTimeState_Init = 0, /*!< Stop times not calculated or programmed */
75 RCL_SchedulerStopTimeState_Found = 1, /*!< Stop times calculated, but not programmed */
76 RCL_SchedulerStopTimeState_Programmed = 2, /*!< Stop times calculated and programmed to timer */
77 } RCL_SchedulerStopTimeState;
78
79 typedef struct RCL_SchedulerStopInfo_s {
80 uint32_t cmdStopEnabled : 1;
81 uint32_t schedStopEnabled : 1;
82 uint32_t apiStopEnabled : 1;
83 RCL_SchedulerStopReason stopReason : 2;
84 uint32_t cmdStopTime;
85 uint32_t schedStopTime;
86 } RCL_SchedulerStopInfo;
87
88 typedef struct RCL_SchedulerState_s {
89 RCL_Command *currCmd;
90 uint32_t nextWantsStop : 1;
91 RCL_SchedulerStopTimeState stopTimeState : 2;
92 RCL_SchedulerStopReason descheduleReason : 2;
93 RCL_Events postedRclEvents; /* Events to be handled by the command handler */
94 uint32_t actualStartTime;
95 RCL_SchedulerStopInfo hardStopInfo;
96 RCL_SchedulerStopInfo gracefulStopInfo;
97 uint16_t requestedPhyFeatures;
98 } RCL_SchedulerState;
99
100 extern RCL_SchedulerState rclSchedulerState;
101
102 /** @defgroup timingHandlerFunctions Timing Handler Functions
103 * These functions are meant mostly to be used by handlers and RCL itself
104 * @{
105 */
106
107 /**
108 * @brief Get relevant status when a command was stopped
109 *
110 * Returns the status to be set for a command that was stopped with the given stop source,
111 * depending on what caused the stop
112 *
113 * @note This function is intended as internal to RCL and its handlers
114 *
115 * @param stopType Stop type observed
116 *
117 * @return Command status that should be produced
118 */
119 RCL_CommandStatus RCL_Scheduler_findStopStatus(RCL_StopType stopType);
120
121 /**
122 * @brief Set start and stop time for LRF based on command
123 *
124 * Sets start and stop times for LRF based on scheduled times
125 *
126 * @note This function is intended as internal to RCL and its handlers
127 *
128 * @param cmd Pointer to running command
129 *
130 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
131 */
132 RCL_CommandStatus RCL_Scheduler_setStartStopTime(const RCL_Command *cmd);
133
134 /**
135 * @brief Set start and stop time for LRF based on command with earliest start time
136 *
137 * Sets start and stop times for LRF based on scheduled times, but delay start if needed due to hardware startup time
138 *
139 * @note This function is intended as internal to RCL and its handlers
140 *
141 * @param cmd Pointer to running command
142 *
143 * @param earliestStartTime Start at earliest at this time, or fail if delay not allowed
144 *
145 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
146 */
147 RCL_CommandStatus RCL_Scheduler_setStartStopTimeEarliestStart(const RCL_Command *cmd, uint32_t earliestStartTime);
148
149 /**
150 * @brief Set start and stop time for LRF
151 *
152 * Sets start and stop times for LRF based on provided times
153 *
154 * @note This function is intended as internal to RCL and its handlers
155 *
156 * @param timing Start and stop times to set
157 *
158 * @param scheduling Scheduling type
159 *
160 * @param allowDelay True if start may be delayed; false if late start is an error
161 *
162 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
163 */
164 RCL_CommandStatus RCL_Scheduler_setCustomStartStopTime(const RCL_CommandTiming *timing, RCL_ScheduleType scheduling, bool allowDelay);
165
166 /**
167 * @brief Set start and stop time for LRF with earliest start time
168 *
169 * Sets start and stop times for LRF based on provided times, but delay start if needed due to hardware startup time
170 *
171 * @note This function is intended as internal to RCL and its handlers
172 *
173 * @param timing Start and stop times to set
174 *
175 * @param scheduling Scheduling type
176 *
177 * @param allowDelay True if start may be delayed; false if late start is an error
178 *
179 * @param earliestStartTime Start at earliest at this time, or fail if delay not allowed
180 *
181 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
182 */
183 RCL_CommandStatus RCL_Scheduler_setCustomStartStopTimeEarliestStart(const RCL_CommandTiming *timing, RCL_ScheduleType scheduling, bool allowDelay, uint32_t earliestStartTime);
184
185 /**
186 * @brief Set stop time for LRF based on command when it does not need a start trigger
187 *
188 * Sets stop times for LRF based on scheduled times, but do not program any start trigger
189 *
190 * @note This function is intended as internal to RCL and its handlers
191 *
192 * @param cmd Pointer to running command
193 *
194 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
195 */
196 RCL_CommandStatus RCL_Scheduler_setCmdStopTimeNoStartTrigger(const RCL_Command *cmd);
197
198 /**
199 * @brief Set new start time for LRF to now, after a previous start
200 *
201 * @note This function is intended as internal to RCL and its handlers
202 *
203 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
204 */
205 RCL_CommandStatus RCL_Scheduler_setNewStartNow(void);
206
207 /**
208 * @brief Set new start time for LRF to given absolute time, after a previous start
209 *
210 * @note This function is intended as internal to RCL and its handlers
211 *
212 * @param startTime Absloute start time
213 *
214 * @param allowDelay True if start may be delayed; false if late start is an error
215 *
216 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
217 */
218 RCL_CommandStatus RCL_Scheduler_setNewStartAbsTime(uint32_t startTime, bool allowDelay);
219
220 /**
221 * @brief Set new start time for LRF to given time relative to previous LRF start
222 *
223 * @note This function is intended as internal to RCL and its handlers
224 *
225 * @param relStartTime Start time relative to previous actual start time of LRF
226 *
227 * @return Command status that should be produced if the command should end or RCL_CmdStatus_Active to go on
228 */
229 RCL_CommandStatus RCL_Scheduler_setNewStartRelTime(uint32_t relStartTime);
230
231 /**
232 * @brief Function to apply relevant stop times
233 *
234 * Sets stop times for LRF based on scheduled times
235 *
236 * @note This function is intended as internal to RCL and its handlers
237 *
238 * @return Stop type if stop needs to be applied immediately
239 */
240 RCL_StopType RCL_Scheduler_setStopTimes(void);
241
242 /** @}
243 */
244
245 /** @defgroup timingApiFunctions Timing API Functions
246 * These functions are useful as part of the API to RCL
247 * @{
248 */
249
250 /**
251 * @brief Find if a time instant occurs after another, allowing wrap-around
252 *
253 * Checks if a time is before or after another. In the processing, a time is assumed to be before
254 * the reference if it is less than 1/8 of the full timer range (134 seconds) before it; otherwise
255 * it is assumed to be in the future. This means that the time presumed to be the latest should
256 * always be the second parameter (%chkTime)
257 *
258 * @param refTime Reference time
259 *
260 * @param chkTime Time to be checked
261 *
262 * @return true if %chkTime comes after %refTime. false if %chkTime comes before %refTime or if they are equal.
263 */
264 bool RCL_Scheduler_isLater(uint32_t refTime, uint32_t chkTime);
265
266 /**
267 * @brief Find the time difference between two times, allowing wrap-around
268 *
269 * Finds the signed difference between two times, saturated at the maximum signed 32-bit integer
270 * value. In the processing, a time is assumed to be before the reference if it is less than 1/8
271 * of the full timer range (134 seconds) before it; otherwise
272 * it is assumed to be in the future.
273 *
274 * @param refTime Reference time
275 *
276 * @param chkTime Time to be checked
277 *
278 * @return Time difference (%chkTime-%refTime) corrected for wrap-around.
279 * Saturated at 0x7FFFFFFF (8 min 57 sec).
280 */
281 int32_t RCL_Scheduler_delta(uint32_t refTime, uint32_t chkTime);
282
283 /**
284 * @brief Get current time
285 *
286 * @return Current SYSTIM time (0.25 us steps) usable for radio command timing
287 */
RCL_Scheduler_getCurrentTime(void)288 static inline uint32_t RCL_Scheduler_getCurrentTime(void)
289 {
290 return hal_get_current_time();
291 }
292
293 /**
294 * @brief Set scheduler stop time
295 *
296 * Sets scheduler stop time for the given stop type, finds which of the
297 * active stop times comes first, sets selection bits accordingly and
298 * reprograms the stop time if it was already programmed.
299 *
300 * @param stopInfo Pointer to stop info for the relevant stop type
301 *
302 * @param schedStopTime New scheduler stop time to apply
303 *
304 * @return Stop type if stop needs to be applied immediately
305 */
306 RCL_StopType RCL_Scheduler_setSchedStopTime(RCL_SchedulerStopInfo *stopInfo, uint32_t schedStopTime);
307
308 /**
309 * @brief Set command stop time
310 *
311 * Sets command stop time for the given stop type, finds which of the
312 * active stop times comes first, sets selection bits accordingly and
313 * reprograms the stop time if it was already programmed.
314 *
315 * @param stopInfo Pointer to stop info for the relevant stop type
316 *
317 * @param cmdStopTime New command stop time to apply
318 *
319 * @return Stop type if stop needs to be applied immediately
320 */
321 RCL_StopType RCL_Scheduler_setCmdStopTime(RCL_SchedulerStopInfo *stopInfo, uint32_t cmdStopTime);
322
323 /**
324 * @brief Cancel scheduler stop time
325 *
326 * Cancels scheduler stop time for the given stop type, finds if there
327 * is still an active stop time, cancels or reprograms the stop time
328 * if it was already programmed.
329 *
330 * @param stopInfo Pointer to stop info for the relevant stop type
331 *
332 * @return Stop type if stop needs to be applied immediately
333 */
334 RCL_StopType RCL_Scheduler_cancelSchedStopTime(RCL_SchedulerStopInfo *stopInfo);
335
336 /**
337 * @brief Cancel command stop time
338 *
339 * Cancels command stop time for the given stop type, finds if there
340 * is still an active stop time, cancels or reprograms the stop time
341 * if it was already programmed.
342 *
343 * @param stopInfo Pointer to stop info for the relevant stop type
344 *
345 * @return Stop type if stop needs to be applied immediately
346 */
347 RCL_StopType RCL_Scheduler_cancelCmdStopTime(RCL_SchedulerStopInfo *stopInfo);
348
349 /**
350 * @brief Post event to command handler
351 *
352 * @param[in] c Command to post event to
353 * @param[in] e Event(s) to post
354 * @return true If command was active and event was posted
355 * @return false If command was not active
356 */
357 bool RCL_Scheduler_postEvent(RCL_Command_Handle c, RCL_Events e);
358
359 /** @}
360 */
361
362 #endif
363