aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/hal/osal/os-less/ARMCMx/osal.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/hal/osal/os-less/ARMCMx/osal.c')
-rw-r--r--lib/chibios/os/hal/osal/os-less/ARMCMx/osal.c467
1 files changed, 467 insertions, 0 deletions
diff --git a/lib/chibios/os/hal/osal/os-less/ARMCMx/osal.c b/lib/chibios/os/hal/osal/os-less/ARMCMx/osal.c
new file mode 100644
index 000000000..a4cb7aabf
--- /dev/null
+++ b/lib/chibios/os/hal/osal/os-less/ARMCMx/osal.c
@@ -0,0 +1,467 @@
1/*
2 ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/**
18 * @file osal.c
19 * @brief OSAL module code.
20 *
21 * @addtogroup OSAL
22 * @{
23 */
24
25#include "osal.h"
26#include "osal_vt.h"
27
28/*===========================================================================*/
29/* Module local definitions. */
30/*===========================================================================*/
31
32/*===========================================================================*/
33/* Module exported variables. */
34/*===========================================================================*/
35
36/**
37 * @brief Pointer to a halt error message.
38 * @note The message is meant to be retrieved by the debugger after the
39 * system halt caused by an unexpected error.
40 */
41const char *osal_halt_msg;
42
43/*===========================================================================*/
44/* Module local types. */
45/*===========================================================================*/
46
47/*===========================================================================*/
48/* Module local variables. */
49/*===========================================================================*/
50
51/*===========================================================================*/
52/* Module local functions. */
53/*===========================================================================*/
54
55static void callback_timeout(void *p) {
56 osalSysLockFromISR();
57 osalThreadResumeI((thread_reference_t *)p, MSG_TIMEOUT);
58 osalSysUnlockFromISR();
59}
60
61/*===========================================================================*/
62/* Module exported functions. */
63/*===========================================================================*/
64
65/**
66 * @brief OSAL module initialization.
67 *
68 * @api
69 */
70void osalInit(void) {
71
72 vtInit();
73
74 OSAL_INIT_HOOK();
75}
76
77/**
78 * @brief System halt with error message.
79 *
80 * @param[in] reason the halt message pointer
81 *
82 * @api
83 */
84#if !defined(__DOXYGEN__)
85__attribute__((weak, noreturn))
86#endif
87void osalSysHalt(const char *reason) {
88
89 osalSysDisable();
90 osal_halt_msg = reason;
91 while (true) {
92 }
93}
94
95/**
96 * @brief Polled delay.
97 * @note The real delay is always few cycles in excess of the specified
98 * value.
99 *
100 * @param[in] cycles number of cycles
101 *
102 * @xclass
103 */
104void osalSysPolledDelayX(rtcnt_t cycles) {
105
106 (void)cycles;
107}
108
109/**
110 * @brief System timer handler.
111 * @details The handler is used for scheduling and Virtual Timers management.
112 *
113 * @iclass
114 */
115void osalOsTimerHandlerI(void) {
116
117 osalDbgCheckClassI();
118
119 vtDoTickI();
120}
121
122/**
123 * @brief Checks if a reschedule is required and performs it.
124 * @note I-Class functions invoked from thread context must not reschedule
125 * by themselves, an explicit reschedule using this function is
126 * required in this scenario.
127 * @note Not implemented in this simplified OSAL.
128 *
129 * @sclass
130 */
131void osalOsRescheduleS(void) {
132
133}
134
135/**
136 * @brief Current system time.
137 * @details Returns the number of system ticks since the @p osalInit()
138 * invocation.
139 * @note The counter can reach its maximum and then restart from zero.
140 * @note This function can be called from any context but its atomicity
141 * is not guaranteed on architectures whose word size is less than
142 * @p systime_t size.
143 *
144 * @return The system time in ticks.
145 *
146 * @xclass
147 */
148systime_t osalOsGetSystemTimeX(void) {
149
150 return vtlist.vt_systime;
151}
152
153/**
154 * @brief Suspends the invoking thread for the specified time.
155 *
156 * @param[in] time the delay in system ticks, the special values are
157 * handled as follow:
158 * - @a TIME_INFINITE is allowed but interpreted as a
159 * normal time specification.
160 * - @a TIME_IMMEDIATE this value is not allowed.
161 * .
162 *
163 * @sclass
164 */
165void osalThreadSleepS(sysinterval_t time) {
166 virtual_timer_t vt;
167 thread_reference_t tr;
168
169 tr = NULL;
170 vtSetI(&vt, time, callback_timeout, (void *)&tr);
171 osalThreadSuspendS(&tr);
172}
173
174/**
175 * @brief Suspends the invoking thread for the specified time.
176 *
177 * @param[in] time the delay in system ticks, the special values are
178 * handled as follow:
179 * - @a TIME_INFINITE is allowed but interpreted as a
180 * normal time specification.
181 * - @a TIME_IMMEDIATE this value is not allowed.
182 * .
183 *
184 * @api
185 */
186void osalThreadSleep(sysinterval_t time) {
187
188 osalSysLock();
189 osalThreadSleepS(time);
190 osalSysUnlock();
191}
192
193/**
194 * @brief Sends the current thread sleeping and sets a reference variable.
195 * @note This function must reschedule, it can only be called from thread
196 * context.
197 *
198 * @param[in] trp a pointer to a thread reference object
199 * @return The wake up message.
200 *
201 * @sclass
202 */
203msg_t osalThreadSuspendS(thread_reference_t *trp) {
204 thread_t self = {MSG_WAIT};
205
206 osalDbgCheck(trp != NULL);
207
208 *trp = &self;
209 while (self.message == MSG_WAIT) {
210 osalSysUnlock();
211 /* A state-changing interrupt could occur here and cause the loop to
212 terminate, an hook macro is executed while waiting.*/
213 OSAL_IDLE_HOOK();
214 osalSysLock();
215 }
216
217 return self.message;
218}
219
220/**
221 * @brief Sends the current thread sleeping and sets a reference variable.
222 * @note This function must reschedule, it can only be called from thread
223 * context.
224 *
225 * @param[in] trp a pointer to a thread reference object
226 * @param[in] timeout the timeout in system ticks, the special values are
227 * handled as follow:
228 * - @a TIME_INFINITE the thread enters an infinite sleep
229 * state.
230 * - @a TIME_IMMEDIATE the thread is not enqueued and
231 * the function returns @p MSG_TIMEOUT as if a timeout
232 * occurred.
233 * .
234 * @return The wake up message.
235 * @retval MSG_TIMEOUT if the operation timed out.
236 *
237 * @sclass
238 */
239msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) {
240 msg_t msg;
241 virtual_timer_t vt;
242
243 osalDbgCheck(trp != NULL);
244
245 if (TIME_INFINITE == timeout)
246 return osalThreadSuspendS(trp);
247
248 vtSetI(&vt, timeout, callback_timeout, (void *)trp);
249 msg = osalThreadSuspendS(trp);
250 if (vtIsArmedI(&vt))
251 vtResetI(&vt);
252
253 return msg;
254}
255
256/**
257 * @brief Wakes up a thread waiting on a thread reference object.
258 * @note This function must not reschedule because it can be called from
259 * ISR context.
260 *
261 * @param[in] trp a pointer to a thread reference object
262 * @param[in] msg the message code
263 *
264 * @iclass
265 */
266void osalThreadResumeI(thread_reference_t *trp, msg_t msg) {
267
268 osalDbgCheck(trp != NULL);
269
270 if (*trp != NULL) {
271 (*trp)->message = msg;
272 *trp = NULL;
273 }
274}
275
276/**
277 * @brief Wakes up a thread waiting on a thread reference object.
278 * @note This function must reschedule, it can only be called from thread
279 * context.
280 *
281 * @param[in] trp a pointer to a thread reference object
282 * @param[in] msg the message code
283 *
284 * @iclass
285 */
286void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {
287
288 osalDbgCheck(trp != NULL);
289
290 if (*trp != NULL) {
291 (*trp)->message = msg;
292 *trp = NULL;
293 }
294}
295
296/**
297 * @brief Enqueues the caller thread.
298 * @details The caller thread is enqueued and put to sleep until it is
299 * dequeued or the specified timeouts expires.
300 *
301 * @param[in] tqp pointer to the threads queue object
302 * @param[in] timeout the timeout in system ticks, the special values are
303 * handled as follow:
304 * - @a TIME_INFINITE the thread enters an infinite sleep
305 * state.
306 * - @a TIME_IMMEDIATE the thread is not enqueued and
307 * the function returns @p MSG_TIMEOUT as if a timeout
308 * occurred.
309 * .
310 * @return The message from @p osalQueueWakeupOneI() or
311 * @p osalQueueWakeupAllI() functions.
312 * @retval MSG_TIMEOUT if the thread has not been dequeued within the
313 * specified timeout or if the function has been
314 * invoked with @p TIME_IMMEDIATE as timeout
315 * specification.
316 *
317 * @sclass
318 */
319msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {
320 msg_t msg;
321 virtual_timer_t vt;
322
323 osalDbgCheck(tqp != NULL);
324
325 if (TIME_IMMEDIATE == timeout)
326 return MSG_TIMEOUT;
327
328 tqp->tr = NULL;
329
330 if (TIME_INFINITE == timeout)
331 return osalThreadSuspendS(&tqp->tr);
332
333 vtSetI(&vt, timeout, callback_timeout, (void *)&tqp->tr);
334 msg = osalThreadSuspendS(&tqp->tr);
335 if (vtIsArmedI(&vt))
336 vtResetI(&vt);
337
338 return msg;
339}
340
341/**
342 * @brief Dequeues and wakes up one thread from the queue, if any.
343 *
344 * @param[in] tqp pointer to the threads queue object
345 * @param[in] msg the message code
346 *
347 * @iclass
348 */
349void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
350
351 osalDbgCheck(tqp != NULL);
352
353 osalThreadResumeI(&tqp->tr, msg);
354}
355
356/**
357 * @brief Dequeues and wakes up all threads from the queue.
358 *
359 * @param[in] tqp pointer to the threads queue object
360 * @param[in] msg the message code
361 *
362 * @iclass
363 */
364void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
365
366 osalDbgCheck(tqp != NULL);
367
368 osalThreadResumeI(&tqp->tr, msg);
369}
370
371/**
372 * @brief Add flags to an event source object.
373 *
374 * @param[in] esp pointer to the event flags object
375 * @param[in] flags flags to be ORed to the flags mask
376 *
377 * @iclass
378 */
379void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {
380
381 osalDbgCheck(esp != NULL);
382
383 esp->flags |= flags;
384 if (esp->cb != NULL) {
385 esp->cb(esp);
386 }
387}
388
389/**
390 * @brief Add flags to an event source object.
391 *
392 * @param[in] esp pointer to the event flags object
393 * @param[in] flags flags to be ORed to the flags mask
394 *
395 * @iclass
396 */
397void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags) {
398
399 osalDbgCheck(esp != NULL);
400
401 osalSysLock();
402 osalEventBroadcastFlagsI(esp, flags);
403 osalSysUnlock();
404}
405
406/**
407 * @brief Event callback setup.
408 * @note The callback is invoked from ISR context and can
409 * only invoke I-Class functions. The callback is meant
410 * to wakeup the task that will handle the event by
411 * calling @p osalEventGetAndClearFlagsI().
412 * @note This function is not part of the OSAL API and is provided
413 * exclusively as an example and for convenience.
414 *
415 * @param[in] esp pointer to the event flags object
416 * @param[in] cb pointer to the callback function
417 * @param[in] param parameter to be passed to the callback function
418 *
419 * @api
420 */
421void osalEventSetCallback(event_source_t *esp,
422 eventcallback_t cb,
423 void *param) {
424
425 osalDbgCheck(esp != NULL);
426
427 esp->cb = cb;
428 esp->param = param;
429}
430
431/**
432 * @brief Locks the specified mutex.
433 * @post The mutex is locked and inserted in the per-thread stack of owned
434 * mutexes.
435 *
436 * @param[in,out] mp pointer to the @p mutex_t object
437 *
438 * @api
439 */
440void osalMutexLock(mutex_t *mp) {
441
442 osalDbgCheck(mp != NULL);
443
444 *mp = 1;
445}
446
447/**
448 * @brief Unlocks the specified mutex.
449 * @note The HAL guarantees to release mutex in reverse lock order. The
450 * mutex being unlocked is guaranteed to be the last locked mutex
451 * by the invoking thread.
452 * The implementation can rely on this behavior and eventually
453 * ignore the @p mp parameter which is supplied in order to support
454 * those OSes not supporting a stack of the owned mutexes.
455 *
456 * @param[in,out] mp pointer to the @p mutex_t object
457 *
458 * @api
459 */
460void osalMutexUnlock(mutex_t *mp) {
461
462 osalDbgCheck(mp != NULL);
463
464 *mp = 0;
465}
466
467/** @} */