1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  * The BSD-3-Clause license can be found at https://spdx.org/licenses/BSD-3-Clause.html
6  */
7 /*!\file osa.h
8  *\brief This file contains OSA wrapper declarations for timer, read/write lock and idle hook.
9  */
10 
11 #ifndef _OSA_H_
12 #define _OSA_H_
13 
14 #include <wifi_config_default.h>
15 #include "fsl_os_abstraction.h"
16 #include <osa_zephyr.h>
17 #include <wmerrno.h>
18 #include <wm_utils.h>
19 
20 /*** Timer Management ***/
21 /** Create timer
22  *
23  * This function creates a timer.
24  *
25  * @param[in] timerHandle Pointer to the timer handle
26  * @param[in] ticks Period in ticks
27  * @param[in] call_back Timer expire callback function
28  * @param[in] cb_arg Timer callback data
29  * @param[in] reload Reload Options, valid values include \ref KOSA_TimerOnce
30  * or \ref KOSA_TimerPeriodic.
31  * @param[in] activate Activate Options, valid values include \ref
32  * OSA_TIMER_AUTO_ACTIVATE or \ref OSA_TIMER_NO_ACTIVATE
33  *
34  * @return KOSA_StatusSuccess if timer created successfully
35  * @return KOSA_StatusError if timer creation fails
36  */
37 osa_status_t OSA_TimerCreate(osa_timer_handle_t timerHandle,
38                              osa_timer_tick ticks,
39                              void (*call_back)(osa_timer_arg_t),
40                              void *cb_arg,
41                              osa_timer_t reload,
42                              osa_timer_activate_t activate);
43 
44 /** Activate timer
45  *
46  * This function activates (or starts) a timer that was previously created using
47  * OSA_TimerCreate(). If the timer had already started and was already in the
48  * active state, then this call is equivalent to OSA_TimerReset().
49  *
50  * @param[in] timerHandle Pointer to a timer handle
51  *
52  * @return KOSA_StatusSuccess if timer activated successfully
53  * @return KOSA_StatusError if timer activation fails
54  *
55  */
56 osa_status_t OSA_TimerActivate(osa_timer_handle_t timerHandle);
57 
58 /** Change timer period
59  *
60  * This function changes the period of a timer that was previously created using
61  * OSA_TimerCreate(). This function changes the period of an active or dormant
62  * state timer.
63  *
64  * @param[in] timerHandle Pointer to a timer handle
65  * @param[in] ntime Time in ticks after which the timer will expire
66  * @param[in] block_time  This option is currently not supported
67  *
68  * @return KOSA_StatusSuccess if timer change successfully
69  * @return KOSA_StatusError if timer change fails
70  */
71 osa_status_t OSA_TimerChange(osa_timer_handle_t timerHandle, osa_timer_tick ntime, osa_timer_tick block_time);
72 
73 /** Check the timer active state
74  *
75  * This function checks if the timer is in the active or dormant state. A timer
76  * is in the dormant state if (a) it has been created but not started, or (b) it
77  * has expired and a one-shot timer.
78  *
79  * @param [in] timerHandle Pointer to a timer handle
80  *
81  * @return true if timer is active
82  * @return false if time is not active
83  */
84 bool OSA_TimerIsRunning(osa_timer_handle_t timerHandle);
85 
86 /**
87  * Get the timer context
88  *
89  * This function helps to retrieve the timer context i.e. 'cb_arg' passed
90  * to OSA_TimerCreate().
91  *
92  * @param[in] timer_t Pointer to timer handle. The timer handle is received
93  * in the timer callback.
94  *
95  * @return The timer context i.e. the callback argument passed to
96  * OSA_TimerCreate().
97  */
98 void *OSA_TimerGetContext(osa_timer_handle_t timerHandle);
99 
100 /** Reset timer
101  *
102  * This function resets a timer that was previously created using using
103  * OSA_TimerCreate(). If the timer had already been started and was already in
104  * the active state, then this call will cause the timer to re-evaluate its
105  * expiry time so that it is relative to when OSA_TimerReset() was called. If
106  * the timer was in the dormant state then this call behaves in the same way as
107  * OSA_TimerActivate().
108  *
109  * @param[in] timerHandle Pointer to a timer handle
110  *
111  * @return KOSA_StatusSuccess if timer reset successfully
112  * @return KOSA_StatusError if timer reset fails
113  */
114 osa_status_t OSA_TimerReset(osa_timer_handle_t timerHandle);
115 
116 /** Deactivate timer
117  *
118  * This function deactivates (or stops) a timer that was previously started.
119  *
120  * @param [in] timerHandle handle populated by OSA_TimerCreate().
121  *
122  * @return KOSA_StatusSuccess if timer deactivate successfully
123  * @return KOSA_StatusError if timer deactivate fails
124  */
125 osa_status_t OSA_TimerDeactivate(osa_timer_handle_t timerHandle);
126 
127 /** Destroy timer
128  *
129  * This function deletes a timer.
130  *
131  * @param[in] timerHandle Pointer to a timer handle
132  *
133  * @return KOSA_StatusSuccess if timer destroy successfully
134  * @return KOSA_StatusError if timer destroy fails
135  */
136 osa_status_t OSA_TimerDestroy(osa_timer_handle_t timerHandle);
137 
138 /*
139  * Reader Writer Locks
140  * This is a generic implementation of reader writer locks
141  * which is reader priority.
142  * Not only it provides mutual exclusion but also synchronization.
143  * Six APIs are exposed to user which include.
144  * -# Create a reader writer lock
145  * -# Delete a reader writer lock
146  * -# Reader lock
147  * -# Reader unlock
148  * -# Writer lock
149  * -# Writer unlock
150  * The locking operation is timeout based.
151  * Caller can give a timeout from 0 (no wait) to
152  * infinite (wait forever)
153  */
154 
155 typedef struct _rw_lock osa_rw_lock_t;
156 /** This is prototype of reader callback */
157 typedef int (*cb_fn)(osa_rw_lock_t *plock, unsigned int wait_time);
158 
159 struct _rw_lock
160 {
161     /** Mutex for reader mutual exclusion */
162     OSA_MUTEX_HANDLE_DEFINE(reader_mutex);
163     /** Mutex for write mutual exclusion */
164     OSA_MUTEX_HANDLE_DEFINE(write_mutex);
165     /** Lock which when held by reader,
166      *  writer cannot enter critical section
167      */
168     OSA_SEMAPHORE_HANDLE_DEFINE(rw_lock);
169     /** Function being called when first reader gets
170      *  the lock
171      */
172     cb_fn reader_cb;
173     /** Counter to maintain number of readers
174      *  in critical section
175      */
176     unsigned int reader_count;
177 };
178 
179 int OSA_RWLockCreateWithCB(osa_rw_lock_t *plock, const char *mutex_name, const char *lock_name, cb_fn r_fn);
180 
181 /** Create reader-writer lock
182  *
183  * This function creates a reader-writer lock.
184  *
185  * @param[in] lock Pointer to a reader-writer lock handle
186  * @param[in] mutex_name Name of the mutex
187  * @param[in] lock_name Name of the lock
188  *
189  * @return WM_SUCCESS on success
190  * @return -WM_FAIL on error
191  */
192 int OSA_RWLockCreate(osa_rw_lock_t *plock, const char *mutex_name, const char *lock_name);
193 
194 /** Delete a reader-write lock
195  *
196  * This function deletes a reader-writer lock.
197  *
198  * @param[in] lock Pointer to the reader-writer lock handle
199  *
200  */
201 void OSA_RWLockDestroy(osa_rw_lock_t *lock);
202 
203 /** Acquire writer lock
204  *
205  * This function acquires a writer lock. While readers can acquire the lock on a
206  * sharing basis, writers acquire the lock in an exclusive manner.
207  *
208  * @param[in] lock Pointer to the reader-writer lock handle
209  * @param[in] wait_time The maximum amount of time, in OS ticks, the task should
210  * block waiting for the lock to be acquired. The special values \ref
211  * osaWaitForever_c and \ref osaWaitNone_c are provided to respectively wait
212  * infinitely or return immediately.
213  *
214  * @return  WM_SUCCESS on success
215  * @return  -WM_FAIL on error
216  *
217  */
218 int OSA_RWLockWriteLock(osa_rw_lock_t *lock, unsigned int wait_time);
219 
220 /** Release writer lock
221  *
222  * This function releases a writer lock previously acquired using
223  * OSA_RWLockWriteLock().
224  *
225  * @param[in] lock Pointer to the reader-writer lock handle
226  */
227 void OSA_RWLockWriteUnlock(osa_rw_lock_t *lock);
228 
229 /** Acquire reader lock
230  *
231  * This function acquires a reader lock. While readers can acquire the lock on a
232  * sharing basis, writers acquire the lock in an exclusive manner.
233  *
234  * @param[in] lock pointer to the reader-writer lock handle
235  * @param[in] wait_time The maximum amount of time, in OS ticks, the task should
236  * block waiting for the lock to be acquired. The special values \ref
237  * osaWaitForever_c and \ref osaWaitNone_c are provided to respectively wait
238  * infinitely or return immediately.
239  *
240  * @return  WM_SUCCESS on success
241  * @return  -WM_FAIL on error
242  *
243  */
244 int OSA_RWLockReadLock(osa_rw_lock_t *lock, unsigned int wait_time);
245 
246 /** Release reader lock
247  *
248  * This function releases a reader lock previously acquired using
249  * OSA_RWLockReadLock().
250  *
251  * @param[in] lock pointer to the reader-writer lock handle
252  *
253  * @return WM_SUCCESS if unlock operation successful.
254  * @return -WM_FAIL if unlock operation failed.
255  */
256 int OSA_RWLockReadUnlock(osa_rw_lock_t *lock);
257 
258 /*** Tick function */
259 #define MAX_CUSTOM_HOOKS 4U
260 
261 extern void (*g_osa_tick_hooks[MAX_CUSTOM_HOOKS])(void);
262 extern void (*g_osa_idle_hooks[MAX_CUSTOM_HOOKS])(void);
263 
264 /** Setup idle function
265  *
266  * This function sets up a callback function which will be called whenever the
267  * system enters the idle thread context.
268  *
269  *  @param[in] func The callback function
270  *
271  *  @return WM_SUCCESS on success
272  *  @return -WM_FAIL on error
273  */
274 int OSA_SetupIdleFunction(void (*func)(void));
275 
276 /** Setup tick function
277  *
278  * This function sets up a callback function which will be called on every
279  * SysTick interrupt.
280  *
281  *  @param[in] func The callback function
282  *
283  *  @return WM_SUCCESS on success
284  *  @return -WM_FAIL on error
285  */
286 int OSA_SetupTickFunction(void (*func)(void));
287 
288 /** Remove idle function
289  *
290  *  This function removes an idle callback function that was registered
291  *  previously using OSA_SetupIdleFunction().
292  *
293  *  @param[in] func The callback function
294  *
295  *  @return WM_SUCCESS on success
296  *  @return -WM_FAIL on error
297  */
298 int OSA_RemoveIdleFunction(void (*func)(void));
299 
300 /** Remove tick function
301  *
302  *  This function removes a tick callback function that was registered
303  *  previously using OSA_SetupTickFunction().
304  *
305  *  @param[in] func Callback function
306  *  @return WM_SUCCESS on success
307  *  @return -WM_FAIL on error
308  */
309 int OSA_RemoveTickFunction(void (*func)(void));
310 
311 /* Init value for rand generator seed */
312 extern uint32_t wm_rand_seed;
313 
314 /** This function initialize the seed for rand generator
315  *  @return a uint32_t random numer
316  */
OSA_Srand(uint32_t seed)317 static inline void OSA_Srand(uint32_t seed)
318 {
319     wm_rand_seed = seed;
320 }
321 
322 /** This function generate a random number
323  *  @return a uint32_t random numer
324  */
OSA_Rand()325 static inline uint32_t OSA_Rand()
326 {
327     if (wm_rand_seed == -1)
328         OSA_Srand(OSA_TimeGetMsec());
329     wm_rand_seed = (uint32_t)((((uint64_t)wm_rand_seed * 279470273UL) % 4294967291UL) & 0xFFFFFFFFUL);
330     return wm_rand_seed;
331 }
332 
333 /** This function generate a random number in a range
334  *  @param [in] low  range low
335  *  @param [in] high range high
336  *  @return a uint32_t random numer
337  */
OSA_RandRange(uint32_t low,uint32_t high)338 static inline uint32_t OSA_RandRange(uint32_t low, uint32_t high)
339 {
340     uint32_t tmp;
341     if (low == high)
342         return low;
343     if (low > high)
344     {
345         tmp  = low;
346         low  = high;
347         high = tmp;
348     }
349     return (low + OSA_Rand() % (high - low));
350 }
351 
352 /** Suspend the given thread
353  *
354  * - The function OSA_ThreadSelfComplete() will \b permanently suspend the
355  * given thread. Passing NULL will suspend the current thread. This
356  * function never returns.
357  * - The thread continues to consume system resources. To delete the thread
358  * the function OSA_TaskDestroy() needs to be called separately.
359  *
360  * @param[in] taskHandle Pointer to thread handle
361  */
362 void OSA_ThreadSelfComplete(osa_task_handle_t taskHandle);
363 
364 /** Return the number of messages stored in queue.
365  *
366  * @param[in] msgqHandle Pointer to handle of the queue to be queried.
367  *
368  * @returns Number of items in the queue
369  */
370 uint32_t OSA_MsgQWaiting(osa_msgq_handle_t msgqHandle);
371 
372 #endif /* ! _OSA_H_ */
373