--- /dev/null
+/*\r
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+*/\r
+\r
+/**\r
+ * @file osal.c\r
+ * @brief OSAL module code.\r
+ *\r
+ * @addtogroup OSAL\r
+ * @{\r
+ */\r
+\r
+#include "osal.h"\r
+#include "osal_vt.h"\r
+\r
+/*===========================================================================*/\r
+/* Module local definitions. */\r
+/*===========================================================================*/\r
+\r
+/*===========================================================================*/\r
+/* Module exported variables. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @brief Pointer to a halt error message.\r
+ * @note The message is meant to be retrieved by the debugger after the\r
+ * system halt caused by an unexpected error.\r
+ */\r
+const char *osal_halt_msg;\r
+\r
+/*===========================================================================*/\r
+/* Module local types. */\r
+/*===========================================================================*/\r
+\r
+/*===========================================================================*/\r
+/* Module local variables. */\r
+/*===========================================================================*/\r
+\r
+/*===========================================================================*/\r
+/* Module local functions. */\r
+/*===========================================================================*/\r
+\r
+static void callback_timeout(void *p) {\r
+ osalSysLockFromISR();\r
+ osalThreadResumeI((thread_reference_t *)p, MSG_TIMEOUT);\r
+ osalSysUnlockFromISR();\r
+}\r
+\r
+/*===========================================================================*/\r
+/* Module exported functions. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @brief OSAL module initialization.\r
+ *\r
+ * @api\r
+ */\r
+void osalInit(void) {\r
+\r
+ vtInit();\r
+\r
+ OSAL_INIT_HOOK();\r
+}\r
+\r
+/**\r
+ * @brief System halt with error message.\r
+ *\r
+ * @param[in] reason the halt message pointer\r
+ *\r
+ * @api\r
+ */\r
+#if !defined(__DOXYGEN__)\r
+__attribute__((weak, noreturn))\r
+#endif\r
+void osalSysHalt(const char *reason) {\r
+\r
+ osalSysDisable();\r
+ osal_halt_msg = reason;\r
+ while (true) {\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Polled delay.\r
+ * @note The real delay is always few cycles in excess of the specified\r
+ * value.\r
+ *\r
+ * @param[in] cycles number of cycles\r
+ *\r
+ * @xclass\r
+ */\r
+void osalSysPolledDelayX(rtcnt_t cycles) {\r
+\r
+ (void)cycles;\r
+}\r
+\r
+/**\r
+ * @brief System timer handler.\r
+ * @details The handler is used for scheduling and Virtual Timers management.\r
+ *\r
+ * @iclass\r
+ */\r
+void osalOsTimerHandlerI(void) {\r
+\r
+ osalDbgCheckClassI();\r
+\r
+ vtDoTickI();\r
+}\r
+\r
+/**\r
+ * @brief Checks if a reschedule is required and performs it.\r
+ * @note I-Class functions invoked from thread context must not reschedule\r
+ * by themselves, an explicit reschedule using this function is\r
+ * required in this scenario.\r
+ * @note Not implemented in this simplified OSAL.\r
+ *\r
+ * @sclass\r
+ */\r
+void osalOsRescheduleS(void) {\r
+\r
+}\r
+\r
+/**\r
+ * @brief Current system time.\r
+ * @details Returns the number of system ticks since the @p osalInit()\r
+ * invocation.\r
+ * @note The counter can reach its maximum and then restart from zero.\r
+ * @note This function can be called from any context but its atomicity\r
+ * is not guaranteed on architectures whose word size is less than\r
+ * @p systime_t size.\r
+ *\r
+ * @return The system time in ticks.\r
+ *\r
+ * @xclass\r
+ */\r
+systime_t osalOsGetSystemTimeX(void) {\r
+\r
+ return vtlist.vt_systime;\r
+}\r
+\r
+/**\r
+ * @brief Suspends the invoking thread for the specified time.\r
+ *\r
+ * @param[in] time the delay in system ticks, the special values are\r
+ * handled as follow:\r
+ * - @a TIME_INFINITE is allowed but interpreted as a\r
+ * normal time specification.\r
+ * - @a TIME_IMMEDIATE this value is not allowed.\r
+ * .\r
+ *\r
+ * @sclass\r
+ */\r
+void osalThreadSleepS(sysinterval_t time) {\r
+ virtual_timer_t vt;\r
+ thread_reference_t tr;\r
+\r
+ tr = NULL;\r
+ vtSetI(&vt, time, callback_timeout, (void *)&tr);\r
+ osalThreadSuspendS(&tr);\r
+}\r
+\r
+/**\r
+ * @brief Suspends the invoking thread for the specified time.\r
+ *\r
+ * @param[in] time the delay in system ticks, the special values are\r
+ * handled as follow:\r
+ * - @a TIME_INFINITE is allowed but interpreted as a\r
+ * normal time specification.\r
+ * - @a TIME_IMMEDIATE this value is not allowed.\r
+ * .\r
+ *\r
+ * @api\r
+ */\r
+void osalThreadSleep(sysinterval_t time) {\r
+\r
+ osalSysLock();\r
+ osalThreadSleepS(time);\r
+ osalSysUnlock();\r
+}\r
+\r
+/**\r
+ * @brief Sends the current thread sleeping and sets a reference variable.\r
+ * @note This function must reschedule, it can only be called from thread\r
+ * context.\r
+ *\r
+ * @param[in] trp a pointer to a thread reference object\r
+ * @return The wake up message.\r
+ *\r
+ * @sclass\r
+ */\r
+msg_t osalThreadSuspendS(thread_reference_t *trp) {\r
+ thread_t self = {MSG_WAIT};\r
+\r
+ osalDbgCheck(trp != NULL);\r
+\r
+ *trp = &self;\r
+ while (self.message == MSG_WAIT) {\r
+ osalSysUnlock();\r
+ /* A state-changing interrupt could occur here and cause the loop to\r
+ terminate, an hook macro is executed while waiting.*/\r
+ OSAL_IDLE_HOOK();\r
+ osalSysLock();\r
+ }\r
+\r
+ return self.message;\r
+}\r
+\r
+/**\r
+ * @brief Sends the current thread sleeping and sets a reference variable.\r
+ * @note This function must reschedule, it can only be called from thread\r
+ * context.\r
+ *\r
+ * @param[in] trp a pointer to a thread reference object\r
+ * @param[in] timeout the timeout in system ticks, the special values are\r
+ * handled as follow:\r
+ * - @a TIME_INFINITE the thread enters an infinite sleep\r
+ * state.\r
+ * - @a TIME_IMMEDIATE the thread is not enqueued and\r
+ * the function returns @p MSG_TIMEOUT as if a timeout\r
+ * occurred.\r
+ * .\r
+ * @return The wake up message.\r
+ * @retval MSG_TIMEOUT if the operation timed out.\r
+ *\r
+ * @sclass\r
+ */\r
+msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout) {\r
+ msg_t msg;\r
+ virtual_timer_t vt;\r
+\r
+ osalDbgCheck(trp != NULL);\r
+\r
+ if (TIME_INFINITE == timeout)\r
+ return osalThreadSuspendS(trp);\r
+\r
+ vtSetI(&vt, timeout, callback_timeout, (void *)trp);\r
+ msg = osalThreadSuspendS(trp);\r
+ if (vtIsArmedI(&vt))\r
+ vtResetI(&vt);\r
+\r
+ return msg;\r
+}\r
+\r
+/**\r
+ * @brief Wakes up a thread waiting on a thread reference object.\r
+ * @note This function must not reschedule because it can be called from\r
+ * ISR context.\r
+ *\r
+ * @param[in] trp a pointer to a thread reference object\r
+ * @param[in] msg the message code\r
+ *\r
+ * @iclass\r
+ */\r
+void osalThreadResumeI(thread_reference_t *trp, msg_t msg) {\r
+\r
+ osalDbgCheck(trp != NULL);\r
+\r
+ if (*trp != NULL) {\r
+ (*trp)->message = msg;\r
+ *trp = NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Wakes up a thread waiting on a thread reference object.\r
+ * @note This function must reschedule, it can only be called from thread\r
+ * context.\r
+ *\r
+ * @param[in] trp a pointer to a thread reference object\r
+ * @param[in] msg the message code\r
+ *\r
+ * @iclass\r
+ */\r
+void osalThreadResumeS(thread_reference_t *trp, msg_t msg) {\r
+\r
+ osalDbgCheck(trp != NULL);\r
+\r
+ if (*trp != NULL) {\r
+ (*trp)->message = msg;\r
+ *trp = NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Enqueues the caller thread.\r
+ * @details The caller thread is enqueued and put to sleep until it is\r
+ * dequeued or the specified timeouts expires.\r
+ *\r
+ * @param[in] tqp pointer to the threads queue object\r
+ * @param[in] timeout the timeout in system ticks, the special values are\r
+ * handled as follow:\r
+ * - @a TIME_INFINITE the thread enters an infinite sleep\r
+ * state.\r
+ * - @a TIME_IMMEDIATE the thread is not enqueued and\r
+ * the function returns @p MSG_TIMEOUT as if a timeout\r
+ * occurred.\r
+ * .\r
+ * @return The message from @p osalQueueWakeupOneI() or\r
+ * @p osalQueueWakeupAllI() functions.\r
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the\r
+ * specified timeout or if the function has been\r
+ * invoked with @p TIME_IMMEDIATE as timeout\r
+ * specification.\r
+ *\r
+ * @sclass\r
+ */\r
+msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout) {\r
+ msg_t msg;\r
+ virtual_timer_t vt;\r
+\r
+ osalDbgCheck(tqp != NULL);\r
+\r
+ if (TIME_IMMEDIATE == timeout)\r
+ return MSG_TIMEOUT;\r
+\r
+ tqp->tr = NULL;\r
+\r
+ if (TIME_INFINITE == timeout)\r
+ return osalThreadSuspendS(&tqp->tr);\r
+\r
+ vtSetI(&vt, timeout, callback_timeout, (void *)&tqp->tr);\r
+ msg = osalThreadSuspendS(&tqp->tr);\r
+ if (vtIsArmedI(&vt))\r
+ vtResetI(&vt);\r
+\r
+ return msg;\r
+}\r
+\r
+/**\r
+ * @brief Dequeues and wakes up one thread from the queue, if any.\r
+ *\r
+ * @param[in] tqp pointer to the threads queue object\r
+ * @param[in] msg the message code\r
+ *\r
+ * @iclass\r
+ */\r
+void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {\r
+\r
+ osalDbgCheck(tqp != NULL);\r
+\r
+ osalThreadResumeI(&tqp->tr, msg);\r
+}\r
+\r
+/**\r
+ * @brief Dequeues and wakes up all threads from the queue.\r
+ *\r
+ * @param[in] tqp pointer to the threads queue object\r
+ * @param[in] msg the message code\r
+ *\r
+ * @iclass\r
+ */\r
+void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {\r
+\r
+ osalDbgCheck(tqp != NULL);\r
+\r
+ osalThreadResumeI(&tqp->tr, msg);\r
+}\r
+\r
+/**\r
+ * @brief Add flags to an event source object.\r
+ *\r
+ * @param[in] esp pointer to the event flags object\r
+ * @param[in] flags flags to be ORed to the flags mask\r
+ *\r
+ * @iclass\r
+ */\r
+void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags) {\r
+\r
+ osalDbgCheck(esp != NULL);\r
+\r
+ esp->flags |= flags;\r
+ if (esp->cb != NULL) {\r
+ esp->cb(esp);\r
+ }\r
+}\r
+\r
+/**\r
+ * @brief Add flags to an event source object.\r
+ *\r
+ * @param[in] esp pointer to the event flags object\r
+ * @param[in] flags flags to be ORed to the flags mask\r
+ *\r
+ * @iclass\r
+ */\r
+void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags) {\r
+\r
+ osalDbgCheck(esp != NULL);\r
+\r
+ osalSysLock();\r
+ osalEventBroadcastFlagsI(esp, flags);\r
+ osalSysUnlock();\r
+}\r
+\r
+/**\r
+ * @brief Event callback setup.\r
+ * @note The callback is invoked from ISR context and can\r
+ * only invoke I-Class functions. The callback is meant\r
+ * to wakeup the task that will handle the event by\r
+ * calling @p osalEventGetAndClearFlagsI().\r
+ * @note This function is not part of the OSAL API and is provided\r
+ * exclusively as an example and for convenience.\r
+ *\r
+ * @param[in] esp pointer to the event flags object\r
+ * @param[in] cb pointer to the callback function\r
+ * @param[in] param parameter to be passed to the callback function\r
+ *\r
+ * @api\r
+ */\r
+void osalEventSetCallback(event_source_t *esp,\r
+ eventcallback_t cb,\r
+ void *param) {\r
+\r
+ osalDbgCheck(esp != NULL);\r
+\r
+ esp->cb = cb;\r
+ esp->param = param;\r
+}\r
+\r
+/**\r
+ * @brief Locks the specified mutex.\r
+ * @post The mutex is locked and inserted in the per-thread stack of owned\r
+ * mutexes.\r
+ *\r
+ * @param[in,out] mp pointer to the @p mutex_t object\r
+ *\r
+ * @api\r
+ */\r
+void osalMutexLock(mutex_t *mp) {\r
+\r
+ osalDbgCheck(mp != NULL);\r
+\r
+ *mp = 1;\r
+}\r
+\r
+/**\r
+ * @brief Unlocks the specified mutex.\r
+ * @note The HAL guarantees to release mutex in reverse lock order. The\r
+ * mutex being unlocked is guaranteed to be the last locked mutex\r
+ * by the invoking thread.\r
+ * The implementation can rely on this behavior and eventually\r
+ * ignore the @p mp parameter which is supplied in order to support\r
+ * those OSes not supporting a stack of the owned mutexes.\r
+ *\r
+ * @param[in,out] mp pointer to the @p mutex_t object\r
+ *\r
+ * @api\r
+ */\r
+void osalMutexUnlock(mutex_t *mp) {\r
+\r
+ osalDbgCheck(mp != NULL);\r
+\r
+ *mp = 0;\r
+}\r
+\r
+/** @} */\r
--- /dev/null
+/*\r
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio\r
+\r
+ Licensed under the Apache License, Version 2.0 (the "License");\r
+ you may not use this file except in compliance with the License.\r
+ You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+*/\r
+\r
+/**\r
+ * @file osal.h\r
+ * @brief OSAL module header.\r
+ *\r
+ * @addtogroup OSAL\r
+ * @{\r
+ */\r
+\r
+#ifndef OSAL_H\r
+#define OSAL_H\r
+\r
+#include <stddef.h>\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+\r
+#include "cmparams.h"\r
+\r
+#include "osalconf.h"\r
+\r
+/*===========================================================================*/\r
+/* Module constants. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @name Common constants\r
+ * @{\r
+ */\r
+#if !defined(FALSE) || defined(__DOXYGEN__)\r
+#define FALSE 0\r
+#endif\r
+\r
+#if !defined(TRUE) || defined(__DOXYGEN__)\r
+#define TRUE 1\r
+#endif\r
+\r
+#define OSAL_SUCCESS false\r
+#define OSAL_FAILED true\r
+/** @} */\r
+\r
+/**\r
+ * @name Messages\r
+ * @{\r
+ */\r
+#define MSG_OK (msg_t)0\r
+#define MSG_RESET (msg_t)-1\r
+#define MSG_TIMEOUT (msg_t)-2\r
+#define MSG_WAIT (msg_t)-10\r
+/** @} */\r
+\r
+/**\r
+ * @name Special time constants\r
+ * @{\r
+ */\r
+#define TIME_IMMEDIATE ((sysinterval_t)0)\r
+#define TIME_INFINITE ((sysinterval_t)-1)\r
+/** @} */\r
+\r
+/**\r
+ * @name Systick modes.\r
+ * @{\r
+ */\r
+#define OSAL_ST_MODE_NONE 0\r
+#define OSAL_ST_MODE_PERIODIC 1\r
+#define OSAL_ST_MODE_FREERUNNING 2\r
+/** @} */\r
+\r
+/**\r
+ * @name Systick parameters.\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Size in bits of the @p systick_t type.\r
+ */\r
+#define OSAL_ST_RESOLUTION 32\r
+\r
+/**\r
+ * @brief Systick mode required by the underlying OS.\r
+ */\r
+#define OSAL_ST_MODE OSAL_ST_MODE_NONE\r
+/** @} */\r
+\r
+/**\r
+ * @name IRQ-related constants\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Total priority levels.\r
+ */\r
+#define OSAL_IRQ_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS)\r
+\r
+/**\r
+ * @brief Highest IRQ priority for HAL drivers.\r
+ */\r
+#if (CORTEX_MODEL == 0) || defined(__DOXYGEN__)\r
+#define OSAL_IRQ_MAXIMUM_PRIORITY 0\r
+#else\r
+#define OSAL_IRQ_MAXIMUM_PRIORITY 1\r
+#endif\r
+\r
+/**\r
+ * @brief Converts from numeric priority to BASEPRI register value.\r
+ */\r
+#define OSAL_BASEPRI(priority) ((priority) << (8U - CORTEX_PRIORITY_BITS))\r
+/** @} */\r
+\r
+/*===========================================================================*/\r
+/* Module pre-compile time settings. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @brief Frequency in Hertz of the system tick.\r
+ */\r
+#if !defined(OSAL_ST_FREQUENCY) || defined(__DOXYGEN__)\r
+#define OSAL_ST_FREQUENCY 1000\r
+#endif\r
+\r
+/**\r
+ * @brief Enables OSAL assertions.\r
+ */\r
+#if !defined(OSAL_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)\r
+#define OSAL_DBG_ENABLE_ASSERTS FALSE\r
+#endif\r
+\r
+/**\r
+ * @brief Enables OSAL functions parameters checks.\r
+ */\r
+#if !defined(OSAL_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)\r
+#define OSAL_DBG_ENABLE_CHECKS FALSE\r
+#endif\r
+\r
+/**\r
+ * @brief OSAL initialization hook.\r
+ */\r
+#if !defined(OSAL_INIT_HOOK) || defined(__DOXYGEN__)\r
+#define OSAL_INIT_HOOK()\r
+#endif\r
+\r
+/**\r
+ * @brief Idle loop hook macro.\r
+ */\r
+#if !defined(OSAL_IDLE_HOOK) || defined(__DOXYGEN__)\r
+#define OSAL_IDLE_HOOK()\r
+#endif\r
+\r
+/*===========================================================================*/\r
+/* Derived constants and error checks. */\r
+/*===========================================================================*/\r
+\r
+/*===========================================================================*/\r
+/* Module data structures and types. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @brief Type of a system status word.\r
+ */\r
+typedef uint32_t syssts_t;\r
+\r
+/**\r
+ * @brief Type of a message.\r
+ */\r
+typedef int32_t msg_t;\r
+\r
+/**\r
+ * @brief Type of system time counter.\r
+ */\r
+typedef uint32_t systime_t;\r
+\r
+/**\r
+ * @brief Type of system time interval.\r
+ */\r
+typedef uint32_t sysinterval_t;\r
+\r
+/**\r
+ * @brief Type of realtime counter.\r
+ */\r
+typedef uint32_t rtcnt_t;\r
+\r
+/**\r
+ * @brief Type of a thread.\r
+ * @note The content of this structure is not part of the API and should\r
+ * not be relied upon. Implementers may define this structure in\r
+ * an entirely different way.\r
+ */\r
+typedef struct {\r
+ volatile msg_t message;\r
+} thread_t;\r
+\r
+/**\r
+ * @brief Type of a thread reference.\r
+ */\r
+typedef thread_t * thread_reference_t;\r
+\r
+/**\r
+ * @brief Type of an event flags mask.\r
+ */\r
+typedef uint32_t eventflags_t;\r
+\r
+/**\r
+ * @brief Type of an event flags object.\r
+ * @note The content of this structure is not part of the API and should\r
+ * not be relied upon. Implementers may define this structure in\r
+ * an entirely different way.\r
+ * @note Retrieval and clearing of the flags are not defined in this\r
+ * API and are implementation-dependent.\r
+ */\r
+typedef struct event_source event_source_t;\r
+\r
+/**\r
+ * @brief Type of an event source callback.\r
+ * @note This type is not part of the OSAL API and is provided\r
+ * exclusively as an example and for convenience.\r
+ */\r
+typedef void (*eventcallback_t)(event_source_t *esp);\r
+\r
+/**\r
+ * @brief Events source object.\r
+ * @note The content of this structure is not part of the API and should\r
+ * not be relied upon. Implementers may define this structure in\r
+ * an entirely different way.\r
+ * @note Retrieval and clearing of the flags are not defined in this\r
+ * API and are implementation-dependent.\r
+ */\r
+struct event_source {\r
+ volatile eventflags_t flags; /**< @brief Stored event flags. */\r
+ eventcallback_t cb; /**< @brief Event source callback. */\r
+ void *param; /**< @brief User defined field. */\r
+};\r
+\r
+/**\r
+ * @brief Type of a mutex.\r
+ * @note If the OS does not support mutexes or there is no OS then them\r
+ * mechanism can be simulated.\r
+ */\r
+typedef uint32_t mutex_t;\r
+\r
+/**\r
+ * @brief Type of a thread queue.\r
+ * @details A thread queue is a queue of sleeping threads, queued threads\r
+ * can be dequeued one at time or all together.\r
+ * @note If the OSAL is implemented on a bare metal machine without RTOS\r
+ * then the queue can be implemented as a single thread reference.\r
+ */\r
+typedef struct {\r
+ thread_reference_t tr;\r
+} threads_queue_t;\r
+\r
+/*===========================================================================*/\r
+/* Module macros. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @name Debug related macros\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Condition assertion.\r
+ * @details If the condition check fails then the OSAL panics with a\r
+ * message and halts.\r
+ * @note The condition is tested only if the @p OSAL_ENABLE_ASSERTIONS\r
+ * switch is enabled.\r
+ * @note The remark string is not currently used except for putting a\r
+ * comment in the code about the assertion.\r
+ *\r
+ * @param[in] c the condition to be verified to be true\r
+ * @param[in] remark a remark string\r
+ *\r
+ * @api\r
+ */\r
+#define osalDbgAssert(c, remark) do { \\r
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \\r
+ if (OSAL_DBG_ENABLE_ASSERTS != FALSE) { \\r
+ if (!(c)) { \\r
+ /*lint -restore*/ \\r
+ osalSysHalt(__func__); \\r
+ } \\r
+ } \\r
+} while (false)\r
+\r
+/**\r
+ * @brief Function parameters check.\r
+ * @details If the condition check fails then the OSAL panics and halts.\r
+ * @note The condition is tested only if the @p OSAL_ENABLE_CHECKS switch\r
+ * is enabled.\r
+ *\r
+ * @param[in] c the condition to be verified to be true\r
+ *\r
+ * @api\r
+ */\r
+#define osalDbgCheck(c) do { \\r
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \\r
+ if (OSAL_DBG_ENABLE_CHECKS != FALSE) { \\r
+ if (!(c)) { \\r
+ /*lint -restore*/ \\r
+ osalSysHalt(__func__); \\r
+ } \\r
+ } \\r
+} while (false)\r
+\r
+/**\r
+ * @brief I-Class state check.\r
+ * @note Implementation is optional.\r
+ */\r
+#define osalDbgCheckClassI()\r
+\r
+/**\r
+ * @brief S-Class state check.\r
+ * @note Implementation is optional.\r
+ */\r
+#define osalDbgCheckClassS()\r
+/** @} */\r
+\r
+/**\r
+ * @name IRQ service routines wrappers\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Priority level verification macro.\r
+ */\r
+#define OSAL_IRQ_IS_VALID_PRIORITY(n) \\r
+ (((n) >= OSAL_IRQ_MAXIMUM_PRIORITY) && ((n) < OSAL_IRQ_PRIORITY_LEVELS))\r
+\r
+/**\r
+ * @brief IRQ prologue code.\r
+ * @details This macro must be inserted at the start of all IRQ handlers.\r
+ */\r
+#define OSAL_IRQ_PROLOGUE()\r
+\r
+/**\r
+ * @brief IRQ epilogue code.\r
+ * @details This macro must be inserted at the end of all IRQ handlers.\r
+ */\r
+#define OSAL_IRQ_EPILOGUE()\r
+\r
+/**\r
+ * @brief IRQ handler function declaration.\r
+ * @details This macro hides the details of an ISR function declaration.\r
+ *\r
+ * @param[in] id a vector name as defined in @p vectors.s\r
+ */\r
+#define OSAL_IRQ_HANDLER(id) void id(void)\r
+/** @} */\r
+\r
+/**\r
+ * @name Time conversion utilities\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Seconds to system ticks.\r
+ * @details Converts from seconds to system ticks number.\r
+ * @note The result is rounded upward to the next tick boundary.\r
+ *\r
+ * @param[in] secs number of seconds\r
+ * @return The number of ticks.\r
+ *\r
+ * @api\r
+ */\r
+#define OSAL_S2I(secs) \\r
+ ((sysinterval_t)((uint32_t)(secs) * (uint32_t)OSAL_ST_FREQUENCY))\r
+\r
+/**\r
+ * @brief Milliseconds to system ticks.\r
+ * @details Converts from milliseconds to system ticks number.\r
+ * @note The result is rounded upward to the next tick boundary.\r
+ *\r
+ * @param[in] msecs number of milliseconds\r
+ * @return The number of ticks.\r
+ *\r
+ * @api\r
+ */\r
+#define OSAL_MS2I(msecs) \\r
+ ((sysinterval_t)((((((uint32_t)(msecs)) * \\r
+ ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000UL) + 1UL))\r
+\r
+/**\r
+ * @brief Microseconds to system ticks.\r
+ * @details Converts from microseconds to system ticks number.\r
+ * @note The result is rounded upward to the next tick boundary.\r
+ *\r
+ * @param[in] usecs number of microseconds\r
+ * @return The number of ticks.\r
+ *\r
+ * @api\r
+ */\r
+#define OSAL_US2I(usecs) \\r
+ ((sysinterval_t)((((((uint32_t)(usecs)) * \\r
+ ((uint32_t)OSAL_ST_FREQUENCY)) - 1UL) / 1000000UL) + 1UL))\r
+/** @} */\r
+\r
+/**\r
+ * @name Time conversion utilities for the realtime counter\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Seconds to realtime counter.\r
+ * @details Converts from seconds to realtime counter cycles.\r
+ * @note The macro assumes that @p freq >= @p 1.\r
+ *\r
+ * @param[in] freq clock frequency, in Hz, of the realtime counter\r
+ * @param[in] sec number of seconds\r
+ * @return The number of cycles.\r
+ *\r
+ * @api\r
+ */\r
+#define OSAL_S2RTC(freq, sec) ((freq) * (sec))\r
+\r
+/**\r
+ * @brief Milliseconds to realtime counter.\r
+ * @details Converts from milliseconds to realtime counter cycles.\r
+ * @note The result is rounded upward to the next millisecond boundary.\r
+ * @note The macro assumes that @p freq >= @p 1000.\r
+ *\r
+ * @param[in] freq clock frequency, in Hz, of the realtime counter\r
+ * @param[in] msec number of milliseconds\r
+ * @return The number of cycles.\r
+ *\r
+ * @api\r
+ */\r
+#define OSAL_MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))\r
+\r
+/**\r
+ * @brief Microseconds to realtime counter.\r
+ * @details Converts from microseconds to realtime counter cycles.\r
+ * @note The result is rounded upward to the next microsecond boundary.\r
+ * @note The macro assumes that @p freq >= @p 1000000.\r
+ *\r
+ * @param[in] freq clock frequency, in Hz, of the realtime counter\r
+ * @param[in] usec number of microseconds\r
+ * @return The number of cycles.\r
+ *\r
+ * @api\r
+ */\r
+#define OSAL_US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))\r
+/** @} */\r
+\r
+/**\r
+ * @name Sleep macros using absolute time\r
+ * @{\r
+ */\r
+/**\r
+ * @brief Delays the invoking thread for the specified number of seconds.\r
+ * @note The specified time is rounded up to a value allowed by the real\r
+ * system tick clock.\r
+ * @note The maximum specifiable value is implementation dependent.\r
+ *\r
+ * @param[in] secs time in seconds, must be different from zero\r
+ *\r
+ * @api\r
+ */\r
+#define osalThreadSleepSeconds(secs) osalThreadSleep(OSAL_S2I(secs))\r
+\r
+/**\r
+ * @brief Delays the invoking thread for the specified number of\r
+ * milliseconds.\r
+ * @note The specified time is rounded up to a value allowed by the real\r
+ * system tick clock.\r
+ * @note The maximum specifiable value is implementation dependent.\r
+ *\r
+ * @param[in] msecs time in milliseconds, must be different from zero\r
+ *\r
+ * @api\r
+ */\r
+#define osalThreadSleepMilliseconds(msecs) osalThreadSleep(OSAL_MS2I(msecs))\r
+\r
+/**\r
+ * @brief Delays the invoking thread for the specified number of\r
+ * microseconds.\r
+ * @note The specified time is rounded up to a value allowed by the real\r
+ * system tick clock.\r
+ * @note The maximum specifiable value is implementation dependent.\r
+ *\r
+ * @param[in] usecs time in microseconds, must be different from zero\r
+ *\r
+ * @api\r
+ */\r
+#define osalThreadSleepMicroseconds(usecs) osalThreadSleep(OSAL_US2I(usecs))\r
+/** @} */\r
+\r
+/*===========================================================================*/\r
+/* External declarations. */\r
+/*===========================================================================*/\r
+\r
+extern const char *osal_halt_msg;\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+ void osalInit(void);\r
+ void osalSysHalt(const char *reason);\r
+ void osalSysPolledDelayX(rtcnt_t cycles);\r
+ void osalOsTimerHandlerI(void);\r
+ void osalOsRescheduleS(void);\r
+ systime_t osalOsGetSystemTimeX(void);\r
+ void osalThreadSleepS(sysinterval_t time);\r
+ void osalThreadSleep(sysinterval_t time);\r
+ msg_t osalThreadSuspendS(thread_reference_t *trp);\r
+ msg_t osalThreadSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);\r
+ void osalThreadResumeI(thread_reference_t *trp, msg_t msg);\r
+ void osalThreadResumeS(thread_reference_t *trp, msg_t msg);\r
+ msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);\r
+ void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg);\r
+ void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg);\r
+ void osalEventBroadcastFlagsI(event_source_t *esp, eventflags_t flags);\r
+ void osalEventBroadcastFlags(event_source_t *esp, eventflags_t flags);\r
+ void osalEventSetCallback(event_source_t *esp,\r
+ eventcallback_t cb,\r
+ void *param);\r
+ void osalMutexLock(mutex_t *mp);\r
+ void osalMutexUnlock(mutex_t *mp);\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+/*===========================================================================*/\r
+/* Module inline functions. */\r
+/*===========================================================================*/\r
+\r
+/**\r
+ * @brief Disables interrupts globally.\r
+ *\r
+ * @special\r
+ */\r
+static inline void osalSysDisable(void) {\r
+\r
+ __disable_irq();\r
+}\r
+\r
+/**\r
+ * @brief Enables interrupts globally.\r
+ *\r
+ * @special\r
+ */\r
+static inline void osalSysEnable(void) {\r
+\r
+ __enable_irq();\r
+}\r
+\r
+/**\r
+ * @brief Enters a critical zone from thread context.\r
+ * @note This function cannot be used for reentrant critical zones.\r
+ *\r
+ * @special\r
+ */\r
+static inline void osalSysLock(void) {\r
+\r
+#if CORTEX_MODEL == 0\r
+ __disable_irq();\r
+#else\r
+ __set_BASEPRI(OSAL_BASEPRI(OSAL_IRQ_MAXIMUM_PRIORITY));\r
+#endif\r
+}\r
+\r
+/**\r
+ * @brief Leaves a critical zone from thread context.\r
+ * @note This function cannot be used for reentrant critical zones.\r
+ *\r
+ * @special\r
+ */\r
+static inline void osalSysUnlock(void) {\r
+\r
+#if CORTEX_MODEL == 0\r
+ __enable_irq();\r
+#else\r
+ __set_BASEPRI(0);\r
+#endif\r
+}\r
+\r
+/**\r
+ * @brief Enters a critical zone from ISR context.\r
+ * @note This function cannot be used for reentrant critical zones.\r
+ *\r
+ * @special\r
+ */\r
+static inline void osalSysLockFromISR(void) {\r
+\r
+#if CORTEX_MODEL == 0\r
+ __disable_irq();\r
+#else\r
+ __set_BASEPRI(OSAL_BASEPRI(OSAL_IRQ_MAXIMUM_PRIORITY));\r
+#endif\r
+}\r
+\r
+/**\r
+ * @brief Leaves a critical zone from ISR context.\r
+ * @note This function cannot be used for reentrant critical zones.\r
+ *\r
+ * @special\r
+ */\r
+static inline void osalSysUnlockFromISR(void) {\r
+\r
+#if CORTEX_MODEL == 0\r
+ __enable_irq();\r
+#else\r
+ __set_BASEPRI(0);\r
+#endif\r
+}\r
+\r
+/**\r
+ * @brief Returns the execution status and enters a critical zone.\r
+ * @details This functions enters into a critical zone and can be called\r
+ * from any context. Because its flexibility it is less efficient\r
+ * than @p chSysLock() which is preferable when the calling context\r
+ * is known.\r
+ * @post The system is in a critical zone.\r
+ *\r
+ * @return The previous system status, the encoding of this\r
+ * status word is architecture-dependent and opaque.\r
+ *\r
+ * @xclass\r
+ */\r
+static inline syssts_t osalSysGetStatusAndLockX(void) {\r
+ syssts_t sts;\r
+\r
+#if CORTEX_MODEL == 0\r
+ sts = (syssts_t)__get_PRIMASK();\r
+ __disable_irq();\r
+#else\r
+ sts = (syssts_t)__get_BASEPRI();\r
+ __set_BASEPRI(OSAL_BASEPRI(OSAL_IRQ_MAXIMUM_PRIORITY));\r
+#endif\r
+ return sts;\r
+}\r
+\r
+/**\r
+ * @brief Restores the specified execution status and leaves a critical zone.\r
+ * @note A call to @p chSchRescheduleS() is automatically performed\r
+ * if exiting the critical zone and if not in ISR context.\r
+ *\r
+ * @param[in] sts the system status to be restored.\r
+ *\r
+ * @xclass\r
+ */\r
+static inline void osalSysRestoreStatusX(syssts_t sts) {\r
+\r
+#if CORTEX_MODEL == 0\r
+ if ((sts & (syssts_t)1) == (syssts_t)0) {\r
+ __enable_irq();\r
+ }\r
+#else\r
+ __set_BASEPRI(sts);\r
+#endif\r
+}\r
+\r
+/**\r
+ * @brief Adds an interval to a system time returning a system time.\r
+ *\r
+ * @param[in] systime base system time\r
+ * @param[in] interval interval to be added\r
+ * @return The new system time.\r
+ *\r
+ * @xclass\r
+ */\r
+static inline systime_t osalTimeAddX(systime_t systime,\r
+ sysinterval_t interval) {\r
+\r
+ return systime + (systime_t)interval;\r
+}\r
+\r
+/**\r
+ * @brief Subtracts two system times returning an interval.\r
+ *\r
+ * @param[in] start first system time\r
+ * @param[in] end second system time\r
+ * @return The interval representing the time difference.\r
+ *\r
+ * @xclass\r
+ */\r
+static inline sysinterval_t osalTimeDiffX(systime_t start, systime_t end) {\r
+\r
+ return (sysinterval_t)((systime_t)(end - start));\r
+}\r
+\r
+/**\r
+ * @brief Checks if the specified time is within the specified time window.\r
+ * @note When start==end then the function returns always false because the\r
+ * time window has zero size.\r
+ * @note This function can be called from any context.\r
+ *\r
+ * @param[in] time the time to be verified\r
+ * @param[in] start the start of the time window (inclusive)\r
+ * @param[in] end the end of the time window (non inclusive)\r
+ * @retval true current time within the specified time window.\r
+ * @retval false current time not within the specified time window.\r
+ *\r
+ * @xclass\r
+ */\r
+static inline bool osalTimeIsInRangeX(systime_t time,\r
+ systime_t start,\r
+ systime_t end) {\r
+\r
+ return (bool)((systime_t)((systime_t)time - (systime_t)start) <\r
+ (systime_t)((systime_t)end - (systime_t)start));\r
+}\r
+\r
+/**\r
+ * @brief Initializes a threads queue object.\r
+ *\r
+ * @param[out] tqp pointer to the threads queue object\r
+ *\r
+ * @init\r
+ */\r
+static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {\r
+\r
+ osalDbgCheck(tqp != NULL);\r
+}\r
+\r
+/**\r
+ * @brief Initializes an event source object.\r
+ *\r
+ * @param[out] esp pointer to the event source object\r
+ *\r
+ * @init\r
+ */\r
+static inline void osalEventObjectInit(event_source_t *esp) {\r
+\r
+ osalDbgCheck(esp != NULL);\r
+\r
+ esp->flags = (eventflags_t)0;\r
+ esp->cb = NULL;\r
+ esp->param = NULL;\r
+}\r
+\r
+/**\r
+ * @brief Initializes s @p mutex_t object.\r
+ *\r
+ * @param[out] mp pointer to the @p mutex_t object\r
+ *\r
+ * @init\r
+ */\r
+static inline void osalMutexObjectInit(mutex_t *mp) {\r
+\r
+ osalDbgCheck(mp != NULL);\r
+\r
+ *mp = 0;\r
+}\r
+\r
+#endif /* OSAL_H */\r
+\r
+/** @} */\r