From 641f2c372605cf405f0dda8536b45a78e0e5e2e2 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 16 Feb 2016 09:59:21 +0000 Subject: Tree reorganization. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8899 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/ext/readme.txt | 7 +- os/common/oslib/include/chbsem.h | 311 ++++++ os/common/oslib/include/chdynamic.h | 94 ++ os/common/oslib/include/chheap.h | 164 ++++ os/common/oslib/include/chmboxes.h | 207 ++++ os/common/oslib/include/chmemcore.h | 130 +++ os/common/oslib/include/chmempools.h | 168 ++++ os/common/oslib/readme.txt | 3 + os/common/oslib/src/chdynamic.c | 150 +++ os/common/oslib/src/chheap.c | 383 ++++++++ os/common/oslib/src/chmboxes.c | 435 +++++++++ os/common/oslib/src/chmemcore.c | 166 ++++ os/common/oslib/src/chmempools.c | 203 ++++ os/common/ports/ARM/chcore.c | 54 ++ os/common/ports/ARM/chcore.h | 564 +++++++++++ os/common/ports/ARM/chcore_timer.h | 124 +++ os/common/ports/ARM/compilers/GCC/chcoreasm.s | 303 ++++++ os/common/ports/ARM/compilers/GCC/chtypes.h | 98 ++ .../ports/ARM/compilers/GCC/mk/port_generic.mk | 7 + os/common/ports/ARMCMx/chcore.c | 54 ++ os/common/ports/ARMCMx/chcore.h | 215 +++++ os/common/ports/ARMCMx/chcore_timer.h | 124 +++ os/common/ports/ARMCMx/chcore_v6m.c | 147 +++ os/common/ports/ARMCMx/chcore_v6m.h | 440 +++++++++ os/common/ports/ARMCMx/chcore_v7m.c | 168 ++++ os/common/ports/ARMCMx/chcore_v7m.h | 698 ++++++++++++++ os/common/ports/ARMCMx/cmsis_os/cmsis_os.c | 554 +++++++++++ os/common/ports/ARMCMx/cmsis_os/cmsis_os.h | 520 ++++++++++ os/common/ports/ARMCMx/cmsis_os/cmsis_os.mk | 4 + .../ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s | 152 +++ .../ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s | 164 ++++ os/common/ports/ARMCMx/compilers/GCC/chtypes.h | 103 ++ .../ports/ARMCMx/compilers/GCC/mk/port_v6m.mk | 8 + .../ports/ARMCMx/compilers/GCC/mk/port_v7m.mk | 8 + .../ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s | 142 +++ .../ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s | 150 +++ os/common/ports/ARMCMx/compilers/IAR/chtypes.h | 98 ++ .../ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s | 139 +++ .../ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s | 148 +++ os/common/ports/ARMCMx/compilers/RVCT/chtypes.h | 98 ++ os/common/ports/ARMCMx/mpu.h | 208 ++++ os/common/ports/AVR/chcore.c | 156 +++ os/common/ports/AVR/chcore.h | 530 +++++++++++ os/common/ports/AVR/chcore_timer.h | 124 +++ os/common/ports/AVR/compilers/GCC/chtypes.h | 103 ++ os/common/ports/AVR/compilers/GCC/mk/port.mk | 7 + os/common/ports/SIMIA32/chcore.c | 120 +++ os/common/ports/SIMIA32/chcore.h | 382 ++++++++ os/common/ports/SIMIA32/compilers/GCC/chtypes.h | 110 +++ os/common/ports/SIMIA32/compilers/GCC/port.mk | 7 + os/common/ports/e200/chcore.c | 54 ++ os/common/ports/e200/chcore.h | 631 ++++++++++++ os/common/ports/e200/compilers/CW/chcoreasm.s | 124 +++ os/common/ports/e200/compilers/CW/chtypes.h | 93 ++ os/common/ports/e200/compilers/CW/ivor.s | 204 ++++ os/common/ports/e200/compilers/GCC/chcoreasm.s | 114 +++ os/common/ports/e200/compilers/GCC/chtypes.h | 93 ++ os/common/ports/e200/compilers/GCC/ivor.s | 258 +++++ os/common/ports/e200/compilers/GCC/mk/port.mk | 8 + os/common/ports/readme.txt | 3 + os/common/ports/templates/chcore.c | 79 ++ os/common/ports/templates/chcore.h | 452 +++++++++ os/common/ports/templates/chtypes.h | 107 +++ .../ARM/compilers/GCC/mk/startup_lpc214x.mk | 10 +- os/common/startup/ARM/compilers/GCC/rules.ld | 1 + .../ARMCMx/compilers/GCC/mk/startup_k20x.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_kl2x.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk | 16 +- .../ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk | 16 +- .../e200/compilers/GCC/mk/startup_spc560bcxx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc560bxx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc560dxx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc560pxx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc563mxx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc564axx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc56ecxx.mk | 12 +- .../e200/compilers/GCC/mk/startup_spc56elxx.mk | 12 +- os/nil/include/ch.h | 1003 ++++++++++++++++++++ os/nil/include/nil.h | 1003 -------------------- os/nil/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk | 8 - os/nil/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk | 8 - os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s | 124 --- os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v7m.s | 130 --- os/nil/ports/ARMCMx/compilers/GCC/niltypes.h | 96 -- os/nil/ports/ARMCMx/nilcore.c | 54 -- os/nil/ports/ARMCMx/nilcore.h | 204 ---- os/nil/ports/ARMCMx/nilcore_timer.h | 124 --- os/nil/ports/ARMCMx/nilcore_v6m.c | 147 --- os/nil/ports/ARMCMx/nilcore_v6m.h | 406 -------- os/nil/ports/ARMCMx/nilcore_v7m.c | 165 ---- os/nil/ports/ARMCMx/nilcore_v7m.h | 576 ----------- os/nil/ports/AVR/compilers/GCC/mk/port.mk | 7 - os/nil/ports/AVR/compilers/GCC/niltypes.h | 96 -- os/nil/ports/AVR/nilcore.c | 137 --- os/nil/ports/AVR/nilcore.h | 418 -------- os/nil/ports/AVR/nilcore_timer.h | 124 --- os/nil/ports/e200/compilers/GCC/ivor.s | 234 ----- .../ports/e200/compilers/GCC/mk/port_spc560bcxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc560bxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc560dxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc560pxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc563mxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc564axx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc56ecxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc56elxx.mk | 14 - .../ports/e200/compilers/GCC/mk/port_spc57emxx.mk | 14 - os/nil/ports/e200/compilers/GCC/niltypes.h | 96 -- os/nil/ports/e200/nilcore.c | 107 --- os/nil/ports/e200/nilcore.h | 555 ----------- os/nil/src/ch.c | 840 ++++++++++++++++ os/nil/src/nil.c | 840 ---------------- os/nil/templates/chconf.h | 274 ++++++ os/nil/templates/nilconf.h | 179 ---- os/nil/templates/nilcore.c | 54 -- os/nil/templates/nilcore.h | 379 -------- os/nil/templates/nilcore_timer.h | 120 --- os/nil/templates/niltypes.h | 96 -- 124 files changed, 13928 insertions(+), 6757 deletions(-) create mode 100644 os/common/oslib/include/chbsem.h create mode 100644 os/common/oslib/include/chdynamic.h create mode 100644 os/common/oslib/include/chheap.h create mode 100644 os/common/oslib/include/chmboxes.h create mode 100644 os/common/oslib/include/chmemcore.h create mode 100644 os/common/oslib/include/chmempools.h create mode 100644 os/common/oslib/readme.txt create mode 100644 os/common/oslib/src/chdynamic.c create mode 100644 os/common/oslib/src/chheap.c create mode 100644 os/common/oslib/src/chmboxes.c create mode 100644 os/common/oslib/src/chmemcore.c create mode 100644 os/common/oslib/src/chmempools.c create mode 100644 os/common/ports/ARM/chcore.c create mode 100644 os/common/ports/ARM/chcore.h create mode 100644 os/common/ports/ARM/chcore_timer.h create mode 100644 os/common/ports/ARM/compilers/GCC/chcoreasm.s create mode 100644 os/common/ports/ARM/compilers/GCC/chtypes.h create mode 100644 os/common/ports/ARM/compilers/GCC/mk/port_generic.mk create mode 100644 os/common/ports/ARMCMx/chcore.c create mode 100644 os/common/ports/ARMCMx/chcore.h create mode 100644 os/common/ports/ARMCMx/chcore_timer.h create mode 100644 os/common/ports/ARMCMx/chcore_v6m.c create mode 100644 os/common/ports/ARMCMx/chcore_v6m.h create mode 100644 os/common/ports/ARMCMx/chcore_v7m.c create mode 100644 os/common/ports/ARMCMx/chcore_v7m.h create mode 100644 os/common/ports/ARMCMx/cmsis_os/cmsis_os.c create mode 100644 os/common/ports/ARMCMx/cmsis_os/cmsis_os.h create mode 100644 os/common/ports/ARMCMx/cmsis_os/cmsis_os.mk create mode 100644 os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s create mode 100644 os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s create mode 100644 os/common/ports/ARMCMx/compilers/GCC/chtypes.h create mode 100644 os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk create mode 100644 os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk create mode 100644 os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s create mode 100644 os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s create mode 100644 os/common/ports/ARMCMx/compilers/IAR/chtypes.h create mode 100644 os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s create mode 100644 os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s create mode 100644 os/common/ports/ARMCMx/compilers/RVCT/chtypes.h create mode 100644 os/common/ports/ARMCMx/mpu.h create mode 100644 os/common/ports/AVR/chcore.c create mode 100644 os/common/ports/AVR/chcore.h create mode 100644 os/common/ports/AVR/chcore_timer.h create mode 100644 os/common/ports/AVR/compilers/GCC/chtypes.h create mode 100644 os/common/ports/AVR/compilers/GCC/mk/port.mk create mode 100644 os/common/ports/SIMIA32/chcore.c create mode 100644 os/common/ports/SIMIA32/chcore.h create mode 100644 os/common/ports/SIMIA32/compilers/GCC/chtypes.h create mode 100644 os/common/ports/SIMIA32/compilers/GCC/port.mk create mode 100644 os/common/ports/e200/chcore.c create mode 100644 os/common/ports/e200/chcore.h create mode 100644 os/common/ports/e200/compilers/CW/chcoreasm.s create mode 100644 os/common/ports/e200/compilers/CW/chtypes.h create mode 100644 os/common/ports/e200/compilers/CW/ivor.s create mode 100644 os/common/ports/e200/compilers/GCC/chcoreasm.s create mode 100644 os/common/ports/e200/compilers/GCC/chtypes.h create mode 100644 os/common/ports/e200/compilers/GCC/ivor.s create mode 100644 os/common/ports/e200/compilers/GCC/mk/port.mk create mode 100644 os/common/ports/readme.txt create mode 100644 os/common/ports/templates/chcore.c create mode 100644 os/common/ports/templates/chcore.h create mode 100644 os/common/ports/templates/chtypes.h create mode 100644 os/nil/include/ch.h delete mode 100644 os/nil/include/nil.h delete mode 100644 os/nil/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk delete mode 100644 os/nil/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk delete mode 100644 os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s delete mode 100644 os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v7m.s delete mode 100644 os/nil/ports/ARMCMx/compilers/GCC/niltypes.h delete mode 100644 os/nil/ports/ARMCMx/nilcore.c delete mode 100644 os/nil/ports/ARMCMx/nilcore.h delete mode 100644 os/nil/ports/ARMCMx/nilcore_timer.h delete mode 100644 os/nil/ports/ARMCMx/nilcore_v6m.c delete mode 100644 os/nil/ports/ARMCMx/nilcore_v6m.h delete mode 100644 os/nil/ports/ARMCMx/nilcore_v7m.c delete mode 100644 os/nil/ports/ARMCMx/nilcore_v7m.h delete mode 100644 os/nil/ports/AVR/compilers/GCC/mk/port.mk delete mode 100644 os/nil/ports/AVR/compilers/GCC/niltypes.h delete mode 100644 os/nil/ports/AVR/nilcore.c delete mode 100644 os/nil/ports/AVR/nilcore.h delete mode 100644 os/nil/ports/AVR/nilcore_timer.h delete mode 100644 os/nil/ports/e200/compilers/GCC/ivor.s delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc560bcxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc560bxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc560dxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc560pxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc563mxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc564axx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc56ecxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc56elxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/mk/port_spc57emxx.mk delete mode 100644 os/nil/ports/e200/compilers/GCC/niltypes.h delete mode 100644 os/nil/ports/e200/nilcore.c delete mode 100644 os/nil/ports/e200/nilcore.h create mode 100644 os/nil/src/ch.c delete mode 100644 os/nil/src/nil.c create mode 100644 os/nil/templates/chconf.h delete mode 100644 os/nil/templates/nilconf.h delete mode 100644 os/nil/templates/nilcore.c delete mode 100644 os/nil/templates/nilcore.h delete mode 100644 os/nil/templates/nilcore_timer.h delete mode 100644 os/nil/templates/niltypes.h diff --git a/os/common/ext/readme.txt b/os/common/ext/readme.txt index 24c7070ee..38d5d4423 100644 --- a/os/common/ext/readme.txt +++ b/os/common/ext/readme.txt @@ -1,6 +1,7 @@ -All the code contained under ./os/ext is not part of the ChibiOS project and -supplied as-is without any additional warranty by ChibiOS. For ownership and -copyright statements see the license details inside the code. +All the code contained under ./os/common/ext is not part of the ChibiOS +project and supplied as-is without any additional warranty by ChibiOS. +For ownership and copyright statements see the license details inside the +code. Some modules may contain changes from the ChibiOS team in order to increase compatibility or usability with ChibiOS itself. diff --git a/os/common/oslib/include/chbsem.h b/os/common/oslib/include/chbsem.h new file mode 100644 index 000000000..ac2b37e9c --- /dev/null +++ b/os/common/oslib/include/chbsem.h @@ -0,0 +1,311 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chbsem.h + * @brief Binary semaphores structures and macros. + * + * @addtogroup binary_semaphores + * @details Binary semaphores related APIs and services. + *

Operation mode

+ * Binary semaphores are implemented as a set of inline functions + * that use the existing counting semaphores primitives. The + * difference between counting and binary semaphores is that the + * counter of binary semaphores is not allowed to grow above the + * value 1. Repeated signal operation are ignored. A binary + * semaphore can thus have only two defined states: + * - Taken, when its counter has a value of zero or lower + * than zero. A negative number represent the number of threads + * queued on the binary semaphore. + * - Not taken, when its counter has a value of one. + * . + * Binary semaphores are different from mutexes because there is no + * concept of ownership, a binary semaphore can be taken by a + * thread and signaled by another thread or an interrupt handler, + * mutexes can only be taken and released by the same thread. Another + * difference is that binary semaphores, unlike mutexes, do not + * implement the priority inheritance protocol.
+ * In order to use the binary semaphores APIs the + * @p CH_CFG_USE_SEMAPHORES option must be enabled in @p chconf.h. + * @{ + */ + +#ifndef _CHBSEM_H_ +#define _CHBSEM_H_ + +#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @extends semaphore_t + * + * @brief Binary semaphore type. + */ +typedef struct { + semaphore_t sem; +} binary_semaphore_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static semaphore initializer. + * @details This macro should be used when statically initializing a semaphore + * that is part of a bigger structure. + * + * @param[in] name the name of the semaphore variable + * @param[in] taken the semaphore initial state + */ +#define _BSEMAPHORE_DATA(name, taken) \ + {_SEMAPHORE_DATA(name.sem, ((taken) ? 0 : 1))} + +/** + * @brief Static semaphore initializer. + * @details Statically initialized semaphores require no explicit + * initialization using @p chBSemInit(). + * + * @param[in] name the name of the semaphore variable + * @param[in] taken the semaphore initial state + */ +#define BSEMAPHORE_DECL(name, taken) \ + binary_semaphore_t name = _BSEMAPHORE_DATA(name, taken) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a binary semaphore. + * + * @param[out] bsp pointer to a @p binary_semaphore_t structure + * @param[in] taken initial state of the binary semaphore: + * - @a false, the initial state is not taken. + * - @a true, the initial state is taken. + * . + * + * @init + */ +static inline void chBSemObjectInit(binary_semaphore_t *bsp, bool taken) { + + chSemObjectInit(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * + * @api + */ +static inline msg_t chBSemWait(binary_semaphore_t *bsp) { + + return chSemWait(&bsp->sem); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * + * @sclass + */ +static inline msg_t chBSemWaitS(binary_semaphore_t *bsp) { + + chDbgCheckClassS(); + + return chSemWaitS(&bsp->sem); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset + * within the specified timeout. + * + * @sclass + */ +static inline msg_t chBSemWaitTimeoutS(binary_semaphore_t *bsp, + systime_t time) { + + chDbgCheckClassS(); + + return chSemWaitTimeoutS(&bsp->sem, time); +} + +/** + * @brief Wait operation on the binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval MSG_OK if the binary semaphore has been successfully taken. + * @retval MSG_RESET if the binary semaphore has been reset using + * @p bsemReset(). + * @retval MSG_TIMEOUT if the binary semaphore has not been signaled or reset + * within the specified timeout. + * + * @api + */ +static inline msg_t chBSemWaitTimeout(binary_semaphore_t *bsp, + systime_t time) { + + return chSemWaitTimeout(&bsp->sem, time); +} + +/** + * @brief Reset operation on the binary semaphore. + * @note The released threads can recognize they were waked up by a reset + * rather than a signal because the @p bsemWait() will return + * @p MSG_RESET instead of @p MSG_OK. + * @note This function does not reschedule. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @param[in] taken new state of the binary semaphore + * - @a false, the new state is not taken. + * - @a true, the new state is taken. + * . + * + * @iclass + */ +static inline void chBSemResetI(binary_semaphore_t *bsp, bool taken) { + + chDbgCheckClassI(); + + chSemResetI(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); +} + +/** + * @brief Reset operation on the binary semaphore. + * @note The released threads can recognize they were waked up by a reset + * rather than a signal because the @p bsemWait() will return + * @p MSG_RESET instead of @p MSG_OK. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @param[in] taken new state of the binary semaphore + * - @a false, the new state is not taken. + * - @a true, the new state is taken. + * . + * + * @api + */ +static inline void chBSemReset(binary_semaphore_t *bsp, bool taken) { + + chSemReset(&bsp->sem, taken ? (cnt_t)0 : (cnt_t)1); +} + +/** + * @brief Performs a signal operation on a binary semaphore. + * @note This function does not reschedule. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * + * @iclass + */ +static inline void chBSemSignalI(binary_semaphore_t *bsp) { + + chDbgCheckClassI(); + + if (bsp->sem.cnt < (cnt_t)1) { + chSemSignalI(&bsp->sem); + } +} + +/** + * @brief Performs a signal operation on a binary semaphore. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * + * @api + */ +static inline void chBSemSignal(binary_semaphore_t *bsp) { + + chSysLock(); + chBSemSignalI(bsp); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Returns the binary semaphore current state. + * + * @param[in] bsp pointer to a @p binary_semaphore_t structure + * @return The binary semaphore current state. + * @retval false if the binary semaphore is not taken. + * @retval true if the binary semaphore is taken. + * + * @iclass + */ +static inline bool chBSemGetStateI(binary_semaphore_t *bsp) { + + chDbgCheckClassI(); + + return (bsp->sem.cnt > (cnt_t)0) ? false : true; +} + +#endif /* CH_CFG_USE_SEMAPHORES == TRUE */ + +#endif /* _CHBSEM_H_ */ + +/** @} */ diff --git a/os/common/oslib/include/chdynamic.h b/os/common/oslib/include/chdynamic.h new file mode 100644 index 000000000..fa00bd83e --- /dev/null +++ b/os/common/oslib/include/chdynamic.h @@ -0,0 +1,94 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chdynamic.h + * @brief Dynamic threads macros and structures. + * + * @addtogroup dynamic_threads + * @{ + */ + +#ifndef _CHDYNAMIC_H_ +#define _CHDYNAMIC_H_ + +#if (CH_CFG_USE_DYNAMIC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* + * Module dependencies check. + */ +#if CH_CFG_USE_WAITEXIT == FALSE +#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_WAITEXIT" +#endif + +#if (CH_CFG_USE_HEAP == FALSE) && (CH_CFG_USE_MEMPOOLS == FALSE) +#error "CH_CFG_USE_DYNAMIC requires CH_CFG_USE_HEAP and/or CH_CFG_USE_MEMPOOLS" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* + * Dynamic threads APIs. + */ +#ifdef __cplusplus +extern "C" { +#endif +#if CH_CFG_USE_HEAP == TRUE + thread_t *chThdCreateFromHeap(memory_heap_t *heapp, size_t size, + tprio_t prio, tfunc_t pf, void *arg); +#endif +#if CH_CFG_USE_MEMPOOLS == TRUE + thread_t *chThdCreateFromMemoryPool(memory_pool_t *mp, tprio_t prio, + tfunc_t pf, void *arg); +#endif +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +#endif /* CH_CFG_USE_DYNAMIC == TRUE */ + +#endif /* _CHDYNAMIC_H_ */ + +/** @} */ diff --git a/os/common/oslib/include/chheap.h b/os/common/oslib/include/chheap.h new file mode 100644 index 000000000..25b1c1ade --- /dev/null +++ b/os/common/oslib/include/chheap.h @@ -0,0 +1,164 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chheap.h + * @brief Heaps macros and structures. + * + * @addtogroup heaps + * @{ + */ + +#ifndef _CHHEAP_H_ +#define _CHHEAP_H_ + +#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief Minimum alignment used for heap. + */ +#define CH_HEAP_ALIGNMENT sizeof (heap_header_t) + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_USE_MEMCORE == FALSE +#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MEMCORE" +#endif + +#if (CH_CFG_USE_MUTEXES == FALSE) && (CH_CFG_USE_SEMAPHORES == FALSE) +#error "CH_CFG_USE_HEAP requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of a memory heap. + */ +typedef struct memory_heap memory_heap_t; + +/** + * @brief Type of a memory heap header. + */ +typedef union heap_header heap_header_t; + +/** + * @brief Memory heap block header. + */ +union heap_header { + stkalign_t align; + struct { + heap_header_t *next; /**< @brief Next block in free list. */ + size_t pages; /**< @brief Size of the area in pages. */ + } free; + struct { + memory_heap_t *heap; /**< @brief Block owner heap. */ + size_t size; /**< @brief Size of the area in bytes. */ + } used; +}; + +/** + * @brief Structure describing a memory heap. + */ +struct memory_heap { + memgetfunc_t provider; /**< @brief Memory blocks provider for + this heap. */ + heap_header_t header; /**< @brief Free blocks list header. */ +#if CH_CFG_USE_MUTEXES == TRUE + mutex_t mtx; /**< @brief Heap access mutex. */ +#else + semaphore_t sem; /**< @brief Heap access semaphore. */ +#endif +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void _heap_init(void); + void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size); + void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align); + void chHeapFree(void *p); + size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Allocates a block of memory from the heap by using the first-fit + * algorithm. + * @details The allocated block is guaranteed to be properly aligned for a + * pointer data type. + * + * @param[in] heapp pointer to a heap descriptor or @p NULL in order to + * access the default heap. + * @param[in] size the size of the block to be allocated. Note that the + * allocated block may be a bit bigger than the requested + * size for alignment and fragmentation reasons. + * @return A pointer to the allocated block. + * @retval NULL if the block cannot be allocated. + * + * @api + */ +static inline void *chHeapAlloc(memory_heap_t *heapp, size_t size) { + + return chHeapAllocAligned(heapp, size, CH_HEAP_ALIGNMENT); +} + +/** + * @brief Returns the size of an allocated block. + * @note The returned value is the requested size, the real size is the + * same value aligned to the next @p CH_HEAP_ALIGNMENT multiple. + * + * @param[in] p pointer to the memory block + * + * @api + */ +static inline size_t chHeapGetSize(const void *p) { + + return ((heap_header_t *)p)->used.size; +} + +#endif /* CH_CFG_USE_HEAP == TRUE */ + +#endif /* _CHHEAP_H_ */ + +/** @} */ diff --git a/os/common/oslib/include/chmboxes.h b/os/common/oslib/include/chmboxes.h new file mode 100644 index 000000000..44d6f9904 --- /dev/null +++ b/os/common/oslib/include/chmboxes.h @@ -0,0 +1,207 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmboxes.h + * @brief Mailboxes macros and structures. + * + * @addtogroup mailboxes + * @{ + */ + +#ifndef _CHMBOXES_H_ +#define _CHMBOXES_H_ + +#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_USE_SEMAPHORES == FALSE +#error "CH_CFG_USE_MAILBOXES requires CH_CFG_USE_SEMAPHORES" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Structure representing a mailbox object. + */ +typedef struct { + msg_t *buffer; /**< @brief Pointer to the mailbox + buffer. */ + msg_t *top; /**< @brief Pointer to the location + after the buffer. */ + msg_t *wrptr; /**< @brief Write pointer. */ + msg_t *rdptr; /**< @brief Read pointer. */ + semaphore_t fullsem; /**< @brief Full counter + @p semaphore_t. */ + semaphore_t emptysem; /**< @brief Empty counter + @p semaphore_t. */ +} mailbox_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static mailbox initializer. + * @details This macro should be used when statically initializing a + * mailbox that is part of a bigger structure. + * + * @param[in] name the name of the mailbox variable + * @param[in] buffer pointer to the mailbox buffer area + * @param[in] size size of the mailbox buffer area + */ +#define _MAILBOX_DATA(name, buffer, size) { \ + (msg_t *)(buffer), \ + (msg_t *)(buffer) + size, \ + (msg_t *)(buffer), \ + (msg_t *)(buffer), \ + _SEMAPHORE_DATA(name.fullsem, 0), \ + _SEMAPHORE_DATA(name.emptysem, size), \ +} + +/** + * @brief Static mailbox initializer. + * @details Statically initialized mailboxes require no explicit + * initialization using @p chMBInit(). + * + * @param[in] name the name of the mailbox variable + * @param[in] buffer pointer to the mailbox buffer area + * @param[in] size size of the mailbox buffer area + */ +#define MAILBOX_DECL(name, buffer, size) \ + mailbox_t name = _MAILBOX_DATA(name, buffer, size) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void chMBObjectInit(mailbox_t *mbp, msg_t *buf, cnt_t n); + void chMBReset(mailbox_t *mbp); + void chMBResetI(mailbox_t *mbp); + msg_t chMBPost(mailbox_t *mbp, msg_t msg, systime_t timeout); + msg_t chMBPostS(mailbox_t *mbp, msg_t msg, systime_t timeout); + msg_t chMBPostI(mailbox_t *mbp, msg_t msg); + msg_t chMBPostAhead(mailbox_t *mbp, msg_t msg, systime_t timeout); + msg_t chMBPostAheadS(mailbox_t *mbp, msg_t msg, systime_t timeout); + msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg); + msg_t chMBFetch(mailbox_t *mbp, msg_t *msgp, systime_t timeout); + msg_t chMBFetchS(mailbox_t *mbp, msg_t *msgp, systime_t timeout); + msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Returns the mailbox buffer size. + * + * @param[in] mbp the pointer to an initialized mailbox_t object + * @return The size of the mailbox. + * + * @iclass + */ +static inline size_t chMBGetSizeI(mailbox_t *mbp) { + + /*lint -save -e9033 [10.8] Perfectly safe pointers + arithmetic.*/ + return (size_t)(mbp->top - mbp->buffer); + /*lint -restore*/ +} + +/** + * @brief Returns the number of free message slots into a mailbox. + * @note Can be invoked in any system state but if invoked out of a locked + * state then the returned value may change after reading. + * @note The returned value can be less than zero when there are waiting + * threads on the internal semaphore. + * + * @param[in] mbp the pointer to an initialized mailbox_t object + * @return The number of empty message slots. + * + * @iclass + */ +static inline cnt_t chMBGetFreeCountI(mailbox_t *mbp) { + + chDbgCheckClassI(); + + return chSemGetCounterI(&mbp->emptysem); +} + +/** + * @brief Returns the number of used message slots into a mailbox. + * @note Can be invoked in any system state but if invoked out of a locked + * state then the returned value may change after reading. + * @note The returned value can be less than zero when there are waiting + * threads on the internal semaphore. + * + * @param[in] mbp the pointer to an initialized mailbox_t object + * @return The number of queued messages. + * + * @iclass + */ +static inline cnt_t chMBGetUsedCountI(mailbox_t *mbp) { + + chDbgCheckClassI(); + + return chSemGetCounterI(&mbp->fullsem); +} + +/** + * @brief Returns the next message in the queue without removing it. + * @pre A message must be waiting in the queue for this function to work + * or it would return garbage. The correct way to use this macro is + * to use @p chMBGetFullCountI() and then use this macro, all within + * a lock state. + * + * @param[in] mbp the pointer to an initialized mailbox_t object + * @return The next message in queue. + * + * @iclass + */ +static inline msg_t chMBPeekI(mailbox_t *mbp) { + + chDbgCheckClassI(); + + return *mbp->rdptr; +} + +#endif /* CH_CFG_USE_MAILBOXES == TRUE */ + +#endif /* _CHMBOXES_H_ */ + +/** @} */ diff --git a/os/common/oslib/include/chmemcore.h b/os/common/oslib/include/chmemcore.h new file mode 100644 index 000000000..f877f0607 --- /dev/null +++ b/os/common/oslib/include/chmemcore.h @@ -0,0 +1,130 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmemcore.h + * @brief Core memory manager macros and structures. + * + * @addtogroup memcore + * @{ + */ + +#ifndef _CHMEMCORE_H_ +#define _CHMEMCORE_H_ + +#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_MEMCORE_SIZE < 0 +#error "invalid CH_CFG_MEMCORE_SIZE value specified" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Memory get function. + */ +typedef void *(*memgetfunc_t)(size_t size, unsigned align); + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void _core_init(void); + void *chCoreAllocAlignedI(size_t size, unsigned align); + void *chCoreAllocAligned(size_t size, unsigned align); + size_t chCoreGetStatusX(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned for a + * pointer data type. + * + * @param[in] size the size of the block to be allocated. + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @iclass + */ +static inline void *chCoreAllocI(size_t size) { + + return chCoreAllocAlignedI(size, PORT_NATURAL_ALIGN); +} + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned for a + * pointer data type. + * + * @param[in] size the size of the block to be allocated. + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @api + */ +static inline void *chCoreAlloc(size_t size) { + + return chCoreAllocAligned(size, PORT_NATURAL_ALIGN); +} + +#endif /* CH_CFG_USE_MEMCORE == TRUE */ + +#endif /* _CHMEMCORE_H_ */ + +/** @} */ diff --git a/os/common/oslib/include/chmempools.h b/os/common/oslib/include/chmempools.h new file mode 100644 index 000000000..2d582f48a --- /dev/null +++ b/os/common/oslib/include/chmempools.h @@ -0,0 +1,168 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmempools.h + * @brief Memory Pools macros and structures. + * + * @addtogroup pools + * @{ + */ + +#ifndef _CHMEMPOOLS_H_ +#define _CHMEMPOOLS_H_ + +#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_CFG_USE_MEMCORE == FALSE +#error "CH_CFG_USE_MEMPOOLS requires CH_CFG_USE_MEMCORE" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Memory pool free object header. + */ +struct pool_header { + struct pool_header *next; /**< @brief Pointer to the next pool + header in the list. */ +}; + +/** + * @brief Memory pool descriptor. + */ +typedef struct { + struct pool_header *next; /**< @brief Pointer to the header. */ + size_t object_size; /**< @brief Memory pool objects + size. */ + memgetfunc_t provider; /**< @brief Memory blocks provider + for this pool. */ +} memory_pool_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Data part of a static memory pool initializer. + * @details This macro should be used when statically initializing a + * memory pool that is part of a bigger structure. + * + * @param[in] name the name of the memory pool variable + * @param[in] size size of the memory pool contained objects + * @param[in] provider memory provider function for the memory pool + */ +#define _MEMORYPOOL_DATA(name, size, provider) \ + {NULL, size, provider} + +/** + * @brief Static memory pool initializer in hungry mode. + * @details Statically initialized memory pools require no explicit + * initialization using @p chPoolInit(). + * + * @param[in] name the name of the memory pool variable + * @param[in] size size of the memory pool contained objects + * @param[in] provider memory provider function for the memory pool or @p NULL + * if the pool is not allowed to grow automatically + */ +#define MEMORYPOOL_DECL(name, size, provider) \ + memory_pool_t name = _MEMORYPOOL_DATA(name, size, provider) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void chPoolObjectInit(memory_pool_t *mp, size_t size, memgetfunc_t provider); + void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n); + void *chPoolAllocI(memory_pool_t *mp); + void *chPoolAlloc(memory_pool_t *mp); + void chPoolFreeI(memory_pool_t *mp, void *objp); + void chPoolFree(memory_pool_t *mp, void *objp); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Adds an object to a memory pool. + * @pre The memory pool must be already been initialized. + * @pre The added object must be of the right size for the specified + * memory pool. + * @pre The added object must be memory aligned to the size of + * @p stkalign_t type. + * @note This function is just an alias for @p chPoolFree() and has been + * added for clarity. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] objp the pointer to the object to be added + * + * @api + */ +static inline void chPoolAdd(memory_pool_t *mp, void *objp) { + + chPoolFree(mp, objp); +} + +/** + * @brief Adds an object to a memory pool. + * @pre The memory pool must be already been initialized. + * @pre The added object must be of the right size for the specified + * memory pool. + * @pre The added object must be memory aligned to the size of + * @p stkalign_t type. + * @note This function is just an alias for @p chPoolFree() and has been + * added for clarity. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] objp the pointer to the object to be added + * + * @iclass + */ +static inline void chPoolAddI(memory_pool_t *mp, void *objp) { + + chDbgCheckClassI(); + + chPoolFreeI(mp, objp); +} + +#endif /* CH_CFG_USE_MEMPOOLS == TRUE */ + +#endif /* _CHMEMPOOLS_H_ */ + +/** @} */ diff --git a/os/common/oslib/readme.txt b/os/common/oslib/readme.txt new file mode 100644 index 000000000..e1c274da4 --- /dev/null +++ b/os/common/oslib/readme.txt @@ -0,0 +1,3 @@ +All the code contained under ./os/common/oslib are optional RTOS modules +compatible with both RT and NIL. The code is placed under ./os/common in +order to prevent code duplication and disalignments. diff --git a/os/common/oslib/src/chdynamic.c b/os/common/oslib/src/chdynamic.c new file mode 100644 index 000000000..7d8b609be --- /dev/null +++ b/os/common/oslib/src/chdynamic.c @@ -0,0 +1,150 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chdynamic.c + * @brief Dynamic threads code. + * + * @addtogroup dynamic_threads + * @details Dynamic threads related APIs and services. + * @note Compatible with RT only. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_DYNAMIC == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Creates a new thread allocating the memory from the heap. + * @pre The configuration options @p CH_CFG_USE_DYNAMIC and + * @p CH_CFG_USE_HEAP must be enabled in order to use this function. + * @note A thread can terminate by calling @p chThdExit() or by simply + * returning from its main function. + * @note The memory allocated for the thread is not released automatically, + * it is responsibility of the creator thread to call @p chThdWait() + * and then release the allocated memory. + * + * @param[in] heapp heap from which allocate the memory or @p NULL for the + * default heap + * @param[in] size size of the working area to be allocated + * @param[in] prio the priority level for the new thread + * @param[in] pf the thread function + * @param[in] arg an argument passed to the thread function. It can be + * @p NULL. + * @return The pointer to the @p thread_t structure allocated for + * the thread into the working space area. + * @retval NULL if the memory cannot be allocated. + * + * @api + */ +thread_t *chThdCreateFromHeap(memory_heap_t *heapp, size_t size, + tprio_t prio, tfunc_t pf, void *arg) { + void *wsp; + + wsp = chHeapAllocAligned(heapp, size, PORT_WORKING_AREA_ALIGN); + if (wsp == NULL) { + return NULL; + } + +#if CH_DBG_FILL_THREADS == TRUE + _thread_memfill((uint8_t *)wsp, + (uint8_t *)wsp + size, + CH_DBG_STACK_FILL_VALUE); +#endif + + return chThdCreateStatic(wsp, size, prio, pf, arg); +} +#endif /* CH_CFG_USE_HEAP == TRUE */ + +#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Creates a new thread allocating the memory from the specified + * memory pool. + * @pre The configuration options @p CH_CFG_USE_DYNAMIC and + * @p CH_CFG_USE_MEMPOOLS must be enabled in order to use this + * function. + * @pre The pool must be initialized to contain only objects with + * alignment @p PORT_WORKING_AREA_ALIGN. + * @note A thread can terminate by calling @p chThdExit() or by simply + * returning from its main function. + * @note The memory allocated for the thread is not released automatically, + * it is responsibility of the creator thread to call @p chThdWait() + * and then release the allocated memory. + * + * @param[in] mp pointer to the memory pool object + * @param[in] prio the priority level for the new thread + * @param[in] pf the thread function + * @param[in] arg an argument passed to the thread function. It can be + * @p NULL. + * @return The pointer to the @p thread_t structure allocated for + * the thread into the working space area. + * @retval NULL if the memory pool is empty. + * + * @api + */ +thread_t *chThdCreateFromMemoryPool(memory_pool_t *mp, tprio_t prio, + tfunc_t pf, void *arg) { + void *wsp; + + chDbgCheck(mp != NULL); + + wsp = chPoolAlloc(mp); + if (wsp == NULL) { + return NULL; + } + +#if CH_DBG_FILL_THREADS == TRUE + _thread_memfill((uint8_t *)wsp, + (uint8_t *)wsp + mp->object_size, + CH_DBG_STACK_FILL_VALUE); +#endif + + return chThdCreateStatic(wsp, mp->object_size, prio, pf, arg); +} +#endif /* CH_CFG_USE_MEMPOOLS == TRUE */ + +#endif /* CH_CFG_USE_DYNAMIC == TRUE */ + +/** @} */ diff --git a/os/common/oslib/src/chheap.c b/os/common/oslib/src/chheap.c new file mode 100644 index 000000000..a35b646ba --- /dev/null +++ b/os/common/oslib/src/chheap.c @@ -0,0 +1,383 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chheap.c + * @brief Heaps code. + * + * @addtogroup heaps + * @details Heap Allocator related APIs. + *

Operation mode

+ * The heap allocator implements a first-fit strategy and its APIs + * are functionally equivalent to the usual @p malloc() and @p free() + * library functions. The main difference is that the OS heap APIs + * are guaranteed to be thread safe and there is the ability to + * return memory blocks aligned to arbitrary powers of two.
+ * @pre In order to use the heap APIs the @p CH_CFG_USE_HEAP option must + * be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_HEAP == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/* + * Defaults on the best synchronization mechanism available. + */ +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) +#define H_LOCK(h) chMtxLock(&(h)->mtx) +#define H_UNLOCK(h) chMtxUnlock(&(h)->mtx) +#else +#define H_LOCK(h) (void) chSemWait(&(h)->sem) +#define H_UNLOCK(h) chSemSignal(&(h)->sem) +#endif + +#define H_BLOCK(hp) ((hp) + 1U) + +#define H_LIMIT(hp) (H_BLOCK(hp) + H_PAGES(hp)) + +#define H_NEXT(hp) ((hp)->free.next) + +#define H_PAGES(hp) ((hp)->free.pages) + +#define H_HEAP(hp) ((hp)->used.heap) + +#define H_SIZE(hp) ((hp)->used.size) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/** + * @brief Default heap descriptor. + */ +static memory_heap_t default_heap; + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the default heap. + * + * @notapi + */ +void _heap_init(void) { + + default_heap.provider = chCoreAllocAligned; + H_NEXT(&default_heap.header) = NULL; + H_PAGES(&default_heap.header) = 0; +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + chMtxObjectInit(&default_heap.mtx); +#else + chSemObjectInit(&default_heap.sem, (cnt_t)1); +#endif +} + +/** + * @brief Initializes a memory heap from a static memory area. + * @pre Both the heap buffer base and the heap size must be aligned to + * the @p heap_header_t type size. + * + * @param[out] heapp pointer to the memory heap descriptor to be initialized + * @param[in] buf heap buffer base + * @param[in] size heap size + * + * @init + */ +void chHeapObjectInit(memory_heap_t *heapp, void *buf, size_t size) { + heap_header_t *hp = buf; + + chDbgCheck((heapp != NULL) && (size > 0U) && + MEM_IS_ALIGNED(buf, CH_HEAP_ALIGNMENT) && + MEM_IS_ALIGNED(size, CH_HEAP_ALIGNMENT)); + + heapp->provider = NULL; + H_NEXT(&heapp->header) = hp; + H_PAGES(&heapp->header) = 0; + H_NEXT(hp) = NULL; + H_PAGES(hp) = (size - sizeof (heap_header_t)) / CH_HEAP_ALIGNMENT; +#if (CH_CFG_USE_MUTEXES == TRUE) || defined(__DOXYGEN__) + chMtxObjectInit(&heapp->mtx); +#else + chSemObjectInit(&heapp->sem, (cnt_t)1); +#endif +} + +/** + * @brief Allocates a block of memory from the heap by using the first-fit + * algorithm. + * @details The allocated block is guaranteed to be properly aligned to the + * specified alignment. + * + * @param[in] heapp pointer to a heap descriptor or @p NULL in order to + * access the default heap. + * @param[in] size the size of the block to be allocated. Note that the + * allocated block may be a bit bigger than the requested + * size for alignment and fragmentation reasons. + * @param[in] align desired memory alignment + * @return A pointer to the aligned allocated block. + * @retval NULL if the block cannot be allocated. + * + * @api + */ +void *chHeapAllocAligned(memory_heap_t *heapp, size_t size, unsigned align) { + heap_header_t *qp, *hp; + size_t pages; + + chDbgCheck((size > 0U) && MEM_IS_VALID_ALIGNMENT(align)); + + /* If an heap is not specified then the default system header is used.*/ + if (heapp == NULL) { + heapp = &default_heap; + } + + /* Minimum alignment is constrained by the heap header structure size.*/ + if (align < CH_HEAP_ALIGNMENT) { + align = CH_HEAP_ALIGNMENT; + } + + /* Size is converted in number of elementary allocation units.*/ + pages = MEM_ALIGN_NEXT(size, CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; + + /* Taking heap mutex/semaphore.*/ + H_LOCK(heapp); + + /* Start of the free blocks list.*/ + qp = &heapp->header; + while (H_NEXT(qp) != NULL) { + heap_header_t *ahp; + + /* Next free block.*/ + hp = H_NEXT(qp); + + /* Pointer aligned to the requested alignment.*/ + ahp = (heap_header_t *)MEM_ALIGN_NEXT(H_BLOCK(hp), align) - 1U; + + if ((ahp < H_LIMIT(hp)) && (pages <= (size_t)(H_LIMIT(hp) - 1U - ahp))) { + /* The block is large enough to contain a correctly aligned area + of sufficient size.*/ + + if (ahp > hp) { + /* The block is not properly aligned, must split it.*/ + size_t bpages; + + bpages = H_LIMIT(hp) - H_BLOCK(ahp); + H_PAGES(hp) = ahp - H_BLOCK(hp); + if (bpages > pages) { + /* The block is bigger than required, must split the excess.*/ + heap_header_t *fp; + + /* Creating the excess block.*/ + fp = H_BLOCK(ahp) + pages; + H_PAGES(fp) = bpages - pages - 1U; + + /* Linking the excess block.*/ + H_NEXT(fp) = H_NEXT(hp); + H_NEXT(hp) = fp; + } + + hp = ahp; + } + else { + /* The block is already properly aligned.*/ + + if (H_PAGES(hp) == pages) { + /* Exact size, getting the whole block.*/ + H_NEXT(qp) = H_NEXT(hp); + } + else { + /* The block is bigger than required, must split the excess.*/ + heap_header_t *fp; + + fp = H_BLOCK(hp) + pages; + H_NEXT(fp) = H_NEXT(hp); + H_PAGES(fp) = H_LIMIT(hp) - H_BLOCK(fp); + H_NEXT(qp) = fp; + } + } + + /* Setting in the block owner heap and size.*/ + H_SIZE(hp) = size; + H_HEAP(hp) = heapp; + + /* Releasing heap mutex/semaphore.*/ + H_UNLOCK(heapp); + + /*lint -save -e9087 [11.3] Safe cast.*/ + return (void *)H_BLOCK(hp); + /*lint -restore*/ + } + + /* Next in the free blocks list.*/ + qp = hp; + } + + /* Releasing heap mutex/semaphore.*/ + H_UNLOCK(heapp); + + /* More memory is required, tries to get it from the associated provider + else fails.*/ + if (heapp->provider != NULL) { + hp = heapp->provider((pages + 1U) * CH_HEAP_ALIGNMENT, align); + if (hp != NULL) { + H_HEAP(hp) = heapp; + H_SIZE(hp) = size; + + /*lint -save -e9087 [11.3] Safe cast.*/ + return (void *)H_BLOCK(hp); + /*lint -restore*/ + } + } + + return NULL; +} + +/** + * @brief Frees a previously allocated memory block. + * + * @param[in] p pointer to the memory block to be freed + * + * @api + */ +void chHeapFree(void *p) { + heap_header_t *qp, *hp; + memory_heap_t *heapp; + + chDbgCheck((p != NULL) && MEM_IS_ALIGNED(p, CH_HEAP_ALIGNMENT)); + + /*lint -save -e9087 [11.3] Safe cast.*/ + hp = (heap_header_t *)p - 1U; + /*lint -restore*/ + heapp = H_HEAP(hp); + qp = &heapp->header; + + /* Size is converted in number of elementary allocation units.*/ + H_PAGES(hp) = MEM_ALIGN_NEXT(H_SIZE(hp), + CH_HEAP_ALIGNMENT) / CH_HEAP_ALIGNMENT; + + /* Taking heap mutex/semaphore.*/ + H_LOCK(heapp); + + while (true) { + chDbgAssert((hp < qp) || (hp >= H_LIMIT(qp)), "within free block"); + + if (((qp == &heapp->header) || (hp > qp)) && + ((H_NEXT(qp) == NULL) || (hp < H_NEXT(qp)))) { + /* Insertion after qp.*/ + H_NEXT(hp) = H_NEXT(qp); + H_NEXT(qp) = hp; + /* Verifies if the newly inserted block should be merged.*/ + if (H_LIMIT(hp) == H_NEXT(hp)) { + /* Merge with the next block.*/ + H_PAGES(hp) += H_PAGES(H_NEXT(hp)) + 1U; + H_NEXT(hp) = H_NEXT(H_NEXT(hp)); + } + if ((H_LIMIT(qp) == hp)) { + /* Merge with the previous block.*/ + H_PAGES(qp) += H_PAGES(hp) + 1U; + H_NEXT(qp) = H_NEXT(hp); + } + break; + } + qp = H_NEXT(qp); + } + + /* Releasing heap mutex/semaphore.*/ + H_UNLOCK(heapp); + + return; +} + +/** + * @brief Reports the heap status. + * @note This function is meant to be used in the test suite, it should + * not be really useful for the application code. + * + * @param[in] heapp pointer to a heap descriptor or @p NULL in order to + * access the default heap. + * @param[in] totalp pointer to a variable that will receive the total + * fragmented free space or @ NULL + * @param[in] largestp pointer to a variable that will receive the largest + * free free block found space or @ NULL + * @return The number of fragments in the heap. + * + * @api + */ +size_t chHeapStatus(memory_heap_t *heapp, size_t *totalp, size_t *largestp) { + heap_header_t *qp; + size_t n, tpages, lpages; + + if (heapp == NULL) { + heapp = &default_heap; + } + + H_LOCK(heapp); + tpages = 0U; + lpages = 0U; + n = 0U; + qp = &heapp->header; + while (H_NEXT(qp) != NULL) { + size_t pages = H_PAGES(H_NEXT(qp)); + + /* Updating counters.*/ + n++; + tpages += pages; + if (pages > lpages) { + lpages = pages; + } + + qp = H_NEXT(qp); + } + + /* Writing out fragmented free memory.*/ + if (totalp != NULL) { + *totalp = tpages * CH_HEAP_ALIGNMENT; + } + + /* Writing out unfragmented free memory.*/ + if (largestp != NULL) { + *largestp = lpages * CH_HEAP_ALIGNMENT; + } + H_UNLOCK(heapp); + + return n; +} + +#endif /* CH_CFG_USE_HEAP == TRUE */ + +/** @} */ diff --git a/os/common/oslib/src/chmboxes.c b/os/common/oslib/src/chmboxes.c new file mode 100644 index 000000000..bb75fee6c --- /dev/null +++ b/os/common/oslib/src/chmboxes.c @@ -0,0 +1,435 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmboxes.c + * @brief Mailboxes code. + * + * @addtogroup mailboxes + * @details Asynchronous messages. + *

Operation mode

+ * A mailbox is an asynchronous communication mechanism.
+ * Operations defined for mailboxes: + * - Post: Posts a message on the mailbox in FIFO order. + * - Post Ahead: Posts a message on the mailbox with urgent + * priority. + * - Fetch: A message is fetched from the mailbox and removed + * from the queue. + * - Reset: The mailbox is emptied and all the stored messages + * are lost. + * . + * A message is a variable of type msg_t that is guaranteed to have + * the same size of and be compatible with (data) pointers (anyway an + * explicit cast is needed). + * If larger messages need to be exchanged then a pointer to a + * structure can be posted in the mailbox but the posting side has + * no predefined way to know when the message has been processed. A + * possible approach is to allocate memory (from a memory pool for + * example) from the posting side and free it on the fetching side. + * Another approach is to set a "done" flag into the structure pointed + * by the message. + * @pre In order to use the mailboxes APIs the @p CH_CFG_USE_MAILBOXES + * option must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MAILBOXES == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes a @p mailbox_t object. + * + * @param[out] mbp the pointer to the @p mailbox_t structure to be + * initialized + * @param[in] buf pointer to the messages buffer as an array of @p msg_t + * @param[in] n number of elements in the buffer array + * + * @init + */ +void chMBObjectInit(mailbox_t *mbp, msg_t *buf, cnt_t n) { + + chDbgCheck((mbp != NULL) && (buf != NULL) && (n > (cnt_t)0)); + + mbp->buffer = buf; + mbp->rdptr = buf; + mbp->wrptr = buf; + mbp->top = &buf[n]; + chSemObjectInit(&mbp->emptysem, n); + chSemObjectInit(&mbp->fullsem, (cnt_t)0); +} + +/** + * @brief Resets a @p mailbox_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued messages are lost. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @api + */ +void chMBReset(mailbox_t *mbp) { + + chSysLock(); + chMBResetI(mbp); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Resets a @p mailbox_t object. + * @details All the waiting threads are resumed with status @p MSG_RESET and + * the queued messages are lost. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * + * @api + */ +void chMBResetI(mailbox_t *mbp) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + mbp->wrptr = mbp->buffer; + mbp->rdptr = mbp->buffer; + chSemResetI(&mbp->emptysem, (cnt_t)(mbp->top - mbp->buffer)); + chSemResetI(&mbp->fullsem, (cnt_t)0); +} + +/** + * @brief Posts a message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBPost(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBPostS(mbp, msg, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Posts a message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBPostS(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck(mbp != NULL); + + rdymsg = chSemWaitTimeoutS(&mbp->emptysem, timeout); + if (rdymsg == MSG_OK) { + *mbp->wrptr++ = msg; + if (mbp->wrptr >= mbp->top) { + mbp->wrptr = mbp->buffer; + } + chSemSignalI(&mbp->fullsem); + chSchRescheduleS(); + } + + return rdymsg; +} + +/** + * @brief Posts a message into a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is full. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be + * posted. + * + * @iclass + */ +msg_t chMBPostI(mailbox_t *mbp, msg_t msg) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + if (chSemGetCounterI(&mbp->emptysem) <= (cnt_t)0) { + return MSG_TIMEOUT; + } + + chSemFastWaitI(&mbp->emptysem); + *mbp->wrptr++ = msg; + if (mbp->wrptr >= mbp->top) { + mbp->wrptr = mbp->buffer; + } + chSemSignalI(&mbp->fullsem); + + return MSG_OK; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBPostAhead(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBPostAheadS(mbp, msg, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details The invoking thread waits until a empty slot in the mailbox becomes + * available or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBPostAheadS(mailbox_t *mbp, msg_t msg, systime_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck(mbp != NULL); + + rdymsg = chSemWaitTimeoutS(&mbp->emptysem, timeout); + if (rdymsg == MSG_OK) { + if (--mbp->rdptr < mbp->buffer) { + mbp->rdptr = mbp->top - 1; + } + *mbp->rdptr = msg; + chSemSignalI(&mbp->fullsem); + chSchRescheduleS(); + } + + return rdymsg; +} + +/** + * @brief Posts an high priority message into a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is full. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[in] msg the message to be posted on the mailbox + * @return The operation status. + * @retval MSG_OK if a message has been correctly posted. + * @retval MSG_TIMEOUT if the mailbox is full and the message cannot be + * posted. + * + * @iclass + */ +msg_t chMBPostAheadI(mailbox_t *mbp, msg_t msg) { + + chDbgCheckClassI(); + chDbgCheck(mbp != NULL); + + if (chSemGetCounterI(&mbp->emptysem) <= (cnt_t)0) { + return MSG_TIMEOUT; + } + chSemFastWaitI(&mbp->emptysem); + if (--mbp->rdptr < mbp->buffer) { + mbp->rdptr = mbp->top - 1; + } + *mbp->rdptr = msg; + chSemSignalI(&mbp->fullsem); + + return MSG_OK; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details The invoking thread waits until a message is posted in the mailbox + * or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @api + */ +msg_t chMBFetch(mailbox_t *mbp, msg_t *msgp, systime_t timeout) { + msg_t rdymsg; + + chSysLock(); + rdymsg = chMBFetchS(mbp, msgp, timeout); + chSysUnlock(); + + return rdymsg; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details The invoking thread waits until a message is posted in the mailbox + * or the specified time runs out. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_RESET if the mailbox has been reset while waiting. + * @retval MSG_TIMEOUT if the operation has timed out. + * + * @sclass + */ +msg_t chMBFetchS(mailbox_t *mbp, msg_t *msgp, systime_t timeout) { + msg_t rdymsg; + + chDbgCheckClassS(); + chDbgCheck((mbp != NULL) && (msgp != NULL)); + + rdymsg = chSemWaitTimeoutS(&mbp->fullsem, timeout); + if (rdymsg == MSG_OK) { + *msgp = *mbp->rdptr++; + if (mbp->rdptr >= mbp->top) { + mbp->rdptr = mbp->buffer; + } + chSemSignalI(&mbp->emptysem); + chSchRescheduleS(); + } + + return rdymsg; +} + +/** + * @brief Retrieves a message from a mailbox. + * @details This variant is non-blocking, the function returns a timeout + * condition if the queue is empty. + * + * @param[in] mbp the pointer to an initialized @p mailbox_t object + * @param[out] msgp pointer to a message variable for the received message + * @return The operation status. + * @retval MSG_OK if a message has been correctly fetched. + * @retval MSG_TIMEOUT if the mailbox is empty and a message cannot be + * fetched. + * + * @iclass + */ +msg_t chMBFetchI(mailbox_t *mbp, msg_t *msgp) { + + chDbgCheckClassI(); + chDbgCheck((mbp != NULL) && (msgp != NULL)); + + if (chSemGetCounterI(&mbp->fullsem) <= (cnt_t)0) { + return MSG_TIMEOUT; + } + chSemFastWaitI(&mbp->fullsem); + *msgp = *mbp->rdptr++; + if (mbp->rdptr >= mbp->top) { + mbp->rdptr = mbp->buffer; + } + chSemSignalI(&mbp->emptysem); + + return MSG_OK; +} +#endif /* CH_CFG_USE_MAILBOXES == TRUE */ + +/** @} */ diff --git a/os/common/oslib/src/chmemcore.c b/os/common/oslib/src/chmemcore.c new file mode 100644 index 000000000..a665b07b2 --- /dev/null +++ b/os/common/oslib/src/chmemcore.c @@ -0,0 +1,166 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmemcore.c + * @brief Core memory manager code. + * + * @addtogroup memcore + * @details Core Memory Manager related APIs and services. + *

Operation mode

+ * The core memory manager is a simplified allocator that only + * allows to allocate memory blocks without the possibility to + * free them.
+ * This allocator is meant as a memory blocks provider for the + * other allocators such as: + * - C-Runtime allocator (through a compiler specific adapter module). + * - Heap allocator (see @ref heaps). + * - Memory pools allocator (see @ref pools). + * . + * By having a centralized memory provider the various allocators + * can coexist and share the main memory.
+ * This allocator, alone, is also useful for very simple + * applications that just require a simple way to get memory + * blocks. + * @pre In order to use the core memory manager APIs the @p CH_CFG_USE_MEMCORE + * option must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MEMCORE == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +static uint8_t *nextmem; +static uint8_t *endmem; + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level memory manager initialization. + * + * @notapi + */ +void _core_init(void) { +#if CH_CFG_MEMCORE_SIZE == 0 + extern uint8_t __heap_base__[]; + extern uint8_t __heap_end__[]; + + /*lint -save -e9033 [10.8] Required cast operations.*/ + nextmem = (uint8_t *)MEM_ALIGN_NEXT(__heap_base__, PORT_NATURAL_ALIGN); + endmem = (uint8_t *)MEM_ALIGN_PREV(__heap_end__, PORT_NATURAL_ALIGN); + /*lint restore*/ +#else + static stkalign_t buffer[MEM_ALIGN_NEXT(CH_CFG_MEMCORE_SIZE) / + PORT_NATURAL_ALIGN]; + + nextmem = (uint8_t *)&buffer[0]; + endmem = (uint8_t *)&buffer[MEM_ALIGN_NEXT(CH_CFG_MEMCORE_SIZE) / + PORT_NATURAL_ALIGN]; +#endif +} + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned to the + * specified alignment. + * + * @param[in] size the size of the block to be allocated. + * @param[in] align desired memory alignment + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @iclass + */ +void *chCoreAllocAlignedI(size_t size, unsigned align) { + uint8_t *p; + + chDbgCheckClassI(); + chDbgCheck(MEM_IS_VALID_ALIGNMENT(align)); + + size = MEM_ALIGN_NEXT(size, align); + p = (uint8_t *)MEM_ALIGN_NEXT(nextmem, align); + + /* ---????? lint -save -e9033 [10.8] The cast is safe.*/ + if ((size_t)(endmem - p) < size) { + /* ---????? lint -restore*/ + return NULL; + } + nextmem = p + size; + + return p; +} + +/** + * @brief Allocates a memory block. + * @details The allocated block is guaranteed to be properly aligned to the + * specified alignment. + * + * @param[in] size the size of the block to be allocated + * @param[in] align desired memory alignment + * @return A pointer to the allocated memory block. + * @retval NULL allocation failed, core memory exhausted. + * + * @api + */ +void *chCoreAllocAligned(size_t size, unsigned align) { + void *p; + + chSysLock(); + p = chCoreAllocAlignedI(size, align); + chSysUnlock(); + + return p; +} + +/** + * @brief Core memory status. + * + * @return The size, in bytes, of the free core memory. + * + * @xclass + */ +size_t chCoreGetStatusX(void) { + + /*lint -save -e9033 [10.8] The cast is safe.*/ + return (size_t)(endmem - nextmem); + /*lint -restore*/ +} +#endif /* CH_CFG_USE_MEMCORE == TRUE */ + +/** @} */ diff --git a/os/common/oslib/src/chmempools.c b/os/common/oslib/src/chmempools.c new file mode 100644 index 000000000..c29fde8f4 --- /dev/null +++ b/os/common/oslib/src/chmempools.c @@ -0,0 +1,203 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chmempools.c + * @brief Memory Pools code. + * + * @addtogroup pools + * @details Memory Pools related APIs and services. + *

Operation mode

+ * The Memory Pools APIs allow to allocate/free fixed size objects in + * constant time and reliably without memory fragmentation + * problems.
+ * Memory Pools do not enforce any alignment constraint on the + * contained object however the objects must be properly aligned + * to contain a pointer to void. + * @pre In order to use the memory pools APIs the @p CH_CFG_USE_MEMPOOLS option + * must be enabled in @p chconf.h. + * @note Compatible with RT and NIL. + * @{ + */ + +#include "ch.h" + +#if (CH_CFG_USE_MEMPOOLS == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes an empty memory pool. + * + * @param[out] mp pointer to a @p memory_pool_t structure + * @param[in] size the size of the objects contained in this memory pool, + * the minimum accepted size is the size of a pointer to + * void. + * @param[in] provider memory provider function for the memory pool or + * @p NULL if the pool is not allowed to grow + * automatically + * + * @init + */ +void chPoolObjectInit(memory_pool_t *mp, size_t size, memgetfunc_t provider) { + + chDbgCheck((mp != NULL) && (size >= sizeof(void *))); + + mp->next = NULL; + mp->object_size = size; + mp->provider = provider; +} + +/** + * @brief Loads a memory pool with an array of static objects. + * @pre The memory pool must be already been initialized. + * @pre The array elements must be of the right size for the specified + * memory pool. + * @post The memory pool contains the elements of the input array. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] p pointer to the array first element + * @param[in] n number of elements in the array + * + * @api + */ +void chPoolLoadArray(memory_pool_t *mp, void *p, size_t n) { + + chDbgCheck((mp != NULL) && (n != 0U)); + + while (n != 0U) { + chPoolAdd(mp, p); + /*lint -save -e9087 [11.3] Safe cast.*/ + p = (void *)(((uint8_t *)p) + mp->object_size); + /*lint -restore*/ + n--; + } +} + +/** + * @brief Allocates an object from a memory pool. + * @pre The memory pool must be already been initialized. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @return The pointer to the allocated object. + * @retval NULL if pool is empty. + * + * @iclass + */ +void *chPoolAllocI(memory_pool_t *mp) { + void *objp; + + chDbgCheckClassI(); + chDbgCheck(mp != NULL); + + objp = mp->next; + /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ + if (objp != NULL) { + mp->next = mp->next->next; + } + else if (mp->provider != NULL) { + objp = mp->provider(mp->object_size, PORT_NATURAL_ALIGN); /* TODO: Alignment is not properly handled */ + } + /*lint -restore*/ + + return objp; +} + +/** + * @brief Allocates an object from a memory pool. + * @pre The memory pool must be already been initialized. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @return The pointer to the allocated object. + * @retval NULL if pool is empty. + * + * @api + */ +void *chPoolAlloc(memory_pool_t *mp) { + void *objp; + + chSysLock(); + objp = chPoolAllocI(mp); + chSysUnlock(); + + return objp; +} + +/** + * @brief Releases an object into a memory pool. + * @pre The memory pool must be already been initialized. + * @pre The freed object must be of the right size for the specified + * memory pool. + * @pre The object must be properly aligned to contain a pointer to void. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] objp the pointer to the object to be released + * + * @iclass + */ +void chPoolFreeI(memory_pool_t *mp, void *objp) { + struct pool_header *php = objp; + + chDbgCheckClassI(); + chDbgCheck((mp != NULL) && (objp != NULL)); + + php->next = mp->next; + mp->next = php; +} + +/** + * @brief Releases an object into a memory pool. + * @pre The memory pool must be already been initialized. + * @pre The freed object must be of the right size for the specified + * memory pool. + * @pre The object must be properly aligned to contain a pointer to void. + * + * @param[in] mp pointer to a @p memory_pool_t structure + * @param[in] objp the pointer to the object to be released + * + * @api + */ +void chPoolFree(memory_pool_t *mp, void *objp) { + + chSysLock(); + chPoolFreeI(mp, objp); + chSysUnlock(); +} + +#endif /* CH_CFG_USE_MEMPOOLS == TRUE */ + +/** @} */ diff --git a/os/common/ports/ARM/chcore.c b/os/common/ports/ARM/chcore.c new file mode 100644 index 000000000..ae495ae2c --- /dev/null +++ b/os/common/ports/ARM/chcore.c @@ -0,0 +1,54 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARM/chcore.c + * @brief ARM port code. + * + * @addtogroup ARM_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** @} */ diff --git a/os/common/ports/ARM/chcore.h b/os/common/ports/ARM/chcore.h new file mode 100644 index 000000000..c83d19e23 --- /dev/null +++ b/os/common/ports/ARM/chcore.h @@ -0,0 +1,564 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARM/chcore.h + * @brief ARM7/9 architecture port macros and structures. + * + * @addtogroup ARM_CORE + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN sizeof (void *) + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN sizeof (stkalign_t) + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t) +/** @} */ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining a generic ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM + +/* The following code is not processed when the file is included from an + asm module because those intrinsic macros are not necessarily defined + by the assembler too.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#else +#error "unsupported compiler" +#endif + +#endif /* !defined(_FROM_ASM_) */ +/** @} */ + +/** + * @name ARM variants + * @{ + */ +#define ARM_CORE_ARM7TDMI 7 +#define ARM_CORE_ARM9 9 +#define ARM_CORE_CORTEX_A8 108 +#define ARM_CORE_CORTEX_A9 109 +/** @} */ + +/* Inclusion of the ARM implementation specific parameters.*/ +#include "armparams.h" + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p chcore_timer.h, if this option is enabled then the file + * @p chcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 32 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 32 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 32 +#endif + +/** + * @brief If enabled allows the idle thread to enter a low power mode. + */ +#ifndef ARM_ENABLE_WFI_IDLE +#define ARM_ENABLE_WFI_IDLE FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/* ARM core check.*/ +#if (ARM_CORE == ARM_CORE_ARM7TDMI) || defined(__DOXYGEN__) +#define PORT_ARCHITECTURE_ARM_ARM7 +#define PORT_ARCHITECTURE_NAME "ARMv4T" +#define PORT_CORE_VARIANT_NAME "ARM7" + +#elif ARM_CORE == ARM_CORE_ARM9 +#define PORT_ARCHITECTURE_ARM_ARM9 +#define PORT_ARCHITECTURE_NAME "ARMv5T" +#define PORT_CORE_VARIANT_NAME "ARM9" + +#elif ARM_CORE == ARM_CORE_CORTEX_A8 +#define PORT_ARCHITECTURE_ARM_CORTEXA8 +#define PORT_ARCHITECTURE_NAME "ARMv7" +#define PORT_CORE_VARIANT_NAME "ARM Cortex-A8" + +#elif ARM_CORE == ARM_CORE_CORTEX_A9 +#define PORT_ARCHITECTURE_ARM_CORTEXA9 +#define PORT_ARCHITECTURE_NAME "ARMv7" +#define PORT_CORE_VARIANT_NAME "ARM Cortex-A9" + +#else +#error "unknown or unsupported ARM core" +#endif + +#if defined(THUMB_PRESENT) +#if defined(THUMB_NO_INTERWORKING) +#define PORT_INFO "Pure THUMB mode" +#else +#define PORT_INFO "Interworking mode" +#endif +#else +#define PORT_INFO "Pure ARM mode" +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits. + */ +typedef uint64_t stkalign_t; + +/** + * @brief Generic ARM register. + */ +typedef void *regarm_t; + +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during an + * interrupt handler. + */ +struct port_extctx { + regarm_t spsr_irq; + regarm_t lr_irq; + regarm_t r0; + regarm_t r1; + regarm_t r2; + regarm_t r3; + regarm_t r12; + regarm_t lr_usr; +}; + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switch. + */ +struct port_intctx { + regarm_t r4; + regarm_t r5; + regarm_t r6; + regarm_t r7; + regarm_t r8; + regarm_t r9; + regarm_t r10; + regarm_t r11; + regarm_t lr; +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details In this port the structure just holds a pointer to the + * @p port_intctx structure representing the stack pointer + * at context switch time. + */ +struct port_context { + struct port_intctx *r13; +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + (tp)->ctx.r13 = (struct port_intctx *)((uint8_t *)(wtop) - \ + sizeof (struct port_intctx)); \ + (tp)->ctx.r13->r4 = (regarm_t)(pf); \ + (tp)->ctx.r13->r5 = (regarm_t)(arg); \ + (tp)->ctx.r13->lr = (regarm_t)(_port_thread_start); \ +} + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ + sizeof(struct port_extctx) + \ + ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief Priority level verification macro. + * @todo Add the required parameters to armparams.h. + */ +#define PORT_IRQ_IS_VALID_PRIORITY(n) false + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() return chSchIsPreemptionRequired() + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) bool id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) \ + __attribute__((interrupt("FIQ"))) void id(void) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * @note Implemented as inlined code for performance reasons. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if defined(THUMB) + +#if CH_DBG_ENABLE_STACK_CHECK == TRUE +#define port_switch(ntp, otp) { \ + register struct port_intctx *r13 asm ("r13"); \ + if ((stkalign_t *)(r13 - 1) < otp->p_stklimit) \ + chSysHalt("stack overflow"); \ + _port_switch_thumb(ntp, otp); \ +} +#else +#define port_switch(ntp, otp) _port_switch_thumb(ntp, otp) +#endif + +#else /* !defined(THUMB) */ + +#if CH_DBG_ENABLE_STACK_CHECK == TRUE +#define port_switch(ntp, otp) { \ + register struct port_intctx *r13 asm ("r13"); \ + if ((stkalign_t *)(r13 - 1) < otp->stklimit) \ + chSysHalt("stack overflow"); \ + _port_switch_arm(ntp, otp); \ +} +#else +#define port_switch(ntp, otp) _port_switch_arm(ntp, otp) +#endif + +#endif /* !defined(THUMB) */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#if defined(THUMB_PRESENT) + syssts_t _port_get_cpsr(void); +#endif +#if defined(THUMB) + void _port_switch_thumb(thread_t *ntp, thread_t *otp); +#else + void _port_switch_arm(thread_t *ntp, thread_t *otp); +#endif + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + */ +static inline void port_init(void) { + +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + syssts_t sts; + +#if defined(THUMB) + sts = _port_get_cpsr(); +#else + __asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :); +#endif + /*lint -save -e530 [9.1] Asm instruction not seen by lint.*/ + return sts; + /*lint -restore*/ +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return (sts & (syssts_t)0x80) == (syssts_t)0; +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + syssts_t sts; + +#if defined(THUMB) + sts = _port_get_cpsr(); +#else + __asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :); +#endif + + /*lint -save -e530 [9.1] Asm instruction not seen by lint.*/ + return (sts & (syssts_t)0x1F) == (syssts_t)0x12; + /*lint -restore*/ +} + +/** + * @brief Kernel-lock action. + * @details In this port it disables the IRQ sources and keeps FIQ sources + * enabled. + */ +static inline void port_lock(void) { + +#if defined(THUMB) + __asm volatile ("bl _port_lock_thumb" : : : "r3", "lr", "memory"); +#else + __asm volatile ("msr CPSR_c, #0x9F" : : : "memory"); +#endif +} + +/** + * @brief Kernel-unlock action. + * @details In this port it enables both the IRQ and FIQ sources. + */ +static inline void port_unlock(void) { + +#if defined(THUMB) + __asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr", "memory"); +#else + __asm volatile ("msr CPSR_c, #0x1F" : : : "memory"); +#endif +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @note Empty in this port. + */ +static inline void port_lock_from_isr(void) { + +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @note Empty in this port. + */ +static inline void port_unlock_from_isr(void) { + +} + +/** + * @brief Disables all the interrupt sources. + * @details In this port it disables both the IRQ and FIQ sources. + * @note Implements a workaround for spurious interrupts taken from the NXP + * LPC214x datasheet. + */ +static inline void port_disable(void) { + +#if defined(THUMB) + __asm volatile ("bl _port_disable_thumb" : : : "r3", "lr", "memory"); +#else + __asm volatile ("mrs r3, CPSR \n\t" + "orr r3, #0x80 \n\t" + "msr CPSR_c, r3 \n\t" + "orr r3, #0x40 \n\t" + "msr CPSR_c, r3" : : : "r3", "memory"); +#endif +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + * @note Interrupt sources above kernel level remains enabled. + * @note In this port it disables the IRQ sources and enables the + * FIQ sources. + */ +static inline void port_suspend(void) { + +#if defined(THUMB) + __asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr", "memory"); +#else + __asm volatile ("msr CPSR_c, #0x9F" : : : "memory"); +#endif +} + +/** + * @brief Enables all the interrupt sources. + * @note In this port it enables both the IRQ and FIQ sources. + */ +static inline void port_enable(void) { + +#if defined(THUMB) + __asm volatile ("bl _port_enable_thumb" : : : "r3", "lr", "memory"); +#else + __asm volatile ("msr CPSR_c, #0x1F" : : : "memory"); +#endif +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + * @note Implemented as an inlined @p WFI instruction. + */ +static inline void port_wait_for_interrupt(void) { + +#if ARM_ENABLE_WFI_IDLE == TRUE + ARM_WFI_IMPL; +#endif +} + +#if CH_CFG_ST_TIMEDELTA > 0 +#if PORT_USE_ALT_TIMER == FALSE +#include "chcore_timer.h" +#else /* PORT_USE_ALT_TIMER */ +#include "chcore_timer_alt.h" +#endif /* PORT_USE_ALT_TIMER */ +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/common/ports/ARM/chcore_timer.h b/os/common/ports/ARM/chcore_timer.h new file mode 100644 index 000000000..07f6e09a0 --- /dev/null +++ b/os/common/ports/ARM/chcore_timer.h @@ -0,0 +1,124 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chcore_timer.h + * @brief System timer header file. + * + * @addtogroup ARM_TIMER + * @{ + */ + +#ifndef _CHCORE_TIMER_H_ +#define _CHCORE_TIMER_H_ + +/* This is the only header in the HAL designed to be include-able alone.*/ +#include "st.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void port_timer_start_alarm(systime_t time) { + + stStartAlarm(time); +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void port_timer_stop_alarm(void) { + + stStopAlarm(); +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void port_timer_set_alarm(systime_t time) { + + stSetAlarm(time); +} + +/** + * @brief Returns the system time. + * + * @return The system time. + * + * @notapi + */ +static inline systime_t port_timer_get_time(void) { + + return stGetCounter(); +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t port_timer_get_alarm(void) { + + return stGetAlarm(); +} + +#endif /* _CHCORE_TIMER_H_ */ + +/** @} */ diff --git a/os/common/ports/ARM/compilers/GCC/chcoreasm.s b/os/common/ports/ARM/compilers/GCC/chcoreasm.s new file mode 100644 index 000000000..f4cc740c8 --- /dev/null +++ b/os/common/ports/ARM/compilers/GCC/chcoreasm.s @@ -0,0 +1,303 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARM/compilers/GCC/chcoreasm.s + * @brief ARM architecture port low level code. + * + * @addtogroup ARM_CORE + * @{ + */ + +#define _FROM_ASM_ +#include "chconf.h" +#include "armparams.h" + +#define FALSE 0 +#define TRUE 1 + +#if !defined(__DOXYGEN__) + +/* + * RTOS-specific context offset. + */ +#if defined(_CHIBIOS_RT_CONF_) +#define CONTEXT_OFFSET 12 +#elif defined(_CHIBIOS_NIL_CONF_) +#define CONTEXT_OFFSET 0 +#else +#error "invalid chconf.h" +#endif + + .set MODE_USR, 0x10 + .set MODE_FIQ, 0x11 + .set MODE_IRQ, 0x12 + .set MODE_SVC, 0x13 + .set MODE_ABT, 0x17 + .set MODE_UND, 0x1B + .set MODE_SYS, 0x1F + + .equ I_BIT, 0x80 + .equ F_BIT, 0x40 + + .text + +/* + * The following functions are only present if there is THUMB code in + * the system. + */ +#if defined(THUMB_PRESENT) + .balign 16 + .code 16 + .thumb_func + .global _port_get_cpsr +_port_get_cpsr: + mov r0, pc + bx r0 +.code 32 + mrs r0, CPSR + bx lr + + .balign 16 + .code 16 + .thumb_func + .global _port_disable_thumb +_port_disable_thumb: + mov r3, pc + bx r3 +.code 32 + mrs r3, CPSR + orr r3, #I_BIT + msr CPSR_c, r3 + orr r3, #F_BIT + msr CPSR_c, r3 + bx lr + + .balign 16 + .code 16 + .thumb_func + .global _port_suspend_thumb +_port_suspend_thumb: + // Goes into _port_unlock_thumb + + .code 16 + .global _port_lock_thumb +_port_lock_thumb: + mov r3, pc + bx r3 + .code 32 + msr CPSR_c, #MODE_SYS | I_BIT + bx lr + + .balign 16 + .code 16 + .thumb_func + .global _port_enable_thumb +_port_enable_thumb: + // Goes into _port_unlock_thumb + + .code 16 + .global _port_unlock_thumb +_port_unlock_thumb: + mov r3, pc + bx r3 + .code 32 + msr CPSR_c, #MODE_SYS + bx lr +#endif /* defined(THUMB_PRESENT) */ + + .balign 16 +#if defined(THUMB_PRESENT) + .code 16 + .thumb_func + .global _port_switch_thumb +_port_switch_thumb: + mov r2, pc + bx r2 + // Goes into _port_switch_arm in ARM mode +#endif /* defined(THUMB_PRESENT) */ + + .code 32 + .global _port_switch_arm +_port_switch_arm: + stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} + str sp, [r1, #12] + ldr sp, [r0, #12] +#if defined(THUMB_PRESENT) + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} + bx lr +#else /* !defined(THUMB_PRESENT)T */ + ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc} +#endif /* !defined(THUMB_PRESENT) */ + +/* + * Common IRQ code. It expects a macro ARM_IRQ_VECTOR_REG with the address + * of a register holding the address of the ISR to be invoked, the ISR + * then returns in the common epilogue code where the context switch will + * be performed, if required. + * System stack frame structure after a context switch in the + * interrupt handler: + * + * High +------------+ + * | LR_USR | -+ + * | r12 | | + * | r3 | | + * | r2 | | External context: IRQ handler frame + * | r1 | | + * | r0 | | + * | LR_IRQ | | (user code return address) + * | PSR_USR | -+ (user code status) + * | .... | <- chSchDoReschedule() stack frame, optimize it for space + * | LR | -+ (system code return address) + * | r11 | | + * | r10 | | + * | r9 | | + * | r8 | | Internal context: chSysSwitch() frame + * | r7 | | + * | r6 | | + * | r5 | | + * SP-> | r4 | -+ + * Low +------------+ + */ + .balign 16 + .code 32 + .global Irq_Handler +Irq_Handler: + stmfd sp!, {r0-r3, r12, lr} + ldr r0, =ARM_IRQ_VECTOR_REG + ldr r0, [r0] +#if !defined(THUMB_NO_INTERWORKING) + ldr lr, =_irq_ret_arm // ISR return point. + bx r0 // Calling the ISR. +_irq_ret_arm: +#else /* defined(THUMB_NO_INTERWORKING) */ + add r1, pc, #1 + bx r1 + .code 16 + bl _bxr0 // Calling the ISR. + mov lr, pc + bx lr + .code 32 +#endif /* defined(THUMB_NO_INTERWORKING) */ + cmp r0, #0 + ldmfd sp!, {r0-r3, r12, lr} + subeqs pc, lr, #4 // No reschedule, returns. + + // Now the frame is created in the system stack, the IRQ + // stack is empty. + msr CPSR_c, #MODE_SYS | I_BIT + stmfd sp!, {r0-r3, r12, lr} + msr CPSR_c, #MODE_IRQ | I_BIT + mrs r0, SPSR + mov r1, lr + msr CPSR_c, #MODE_SYS | I_BIT + stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ. + + // Context switch. +#if defined(THUMB_NO_INTERWORKING) + add r0, pc, #1 + bx r0 + .code 16 +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif + mov lr, pc + bx lr + .code 32 +#else /* !defined(THUMB_NO_INTERWORKING) */ +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#endif /* !defined(THUMB_NO_INTERWORKING) */ + + // Re-establish the IRQ conditions again. + ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ. + msr CPSR_c, #MODE_IRQ | I_BIT + msr SPSR_fsxc, r0 + mov lr, r1 + msr CPSR_c, #MODE_SYS | I_BIT + ldmfd sp!, {r0-r3, r12, lr} + msr CPSR_c, #MODE_IRQ | I_BIT + subs pc, lr, #4 +#if defined(THUMB_NO_INTERWORKING) + .code 16 +_bxr0: bx r0 +#endif + +/* + * Threads trampoline code. + * NOTE: The threads always start in ARM mode and then switches to the + * thread-function mode. + */ + .balign 16 + .code 32 + .globl _port_thread_start +_port_thread_start: +#if defined(THUMB_NO_INTERWORKING) + add r0, pc, #1 + bx r0 + .code 16 +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif + bl _port_unlock_thumb + mov r0, r5 + bl _bxr4 +#if defined(_CHIBIOS_RT_CONF_) + mov r0, #0 /* MSG_OK */ + bl chThdExit +_zombies: b _zombies +#endif +#if defined(_CHIBIOS_NIL_CONF_) + mov r0, #0 + bl chSysHalt +#endif +_bxr4: bx r4 + +#else /* !defined(THUMB_NO_INTERWORKING) */ +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif + msr CPSR_c, #MODE_SYS + mov r0, r5 + mov lr, pc + bx r4 +#if defined(_CHIBIOS_RT_CONF_) + mov r0, #0 /* MSG_OK */ + bl chThdExit +_zombies: b _zombies +#endif +#if defined(_CHIBIOS_NIL_CONF_) + mov r0, #0 + bl chSysHalt +#endif + +#endif /* !defined(THUMB_NO_INTERWORKING) */ + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARM/compilers/GCC/chtypes.h b/os/common/ports/ARM/compilers/GCC/chtypes.h new file mode 100644 index 000000000..5ea352765 --- /dev/null +++ b/os/common/ports/ARM/compilers/GCC/chtypes.h @@ -0,0 +1,98 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARM/compilers/GCC/chtypes.h + * @brief ARM port system types. + * + * @addtogroup ARM_GCC_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __attribute__((packed)) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk b/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk new file mode 100644 index 000000000..5762f96a0 --- /dev/null +++ b/os/common/ports/ARM/compilers/GCC/mk/port_generic.mk @@ -0,0 +1,7 @@ +# List of the ChibiOS/RT ARM generic port files. +PORTSRC = ${CHIBIOS}/os/common/ports/ARM/chcore.c + +PORTASM = $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/chcoreasm.s + +PORTINC = ${CHIBIOS}/os/common/ports/ARM \ + ${CHIBIOS}/os/common/ports/ARM/compilers/GCC diff --git a/os/common/ports/ARMCMx/chcore.c b/os/common/ports/ARMCMx/chcore.c new file mode 100644 index 000000000..81c61c505 --- /dev/null +++ b/os/common/ports/ARMCMx/chcore.c @@ -0,0 +1,54 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore.c + * @brief ARM Cortex-Mx port code. + * + * @addtogroup ARMCMx_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** @} */ diff --git a/os/common/ports/ARMCMx/chcore.h b/os/common/ports/ARMCMx/chcore.h new file mode 100644 index 000000000..16743bbdf --- /dev/null +++ b/os/common/ports/ARMCMx/chcore.h @@ -0,0 +1,215 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore.h + * @brief ARM Cortex-Mx port macros and structures. + * + * @addtogroup ARMCMx_CORE + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining a generic ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM + +/* The following code is not processed when the file is included from an + asm module because those intrinsic macros are not necessarily defined + by the assembler too.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#elif defined(__ICCARM__) +#define PORT_COMPILER_NAME "IAR" + +#elif defined(__CC_ARM) +#define PORT_COMPILER_NAME "RVCT" + +#else +#error "unsupported compiler" +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/** @} */ + +/* Inclusion of the Cortex-Mx implementation specific parameters.*/ +#include "cmparams.h" + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p chcore_timer.h, if this option is enabled then the file + * @p chcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of a generic ARM register. + */ +typedef void *regarm_t; + +/** + * @brief Type of stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits, + * 32 bits alignment is supported by hardware but deprecated by ARM, + * the implementation choice is to not offer the option. + */ +typedef uint64_t stkalign_t; + +/* The following declarations are there just for Doxygen documentation, the + real declarations are inside the sub-headers being specific for the + sub-architectures.*/ +#if defined(__DOXYGEN__) +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + * @note It is implemented to match the Cortex-Mx exception context. + */ +struct port_extctx {}; + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switch. + */ +struct port_intctx {}; +#endif /* defined(__DOXYGEN__) */ + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details In this port the structure just holds a pointer to the + * @p port_intctx structure representing the stack pointer + * at context switch time. + */ +struct port_context { + struct port_intctx *r13; +}; + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Total priority levels. + */ +#define CORTEX_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS) + +/** + * @brief Minimum priority level. + * @details This minimum priority level is calculated from the number of + * priority bits supported by the specific Cortex-Mx implementation. + */ +#define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1) + +/** + * @brief Maximum priority level. + * @details The maximum allowed priority level is always zero. + */ +#define CORTEX_MAXIMUM_PRIORITY 0U + +/** + * @brief Priority level to priority mask conversion macro. + */ +#define CORTEX_PRIO_MASK(n) \ + ((n) << (8U - (unsigned)CORTEX_PRIORITY_BITS)) + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_PRIORITY(n) \ + (((n) >= 0U) && ((n) < CORTEX_PRIORITY_LEVELS)) + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \ + (((n) >= CORTEX_MAX_KERNEL_PRIORITY) && ((n) < CORTEX_PRIORITY_LEVELS)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/* Includes the sub-architecture-specific part.*/ +#if (CORTEX_MODEL == 0) || (CORTEX_MODEL == 1) +#include "chcore_v6m.h" +#elif (CORTEX_MODEL == 3) || (CORTEX_MODEL == 4) || (CORTEX_MODEL == 7) +#include "mpu.h" +#include "chcore_v7m.h" +#else +#error "unknown Cortex-M variant" +#endif + +#if !defined(_FROM_ASM_) + +#if CH_CFG_ST_TIMEDELTA > 0 +#if PORT_USE_ALT_TIMER == FALSE +#include "chcore_timer.h" +#else /* PORT_USE_ALT_TIMER != FALSE */ +#include "chcore_timer_alt.h" +#endif /* PORT_USE_ALT_TIMER != FALSE */ +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/chcore_timer.h b/os/common/ports/ARMCMx/chcore_timer.h new file mode 100644 index 000000000..7d607a096 --- /dev/null +++ b/os/common/ports/ARMCMx/chcore_timer.h @@ -0,0 +1,124 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chcore_timer.h + * @brief System timer header file. + * + * @addtogroup ARMCMx_TIMER + * @{ + */ + +#ifndef _CHCORE_TIMER_H_ +#define _CHCORE_TIMER_H_ + +/* This is the only header in the HAL designed to be include-able alone.*/ +#include "st.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void port_timer_start_alarm(systime_t time) { + + stStartAlarm(time); +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void port_timer_stop_alarm(void) { + + stStopAlarm(); +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void port_timer_set_alarm(systime_t time) { + + stSetAlarm(time); +} + +/** + * @brief Returns the system time. + * + * @return The system time. + * + * @notapi + */ +static inline systime_t port_timer_get_time(void) { + + return stGetCounter(); +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t port_timer_get_alarm(void) { + + return stGetAlarm(); +} + +#endif /* _CHCORE_TIMER_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/chcore_v6m.c b/os/common/ports/ARMCMx/chcore_v6m.c new file mode 100644 index 000000000..b799a8724 --- /dev/null +++ b/os/common/ports/ARMCMx/chcore_v6m.c @@ -0,0 +1,147 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chcore_v6m.c + * @brief ARMv6-M architecture port code. + * + * @addtogroup ARMCMx_V6M_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module interrupt handlers. */ +/*===========================================================================*/ + +#if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__) +/** + * @brief NMI vector. + * @details The NMI vector is used for exception mode re-entering after a + * context switch. + */ +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void NMI_Handler(void) { +/*lint -restore*/ + + /* The port_extctx structure is pointed by the PSP register.*/ + struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp++; + + /* Writing back the modified PSP value.*/ + __set_PSP((uint32_t)ctxp); + + /* Restoring the normal interrupts status.*/ + port_unlock_from_isr(); +} +#endif /* !CORTEX_ALTERNATE_SWITCH */ + +#if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__) +/** + * @brief PendSV vector. + * @details The PendSV vector is used for exception mode re-entering after a + * context switch. + */ +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void PendSV_Handler(void) { +/*lint -restore*/ + + /* The port_extctx structure is pointed by the PSP register.*/ + struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp++; + + /* Writing back the modified PSP value.*/ + __set_PSP((uint32_t)ctxp); +} +#endif /* CORTEX_ALTERNATE_SWITCH */ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief IRQ epilogue code. + * + * @param[in] lr value of the @p LR register on ISR entry + */ +void _port_irq_epilogue(regarm_t lr) { + + if (lr != (regarm_t)0xFFFFFFF1U) { + struct port_extctx *ctxp; + + port_lock_from_isr(); + + /* The extctx structure is pointed by the PSP register.*/ + ctxp = (struct port_extctx *)__get_PSP(); + + /* Adding an artificial exception return context, there is no need to + populate it fully.*/ + ctxp--; + + /* Writing back the modified PSP value.*/ + __set_PSP((uint32_t)ctxp); + + /* Setting up a fake XPSR register value.*/ + ctxp->xpsr = (regarm_t)0x01000000; + + /* The exit sequence is different depending on if a preemption is + required or not.*/ + if (chSchIsPreemptionRequired()) { + /* Preemption is required we need to enforce a context switch.*/ + ctxp->pc = (regarm_t)_port_switch_from_isr; + } + else { + /* Preemption not required, we just need to exit the exception + atomically.*/ + ctxp->pc = (regarm_t)_port_exit_from_isr; + } + + /* Note, returning without unlocking is intentional, this is done in + order to keep the rest of the context switch atomic.*/ + } +} + +/** @} */ diff --git a/os/common/ports/ARMCMx/chcore_v6m.h b/os/common/ports/ARMCMx/chcore_v6m.h new file mode 100644 index 000000000..0ff3288b6 --- /dev/null +++ b/os/common/ports/ARMCMx/chcore_v6m.h @@ -0,0 +1,440 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chcore_v6m.h + * @brief ARMv6-M architecture port macros and structures. + * + * @addtogroup ARMCMx_V6M_CORE + * @{ + */ + +#ifndef _CHCORE_V6M_H_ +#define _CHCORE_V6M_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN sizeof (void *) + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN sizeof (stkalign_t) + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN PORT_STACK_ALIGN +/** @} */ + +/** + * @brief PendSV priority level. + * @note This priority is enforced to be equal to @p 0, + * this handler always has the highest priority that cannot preempt + * the kernel. + */ +#define CORTEX_PRIORITY_PENDSV 0 + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 16 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) +#define PORT_IDLE_THREAD_STACK_SIZE 16 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * @note In this port this value is conservatively set to 64 because the + * function @p chSchDoReschedule() can have a stack frame, especially + * with compiler optimizations disabled. The value can be reduced + * when compiler optimizations are enabled. + */ +#if !defined(PORT_INT_REQUIRED_STACK) +#define PORT_INT_REQUIRED_STACK 64 +#endif + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#if !defined(CORTEX_ENABLE_WFI_IDLE) +#define CORTEX_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief Alternate preemption method. + * @details Activating this option will make the Kernel use the PendSV + * handler for preemption instead of the NMI handler. + */ +#ifndef CORTEX_ALTERNATE_SWITCH +#define CORTEX_ALTERNATE_SWITCH FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @name Architecture and Compiler + * @{ + */ +#if ((CORTEX_MODEL == 0) && !defined(__CORE_CM0PLUS_H_DEPENDANT)) || \ + defined(__DOXYGEN__) +/** + * @brief Macro defining the specific ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM_v6M + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "ARMv6-M" + +/** + * @brief Name of the architecture variant. + */ +#define PORT_CORE_VARIANT_NAME "Cortex-M0" + +#elif (CORTEX_MODEL == 0) && defined(__CORE_CM0PLUS_H_DEPENDANT) +#define PORT_ARCHITECTURE_ARM_v6M +#define PORT_ARCHITECTURE_NAME "ARMv6-M" +#define PORT_CORE_VARIANT_NAME "Cortex-M0+" +#endif + +/** + * @brief Port-specific information string. + */ +#if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__) +#define PORT_INFO "Preemption through NMI" +#else +#define PORT_INFO "Preemption through PendSV" +#endif +/** @} */ + +/** + * @brief Maximum usable priority for normal ISRs. + */ +#if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__) +#define CORTEX_MAX_KERNEL_PRIORITY 1 +#else +#define CORTEX_MAX_KERNEL_PRIORITY 0 +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) + + /* The documentation of the following declarations is in chconf.h in order + to not have duplicated structure names into the documentation.*/ +#if !defined(__DOXYGEN__) +struct port_extctx { + regarm_t r0; + regarm_t r1; + regarm_t r2; + regarm_t r3; + regarm_t r12; + regarm_t lr_thd; + regarm_t pc; + regarm_t xpsr; +}; + +struct port_intctx { + regarm_t r8; + regarm_t r9; + regarm_t r10; + regarm_t r11; + regarm_t r4; + regarm_t r5; + regarm_t r6; + regarm_t r7; + regarm_t lr; +}; +#endif /* !defined(__DOXYGEN__) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + (tp)->ctx.r13 = (struct port_intctx *)((uint8_t *)(wtop) - \ + sizeof (struct port_intctx)); \ + (tp)->ctx.r13->r4 = (regarm_t)(pf); \ + (tp)->ctx.r13->r5 = (regarm_t)(arg); \ + (tp)->ctx.r13->lr = (regarm_t)_port_thread_start; \ +} + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) (sizeof (struct port_intctx) + \ + sizeof (struct port_extctx) + \ + ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_IRQ_PROLOGUE() \ + regarm_t _saved_lr = (regarm_t)__builtin_return_address(0) +#elif defined(__ICCARM__) +#define PORT_IRQ_PROLOGUE() \ + regarm_t _saved_lr = (regarm_t)__get_LR() +#elif defined(__CC_ARM) +#define PORT_IRQ_PROLOGUE() \ + regarm_t _saved_lr = (regarm_t)__return_address() +#endif + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) void id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) void id(void) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__) +#define port_switch(ntp, otp) _port_switch(ntp, otp) +#else +#define port_switch(ntp, otp) { \ + struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ + if ((stkalign_t *)(r13 - 1) < (otp)->stklimit) { \ + chSysHalt("stack overflow"); \ + } \ + _port_switch(ntp, otp); \ +} +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void _port_irq_epilogue(regarm_t lr); + void _port_switch(thread_t *ntp, thread_t *otp); + void _port_thread_start(void); + void _port_switch_from_isr(void); + void _port_exit_from_isr(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + */ +static inline void port_init(void) { + + NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + + return (syssts_t)__get_PRIMASK(); +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return (sts & (syssts_t)1) == (syssts_t)0; +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + + return (bool)((__get_IPSR() & 0x1FFU) != 0U); +} + +/** + * @brief Kernel-lock action. + * @details In this port this function disables interrupts globally. + */ +static inline void port_lock(void) { + + __disable_irq(); +} + +/** + * @brief Kernel-unlock action. + * @details In this port this function enables interrupts globally. + */ +static inline void port_unlock(void) { + + __enable_irq(); +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details In this port this function disables interrupts globally. + * @note Same as @p port_lock() in this port. + */ +static inline void port_lock_from_isr(void) { + + port_lock(); +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details In this port this function enables interrupts globally. + * @note Same as @p port_lock() in this port. + */ +static inline void port_unlock_from_isr(void) { + + port_unlock(); +} + +/** + * @brief Disables all the interrupt sources. + */ +static inline void port_disable(void) { + + __disable_irq(); +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + */ +static inline void port_suspend(void) { + + __disable_irq(); +} + +/** + * @brief Enables all the interrupt sources. + */ +static inline void port_enable(void) { + + __enable_irq(); +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + * @note Implemented as an inlined @p WFI instruction. + */ +static inline void port_wait_for_interrupt(void) { + +#if CORTEX_ENABLE_WFI_IDLE == TRUE + __WFI(); +#endif +} + +#endif /* _FROM_ASM_ */ + +#endif /* _CHCORE_V6M_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/chcore_v7m.c b/os/common/ports/ARMCMx/chcore_v7m.c new file mode 100644 index 000000000..82cbb1c32 --- /dev/null +++ b/os/common/ports/ARMCMx/chcore_v7m.c @@ -0,0 +1,168 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chcore_v7m.c + * @brief ARMv7-M architecture port code. + * + * @addtogroup ARMCMx_V7M_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module interrupt handlers. */ +/*===========================================================================*/ + +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) +/** + * @brief SVC vector. + * @details The SVC vector is used for exception mode re-entering after a + * context switch. + * @note The PendSV vector is only used in advanced kernel mode. + */ +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void SVC_Handler(void) { +/*lint -restore*/ + struct port_extctx *ctxp; + +#if CORTEX_USE_FPU + /* Enforcing unstacking of the FP part of the context.*/ + FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; +#endif + + /* The port_extctx structure is pointed by the PSP register.*/ + ctxp = (struct port_extctx *)__get_PSP(); + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp++; + + /* Restoring real position of the original stack frame.*/ + __set_PSP((uint32_t)ctxp); + + /* Restoring the normal interrupts status.*/ + port_unlock_from_isr(); +} +#endif /* CORTEX_SIMPLIFIED_PRIORITY == FALSE */ + +#if (CORTEX_SIMPLIFIED_PRIORITY == TRUE) || defined(__DOXYGEN__) +/** + * @brief PendSV vector. + * @details The PendSV vector is used for exception mode re-entering after a + * context switch. + * @note The PendSV vector is only used in compact kernel mode. + */ +/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ +void PendSV_Handler(void) { +/*lint -restore*/ + struct port_extctx *ctxp; + +#if CORTEX_USE_FPU + /* Enforcing unstacking of the FP part of the context.*/ + FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; +#endif + + /* The port_extctx structure is pointed by the PSP register.*/ + ctxp = (struct port_extctx *)__get_PSP(); + + /* Discarding the current exception context and positioning the stack to + point to the real one.*/ + ctxp++; + + /* Writing back the modified PSP value.*/ + __set_PSP((uint32_t)ctxp); +} +#endif /* CORTEX_SIMPLIFIED_PRIORITY == TRUE */ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Exception exit redirection to _port_switch_from_isr(). + */ +void _port_irq_epilogue(void) { + + port_lock_from_isr(); + if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0U) { + struct port_extctx *ctxp; + +#if CORTEX_USE_FPU == TRUE + /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ + (void) __get_FPSCR(); +#endif + + /* The port_extctx structure is pointed by the PSP register.*/ + ctxp = (struct port_extctx *)__get_PSP(); + + /* Adding an artificial exception return context, there is no need to + populate it fully.*/ + ctxp--; + + /* Setting up a fake XPSR register value.*/ + ctxp->xpsr = (regarm_t)0x01000000; +#if CORTEX_USE_FPU == TRUE + ctxp->fpscr = (regarm_t)FPU->FPDSCR; +#endif + + /* Writing back the modified PSP value.*/ + __set_PSP((uint32_t)ctxp); + + /* The exit sequence is different depending on if a preemption is + required or not.*/ + if (chSchIsPreemptionRequired()) { + /* Preemption is required we need to enforce a context switch.*/ + ctxp->pc = (regarm_t)_port_switch_from_isr; + } + else { + /* Preemption not required, we just need to exit the exception + atomically.*/ + ctxp->pc = (regarm_t)_port_exit_from_isr; + } + + /* Note, returning without unlocking is intentional, this is done in + order to keep the rest of the context switch atomic.*/ + return; + } + port_unlock_from_isr(); +} + +/** @} */ diff --git a/os/common/ports/ARMCMx/chcore_v7m.h b/os/common/ports/ARMCMx/chcore_v7m.h new file mode 100644 index 000000000..3c0dfc4a1 --- /dev/null +++ b/os/common/ports/ARMCMx/chcore_v7m.h @@ -0,0 +1,698 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file chcore_v7m.h + * @brief ARMv7-M architecture port macros and structures. + * + * @addtogroup ARMCMx_V7M_CORE + * @{ + */ + +#ifndef _CHCORE_V7M_H_ +#define _CHCORE_V7M_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT TRUE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN sizeof (void *) + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN sizeof (stkalign_t) + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN (PORT_ENABLE_GUARD_PAGES == TRUE ? \ + 32U : PORT_STACK_ALIGN) +/** @} */ + +/** + * @brief Disabled value for BASEPRI register. + */ +#define CORTEX_BASEPRI_DISABLED 0U + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables stack overflow guard pages using MPU. + * @note This option can only be enabled if also option + * @p CH_DBG_ENABLE_STACK_CHECK is enabled. + * @note The use of this option has an overhead of 32 bytes for each + * thread. + */ +#if !defined(PORT_ENABLE_GUARD_PAGES) || defined(__DOXYGEN__) +#define PORT_ENABLE_GUARD_PAGES FALSE +#endif + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 16 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 16 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * @note In this port this value is conservatively set to 64 because the + * function @p chSchDoReschedule() can have a stack frame, especially + * with compiler optimizations disabled. The value can be reduced + * when compiler optimizations are enabled. + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 64 +#endif + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#if !defined(CORTEX_ENABLE_WFI_IDLE) +#define CORTEX_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief FPU support in context switch. + * @details Activating this option activates the FPU support in the kernel. + */ +#if !defined(CORTEX_USE_FPU) +#define CORTEX_USE_FPU CORTEX_HAS_FPU +#elif (CORTEX_USE_FPU == TRUE) && (CORTEX_HAS_FPU == FALSE) +/* This setting requires an FPU presence check in case it is externally + redefined.*/ +#error "the selected core does not have an FPU" +#endif + +/** + * @brief Simplified priority handling flag. + * @details Activating this option makes the Kernel work in compact mode. + * In compact mode interrupts are disabled globally instead of + * raising the priority mask to some intermediate level. + */ +#if !defined(CORTEX_SIMPLIFIED_PRIORITY) +#define CORTEX_SIMPLIFIED_PRIORITY FALSE +#endif + +/** + * @brief SVCALL handler priority. + * @note The default SVCALL handler priority is defaulted to + * @p CORTEX_MAXIMUM_PRIORITY+1, this reserves the + * @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts + * priority level. + */ +#if !defined(CORTEX_PRIORITY_SVCALL) +#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1U) +#elif !PORT_IRQ_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL) +/* If it is externally redefined then better perform a validity check on it.*/ +#error "invalid priority level specified for CORTEX_PRIORITY_SVCALL" +#endif + +/** + * @brief NVIC VTOR initialization expression. + */ +#if !defined(CORTEX_VTOR_INIT) || defined(__DOXYGEN__) +#define CORTEX_VTOR_INIT 0x00000000U +#endif + +/** + * @brief NVIC PRIGROUP initialization expression. + * @details The default assigns all available priority bits as preemption + * priority with no sub-priority. + */ +#if !defined(CORTEX_PRIGROUP_INIT) || defined(__DOXYGEN__) +#define CORTEX_PRIGROUP_INIT (7 - CORTEX_PRIORITY_BITS) +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) +/** + * @brief MPU guard page size. + */ +#if (PORT_ENABLE_GUARD_PAGES == TRUE) || defined(__DOXYGEN__) + #if CH_DBG_ENABLE_STACK_CHECK == FALSE + #error "PORT_ENABLE_GUARD_PAGES requires CH_DBG_ENABLE_STACK_CHECK" + #endif + #if __MPU_PRESENT == 0 + #error "MPU not present in current device" + #endif + #define PORT_GUARD_PAGE_SIZE 32U +#else + #define PORT_GUARD_PAGE_SIZE 0U +#endif +#endif /* !defined(_FROM_ASM_) */ + +/** + * @name Architecture and Compiler + * @{ + */ +#if (CORTEX_MODEL == 3) || defined(__DOXYGEN__) +/** + * @brief Macro defining the specific ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM_v7M + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "ARMv7-M" + +/** + * @brief Name of the architecture variant. + */ +#if (PORT_ENABLE_GUARD_PAGES == FALSE) || defined(__DOXYGEN__) + #define PORT_CORE_VARIANT_NAME "Cortex-M3" +#else + #define PORT_CORE_VARIANT_NAME "Cortex-M3 (MPU)" +#endif + +#elif (CORTEX_MODEL == 4) + #define PORT_ARCHITECTURE_ARM_v7ME + #define PORT_ARCHITECTURE_NAME "ARMv7E-M" + #if CORTEX_USE_FPU + #if PORT_ENABLE_GUARD_PAGES == FALSE + #define PORT_CORE_VARIANT_NAME "Cortex-M4F" + #else + #define PORT_CORE_VARIANT_NAME "Cortex-M4F (MPU)" + #endif + #else + #if PORT_ENABLE_GUARD_PAGES == FALSE + #define PORT_CORE_VARIANT_NAME "Cortex-M4" + #else + #define PORT_CORE_VARIANT_NAME "Cortex-M4 (MPU)" + #endif + #endif + +#elif (CORTEX_MODEL == 7) + #define PORT_ARCHITECTURE_ARM_v7ME + #define PORT_ARCHITECTURE_NAME "ARMv7E-M" + #if CORTEX_USE_FPU + #if PORT_ENABLE_GUARD_PAGES == FALSE + #define PORT_CORE_VARIANT_NAME "Cortex-M7F" + #else + #define PORT_CORE_VARIANT_NAME "Cortex-M7F (MPU)" + #endif + #else + #if PORT_ENABLE_GUARD_PAGES == FALSE + #define PORT_CORE_VARIANT_NAME "Cortex-M7" + #else + #define PORT_CORE_VARIANT_NAME "Cortex-M7 (MPU)" + #endif + #endif +#endif + +/** + * @brief Port-specific information string. + */ +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) +#define PORT_INFO "Advanced kernel mode" +#else +#define PORT_INFO "Compact kernel mode" +#endif +/** @} */ + +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) +/** + * @brief Maximum usable priority for normal ISRs. + */ +#define CORTEX_MAX_KERNEL_PRIORITY (CORTEX_PRIORITY_SVCALL + 1U) + +/** + * @brief BASEPRI level within kernel lock. + */ +#define CORTEX_BASEPRI_KERNEL \ + CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY) +#else + +#define CORTEX_MAX_KERNEL_PRIORITY 0U +#endif + +/** + * @brief PendSV priority level. + * @note This priority is enforced to be equal to + * @p CORTEX_MAX_KERNEL_PRIORITY, this handler always have the + * highest priority that cannot preempt the kernel. + */ +#define CORTEX_PRIORITY_PENDSV CORTEX_MAX_KERNEL_PRIORITY + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/* The documentation of the following declarations is in chconf.h in order + to not have duplicated structure names into the documentation.*/ +#if !defined(__DOXYGEN__) +struct port_extctx { + regarm_t r0; + regarm_t r1; + regarm_t r2; + regarm_t r3; + regarm_t r12; + regarm_t lr_thd; + regarm_t pc; + regarm_t xpsr; +#if CORTEX_USE_FPU + regarm_t s0; + regarm_t s1; + regarm_t s2; + regarm_t s3; + regarm_t s4; + regarm_t s5; + regarm_t s6; + regarm_t s7; + regarm_t s8; + regarm_t s9; + regarm_t s10; + regarm_t s11; + regarm_t s12; + regarm_t s13; + regarm_t s14; + regarm_t s15; + regarm_t fpscr; + regarm_t reserved; +#endif /* CORTEX_USE_FPU */ +}; + +struct port_intctx { +#if CORTEX_USE_FPU + regarm_t s16; + regarm_t s17; + regarm_t s18; + regarm_t s19; + regarm_t s20; + regarm_t s21; + regarm_t s22; + regarm_t s23; + regarm_t s24; + regarm_t s25; + regarm_t s26; + regarm_t s27; + regarm_t s28; + regarm_t s29; + regarm_t s30; + regarm_t s31; +#endif /* CORTEX_USE_FPU */ + regarm_t r4; + regarm_t r5; + regarm_t r6; + regarm_t r7; + regarm_t r8; + regarm_t r9; + regarm_t r10; + regarm_t r11; + regarm_t lr; +}; +#endif /* !defined(__DOXYGEN__) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + (tp)->ctx.r13 = (struct port_intctx *)((uint8_t *)(wtop) - \ + sizeof (struct port_intctx)); \ + (tp)->ctx.r13->r4 = (regarm_t)(pf); \ + (tp)->ctx.r13->r5 = (regarm_t)(arg); \ + (tp)->ctx.r13->lr = (regarm_t)_port_thread_start; \ +} + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) ((size_t)PORT_GUARD_PAGE_SIZE + \ + sizeof (struct port_intctx) + \ + sizeof (struct port_extctx) + \ + (size_t)(n) + \ + (size_t)PORT_INT_REQUIRED_STACK) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#if (PORT_ENABLE_GUARD_PAGES == FALSE) || defined(__DOXYGEN__) +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] +#else +#define PORT_WORKING_AREA(s, n) \ + ALIGNED_VAR(32) stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] +#endif + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() _port_irq_epilogue() + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) void id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) void id(void) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__) +#define port_switch(ntp, otp) _port_switch(ntp, otp) +#else +#if PORT_ENABLE_GUARD_PAGES == FALSE +#define port_switch(ntp, otp) { \ + struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ + if ((stkalign_t *)(r13 - 1) < (otp)->stklimit) { \ + chSysHalt("stack overflow"); \ + } \ + _port_switch(ntp, otp); \ +} +#else +#define port_switch(ntp, otp) { \ + _port_switch(ntp, otp); \ + \ + /* Setting up the guard page for the switched-in thread.*/ \ + mpuConfigureRegion(MPU_REGION_0, \ + chThdGetSelfX()->stklimit, \ + MPU_RASR_ATTR_AP_NA_NA | \ + MPU_RASR_ATTR_NON_CACHEABLE | \ + MPU_RASR_SIZE_32 | \ + MPU_RASR_ENABLE); \ +} +#endif +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void _port_irq_epilogue(void); + void _port_switch(thread_t *ntp, thread_t *otp); + void _port_thread_start(void); + void _port_switch_from_isr(void); + void _port_exit_from_isr(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + */ +static inline void port_init(void) { + + /* Initialization of the vector table and priority related settings.*/ + SCB->VTOR = CORTEX_VTOR_INIT; + + /* Initializing priority grouping.*/ + NVIC_SetPriorityGrouping(CORTEX_PRIGROUP_INIT); + + /* DWT cycle counter enable, note, the M7 requires DWT unlocking.*/ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; +#if CORTEX_MODEL == 7 + DWT->LAR = 0xC5ACCE55U; +#endif + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + + /* Initialization of the system vectors used by the port.*/ +#if CORTEX_SIMPLIFIED_PRIORITY == FALSE + NVIC_SetPriority(SVCall_IRQn, CORTEX_PRIORITY_SVCALL); +#endif + NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); + +#if PORT_ENABLE_GUARD_PAGES == TRUE + { + extern stkalign_t __main_thread_stack_base__; + + /* Setting up the guard page on the main() function stack base + initially.*/ + mpuConfigureRegion(MPU_REGION_0, + &__main_thread_stack_base__, + MPU_RASR_ATTR_AP_NA_NA | + MPU_RASR_ATTR_NON_CACHEABLE | + MPU_RASR_SIZE_32 | + MPU_RASR_ENABLE); + + /* MPU is enabled.*/ + mpuEnable(MPU_CTRL_PRIVDEFENA); + } +#endif +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + syssts_t sts; + +#if CORTEX_SIMPLIFIED_PRIORITY == FALSE + sts = (syssts_t)__get_BASEPRI(); +#else /* CORTEX_SIMPLIFIED_PRIORITY */ + sts = (syssts_t)__get_PRIMASK(); +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ + return sts; +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + +#if CORTEX_SIMPLIFIED_PRIORITY == FALSE + return sts == (syssts_t)CORTEX_BASEPRI_DISABLED; +#else /* CORTEX_SIMPLIFIED_PRIORITY */ + return (sts & (syssts_t)1) == (syssts_t)0; +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + + return (bool)((__get_IPSR() & 0x1FFU) != 0U); +} + +/** + * @brief Kernel-lock action. + * @details In this port this function raises the base priority to kernel + * level. + */ +static inline void port_lock(void) { + +#if CORTEX_SIMPLIFIED_PRIORITY == FALSE +#if defined(__CM7_REV) +#if __CM7_REV <= 1 + __disable_irq(); +#endif +#endif + __set_BASEPRI(CORTEX_BASEPRI_KERNEL); +#if defined(__CM7_REV) +#if __CM7_REV <= 1 + __enable_irq(); +#endif +#endif +#else /* CORTEX_SIMPLIFIED_PRIORITY */ + __disable_irq(); +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ +} + +/** + * @brief Kernel-unlock action. + * @details In this port this function lowers the base priority to user + * level. + */ +static inline void port_unlock(void) { + +#if CORTEX_SIMPLIFIED_PRIORITY == FALSE + __set_BASEPRI(CORTEX_BASEPRI_DISABLED); +#else /* CORTEX_SIMPLIFIED_PRIORITY */ + __enable_irq(); +#endif /* CORTEX_SIMPLIFIED_PRIORITY */ +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details In this port this function raises the base priority to kernel + * level. + * @note Same as @p port_lock() in this port. + */ +static inline void port_lock_from_isr(void) { + + port_lock(); +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details In this port this function lowers the base priority to user + * level. + * @note Same as @p port_unlock() in this port. + */ +static inline void port_unlock_from_isr(void) { + + port_unlock(); +} + +/** + * @brief Disables all the interrupt sources. + * @note In this port it disables all the interrupt sources by raising + * the priority mask to level 0. + */ +static inline void port_disable(void) { + + __disable_irq(); +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + * @note Interrupt sources above kernel level remains enabled. + * @note In this port it raises/lowers the base priority to kernel level. + */ +static inline void port_suspend(void) { + +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) + __set_BASEPRI(CORTEX_BASEPRI_KERNEL); + __enable_irq(); +#else + __disable_irq(); +#endif +} + +/** + * @brief Enables all the interrupt sources. + * @note In this port it lowers the base priority to user level. + */ +static inline void port_enable(void) { + +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) + __set_BASEPRI(CORTEX_BASEPRI_DISABLED); +#endif + __enable_irq(); +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + * @note Implemented as an inlined @p WFI instruction. + */ +static inline void port_wait_for_interrupt(void) { + +#if CORTEX_ENABLE_WFI_IDLE == TRUE + __WFI(); +#endif +} + +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +static inline rtcnt_t port_rt_get_counter_value(void) { + + return DWT->CYCCNT; +} + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CHCORE_V7M_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/cmsis_os/cmsis_os.c b/os/common/ports/ARMCMx/cmsis_os/cmsis_os.c new file mode 100644 index 000000000..df4b6ba31 --- /dev/null +++ b/os/common/ports/ARMCMx/cmsis_os/cmsis_os.c @@ -0,0 +1,554 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/* + Concepts and parts of this file have been contributed by Andre R. + */ + +/** + * @file cmsis_os.c + * @brief CMSIS RTOS module code. + * + * @addtogroup CMSIS_OS + * @{ + */ + +#include "cmsis_os.h" +#include + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +int32_t cmsis_os_started; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +static memory_pool_t sempool; +static semaphore_t semaphores[CMSIS_CFG_NUM_SEMAPHORES]; + +static memory_pool_t timpool; +static struct os_timer_cb timers[CMSIS_CFG_NUM_TIMERS]; + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/** + * @brief Virtual timers common callback. + */ +static void timer_cb(void const *arg) { + + osTimerId timer_id = (osTimerId)arg; + timer_id->ptimer(timer_id->argument); + if (timer_id->type == osTimerPeriodic) { + chSysLockFromISR(); + chVTDoSetI(&timer_id->vt, MS2ST(timer_id->millisec), + (vtfunc_t)timer_cb, timer_id); + chSysUnlockFromISR(); + } +} + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Kernel initialization. + */ +osStatus osKernelInitialize(void) { + + cmsis_os_started = 0; + + chSysInit(); + chThdSetPriority(HIGHPRIO); + + chPoolObjectInit(&sempool, sizeof(semaphore_t), chCoreAlloc); + chPoolLoadArray(&sempool, semaphores, CMSIS_CFG_NUM_SEMAPHORES); + + chPoolObjectInit(&timpool, sizeof(virtual_timer_t), chCoreAlloc); + chPoolLoadArray(&timpool, timers, CMSIS_CFG_NUM_TIMERS); + + return osOK; +} + +/** + * @brief Kernel start. + */ +osStatus osKernelStart(void) { + + cmsis_os_started = 1; + + chThdSetPriority(NORMALPRIO); + + return osOK; +} + +/** + * @brief Creates a thread. + */ +osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument) { + size_t size; + + size = thread_def->stacksize == 0 ? CMSIS_CFG_DEFAULT_STACK : + thread_def->stacksize; + return (osThreadId)chThdCreateFromHeap(0, + THD_WORKING_AREA_SIZE(size), + NORMALPRIO+thread_def->tpriority, + (tfunc_t)thread_def->pthread, + argument); +} + +/** + * @brief Thread termination. + * @note The thread is not really terminated but asked to terminate which + * is not compliant. + */ +osStatus osThreadTerminate(osThreadId thread_id) { + + if (thread_id == osThreadGetId()) { + /* Note, no memory will be recovered unless a cleaner thread is + implemented using the registry.*/ + chThdExit(0); + } + chThdTerminate(thread_id); + chThdWait((thread_t *)thread_id); + + return osOK; +} + +/** + * @brief Change thread priority. + * @note This can interfere with the priority inheritance mechanism. + */ +osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio) { + osPriority oldprio; + thread_t * tp = (thread_t *)thread_id; + + chSysLock(); + + /* Changing priority.*/ +#if CH_CFG_USE_MUTEXES + oldprio = (osPriority)tp->p_realprio; + if ((tp->p_prio == tp->p_realprio) || ((tprio_t)newprio > tp->p_prio)) + tp->p_prio = (tprio_t)newprio; + tp->p_realprio = (tprio_t)newprio; +#else + oldprio = tp->p_prio; + tp->p_prio = (tprio_t)newprio; +#endif + + /* The following states need priority queues reordering.*/ + switch (tp->p_state) { +#if CH_CFG_USE_MUTEXES | \ + CH_CFG_USE_CONDVARS | \ + (CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY) | \ + (CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY) +#if CH_CFG_USE_MUTEXES + case CH_STATE_WTMTX: +#endif +#if CH_CFG_USE_CONDVARS + case CH_STATE_WTCOND: +#endif +#if CH_CFG_USE_SEMAPHORES && CH_CFG_USE_SEMAPHORES_PRIORITY + case CH_STATE_WTSEM: +#endif +#if CH_CFG_USE_MESSAGES && CH_CFG_USE_MESSAGES_PRIORITY + case CH_STATE_SNDMSGQ: +#endif + /* Re-enqueues tp with its new priority on the queue.*/ + queue_prio_insert(queue_dequeue(tp), + (threads_queue_t *)tp->p_u.wtobjp); + break; +#endif + case CH_STATE_READY: +#if CH_DBG_ENABLE_ASSERTS + /* Prevents an assertion in chSchReadyI().*/ + tp->p_state = CH_STATE_CURRENT; +#endif + /* Re-enqueues tp with its new priority on the ready list.*/ + chSchReadyI(queue_dequeue(tp)); + break; + } + + /* Rescheduling.*/ + chSchRescheduleS(); + + chSysUnlock(); + + return oldprio; +} + +/** + * @brief Create a timer. + */ +osTimerId osTimerCreate(const osTimerDef_t *timer_def, + os_timer_type type, + void *argument) { + + osTimerId timer = chPoolAlloc(&timpool); + chVTObjectInit(&timer->vt); + timer->ptimer = timer_def->ptimer; + timer->type = type; + timer->argument = argument; + return timer; +} + +/** + * @brief Start a timer. + */ +osStatus osTimerStart(osTimerId timer_id, uint32_t millisec) { + + if ((millisec == 0) || (millisec == osWaitForever)) + return osErrorValue; + + timer_id->millisec = millisec; + chVTSet(&timer_id->vt, MS2ST(millisec), (vtfunc_t)timer_cb, timer_id); + + return osOK; +} + +/** + * @brief Stop a timer. + */ +osStatus osTimerStop(osTimerId timer_id) { + + chVTReset(&timer_id->vt); + + return osOK; +} + +/** + * @brief Delete a timer. + */ +osStatus osTimerDelete(osTimerId timer_id) { + + chVTReset(&timer_id->vt); + chPoolFree(&timpool, (void *)timer_id); + + return osOK; +} + +/** + * @brief Send signals. + */ +int32_t osSignalSet(osThreadId thread_id, int32_t signals) { + int32_t oldsignals; + + syssts_t sts = chSysGetStatusAndLockX(); + oldsignals = (int32_t)thread_id->p_epending; + chEvtSignalI((thread_t *)thread_id, (eventmask_t)signals); + chSysRestoreStatusX(sts); + + return oldsignals; +} + +/** + * @brief Clear signals. + */ +int32_t osSignalClear(osThreadId thread_id, int32_t signals) { + eventmask_t m; + + chSysLock(); + + m = thread_id->p_epending & (eventmask_t)signals; + thread_id->p_epending &= ~(eventmask_t)signals; + + chSysUnlock(); + + return (int32_t)m; +} + +/** + * @brief Wait for signals. + */ +osEvent osSignalWait(int32_t signals, uint32_t millisec) { + osEvent event; + systime_t timeout = ((millisec == 0) || (millisec == osWaitForever)) ? + TIME_INFINITE : MS2ST(millisec); + + if (signals == 0) + event.value.signals = (uint32_t)chEvtWaitAnyTimeout(ALL_EVENTS, timeout); + else + event.value.signals = (uint32_t)chEvtWaitAllTimeout((eventmask_t)signals, + timeout); + + /* Type of event.*/ + if (event.value.signals == 0) + event.status = osEventTimeout; + else + event.status = osEventSignal; + + return event; +} + +/** + * @brief Create a semaphore. + * @note @p semaphore_def is not used. + * @note Can involve memory allocation. + */ +osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, + int32_t count) { + + (void)semaphore_def; + + semaphore_t *sem = chPoolAlloc(&sempool); + chSemObjectInit(sem, (cnt_t)count); + return sem; +} + +/** + * @brief Wait on a semaphore. + */ +int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec) { + systime_t timeout = ((millisec == 0) || (millisec == osWaitForever)) ? + TIME_INFINITE : MS2ST(millisec); + + msg_t msg = chSemWaitTimeout((semaphore_t *)semaphore_id, timeout); + switch (msg) { + case MSG_OK: + return osOK; + case MSG_TIMEOUT: + return osErrorTimeoutResource; + } + return osErrorResource; +} + +/** + * @brief Release a semaphore. + */ +osStatus osSemaphoreRelease(osSemaphoreId semaphore_id) { + + syssts_t sts = chSysGetStatusAndLockX(); + chSemSignalI((semaphore_t *)semaphore_id); + chSysRestoreStatusX(sts); + + return osOK; +} + +/** + * @brief Deletes a semaphore. + * @note After deletion there could be references in the system to a + * non-existent semaphore. + */ +osStatus osSemaphoreDelete(osSemaphoreId semaphore_id) { + + chSemReset((semaphore_t *)semaphore_id, 0); + chPoolFree(&sempool, (void *)semaphore_id); + + return osOK; +} + +/** + * @brief Create a mutex. + * @note @p mutex_def is not used. + * @note Can involve memory allocation. + */ +osMutexId osMutexCreate(const osMutexDef_t *mutex_def) { + + (void)mutex_def; + + binary_semaphore_t *mtx = chPoolAlloc(&sempool); + chBSemObjectInit(mtx, false); + return mtx; +} + +/** + * @brief Wait on a mutex. + */ +osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec) { + systime_t timeout = ((millisec == 0) || (millisec == osWaitForever)) ? + TIME_INFINITE : MS2ST(millisec); + + msg_t msg = chBSemWaitTimeout((binary_semaphore_t *)mutex_id, timeout); + switch (msg) { + case MSG_OK: + return osOK; + case MSG_TIMEOUT: + return osErrorTimeoutResource; + } + return osErrorResource; +} + +/** + * @brief Release a mutex. + */ +osStatus osMutexRelease(osMutexId mutex_id) { + + syssts_t sts = chSysGetStatusAndLockX(); + chBSemSignalI((binary_semaphore_t *)mutex_id); + chSysRestoreStatusX(sts); + + return osOK; +} + +/** + * @brief Deletes a mutex. + * @note After deletion there could be references in the system to a + * non-existent semaphore. + */ +osStatus osMutexDelete(osMutexId mutex_id) { + + chSemReset((semaphore_t *)mutex_id, 0); + chPoolFree(&sempool, (void *)mutex_id); + + return osOK; +} + +/** + * @brief Create a memory pool. + * @note The pool is not really created because it is allocated statically, + * this function just re-initializes it. + */ +osPoolId osPoolCreate(const osPoolDef_t *pool_def) { + + chPoolObjectInit(pool_def->pool, (size_t)pool_def->item_sz, NULL); + chPoolLoadArray(pool_def->pool, pool_def->items, (size_t)pool_def->pool_sz); + + return (osPoolId)pool_def->pool; +} + +/** + * @brief Allocate an object. + */ +void *osPoolAlloc(osPoolId pool_id) { + void *object; + + syssts_t sts = chSysGetStatusAndLockX(); + object = chPoolAllocI((memory_pool_t *)pool_id); + chSysRestoreStatusX(sts); + + return object; +} + +/** + * @brief Allocate an object clearing it. + */ +void *osPoolCAlloc(osPoolId pool_id) { + void *object; + + object = chPoolAllocI((memory_pool_t *)pool_id); + memset(object, 0, pool_id->mp_object_size); + return object; +} + +/** + * @brief Free an object. + */ +osStatus osPoolFree(osPoolId pool_id, void *block) { + + syssts_t sts = chSysGetStatusAndLockX(); + chPoolFreeI((memory_pool_t *)pool_id, block); + chSysRestoreStatusX(sts); + + return osOK; +} + +/** + * @brief Create a message queue. + * @note The queue is not really created because it is allocated statically, + * this function just re-initializes it. + */ +osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, + osThreadId thread_id) { + + /* Ignoring this parameter for now.*/ + (void)thread_id; + + if (queue_def->item_sz > sizeof (msg_t)) + return NULL; + + chMBObjectInit(queue_def->mailbox, + queue_def->items, + (size_t)queue_def->queue_sz); + + return (osMessageQId) queue_def->mailbox; +} + +/** + * @brief Put a message in the queue. + */ +osStatus osMessagePut(osMessageQId queue_id, + uint32_t info, + uint32_t millisec) { + msg_t msg; + systime_t timeout = ((millisec == 0) || (millisec == osWaitForever)) ? + TIME_INFINITE : MS2ST(millisec); + + if (port_is_isr_context()) { + + /* Waiting makes no sense in ISRs so any value except "immediate" + makes no sense.*/ + if (millisec != 0) + return osErrorValue; + + chSysLockFromISR(); + msg = chMBPostI((mailbox_t *)queue_id, (msg_t)info); + chSysUnlockFromISR(); + } + else + msg = chMBPost((mailbox_t *)queue_id, (msg_t)info, timeout); + + return msg == MSG_OK ? osOK : osEventTimeout; +} + +/** + * @brief Get a message from the queue. + */ +osEvent osMessageGet(osMessageQId queue_id, + uint32_t millisec) { + msg_t msg; + osEvent event; + systime_t timeout = ((millisec == 0) || (millisec == osWaitForever)) ? + TIME_INFINITE : MS2ST(millisec); + + event.def.message_id = queue_id; + + if (port_is_isr_context()) { + + /* Waiting makes no sense in ISRs so any value except "immediate" + makes no sense.*/ + if (millisec != 0) { + event.status = osErrorValue; + return event; + } + + chSysLockFromISR(); + msg = chMBFetchI((mailbox_t *)queue_id, (msg_t*)&event.value.v); + chSysUnlockFromISR(); + } + else { + msg = chMBFetch((mailbox_t *)queue_id, (msg_t*)&event.value.v, timeout); + } + + /* Returned event type.*/ + event.status = msg == MSG_OK ? osEventMessage : osEventTimeout; + return event; +} + +/** @} */ diff --git a/os/common/ports/ARMCMx/cmsis_os/cmsis_os.h b/os/common/ports/ARMCMx/cmsis_os/cmsis_os.h new file mode 100644 index 000000000..23f12a0b6 --- /dev/null +++ b/os/common/ports/ARMCMx/cmsis_os/cmsis_os.h @@ -0,0 +1,520 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/* + Concepts and parts of this file have been contributed by Andre R. + */ + +/** + * @file cmsis_os.h + * @brief CMSIS RTOS module macros and structures. + * + * @addtogroup CMSIS_OS + * @{ + */ + +#ifndef _CMSIS_OS_H_ +#define _CMSIS_OS_H_ + +#include "ch.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief API version. + */ +#define osCMSIS 0x10002 + +/** + * @brief Kernel version. + */ +#define osKernelSystemId "KERNEL V1.00" + +/** + * @brief ChibiOS/RT version encoded for CMSIS. + */ +#define osCMSIS_KERNEL ((CH_KERNEL_MAJOR << 16) | \ + (CH_KERNEL_MINOR << 8) | \ + (CH_KERNEL_PATCH)) + +/** + * @name CMSIS Capabilities + * @{ + */ +#define osFeature_MainThread 1 +#define osFeature_Pool 1 +#define osFeature_MailQ 0 +#define osFeature_MessageQ 1 +#define osFeature_Signals 24 +#define osFeature_Semaphore ((1U << 31) - 1U) +#define osFeature_Wait 0 +#define osFeature_SysTick 1 +/**< @} */ + +/** + * @brief Wait forever specification for timeouts. + */ +#define osWaitForever TIME_INFINITE + +/** + * @brief System tick frequency. + */ +#define osKernelSysTickFrequency CH_CFG_FREQUENCY + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Number of pre-allocated static semaphores/mutexes. + */ +#if !defined(CMSIS_CFG_DEFAULT_STACK) +#define CMSIS_CFG_DEFAULT_STACK 256 +#endif + +/** + * @brief Number of pre-allocated static semaphores/mutexes. + */ +#if !defined(CMSIS_CFG_NUM_SEMAPHORES) +#define CMSIS_CFG_NUM_SEMAPHORES 4 +#endif + +/** + * @brief Number of pre-allocated static timers. + */ +#if !defined(CMSIS_CFG_NUM_TIMERS) +#define CMSIS_CFG_NUM_TIMERS 4 +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !CH_CFG_USE_MEMPOOLS +#error "CMSIS RTOS requires CH_CFG_USE_MEMPOOLS" +#endif + +#if !CH_CFG_USE_EVENTS +#error "CMSIS RTOS requires CH_CFG_USE_EVENTS" +#endif + +#if !CH_CFG_USE_EVENTS_TIMEOUT +#error "CMSIS RTOS requires CH_CFG_USE_EVENTS_TIMEOUT" +#endif + +#if !CH_CFG_USE_SEMAPHORES +#error "CMSIS RTOS requires CH_CFG_USE_SEMAPHORES" +#endif + +#if !CH_CFG_USE_DYNAMIC +#error "CMSIS RTOS requires CH_CFG_USE_DYNAMIC" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of priority levels. + */ +typedef enum { + osPriorityIdle = -3, + osPriorityLow = -2, + osPriorityBelowNormal = -1, + osPriorityNormal = 0, + osPriorityAboveNormal = +1, + osPriorityHigh = +2, + osPriorityRealtime = +3, + osPriorityError = 0x84 +} osPriority; + +/** + * @brief Type of error codes. + */ +typedef enum { + osOK = 0, + osEventSignal = 0x08, + osEventMessage = 0x10, + osEventMail = 0x20, + osEventTimeout = 0x40, + osErrorParameter = 0x80, + osErrorResource = 0x81, + osErrorTimeoutResource = 0xC1, + osErrorISR = 0x82, + osErrorISRRecursive = 0x83, + osErrorPriority = 0x84, + osErrorNoMemory = 0x85, + osErrorValue = 0x86, + osErrorOS = 0xFF, + os_status_reserved = 0x7FFFFFFF +} osStatus; + +/** + * @brief Type of a timer mode. + */ +typedef enum { + osTimerOnce = 0, + osTimerPeriodic = 1 +} os_timer_type; + +/** + * @brief Type of thread functions. + */ +typedef void (*os_pthread) (void const *argument); + +/** + * @brief Type of timer callback. + */ +typedef void (*os_ptimer) (void const *argument); + +/** + * @brief Type of pointer to thread control block. + */ +typedef thread_t *osThreadId; + +/** + * @brief Type of pointer to timer control block. + */ +typedef struct os_timer_cb { + virtual_timer_t vt; + os_timer_type type; + os_ptimer ptimer; + void *argument; + uint32_t millisec; +} *osTimerId; + +/** + * @brief Type of pointer to mutex control block. + */ +typedef binary_semaphore_t *osMutexId; + +/** + * @brief Type of pointer to semaphore control block. + */ +typedef semaphore_t *osSemaphoreId; + +/** + * @brief Type of pointer to memory pool control block. + */ +typedef memory_pool_t *osPoolId; + +/** + * @brief Type of pointer to message queue control block. + */ +typedef struct mailbox *osMessageQId; + +/** + * @brief Type of an event. + */ +typedef struct { + osStatus status; + union { + uint32_t v; + void *p; + int32_t signals; + } value; + union { +/* osMailQId mail_id;*/ + osMessageQId message_id; + } def; +} osEvent; + +/** + * @brief Type of a thread definition block. + */ +typedef struct os_thread_def { + os_pthread pthread; + osPriority tpriority; + uint32_t stacksize; +} osThreadDef_t; + +/** + * @brief Type of a timer definition block. + */ +typedef struct os_timer_def { + os_ptimer ptimer; +} osTimerDef_t; + +/** + * @brief Type of a mutex definition block. + */ +typedef struct os_mutex_def { + uint32_t dummy; +} osMutexDef_t; + +/** + * @brief Type of a semaphore definition block. + */ +typedef struct os_semaphore_def { + uint32_t dummy; +} osSemaphoreDef_t; + +/** + * @brief Type of a memory pool definition block. + */ +typedef struct os_pool_def { + uint32_t pool_sz; + uint32_t item_sz; + memory_pool_t *pool; + void *items; +} osPoolDef_t; + +/** + * @brief Type of a message queue definition block. + */ +typedef struct os_messageQ_def { + uint32_t queue_sz; + uint32_t item_sz; + mailbox_t *mailbox; + void *items; +} osMessageQDef_t; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Convert a microseconds value to a RTOS kernel system timer value. + */ +#define osKernelSysTickMicroSec(microsec) (((uint64_t)microsec * \ + (osKernelSysTickFrequency)) / \ + 1000000) + +/** + * @brief Create a Thread definition. + */ +#if defined(osObjectsExternal) +#define osThreadDef(name, priority, instances, stacksz) \ + extern const osThreadDef_t os_thread_def_##name +#else +#define osThreadDef(name, priority, stacksz) \ +const osThreadDef_t os_thread_def_##name = { \ + (name), \ + (priority), \ + (stacksz) \ +} +#endif + +/** + * @brief Access a Thread definition. + */ +#define osThread(name) &os_thread_def_##name + +/** + * @brief Define a Timer object. + */ +#if defined(osObjectsExternal) +#define osTimerDef(name, function) \ + extern const osTimerDef_t os_timer_def_##name +#else +#define osTimerDef(name, function) \ +const osTimerDef_t os_timer_def_##name = { \ + (function) \ +} +#endif + +/** + * @brief Access a Timer definition. + */ +#define osTimer(name) &os_timer_def_##name + +/** + * @brief Define a Mutex. + */ +#if defined(osObjectsExternal) +#define osMutexDef(name) extern const osMutexDef_t os_mutex_def_##name +#else +#define osMutexDef(name) const osMutexDef_t os_mutex_def_##name = {0} +#endif + +/** + * @brief Access a Mutex definition. + */ +#define osMutex(name) &os_mutex_def_##name + +/** + * @brief Define a Semaphore. + */ +#if defined(osObjectsExternal) +#define osSemaphoreDef(name) \ + extern const osSemaphoreDef_t os_semaphore_def_##name +#else // define the object +#define osSemaphoreDef(name) \ + const osSemaphoreDef_t os_semaphore_def_##name = {0} +#endif + +/** + * @brief Access a Semaphore definition. + */ +#define osSemaphore(name) &os_semaphore_def_##name + +/** + * @brief Define a Memory Pool. + */ +#if defined(osObjectsExternal) +#define osPoolDef(name, no, type) \ + extern const osPoolDef_t os_pool_def_##name +#else +#define osPoolDef(name, no, type) \ +static const type os_pool_buf_##name[no]; \ +static memory_pool_t os_pool_obj_##name; \ +const osPoolDef_t os_pool_def_##name = { \ + (no), \ + sizeof (type), \ + (void *)&os_pool_obj_##name, \ + (void *)&os_pool_buf_##name[0] \ +} +#endif + +/** + * @brief Access a Memory Pool definition. + */ +#define osPool(name) &os_pool_def_##name + +/** + * @brief Define a Message Queue. + */ +#if defined(osObjectsExternal) +#define osMessageQDef(name, queue_sz, type) \ + extern const osMessageQDef_t os_messageQ_def_##name +#else +#define osMessageQDef(name, queue_sz, type) \ +static const msg_t os_messageQ_buf_##name[queue_sz]; \ +static mailbox_t os_messageQ_obj_##name; \ +const osMessageQDef_t os_messageQ_def_##name = { \ + (queue_sz), \ + sizeof (type) \ + (void *)&os_messageQ_obj_##name, \ + (void *)&os_messageQ_buf_##name[0] \ +} +#endif + +/** + * @brief Access a Message Queue definition. + */ +#define osMessageQ(name) &os_messageQ_def_##name + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +extern int32_t cmsis_os_started; + +#ifdef __cplusplus +extern "C" { +#endif + osStatus osKernelInitialize(void); + osStatus osKernelStart(void); + osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *argument); + osStatus osThreadTerminate(osThreadId thread_id); + osStatus osThreadSetPriority(osThreadId thread_id, osPriority newprio); + /*osEvent osWait(uint32_t millisec);*/ + osTimerId osTimerCreate(const osTimerDef_t *timer_def, + os_timer_type type, + void *argument); + osStatus osTimerStart(osTimerId timer_id, uint32_t millisec); + osStatus osTimerStop(osTimerId timer_id); + osStatus osTimerDelete(osTimerId timer_id); + int32_t osSignalSet(osThreadId thread_id, int32_t signals); + int32_t osSignalClear(osThreadId thread_id, int32_t signals); + osEvent osSignalWait(int32_t signals, uint32_t millisec); + osSemaphoreId osSemaphoreCreate(const osSemaphoreDef_t *semaphore_def, + int32_t count); + int32_t osSemaphoreWait(osSemaphoreId semaphore_id, uint32_t millisec); + osStatus osSemaphoreRelease(osSemaphoreId semaphore_id); + osStatus osSemaphoreDelete(osSemaphoreId semaphore_id); + osMutexId osMutexCreate(const osMutexDef_t *mutex_def); + osStatus osMutexWait(osMutexId mutex_id, uint32_t millisec); + osStatus osMutexRelease(osMutexId mutex_id); + osStatus osMutexDelete(osMutexId mutex_id); + osPoolId osPoolCreate(const osPoolDef_t *pool_def); + void *osPoolAlloc(osPoolId pool_id); + void *osPoolCAlloc(osPoolId pool_id); + osStatus osPoolFree(osPoolId pool_id, void *block); + osMessageQId osMessageCreate(const osMessageQDef_t *queue_def, + osThreadId thread_id); + osStatus osMessagePut(osMessageQId queue_id, + uint32_t info, + uint32_t millisec); + osEvent osMessageGet(osMessageQId queue_id, + uint32_t millisec); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief To be or not to be. + */ +static inline int32_t osKernelRunning(void) { + + return cmsis_os_started; +} + +/** + * @brief System ticks since start. + */ +static inline uint32_t osKernelSysTick(void) { + + return (uint32_t)chVTGetSystemTimeX(); +} + +/** + * @brief Returns the current thread. + */ +static inline osThreadId osThreadGetId(void) { + + return (osThreadId)chThdGetSelfX(); +} + +/** + * @brief Thread time slice yield. + */ +static inline osStatus osThreadYield(void) { + + chThdYield(); + + return osOK; +} + +/** + * @brief Returns priority of a thread. + */ +static inline osPriority osThreadGetPriority(osThreadId thread_id) { + + return thread_id->p_prio; +} + +/** + * @brief Thread delay in milliseconds. + */ +static inline osStatus osDelay(uint32_t millisec) { + + chThdSleepMilliseconds(millisec); + + return osOK; +} + +#endif /* _CMSIS_OS_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/cmsis_os/cmsis_os.mk b/os/common/ports/ARMCMx/cmsis_os/cmsis_os.mk new file mode 100644 index 000000000..d679622ad --- /dev/null +++ b/os/common/ports/ARMCMx/cmsis_os/cmsis_os.mk @@ -0,0 +1,4 @@ +# List of the ChibiOS/RT CMSIS RTOS wrapper. +CMSISRTOSSRC = ${CHIBIOS}/os/rt/ports/ARMCMx/cmsis_os/cmsis_os.c + +CMSISRTOSINC = ${CHIBIOS}/os/rt/ports/ARMCMx/cmsis_os diff --git a/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s b/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s new file mode 100644 index 000000000..935c7630f --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s @@ -0,0 +1,152 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file compilers/GCC/chcoreasm_v6m.s + * @brief ARMv6-M architecture port low level code. + * + * @addtogroup ARMCMx_GCC_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +/* + * RTOS-specific context offset. + */ +#if defined(_CHIBIOS_RT_CONF_) +#define CONTEXT_OFFSET 12 +#elif defined(_CHIBIOS_NIL_CONF_) +#define CONTEXT_OFFSET 0 +#else +#error "invalid chconf.h" +#endif + + .set SCB_ICSR, 0xE000ED04 + .set ICSR_PENDSVSET, 0x10000000 + .set ICSR_NMIPENDSET, 0x80000000 + + .cpu cortex-m0 + .fpu softvfp + + .thumb + .text + +/*--------------------------------------------------------------------------* + * Performs a context switch between two threads. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_switch +_port_switch: + push {r4, r5, r6, r7, lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4, r5, r6, r7} + + mov r3, sp + str r3, [r1, #CONTEXT_OFFSET] + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 + + pop {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + pop {r4, r5, r6, r7, pc} + +/*--------------------------------------------------------------------------* + * Start a thread by invoking its work function. + * + * Threads execution starts here, the code leaves the system critical zone + * and then jumps into the thread function passed in register R4. The + * register R5 contains the thread parameter. The function chThdExit() is + * called on thread function return. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_thread_start +_port_thread_start: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + cpsie i + mov r0, r5 + blx r4 + movs r0, #0 /* MSG_OK */ + bl chThdExit + +/*--------------------------------------------------------------------------* + * Post-IRQ switch code. + * + * Exception handlers return here for context switching. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_switch_from_isr +_port_switch_from_isr: +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + .globl _port_exit_from_isr +_port_exit_from_isr: + ldr r2, .L2 + ldr r3, .L3 + str r3, [r2, #0] +#if CORTEX_ALTERNATE_SWITCH + cpsie i +#endif +.L1: b .L1 + + .align 2 +.L2: .word SCB_ICSR +#if CORTEX_ALTERNATE_SWITCH +.L3: .word ICSR_PENDSVSET +#else +.L3: .word ICSR_NMIPENDSET +#endif + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s b/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s new file mode 100644 index 000000000..7a77ba406 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s @@ -0,0 +1,164 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file compilers/GCC/chcoreasm_v7m.s + * @brief ARMv7-M architecture port low level code. + * + * @addtogroup ARMCMx_GCC_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +/* + * RTOS-specific context offset. + */ +#if defined(_CHIBIOS_RT_CONF_) +#define CONTEXT_OFFSET 12 +#elif defined(_CHIBIOS_NIL_CONF_) +#define CONTEXT_OFFSET 0 +#else +#error "invalid chconf.h" +#endif + + .set SCB_ICSR, 0xE000ED04 + .set ICSR_PENDSVSET, 0x10000000 + + .syntax unified + .cpu cortex-m4 +#if CORTEX_USE_FPU + .fpu fpv4-sp-d16 +#else + .fpu softvfp +#endif + + .thumb + .text + +/*--------------------------------------------------------------------------* + * Performs a context switch between two threads. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_switch +_port_switch: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} +#if CORTEX_USE_FPU + vpush {s16-s31} +#endif + + str sp, [r1, #CONTEXT_OFFSET] +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \ + ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4)) + /* Workaround for ARM errata 752419, only applied if + condition exists for it to be triggered.*/ + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 +#else + ldr sp, [r0, #CONTEXT_OFFSET] +#endif + +#if CORTEX_USE_FPU + vpop {s16-s31} +#endif + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + +/*--------------------------------------------------------------------------* + * Start a thread by invoking its work function. + * + * Threads execution starts here, the code leaves the system critical zone + * and then jumps into the thread function passed in register R4. The + * register R5 contains the thread parameter. The function chThdExit() is + * called on thread function return. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_thread_start +_port_thread_start: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +#if CORTEX_SIMPLIFIED_PRIORITY + cpsie i +#else + movs r3, #0 /* CORTEX_BASEPRI_DISABLED */ + msr BASEPRI, r3 +#endif + mov r0, r5 + blx r4 +#if defined(_CHIBIOS_RT_CONF_) + movs r0, #0 /* MSG_OK */ + bl chThdExit +#endif +#if defined(_CHIBIOS_NIL_CONF_) + mov r3, #0 + bl chSysHalt +#endif + +/*--------------------------------------------------------------------------* + * Post-IRQ switch code. + * + * Exception handlers return here for context switching. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_switch_from_isr +_port_switch_from_isr: +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + .globl _port_exit_from_isr +_port_exit_from_isr: +#if CORTEX_SIMPLIFIED_PRIORITY + movw r3, #:lower16:SCB_ICSR + movt r3, #:upper16:SCB_ICSR + mov r2, ICSR_PENDSVSET + str r2, [r3, #0] + cpsie i +#else /* !CORTEX_SIMPLIFIED_PRIORITY */ + svc #0 +#endif /* !CORTEX_SIMPLIFIED_PRIORITY */ +.L1: b .L1 + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/GCC/chtypes.h b/os/common/ports/ARMCMx/compilers/GCC/chtypes.h new file mode 100644 index 000000000..15ab05a62 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/chtypes.h @@ -0,0 +1,103 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/compilers/GCC/chtypes.h + * @brief ARM Cortex-Mx port system types. + * + * @addtogroup ARMCMx_GCC_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __attribute__((packed)) + +/** + * @brief Memory alignment enforcement for variables. + */ +#define ALIGNED_VAR(n) __attribute__((aligned(n))) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk b/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk new file mode 100644 index 000000000..383457de6 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk @@ -0,0 +1,8 @@ +# List of the ChibiOS/RT Cortex-M0 STM32F0xx port files. +PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \ + $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v6m.c + +PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s + +PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \ + $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC diff --git a/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk b/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk new file mode 100644 index 000000000..86bf45e7b --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk @@ -0,0 +1,8 @@ +# List of the ChibiOS/RT ARMv7M generic port files. +PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/chcore.c \ + $(CHIBIOS)/os/common/ports/ARMCMx/chcore_v7m.c + +PORTASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s + +PORTINC = $(CHIBIOS)/os/common/ports/ARMCMx \ + $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC diff --git a/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s b/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s new file mode 100644 index 000000000..ad2820dfa --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s @@ -0,0 +1,142 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file compilers/IAR/chcoreasm_v6m.s + * @brief ARMv6-M architecture port low level code. + * + * @addtogroup ARMCMx_IAR_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + + MODULE ?chcoreasm_v6m + + AAPCS INTERWORK, VFP_COMPATIBLE + PRESERVE8 + +CONTEXT_OFFSET SET 12 +SCB_ICSR SET 0xE000ED04 + + SECTION .text:CODE:NOROOT(2) + + EXTERN chThdExit + EXTERN chSchDoReschedule +#if CH_DBG_STATISTICS + EXTERN _stats_start_measure_crit_thd + EXTERN _stats_stop_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + EXTERN _dbg_check_unlock + EXTERN _dbg_check_lock +#endif + + THUMB + +/* + * Performs a context switch between two threads. + */ + PUBLIC _port_switch +_port_switch: + push {r4, r5, r6, r7, lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4, r5, r6, r7} + mov r3, sp + str r3, [r1, #CONTEXT_OFFSET] + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 + pop {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + pop {r4, r5, r6, r7, pc} + +/* + * Start a thread by invoking its work function. + * If the work function returns @p chThdExit() is automatically invoked. + */ + PUBLIC _port_thread_start +_port_thread_start: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + cpsie i + mov r0, r5 + blx r4 + bl chThdExit + +/* + * Post-IRQ switch code. + * Exception handlers return here for context switching. + */ + PUBLIC _port_switch_from_isr + PUBLIC _port_exit_from_isr +_port_switch_from_isr: +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +_port_exit_from_isr: + ldr r2, =SCB_ICSR + movs r3, #128 +#if CORTEX_ALTERNATE_SWITCH + lsls r3, r3, #21 + str r3, [r2, #0] + cpsie i +#else + lsls r3, r3, #24 + str r3, [r2, #0] +#endif +waithere: + b waithere + + END + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s b/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s new file mode 100644 index 000000000..2f58a73aa --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s @@ -0,0 +1,150 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file compilers/IAR/chcoreasm_v7m.s + * @brief ARMv7-M architecture port low level code. + * + * @addtogroup ARMCMx_IAR_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + + MODULE ?chcoreasm_v7m + + AAPCS INTERWORK, VFP_COMPATIBLE + PRESERVE8 + +CONTEXT_OFFSET SET 12 +SCB_ICSR SET 0xE000ED04 +ICSR_PENDSVSET SET 0x10000000 + + SECTION .text:CODE:NOROOT(2) + + EXTERN chThdExit + EXTERN chSchDoReschedule +#if CH_DBG_STATISTICS + EXTERN _stats_start_measure_crit_thd + EXTERN _stats_stop_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + EXTERN _dbg_check_unlock + EXTERN _dbg_check_lock +#endif + + THUMB + +/* + * Performs a context switch between two threads. + */ + PUBLIC _port_switch +_port_switch: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} +#if CORTEX_USE_FPU + vpush {s16-s31} +#endif + + str sp, [r1, #CONTEXT_OFFSET] +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \ + ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4)) + /* Workaround for ARM errata 752419, only applied if + condition exists for it to be triggered.*/ + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 +#else + ldr sp, [r0, #CONTEXT_OFFSET] +#endif + +#if CORTEX_USE_FPU + vpop {s16-s31} +#endif + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + +/* + * Start a thread by invoking its work function. + * If the work function returns @p chThdExit() is automatically invoked. + */ + PUBLIC _port_thread_start +_port_thread_start: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +#if CORTEX_SIMPLIFIED_PRIORITY + cpsie i +#else + movs r3, #0 /* CORTEX_BASEPRI_DISABLED */ + msr BASEPRI, r3 +#endif + mov r0, r5 + blx r4 + bl chThdExit + +/* + * Post-IRQ switch code. + * Exception handlers return here for context switching. + */ + PUBLIC _port_switch_from_isr + PUBLIC _port_exit_from_isr +_port_switch_from_isr: +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +_port_exit_from_isr: +#if CORTEX_SIMPLIFIED_PRIORITY + mov r3, #LWRD SCB_ICSR + movt r3, #HWRD SCB_ICSR + mov r2, #ICSR_PENDSVSET + str r2, [r3] + cpsie i +#else + svc #0 +#endif +.L3: b .L3 + + END + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/IAR/chtypes.h b/os/common/ports/ARMCMx/compilers/IAR/chtypes.h new file mode 100644 index 000000000..2078217da --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/IAR/chtypes.h @@ -0,0 +1,98 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/compilers/IAR/chtypes.h + * @brief ARM Cortex-Mx port system types. + * + * @addtogroup ARMCMx_IAR_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE (!FALSE) +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __packed + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s b/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s new file mode 100644 index 000000000..e61662f38 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s @@ -0,0 +1,139 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file compilers/RVCT/chcoreasm_v6m.s + * @brief ARMv6-M architecture port low level code. + * + * @addtogroup ARMCMx_RVCT_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +CONTEXT_OFFSET EQU 12 +SCB_ICSR EQU 0xE000ED04 + + PRESERVE8 + THUMB + AREA |.text|, CODE, READONLY + + IMPORT chThdExit + IMPORT chSchDoReschedule +#if CH_DBG_STATISTICS + IMPORT _stats_start_measure_crit_thd + IMPORT _stats_stop_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + IMPORT _dbg_check_unlock + IMPORT _dbg_check_lock +#endif + +/* + * Performs a context switch between two threads. + */ + EXPORT _port_switch +_port_switch PROC + push {r4, r5, r6, r7, lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4, r5, r6, r7} + mov r3, sp + str r3, [r1, #CONTEXT_OFFSET] + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 + pop {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + pop {r4, r5, r6, r7, pc} + ENDP + +/* + * Start a thread by invoking its work function. + * If the work function returns @p chThdExit() is automatically invoked. + */ + EXPORT _port_thread_start +_port_thread_start PROC +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + cpsie i + mov r0, r5 + blx r4 + bl chThdExit + ENDP + +/* + * Post-IRQ switch code. + * Exception handlers return here for context switching. + */ + EXPORT _port_switch_from_isr + EXPORT _port_exit_from_isr +_port_switch_from_isr PROC +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +_port_exit_from_isr + ldr r2, =SCB_ICSR + movs r3, #128 +#if CORTEX_ALTERNATE_SWITCH + lsls r3, r3, #21 + str r3, [r2, #0] + cpsie i +#else + lsls r3, r3, #24 + str r3, [r2, #0] +#endif +waithere b waithere + ENDP + + END + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s b/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s new file mode 100644 index 000000000..69bfaa59c --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s @@ -0,0 +1,148 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file compilers/RVCT/chcoreasm_v7m.s + * @brief ARMv7-M architecture port low level code. + * + * @addtogroup ARMCMx_RVCT_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +CONTEXT_OFFSET EQU 12 +SCB_ICSR EQU 0xE000ED04 +ICSR_PENDSVSET EQU 0x10000000 + + PRESERVE8 + THUMB + AREA |.text|, CODE, READONLY + + IMPORT chThdExit + IMPORT chSchDoReschedule +#if CH_DBG_STATISTICS + IMPORT _stats_start_measure_crit_thd + IMPORT _stats_stop_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + IMPORT _dbg_check_unlock + IMPORT _dbg_check_lock +#endif + +/* + * Performs a context switch between two threads. + */ + EXPORT _port_switch +_port_switch PROC + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} +#if CORTEX_USE_FPU + vpush {s16-s31} +#endif + + str sp, [r1, #CONTEXT_OFFSET] +#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \ + ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4)) + /* Workaround for ARM errata 752419, only applied if + condition exists for it to be triggered.*/ + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 +#else + ldr sp, [r0, #CONTEXT_OFFSET] +#endif + +#if CORTEX_USE_FPU + vpop {s16-s31} +#endif + pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} + ENDP + +/* + * Start a thread by invoking its work function. + * If the work function returns @p chThdExit() is automatically invoked. + */ + EXPORT _port_thread_start +_port_thread_start PROC +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +#if CORTEX_SIMPLIFIED_PRIORITY + cpsie i +#else + movs r3, #0 /* CORTEX_BASEPRI_DISABLED */ + msr BASEPRI, r3 +#endif + mov r0, r5 + blx r4 + bl chThdExit + ENDP + +/* + * Post-IRQ switch code. + * Exception handlers return here for context switching. + */ + EXPORT _port_switch_from_isr + EXPORT _port_exit_from_isr +_port_switch_from_isr PROC +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchDoReschedule +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif +_port_exit_from_isr +#if CORTEX_SIMPLIFIED_PRIORITY + mov r3, #SCB_ICSR :AND: 0xFFFF + movt r3, #SCB_ICSR :SHR: 16 + mov r2, #ICSR_PENDSVSET + str r2, [r3, #0] + cpsie i +#else + svc #0 +#endif +waithere b waithere + ENDP + + END + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h b/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h new file mode 100644 index 000000000..ce846a912 --- /dev/null +++ b/os/common/ports/ARMCMx/compilers/RVCT/chtypes.h @@ -0,0 +1,98 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/compilers/RVCT/chtypes.h + * @brief ARM Cortex-Mx port system types. + * + * @addtogroup ARMCMx_RVCT_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE (!FALSE) +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __packed + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/ARMCMx/mpu.h b/os/common/ports/ARMCMx/mpu.h new file mode 100644 index 000000000..ec025e112 --- /dev/null +++ b/os/common/ports/ARMCMx/mpu.h @@ -0,0 +1,208 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file common/ARMCMx/mpu.h + * @brief Cortex-Mx MPU support macros and structures. + * + * @addtogroup COMMON_ARMCMx_MPU + * @{ + */ + +#ifndef _MPU_H_ +#define _MPU_H_ + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name MPU registers definitions + * @{ + */ +#define MPU_TYPE_SEPARATED (1U << 0U) +#define MPU_TYPE_DREGION(n) (((n) >> 8U) & 255U) +#define MPU_TYPE_IREGION(n) (((n) >> 16U) & 255U) + +#define MPU_CTRL_ENABLE (1U << 0U) +#define MPU_CTRL_HFNMIENA (1U << 1U) +#define MPU_CTRL_PRIVDEFENA (1U << 2U) + +#define MPU_RNR_REGION_MASK (255U << 0U) +#define MPU_RNR_REGION(n) ((n) << 0U) + +#define MPU_RBAR_REGION_MASK (15U << 0U) +#define MPU_RBAR_REGION(n) ((n) << 0U) +#define MPU_RBAR_VALID (1U << 4U) +#define MPU_RBAR_ADDR_MASK 0xFFFFFFE0U +#define MPU_RBAR_ADDR(n) ((n) << 5U) + +#define MPU_RASR_ENABLE (1U << 0U) +#define MPU_RASR_SIZE_MASK (31U << 1U) +#define MPU_RASR_SIZE(n) ((n) << 1U) +#define MPU_RASR_SIZE_32 MPU_RASR_SIZE(4U) +#define MPU_RASR_SIZE_64 MPU_RASR_SIZE(5U) +#define MPU_RASR_SIZE_128 MPU_RASR_SIZE(6U) +#define MPU_RASR_SIZE_256 MPU_RASR_SIZE(7U) +#define MPU_RASR_SIZE_512 MPU_RASR_SIZE(8U) +#define MPU_RASR_SIZE_1K MPU_RASR_SIZE(9U) +#define MPU_RASR_SIZE_2K MPU_RASR_SIZE(10U) +#define MPU_RASR_SIZE_4K MPU_RASR_SIZE(11U) +#define MPU_RASR_SIZE_8K MPU_RASR_SIZE(12U) +#define MPU_RASR_SIZE_16K MPU_RASR_SIZE(13U) +#define MPU_RASR_SIZE_32K MPU_RASR_SIZE(14U) +#define MPU_RASR_SIZE_64K MPU_RASR_SIZE(15U) +#define MPU_RASR_SIZE_128K MPU_RASR_SIZE(16U) +#define MPU_RASR_SIZE_256K MPU_RASR_SIZE(17U) +#define MPU_RASR_SIZE_512K MPU_RASR_SIZE(18U) +#define MPU_RASR_SIZE_1M MPU_RASR_SIZE(19U) +#define MPU_RASR_SIZE_2M MPU_RASR_SIZE(20U) +#define MPU_RASR_SIZE_4M MPU_RASR_SIZE(21U) +#define MPU_RASR_SIZE_8M MPU_RASR_SIZE(22U) +#define MPU_RASR_SIZE_16M MPU_RASR_SIZE(23U) +#define MPU_RASR_SIZE_32M MPU_RASR_SIZE(24U) +#define MPU_RASR_SIZE_64M MPU_RASR_SIZE(25U) +#define MPU_RASR_SIZE_128M MPU_RASR_SIZE(26U) +#define MPU_RASR_SIZE_256M MPU_RASR_SIZE(27U) +#define MPU_RASR_SIZE_512M MPU_RASR_SIZE(28U) +#define MPU_RASR_SIZE_1G MPU_RASR_SIZE(29U) +#define MPU_RASR_SIZE_2G MPU_RASR_SIZE(30U) +#define MPU_RASR_SIZE_4G MPU_RASR_SIZE(31U) +#define MPU_RASR_SRD_MASK (255U << 8U) +#define MPU_RASR_SRD(n) ((n) << 8U) +#define MPU_RASR_SRD_ALL (0U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB0 (1U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB1 (2U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB2 (4U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB3 (8U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB4 (16U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB5 (32U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB6 (64U << 8U) +#define MPU_RASR_SRD_DISABLE_SUB7 (128U << 8U) +#define MPU_RASR_ATTR_B (1U << 16U) +#define MPU_RASR_ATTR_C (1U << 17U) +#define MPU_RASR_ATTR_S (1U << 18U) +#define MPU_RASR_ATTR_TEX_MASK (7U << 19U) +#define MPU_RASR_ATTR_TEX(n) ((n) << 19U) +#define MPU_RASR_ATTR_AP_MASK (7U << 24U) +#define MPU_RASR_ATTR_AP(n) ((n) << 24U) +#define MPU_RASR_ATTR_AP_NA_NA (0U << 24U) +#define MPU_RASR_ATTR_AP_RW_NA (1U << 24U) +#define MPU_RASR_ATTR_AP_RW_RO (2U << 24U) +#define MPU_RASR_ATTR_AP_RW_RW (3U << 24U) +#define MPU_RASR_ATTR_AP_RO_NA (5U << 24U) +#define MPU_RASR_ATTR_AP_RO_RO (6U << 24U) +#define MPU_RASR_ATTR_XN (1U << 28U) +/** @} */ + +/** + * @name Region attributes + * @{ + */ +#define MPU_RASR_ATTR_STRONGLY_ORDERED (MPU_RASR_ATTR_TEX(0)) +#define MPU_RASR_ATTR_SHARED_DEVICE (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_B) +#define MPU_RASR_ATTR_CACHEABLE_WT_NWA (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_C) +#define MPU_RASR_ATTR_CACHEABLE_WB_NWA (MPU_RASR_ATTR_TEX(0) | MPU_RASR_ATTR_B | MPU_RASR_ATTR_C) +#define MPU_RASR_ATTR_NON_CACHEABLE (MPU_RASR_ATTR_TEX(1)) +#define MPU_RASR_ATTR_CACHEABLE_WB_WA (MPU_RASR_ATTR_TEX(1) | MPU_RASR_ATTR_B | MPU_RASR_ATTR_C) +#define MPU_RASR_ATTR_NON_SHARED_DEVICE (MPU_RASR_ATTR_TEX(2)) +/** @} */ + +/** + * @name Region identifiers + * @{ + */ +#define MPU_REGION_0 0U +#define MPU_REGION_1 1U +#define MPU_REGION_2 2U +#define MPU_REGION_3 3U +#define MPU_REGION_4 4U +#define MPU_REGION_5 5U +#define MPU_REGION_6 6U +#define MPU_REGION_7 7U +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Enables the MPU. + * @note MEMFAULENA is enabled in SCB_SHCSR. + * + * @param[in] ctrl MPU control modes as defined in @p MPU_CTRL register, + * the enable bit is enforced + * + * @api + */ +#define mpuEnable(ctrl) { \ + MPU->CTRL = ((uint32_t)ctrl) | MPU_CTRL_ENABLE; \ + SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; \ +} + +/** + * @brief Disables the MPU. + * @note MEMFAULENA is disabled in SCB_SHCSR. + * + * @api + */ +#define mpuDisable() { \ + SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; \ + MPU->CTRL = 0; \ +} + +/** + * @brief Configures an MPU region. + * + * @param[in] region the region number + * @param[in] address start address of the region, note, there are alignment + * constraints + * @param[in] attribs attributes mask as defined in @p MPU_RASR register + * + * @api + */ +#define mpuConfigureRegion(region, addr, attribs) { \ + MPU->RNR = ((uint32_t)region); \ + MPU->RBAR = ((uint32_t)addr); \ + MPU->RASR = ((uint32_t)attribs); \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _MPU_H_ */ + +/** @} */ diff --git a/os/common/ports/AVR/chcore.c b/os/common/ports/AVR/chcore.c new file mode 100644 index 000000000..25a6e9c75 --- /dev/null +++ b/os/common/ports/AVR/chcore.c @@ -0,0 +1,156 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file AVR/chcore.c + * @brief AVR architecture port code. + * + * @addtogroup AVR_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/* Executing-in-ISR global flag.*/ +bool __avr_in_isr; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + * + * @todo Put into an asm module, use of naked attribute is problematic. + */ +#if !defined(__DOXYGEN__) +__attribute__((naked, weak)) +#endif +void port_switch(thread_t *ntp, thread_t *otp) { + + asm volatile ("push r2"); + asm volatile ("push r3"); + asm volatile ("push r4"); + asm volatile ("push r5"); + asm volatile ("push r6"); + asm volatile ("push r7"); + asm volatile ("push r8"); + asm volatile ("push r9"); + asm volatile ("push r10"); + asm volatile ("push r11"); + asm volatile ("push r12"); + asm volatile ("push r13"); + asm volatile ("push r14"); + asm volatile ("push r15"); + asm volatile ("push r16"); + asm volatile ("push r17"); + asm volatile ("push r28"); + asm volatile ("push r29"); + +#if defined(_CHIBIOS_RT_) + asm volatile ("movw r30, r22"); + asm volatile ("in r0, 0x3d"); + asm volatile ("std Z+5, r0"); + asm volatile ("in r0, 0x3e"); + asm volatile ("std Z+6, r0"); + + asm volatile ("movw r30, r24"); + asm volatile ("ldd r0, Z+5"); + asm volatile ("out 0x3d, r0"); + asm volatile ("ldd r0, Z+6"); + asm volatile ("out 0x3e, r0"); +#endif + +#if defined(_CHIBIOS_NIL_) + asm volatile ("movw r30, r22"); + asm volatile ("in r0, 0x3d"); + asm volatile ("std Z+0, r0"); + asm volatile ("in r0, 0x3e"); + asm volatile ("std Z+1, r0"); + + asm volatile ("movw r30, r24"); + asm volatile ("ldd r0, Z+0"); + asm volatile ("out 0x3d, r0"); + asm volatile ("ldd r0, Z+1"); + asm volatile ("out 0x3e, r0"); +#endif + + asm volatile ("pop r29"); + asm volatile ("pop r28"); + asm volatile ("pop r17"); + asm volatile ("pop r16"); + asm volatile ("pop r15"); + asm volatile ("pop r14"); + asm volatile ("pop r13"); + asm volatile ("pop r12"); + asm volatile ("pop r11"); + asm volatile ("pop r10"); + asm volatile ("pop r9"); + asm volatile ("pop r8"); + asm volatile ("pop r7"); + asm volatile ("pop r6"); + asm volatile ("pop r5"); + asm volatile ("pop r4"); + asm volatile ("pop r3"); + asm volatile ("pop r2"); + asm volatile ("ret"); +} + +/** + * @brief Start a thread by invoking its work function. + * @details If the work function returns @p chThdExit() is automatically + * invoked. + */ +void _port_thread_start(void) { + + chSysUnlock(); + asm volatile ("movw r24, r4"); + asm volatile ("movw r30, r2"); + asm volatile ("icall"); + asm volatile ("call chThdExit"); +} + +/** @} */ diff --git a/os/common/ports/AVR/chcore.h b/os/common/ports/AVR/chcore.h new file mode 100644 index 000000000..8f7715b92 --- /dev/null +++ b/os/common/ports/AVR/chcore.h @@ -0,0 +1,530 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file templates/chcore.h + * @brief Port related template macros and structures. + * @details This file is a template of the system driver macros provided by + * a port. + * + * @addtogroup core + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN 1U + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN 1U + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN 1U +/** @} */ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining an AVR architecture. + */ +#define PORT_ARCHITECTURE_AVR + +/** + * @brief Macro defining the specific AVR architecture. + */ +#define PORT_ARCHITECTURE_AVR_MEGAAVR + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "MegaAVR" + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#else +#error "unsupported compiler" +#endif + +/** + * @brief Port-specific information string. + */ +#define PORT_INFO "None" +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 8 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 32 +#endif + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p chcore_timer.h, if this option is enabled then the file + * @p chcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/** + * @brief Activate for devices with extended code addressing. + */ +#if !defined(PORT_AVR_3BYTES_PC) || defined(__DOXYGEN__) +#define PORT_AVR_3BYTES_PC FALSE +#endif +/** + * @brief Enables a "wait for interrupt" instruction in the idle loop. + */ +#if !defined(PORT_AVR_WFI_SLEEP_IDLE) || defined(__DOXYGEN__) +#define PORT_AVR_WFI_SLEEP_IDLE FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 8 bits. + */ +typedef uint8_t stkalign_t; + +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + * @note R2 and R13 are not saved because those are assumed to be immutable + * during the system life cycle. + */ +struct port_extctx { + uint8_t _next; + uint8_t r31; + uint8_t r30; + uint8_t r27; + uint8_t r26; + uint8_t r25; + uint8_t r24; + uint8_t r23; + uint8_t r22; + uint8_t r21; + uint8_t r20; + uint8_t r19; + uint8_t r18; + uint8_t sr; + uint8_t r1; + uint8_t r0; +#if PORT_AVR_3BYTES_PC + uint8_t pcx; +#endif + uint16_t pc; +}; + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switching. + * @note R2 and R13 are not saved because those are assumed to be immutable + * during the system life cycle. + * @note LR is stored in the caller context so it is not present in this + * structure. + */ +struct port_intctx { + uint8_t _next; + uint8_t r29; + uint8_t r28; + uint8_t r17; + uint8_t r16; + uint8_t r15; + uint8_t r14; + uint8_t r13; + uint8_t r12; + uint8_t r11; + uint8_t r10; + uint8_t r9; + uint8_t r8; + uint8_t r7; + uint8_t r6; + uint8_t r5; + uint8_t r4; + uint8_t r3; + uint8_t r2; +#if PORT_AVR_3BYTES_PC + uint8_t pcx; +#endif + uint8_t pcl; + uint8_t pch; +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details This structure usually contains just the saved stack pointer + * defined as a pointer to a @p port_intctx structure. + */ +struct port_context { + struct port_intctx *sp; +}; + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#if PORT_AVR_3BYTES_PC || defined(__DOXYGEN__) +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + tp->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \ + sizeof(struct port_intctx)); \ + tp->ctx.sp->r2 = (uint8_t)(pf); \ + tp->ctx.sp->r3 = (uint8_t)((pf) >> 8); \ + tp->ctx.sp->r4 = (uint8_t)(arg); \ + tp->ctx.sp->r5 = (uint8_t)((arg) >> 8); \ + tp->ctx.sp->pcx = (uint8_t)0; \ + tp->ctx.sp->pcl = (uint8_t)_port_thread_start >> 8; \ + tp->ctx.sp->pch = (uint8_t)_port_thread_start; \ +} +#else /* !PORT_AVR_3BYTES_PC */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + tp->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \ + sizeof(struct port_intctx)); \ + tp->ctx.sp->r2 = (uint8_t)(pf); \ + tp->ctx.sp->r3 = (uint8_t)((pf) >> 8); \ + tp->ctx.sp->r4 = (uint8_t)(arg); \ + tp->ctx.sp->r5 = (uint8_t)((arg) >> 8); \ + tp->ctx.sp->pcl = (uint8_t)_port_thread_start >> 8; \ + tp->ctx.sp->pch = (uint8_t)_port_thread_start; \ +} +} +#endif /* !PORT_AVR_3BYTES_PC */ + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) ((sizeof(struct port_intctx) - 1) + \ + (sizeof(struct port_extctx) - 1) + \ + ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_PRIORITY(n) false + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) false + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + * @note This code tricks the compiler to save all the specified registers + * by "touching" them. + */ +#define PORT_IRQ_PROLOGUE() { \ + asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \ + "r25", "r26", "r27", "r30", "r31"); \ + __avr_in_isr = true; \ +} + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() { \ + __avr_in_isr == false; \ + _dbg_check_lock(); \ + if (chSchIsPreemptionRequired()) \ + chSchDoReschedule(); \ + _dbg_check_unlock(); \ +} + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) ISR(id) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) ISR(id) + +/** + * @brief Port-related initialization code. + * @note This function is empty in this port. + */ +#define port_init() { \ + __avr_in_isr = true; \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +#ifdef __cplusplus +extern "C" { +#endif + void port_switch(thread_t *ntp, thread_t *otp); + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + + return SREG; +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return (bool)((sts & 0x80) != 0); +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + + return __avr_in_isr; +} + +/** + * @brief Kernel-lock action. + * @details Usually this function just disables interrupts but may perform more + * actions. + */ +static inline void port_lock(void) { + + asm volatile ("cli" : : : "memory"); +} + +/** + * @brief Kernel-unlock action. + * @details Usually this function just enables interrupts but may perform more + * actions. + */ +static inline void port_unlock(void) { + + asm volatile ("sei" : : : "memory"); +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details This function is invoked before invoking I-class APIs from + * interrupt handlers. The implementation is architecture dependent, + * in its simplest form it is void. + * @note This function is empty in this port. + */ +static inline void port_lock_from_isr(void) { + +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details This function is invoked after invoking I-class APIs from interrupt + * handlers. The implementation is architecture dependent, in its + * simplest form it is void. + * @note This function is empty in this port. + */ +static inline void port_unlock_from_isr(void) { + +} + +/** + * @brief Disables all the interrupt sources. + * @note Of course non-maskable interrupt sources are not included. + */ +static inline void port_disable(void) { + + asm volatile ("cli" : : : "memory"); +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + * @note Interrupt sources above kernel level remains enabled. + */ +static inline void port_suspend(void) { + + asm volatile ("cli" : : : "memory"); +} + +/** + * @brief Enables all the interrupt sources. + */ +static inline void port_enable(void) { + + asm volatile ("sei" : : : "memory"); +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + */ +static inline void port_wait_for_interrupt(void) { + +#if PORT_AVR_WFI_SLEEP_IDLE + asm volatile ("sleep" : : : "memory"); +#endif +} + +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +static inline rtcnt_t port_rt_get_counter_value(void) { + + return 0; +} + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module late inclusions. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +#if CH_CFG_ST_TIMEDELTA > 0 +#if !PORT_USE_ALT_TIMER +#include "chcore_timer.h" +#else /* PORT_USE_ALT_TIMER */ +#include "chcore_timer_alt.h" +#endif /* PORT_USE_ALT_TIMER */ +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/common/ports/AVR/chcore_timer.h b/os/common/ports/AVR/chcore_timer.h new file mode 100644 index 000000000..58b01a19e --- /dev/null +++ b/os/common/ports/AVR/chcore_timer.h @@ -0,0 +1,124 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file AVR/chcore_timer.h + * @brief System timer header file. + * + * @addtogroup AVR_TIMER + * @{ + */ + +#ifndef _CHCORE_TIMER_H_ +#define _CHCORE_TIMER_H_ + +/* This is the only header in the HAL designed to be include-able alone.*/ +#include "st.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * + * @param[in] time the time to be set for the first alarm + * + * @notapi + */ +static inline void port_timer_start_alarm(systime_t time) { + + stStartAlarm(time); +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +static inline void port_timer_stop_alarm(void) { + + stStopAlarm(); +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +static inline void port_timer_set_alarm(systime_t time) { + + stSetAlarm(time); +} + +/** + * @brief Returns the system time. + * + * @return The system time. + * + * @notapi + */ +static inline systime_t port_timer_get_time(void) { + + return stGetCounter(); +} + +/** + * @brief Returns the current alarm time. + * + * @return The currently set alarm time. + * + * @notapi + */ +static inline systime_t port_timer_get_alarm(void) { + + return stGetAlarm(); +} + +#endif /* _CHCORE_TIMER_H_ */ + +/** @} */ diff --git a/os/common/ports/AVR/compilers/GCC/chtypes.h b/os/common/ports/AVR/compilers/GCC/chtypes.h new file mode 100644 index 000000000..1dbab59d4 --- /dev/null +++ b/os/common/ports/AVR/compilers/GCC/chtypes.h @@ -0,0 +1,103 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file AVR/compilers/GCC/chtypes.h + * @brief AVR architecture port system types. + * + * @addtogroup AVR_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE (!FALSE) +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint8_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint8_t tprio_t; /**< Thread priority. */ +typedef int16_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint8_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint8_t eventflags_t; /**< Mask of event flags. */ +typedef uint8_t cnt_t; /**< Generic signed counter. */ +typedef uint8_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __attribute__((packed)) + +/** + * @brief Memory alignment enforcement for variables. + */ +#define ALIGNED_VAR(n) __attribute__((aligned(n))) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/AVR/compilers/GCC/mk/port.mk b/os/common/ports/AVR/compilers/GCC/mk/port.mk new file mode 100644 index 000000000..ff129b8e0 --- /dev/null +++ b/os/common/ports/AVR/compilers/GCC/mk/port.mk @@ -0,0 +1,7 @@ +# List of the ChibiOS/RT AVR port files. +PORTSRC = ${CHIBIOS}/os/rt/ports/AVR/chcore.c + +PORTASM = + +PORTINC = ${CHIBIOS}/os/rt/ports/AVR \ + ${CHIBIOS}/os/rt/ports/AVR/compilers/GCC diff --git a/os/common/ports/SIMIA32/chcore.c b/os/common/ports/SIMIA32/chcore.c new file mode 100644 index 000000000..92d0fed7f --- /dev/null +++ b/os/common/ports/SIMIA32/chcore.c @@ -0,0 +1,120 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SIMIA32/chcore.c + * @brief Simulator on IA32 port code. + * + * @addtogroup SIMIA32_GCC_CORE + * @{ + */ + +#include + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +bool port_isr_context_flag; +syssts_t port_irq_sts; + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * Performs a context switch between two threads. + * @param otp the thread to be switched out + * @param ntp the thread to be switched in + */ +__attribute__((used)) +static void __dummy(thread_t *ntp, thread_t *otp) { + (void)ntp; (void)otp; + + asm volatile ( +#if defined(WIN32) + ".globl @port_switch@8 \n\t" + "@port_switch@8:" +#elif defined(__APPLE__) + ".globl _port_switch \n\t" + "_port_switch:" +#else + ".globl port_switch \n\t" + "port_switch:" +#endif + "push %ebp \n\t" + "push %esi \n\t" + "push %edi \n\t" + "push %ebx \n\t" + "movl %esp, 12(%edx) \n\t" + "movl 12(%ecx), %esp \n\t" + "pop %ebx \n\t" + "pop %edi \n\t" + "pop %esi \n\t" + "pop %ebp \n\t" + "ret"); +} + +/** + * @brief Start a thread by invoking its work function. + * @details If the work function returns @p chThdExit() is automatically + * invoked. + */ +__attribute__((cdecl, noreturn)) +void _port_thread_start(msg_t (*pf)(void *), void *p) { + + chSysUnlock(); + pf(p); + chThdExit(0); + while(1); +} + + +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +rtcnt_t port_rt_get_counter_value(void) { + LARGE_INTEGER n; + + QueryPerformanceCounter(&n); + + return (rtcnt_t)(n.QuadPart / 1000LL); +} + +/** @} */ diff --git a/os/common/ports/SIMIA32/chcore.h b/os/common/ports/SIMIA32/chcore.h new file mode 100644 index 000000000..c9b9d6861 --- /dev/null +++ b/os/common/ports/SIMIA32/chcore.h @@ -0,0 +1,382 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SIMIA32/chcore.h + * @brief Simulator on IA32 port macros and structures. + * + * @addtogroup SIMIA32_GCC_CORE + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * Macro defining the a simulated architecture into x86. + */ +#define PORT_ARCHITECTURE_SIMIA32 + +/** + * Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "Simulator" + +/** + * @brief Name of the architecture variant (optional). + */ +#define PORT_CORE_VARIANT_NAME "x86 (integer only)" + +/** + * @brief Name of the compiler supported by this port. + */ +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +/** + * @brief Port-specific information string. + */ +#define PORT_INFO "No preemption" + +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT TRUE + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + */ +#ifndef PORT_IDLE_THREAD_STACK_SIZE +#define PORT_IDLE_THREAD_STACK_SIZE 256 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + */ +#ifndef PORT_INT_REQUIRED_STACK +#define PORT_INT_REQUIRED_STACK 16384 +#endif + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p chcore_timer.h, if this option is enabled then the file + * @p chcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if CH_DBG_ENABLE_STACK_CHECK +#error "option CH_DBG_ENABLE_STACK_CHECK not supported by this port" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief 16 bytes stack and memory alignment enforcement. + */ +typedef struct { + uint8_t a[16]; +} stkalign_t __attribute__((aligned(16))); + +/** + * @brief Type of a generic x86 register. + */ +typedef void *regx86; + +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + */ +struct port_extctx { +}; + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switch. + */ +struct port_intctx { + regx86 ebx; + regx86 edi; + regx86 esi; + regx86 ebp; + regx86 eip; +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details In this port the structure just holds a pointer to the + * @p port_intctx structure representing the stack pointer + * at context switch time. + */ +struct context { + struct port_intctx *esp; +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +#define APUSH(p, a) do { \ + (p) -= sizeof(void *); \ + *(void **)(p) = (void*)(a); \ +} while (false) + +/* Darwin requires the stack to be aligned to a 16-byte boundary at + * the time of a call instruction (in case the called function needs + * to save MMX registers). This aligns to 'mod' module 16, so that we'll end + * up with the right alignment after pushing the args. */ +#define AALIGN(p, mask, mod) \ + p = (void *)((((uint32_t)(p) - (uint32_t)(mod)) & ~(uint32_t)(mask)) + (uint32_t)(mod)) \ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, workspace, wsize, pf, arg) { \ + /*lint -save -e611 -e9033 -e9074 -e9087 [10.8, 11.1, 11.3] Valid casts.*/ \ + uint8_t *esp = (uint8_t *)workspace + wsize; \ + APUSH(esp, 0); \ + uint8_t *savebp = esp; \ + AALIGN(esp, 15, 8); \ + APUSH(esp, arg); \ + APUSH(esp, pf); \ + APUSH(esp, 0); \ + esp -= sizeof(struct port_intctx); \ + ((struct port_intctx *)esp)->eip = (void *)_port_thread_start; \ + ((struct port_intctx *)esp)->ebx = NULL; \ + ((struct port_intctx *)esp)->edi = NULL; \ + ((struct port_intctx *)esp)->esi = NULL; \ + ((struct port_intctx *)esp)->ebp = (void *)savebp; \ + (tp)->p_ctx.esp = (struct port_intctx *)esp; \ + /*lint -restore*/ \ +} + + /** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) ((sizeof(void *) * 4U) + \ + sizeof(struct port_intctx) + \ + ((size_t)(n)) + \ + ((size_t)(PORT_INT_REQUIRED_STACK))) + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() { \ + port_isr_context_flag = true; \ +} + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() { \ + port_isr_context_flag = false; \ +} + + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) void id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) void id(void) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +extern bool port_isr_context_flag; +extern syssts_t port_irq_sts; + +#ifdef __cplusplus +extern "C" { +#endif + /*lint -save -e950 [Dir-2.1] Non-ANSI keywords are fine in the port layer.*/ + __attribute__((fastcall)) void port_switch(thread_t *ntp, thread_t *otp); + __attribute__((cdecl, noreturn)) void _port_thread_start(msg_t (*pf)(void *p), + void *p); + /*lint -restore*/ + rtcnt_t port_rt_get_counter_value(void); + void _sim_check_for_interrupts(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + */ +static inline void port_init(void) { + + port_irq_sts = (syssts_t)0; + port_isr_context_flag = false; +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + + return port_irq_sts; +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return sts == (syssts_t)0; +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + + return port_isr_context_flag; +} + +/** + * @brief Kernel-lock action. + * @details In this port this function disables interrupts globally. + */ +static inline void port_lock(void) { + + port_irq_sts = (syssts_t)1; +} + +/** + * @brief Kernel-unlock action. + * @details In this port this function enables interrupts globally. + */ +static inline void port_unlock(void) { + + port_irq_sts = (syssts_t)0; +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details In this port this function disables interrupts globally. + * @note Same as @p port_lock() in this port. + */ +static inline void port_lock_from_isr(void) { + + port_irq_sts = (syssts_t)1; +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details In this port this function enables interrupts globally. + * @note Same as @p port_lock() in this port. + */ +static inline void port_unlock_from_isr(void) { + + port_irq_sts = (syssts_t)0; +} + +/** + * @brief Disables all the interrupt sources. + */ +static inline void port_disable(void) { + + port_irq_sts = (syssts_t)1; +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + */ +static inline void port_suspend(void) { + + port_irq_sts = (syssts_t)1; +} + +/** + * @brief Enables all the interrupt sources. + */ +static inline void port_enable(void) { + + port_irq_sts = (syssts_t)0; +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + * @note Implemented as an inlined @p WFI instruction. + */ +static inline void port_wait_for_interrupt(void) { + + _sim_check_for_interrupts(); +} + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/common/ports/SIMIA32/compilers/GCC/chtypes.h b/os/common/ports/SIMIA32/compilers/GCC/chtypes.h new file mode 100644 index 000000000..175a44287 --- /dev/null +++ b/os/common/ports/SIMIA32/compilers/GCC/chtypes.h @@ -0,0 +1,110 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file SIMIA32/compilers/GCC/chtypes.h + * @brief Simulator on IA32 port system types. + * + * @addtogroup SIMIA32_GCC_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif +/** @} */ + +/** + * @name Derived generic types + * @{ + */ +typedef volatile int8_t vint8_t; /**< Volatile signed 8 bits. */ +typedef volatile uint8_t vuint8_t; /**< Volatile unsigned 8 bits. */ +typedef volatile int16_t vint16_t; /**< Volatile signed 16 bits. */ +typedef volatile uint16_t vuint16_t; /**< Volatile unsigned 16 bits. */ +typedef volatile int32_t vint32_t; /**< Volatile signed 32 bits. */ +typedef volatile uint32_t vuint32_t; /**< Volatile unsigned 32 bits. */ +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __attribute__((packed)) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/SIMIA32/compilers/GCC/port.mk b/os/common/ports/SIMIA32/compilers/GCC/port.mk new file mode 100644 index 000000000..0d5f0903d --- /dev/null +++ b/os/common/ports/SIMIA32/compilers/GCC/port.mk @@ -0,0 +1,7 @@ +# List of the ChibiOS/RT SIMIA32 port files. +PORTSRC = ${CHIBIOS}/os/rt/ports/SIMIA32/chcore.c + +PORTASM = + +PORTINC = ${CHIBIOS}/os/rt/ports/SIMIA32/compilers/GCC \ + ${CHIBIOS}/os/rt/ports/SIMIA32 diff --git a/os/common/ports/e200/chcore.c b/os/common/ports/e200/chcore.c new file mode 100644 index 000000000..5f410b88f --- /dev/null +++ b/os/common/ports/e200/chcore.c @@ -0,0 +1,54 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file e200/chcore.c + * @brief Power e200 port code. + * + * @addtogroup PPC_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** @} */ diff --git a/os/common/ports/e200/chcore.h b/os/common/ports/e200/chcore.h new file mode 100644 index 000000000..43e8bb151 --- /dev/null +++ b/os/common/ports/e200/chcore.h @@ -0,0 +1,631 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file PPC/chcore.h + * @brief Power e200 port macros and structures. + * + * @addtogroup PPC_CORE + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +#include "intc.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN sizeof (void *) + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN sizeof (stkalign_t) + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t) +/** @} */ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining an PPC architecture. + */ +#define PORT_ARCHITECTURE_PPC + +/** + * @brief Macro defining the specific PPC architecture. + */ +#define PORT_ARCHITECTURE_PPC_E200 + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "Power Architecture" + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#elif defined(__MWERKS__) +#define PORT_COMPILER_NAME "CW" + +#else +#error "unsupported compiler" +#endif +/** @} */ + +/** + * @name E200 core variants + * @{ + */ +#define PPC_VARIANT_e200z0 200 +#define PPC_VARIANT_e200z2 202 +#define PPC_VARIANT_e200z3 203 +#define PPC_VARIANT_e200z4 204 +/** @} */ + +/* Inclusion of the PPC implementation specific parameters.*/ +#include "ppcparams.h" +#include "vectors.h" + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 32 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 32 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * @note In this port this value is conservatively is set to 256 because + * there is no separate interrupts stack (yet). + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 256 +#endif + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p chcore_timer.h, if this option is enabled then the file + * @p chcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/** + * @brief Use VLE instruction set. + * @note This parameter is usually set in the Makefile. + */ +#if !defined(PPC_USE_VLE) || defined(__DOXYGEN__) +#define PPC_USE_VLE TRUE +#endif + +/** + * @brief Enables the use of the @p WFI instruction. + */ +#if !defined(PPC_ENABLE_WFI_IDLE) || defined(__DOXYGEN__) +#define PPC_ENABLE_WFI_IDLE FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if PPC_USE_VLE && !PPC_SUPPORTS_VLE +#error "the selected MCU does not support VLE instructions set" +#endif + +#if !PPC_USE_VLE && !PPC_SUPPORTS_BOOKE +#error "the selected MCU does not support BookE instructions set" +#endif + +/** + * @brief Name of the architecture variant. + */ +#if (PPC_VARIANT == PPC_VARIANT_e200z0) || defined(__DOXYGEN__) +#define PORT_CORE_VARIANT_NAME "e200z0" +#elif PPC_VARIANT == PPC_VARIANT_e200z2 +#define PORT_CORE_VARIANT_NAME "e200z2" +#elif PPC_VARIANT == PPC_VARIANT_e200z3 +#define PORT_CORE_VARIANT_NAME "e200z3" +#elif PPC_VARIANT == PPC_VARIANT_e200z4 +#define PORT_CORE_VARIANT_NAME "e200z4" +#else +#error "unknown or unsupported PowerPC variant specified" +#endif + +/** + * @brief Port-specific information string. + */ +#if PPC_USE_VLE +#define PORT_INFO "VLE mode" +#else +#define PORT_INFO "Book-E mode" +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits. + */ +typedef uint64_t stkalign_t; + +/** + * @brief Generic PPC register. + */ +typedef void *regppc_t; + +/** + * @brief Mandatory part of a stack frame. + */ +struct port_eabi_frame { + uint32_t slink; /**< Stack back link. */ + uint32_t shole; /**< Stack hole for LR storage. */ +}; + +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + * @note R2 and R13 are not saved because those are assumed to be immutable + * during the system life cycle. + */ +struct port_extctx { + struct port_eabi_frame frame; + /* Start of the e_stmvsrrw frame (offset 8).*/ + regppc_t pc; + regppc_t msr; + /* Start of the e_stmvsprw frame (offset 16).*/ + regppc_t cr; + regppc_t lr; + regppc_t ctr; + regppc_t xer; + /* Start of the e_stmvgprw frame (offset 32).*/ + regppc_t r0; + regppc_t r3; + regppc_t r4; + regppc_t r5; + regppc_t r6; + regppc_t r7; + regppc_t r8; + regppc_t r9; + regppc_t r10; + regppc_t r11; + regppc_t r12; + regppc_t padding; +}; + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switching. + * @note R2 and R13 are not saved because those are assumed to be immutable + * during the system life cycle. + * @note LR is stored in the caller context so it is not present in this + * structure. + */ +struct port_intctx { + regppc_t cr; /* Part of it is not volatile... */ + regppc_t r14; + regppc_t r15; + regppc_t r16; + regppc_t r17; + regppc_t r18; + regppc_t r19; + regppc_t r20; + regppc_t r21; + regppc_t r22; + regppc_t r23; + regppc_t r24; + regppc_t r25; + regppc_t r26; + regppc_t r27; + regppc_t r28; + regppc_t r29; + regppc_t r30; + regppc_t r31; + regppc_t padding; +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details This structure usually contains just the saved stack pointer + * defined as a pointer to a @p port_intctx structure. + */ +struct port_context { + struct port_intctx *sp; +}; + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ + uint8_t *sp = (uint8_t *)(wtop) - sizeof(struct port_eabi_frame); \ + ((struct port_eabi_frame *)sp)->slink = 0; \ + ((struct port_eabi_frame *)sp)->shole = (uint32_t)_port_thread_start; \ + (tp)->ctx.sp = (struct port_intctx *)(sp - sizeof(struct port_intctx)); \ + (tp)->ctx.sp->r31 = (regppc_t)(arg); \ + (tp)->ctx.sp->r30 = (regppc_t)(pf); \ +} + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ + sizeof(struct port_extctx) + \ + ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) void id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) void id(void) + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_PRIORITY(n) \ + (((n) >= 0U) && ((n) < INTC_PRIORITY_LEVELS)) + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \ + (((n) >= 0U) && ((n) < INTC_PRIORITY_LEVELS)) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if !CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) +#define port_switch(ntp, otp) _port_switch(ntp, otp) +#else +#define port_switch(ntp, otp) { \ + register struct port_intctx *sp asm ("%r1"); \ + if ((stkalign_t *)(sp - 1) < otp->stklimit) \ + chSysHalt("stack overflow"); \ + _port_switch(ntp, otp); \ +} +#endif + +/** + * @brief Writes to a special register. + * + * @param[in] spr special register number + * @param[in] val value to be written, must be an automatic variable + */ +#define port_write_spr(spr, val) \ + asm volatile ("mtspr %[p0], %[p1]" : : [p0] "n" (spr), [p1] "r" (val)) + +/** + * @brief Writes to a special register. + * + * @param[in] spr special register number + * @param[in] val returned value, must be an automatic variable + */ +#define port_read_spr(spr, val) \ + asm volatile ("mfspr %[p0], %[p1]" : [p0] "=r" (val) : [p1] "n" (spr)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +#ifdef __cplusplus +extern "C" { +#endif + void _port_switch(thread_t *ntp, thread_t *otp); + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Kernel port layer initialization. + * @details IVOR4 and IVOR10 initialization. + */ +static inline void port_init(void) { + uint32_t n; + unsigned i; + + /* Initializing the SPRG0 register to zero, it is required for interrupts + handling.*/ + n = 0; + port_write_spr(272, n); + +#if PPC_SUPPORTS_IVORS + { + /* The CPU supports IVOR registers, the kernel requires IVOR4 and IVOR10 + and the initialization is performed here.*/ + extern void _IVOR4(void); + port_write_spr(404, _IVOR4); + +#if PPC_SUPPORTS_DECREMENTER + extern void _IVOR10(void); + port_write_spr(410, _IVOR10); +#endif + } +#endif + + /* INTC initialization, software vector mode, 4 bytes vectors, starting + at priority 0.*/ + INTC_BCR = 0; + for (i = 0; i < PPC_CORE_NUMBER; i++) { + INTC_CPR(i) = 0; + INTC_IACKR(i) = (uint32_t)_vectors; + } +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + uint32_t sts; + + asm volatile ("mfmsr %[p0]" : [p0] "=r" (sts) :); + return sts; +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return (bool)((sts & (1 << 15)) != 0); +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + uint32_t sprg0; + + /* The SPRG0 register is increased before entering interrupt handlers and + decreased at the end.*/ + port_read_spr(272, sprg0); + return (bool)(sprg0 > 0); +} + +/** + * @brief Kernel-lock action. + * @note Implemented as global interrupt disable. + */ +static inline void port_lock(void) { + + asm volatile ("wrteei 0" : : : "memory"); +} + +/** + * @brief Kernel-unlock action. + * @note Implemented as global interrupt enable. + */ +static inline void port_unlock(void) { + + asm volatile("wrteei 1" : : : "memory"); +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @note Implementation not needed. + */ +static inline void port_lock_from_isr(void) { + +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @note Implementation not needed. + */ +static inline void port_unlock_from_isr(void) { + +} + +/** + * @brief Disables all the interrupt sources. + * @note Implemented as global interrupt disable. + */ +static inline void port_disable(void) { + + asm volatile ("wrteei 0" : : : "memory"); +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + * @note Same as @p port_disable() in this port, there is no difference + * between the two states. + */ +static inline void port_suspend(void) { + + asm volatile ("wrteei 0" : : : "memory"); +} + +/** + * @brief Enables all the interrupt sources. + * @note Implemented as global interrupt enable. + */ +static inline void port_enable(void) { + + asm volatile ("wrteei 1" : : : "memory"); +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + * @note Implemented as an inlined @p wait instruction. + */ +static inline void port_wait_for_interrupt(void) { + +#if PPC_ENABLE_WFI_IDLE + asm volatile ("wait" : : : "memory"); +#endif +} + +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +static inline rtcnt_t port_rt_get_counter_value(void) { + + return 0; +} + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module late inclusions. */ +/*===========================================================================*/ + +#if !defined(_FROM_ASM_) + +#if CH_CFG_ST_TIMEDELTA > 0 +#if !PORT_USE_ALT_TIMER +#include "chcore_timer.h" +#else /* PORT_USE_ALT_TIMER */ +#include "chcore_timer_alt.h" +#endif /* PORT_USE_ALT_TIMER */ +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/CW/chcoreasm.s b/os/common/ports/e200/compilers/CW/chcoreasm.s new file mode 100644 index 000000000..85da7221f --- /dev/null +++ b/os/common/ports/e200/compilers/CW/chcoreasm.s @@ -0,0 +1,124 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file e200/compilers/GCC/chcoreasm.s + * @brief Power Architecture port low level code. + * + * @addtogroup PPC_GCC_CORE + * @{ + */ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +/*===========================================================================*/ +/* Code section. */ +/*===========================================================================*/ + +/* + * Imports the PPC configuration headers. + */ +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +/* + * RTOS-specific context offset. + */ +#if defined(_CHIBIOS_RT_CONF_) +#define CONTEXT_OFFSET 12 +#elif defined(_CHIBIOS_NIL_CONF_) +#define CONTEXT_OFFSET 0 +#else +#error "invalid chconf.h" +#endif + +#if defined(_CHIBIOS_RT_CONF_) + .extern chThdExit +#endif + +#if PPC_USE_VLE == TRUE + .section .text_vle, 16 + + .align 2 + .globl _port_switch + .type _port_switch, @function +_port_switch: + e_subi r1, r1, 80 + se_mflr r0 + e_stw r0, 84(r1) + mfcr r0 + se_stw r0, 0(r1) + e_stmw r14, 4(r1) + + se_stw r1, 12(r4) + se_lwz r1, 12(r3) + + e_lmw r14, 4(r1) + se_lwz r0, 0(r1) + mtcr r0 + e_lwz r0, 84(r1) + se_mtlr r0 + e_addi r1, r1, 80 + se_blr + + .align 2 + .globl _port_thread_start + .type _port_thread_start, @function +_port_thread_start: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + wrteei 1 + mr r3, r31 + mtctr r30 + se_bctrl +#if defined(_CHIBIOS_RT_CONF_) + se_li r0, 0 + e_bl chThdExit +#endif +#if defined(_CHIBIOS_NIL_CONF_) + se_li r0, 0 + e_bl chSysHalt +#endif + +#else /* PPC_USE_VLE == FALSE */ + +#error "non-VLE mode not yet implemented" + +#endif /* PPC_USE_VLE == FALSE */ + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/CW/chtypes.h b/os/common/ports/e200/compilers/CW/chtypes.h new file mode 100644 index 000000000..e0fa7f6b3 --- /dev/null +++ b/os/common/ports/e200/compilers/CW/chtypes.h @@ -0,0 +1,93 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file e200/compilers/CW/chtypes.h + * @brief Power e200 port system types. + * + * @addtogroup PPC_CW_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/CW/ivor.s b/os/common/ports/e200/compilers/CW/ivor.s new file mode 100644 index 000000000..d8bbcad65 --- /dev/null +++ b/os/common/ports/e200/compilers/CW/ivor.s @@ -0,0 +1,204 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ivor.s + * @brief Kernel ISRs. + * + * @addtogroup PPC_CORE + * @{ + */ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +/*===========================================================================*/ +/* Code section. */ +/*===========================================================================*/ + +/* + * Imports the PPC configuration headers. + */ +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + + .extern _stats_start_measure_crit_thd + .extern _stats_stop_measure_crit_thd + .extern _dbg_check_lock + .extern _dbg_check_unlock + .extern chSchIsPreemptionRequired + .extern chSchDoReschedule + .extern chSysTimerHandlerI + + .section .handlers, text_vle + +#if PPC_USE_VLE == TRUE + +#if PPC_SUPPORTS_DECREMENTER + /* + * _IVOR10 handler (Book-E decrementer). + */ + .align 16 + .globl _IVOR10 + .type _IVOR10, @function +_IVOR10: + /* Saving the external context (port_extctx structure).*/ + e_stwu r1, -80(r1) + e_stmvsrrw 8(r1) /* Saves PC, MSR. */ + e_stmvsprw 16(r1) /* Saves CR, LR, CTR, XER. */ + e_stmvgprw 32(r1) /* Saves GPR0, GPR3...GPR12. */ + + /* Increasing the SPGR0 register.*/ + mfspr r0, 272 + se_addi r0, 1 + mtspr 272, r0 + + /* Reset DIE bit in TSR register.*/ + e_lis r3, 0x0800 /* DIS bit mask. */ + mtspr 336, r3 /* TSR register. */ + + /* Restoring pre-IRQ MSR register value.*/ + mfSRR1 r0 +#if !PPC_USE_IRQ_PREEMPTION + /* No preemption, keeping EE disabled.*/ + se_bclri r0, 16 /* EE = bit 16. */ +#endif + mtMSR r0 + +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_enter_isr + bl _dbg_check_lock_from_isr +#endif + /* System tick handler invocation.*/ + e_bl chSysTimerHandlerI +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock_from_isr + bl _dbg_check_leave_isr +#endif + +#if PPC_USE_IRQ_PREEMPTION + /* Prevents preemption again.*/ + wrteei 0 +#endif + + /* Jumps to the common IVOR epilogue code.*/ + se_b _ivor_exit +#endif /* PPC_SUPPORTS_DECREMENTER */ + + /* + * _IVOR4 handler (Book-E external interrupt). + */ + .align 16 + .globl _IVOR4 + .type _IVOR4, @function +_IVOR4: + /* Saving the external context (port_extctx structure).*/ + e_stwu r1, -80(r1) + e_stmvsrrw 8(r1) /* Saves PC, MSR. */ + e_stmvsprw 16(r1) /* Saves CR, LR, CTR, XER. */ + e_stmvgprw 32(r1) /* Saves GPR0, GPR3...GPR12. */ + + /* Increasing the SPGR0 register.*/ + mfspr r0, 272 + se_addi r0, 1 + mtspr 272, r0 + + /* Software vector address from the INTC register.*/ + e_lis r3, INTC_IACKR_ADDR@h + e_or2i r3, INTC_IACKR_ADDR@l /* IACKR register address. */ + se_lwz r3, 0(r3) /* IACKR register value. */ + se_lwz r3, 0(r3) + mtCTR r3 /* Software handler address. */ + + /* Restoring pre-IRQ MSR register value.*/ + mfSRR1 r0 +#if !PPC_USE_IRQ_PREEMPTION + /* No preemption, keeping EE disabled.*/ + se_bclri r0, 16 /* EE = bit 16. */ +#endif + mtMSR r0 + + /* Exectes the software handler.*/ + se_bctrl + +#if PPC_USE_IRQ_PREEMPTION + /* Prevents preemption again.*/ + wrteei 0 +#endif + + /* Informs the INTC that the interrupt has been served.*/ + mbar 0 + e_lis r3, INTC_EOIR_ADDR@h + e_or2i r3, INTC_EOIR_ADDR@l + se_stw r3, 0(r3) /* Writing any value should do. */ + + /* Common IVOR epilogue code, context restore.*/ + .globl _ivor_exit +_ivor_exit: + /* Decreasing the SPGR0 register.*/ + mfspr r0, 272 + se_subi r0, 1 + mtspr 272, r0 + +#if CH_DBG_STATISTICS + e_bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + e_bl _dbg_check_lock +#endif + e_bl chSchIsPreemptionRequired + e_cmpli cr0, r3, 0 + se_beq .noresch + e_bl chSchDoReschedule +.noresch: +#if CH_DBG_SYSTEM_STATE_CHECK + e_bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + e_bl _stats_stop_measure_crit_thd +#endif + + /* Restoring the external context.*/ + e_lmvgprw 32(r1) /* Restores GPR0, GPR3...GPR12. */ + e_lmvsprw 16(r1) /* Restores CR, LR, CTR, XER. */ + e_lmvsrrw 8(r1) /* Restores PC, MSR. */ + e_addi r1, r1, 80 /* Back to the previous frame. */ + se_rfi + +#else /* PPC_USE_VLE == FALSE */ + +#error "non-VLE mode not yet implemented" + +#endif /* PPC_USE_VLE == FALSE */ + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/GCC/chcoreasm.s b/os/common/ports/e200/compilers/GCC/chcoreasm.s new file mode 100644 index 000000000..5d915247c --- /dev/null +++ b/os/common/ports/e200/compilers/GCC/chcoreasm.s @@ -0,0 +1,114 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file e200/compilers/GCC/chcoreasm.s + * @brief Power Architecture port low level code. + * + * @addtogroup PPC_GCC_CORE + * @{ + */ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +/*===========================================================================*/ +/* Code section. */ +/*===========================================================================*/ + +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + +/* + * RTOS-specific context offset. + */ +#if defined(_CHIBIOS_RT_CONF_) +#define CONTEXT_OFFSET 12 +#elif defined(_CHIBIOS_NIL_CONF_) +#define CONTEXT_OFFSET 0 +#else +#error "invalid chconf.h" +#endif + +#if PPC_USE_VLE == TRUE + .section .text_vle, "ax" +#else + .section .text, "ax" +#endif + + .align 2 + .globl _port_switch + .type _port_switch, @function +_port_switch: + subi %sp, %sp, 80 + mflr %r0 + stw %r0, 84(%sp) + mfcr %r0 + stw %r0, 0(%sp) + stmw %r14, 4(%sp) + + stw %sp, 12(%r4) + lwz %sp, 12(%r3) + + lmw %r14, 4(%sp) + lwz %r0, 0(%sp) + mtcr %r0 + lwz %r0, 84(%sp) + mtlr %r0 + addi %sp, %sp, 80 + blr + + .align 2 + .globl _port_thread_start + .type _port_thread_start, @function +_port_thread_start: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + wrteei 1 + mr %r3, %r31 + mtctr %r30 + bctrl +#if defined(_CHIBIOS_RT_CONF_) + li %r0, 0 + bl chThdExit +#endif +#if defined(_CHIBIOS_NIL_CONF_) + se_li %r0, 0 + e_bl chSysHalt +#endif + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/GCC/chtypes.h b/os/common/ports/e200/compilers/GCC/chtypes.h new file mode 100644 index 000000000..38d4fd59e --- /dev/null +++ b/os/common/ports/e200/compilers/GCC/chtypes.h @@ -0,0 +1,93 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file e200/compilers/GCC/chtypes.h + * @brief Power e200 port system types. + * + * @addtogroup PPC_GCC_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/GCC/ivor.s b/os/common/ports/e200/compilers/GCC/ivor.s new file mode 100644 index 000000000..4b1c95dd6 --- /dev/null +++ b/os/common/ports/e200/compilers/GCC/ivor.s @@ -0,0 +1,258 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ivor.s + * @brief Kernel ISRs. + * + * @addtogroup PPC_CORE + * @{ + */ + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +/* + * Imports the PPC configuration headers. + */ +#define _FROM_ASM_ +#include "chconf.h" +#include "chcore.h" + +#if !defined(__DOXYGEN__) + + .section .handlers, "ax" + +#if PPC_SUPPORTS_DECREMENTER + /* + * _IVOR10 handler (Book-E decrementer). + */ + .align 4 + .globl _IVOR10 + .type _IVOR10, @function +_IVOR10: + /* Saving the external context (port_extctx structure).*/ + stwu %sp, -80(%sp) +#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI + e_stmvsrrw 8(%sp) /* Saves PC, MSR. */ + e_stmvsprw 16(%sp) /* Saves CR, LR, CTR, XER. */ + e_stmvgprw 32(%sp) /* Saves GPR0, GPR3...GPR12. */ +#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + stw %r0, 32(%sp) /* Saves GPR0. */ + mfSRR0 %r0 + stw %r0, 8(%sp) /* Saves PC. */ + mfSRR1 %r0 + stw %r0, 12(%sp) /* Saves MSR. */ + mfCR %r0 + stw %r0, 16(%sp) /* Saves CR. */ + mfLR %r0 + stw %r0, 20(%sp) /* Saves LR. */ + mfCTR %r0 + stw %r0, 24(%sp) /* Saves CTR. */ + mfXER %r0 + stw %r0, 28(%sp) /* Saves XER. */ + stw %r3, 36(%sp) /* Saves GPR3...GPR12. */ + stw %r4, 40(%sp) + stw %r5, 44(%sp) + stw %r6, 48(%sp) + stw %r7, 52(%sp) + stw %r8, 56(%sp) + stw %r9, 60(%sp) + stw %r10, 64(%sp) + stw %r11, 68(%sp) + stw %r12, 72(%sp) +#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + + /* Increasing the SPGR0 register.*/ + mfspr %r0, 272 + eaddi %r0, %r0, 1 + mtspr 272, %r0 + + /* Reset DIE bit in TSR register.*/ + lis %r3, 0x0800 /* DIS bit mask. */ + mtspr 336, %r3 /* TSR register. */ + + /* Restoring pre-IRQ MSR register value.*/ + mfSRR1 %r0 +#if !PPC_USE_IRQ_PREEMPTION + /* No preemption, keeping EE disabled.*/ + se_bclri %r0, 16 /* EE = bit 16. */ +#endif + mtMSR %r0 + +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_enter_isr + bl _dbg_check_lock_from_isr +#endif + /* System tick handler invocation.*/ + bl chSysTimerHandlerI +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock_from_isr + bl _dbg_check_leave_isr +#endif + +#if PPC_USE_IRQ_PREEMPTION + /* Prevents preemption again.*/ + wrteei 0 +#endif + + /* Jumps to the common IVOR epilogue code.*/ + b _ivor_exit +#endif /* PPC_SUPPORTS_DECREMENTER */ + + /* + * _IVOR4 handler (Book-E external interrupt). + */ + .align 4 + .globl _IVOR4 + .type _IVOR4, @function +_IVOR4: + /* Saving the external context (port_extctx structure).*/ + stwu %sp, -80(%sp) +#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI + e_stmvsrrw 8(%sp) /* Saves PC, MSR. */ + e_stmvsprw 16(%sp) /* Saves CR, LR, CTR, XER. */ + e_stmvgprw 32(%sp) /* Saves GPR0, GPR3...GPR12. */ +#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + stw %r0, 32(%sp) /* Saves GPR0. */ + mfSRR0 %r0 + stw %r0, 8(%sp) /* Saves PC. */ + mfSRR1 %r0 + stw %r0, 12(%sp) /* Saves MSR. */ + mfCR %r0 + stw %r0, 16(%sp) /* Saves CR. */ + mfLR %r0 + stw %r0, 20(%sp) /* Saves LR. */ + mfCTR %r0 + stw %r0, 24(%sp) /* Saves CTR. */ + mfXER %r0 + stw %r0, 28(%sp) /* Saves XER. */ + stw %r3, 36(%sp) /* Saves GPR3...GPR12. */ + stw %r4, 40(%sp) + stw %r5, 44(%sp) + stw %r6, 48(%sp) + stw %r7, 52(%sp) + stw %r8, 56(%sp) + stw %r9, 60(%sp) + stw %r10, 64(%sp) + stw %r11, 68(%sp) + stw %r12, 72(%sp) +#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + + /* Increasing the SPGR0 register.*/ + mfspr %r0, 272 + eaddi %r0, %r0, 1 + mtspr 272, %r0 + + /* Software vector address from the INTC register.*/ + lis %r3, INTC_IACKR_ADDR@h + ori %r3, %r3, INTC_IACKR_ADDR@l /* IACKR register address. */ + lwz %r3, 0(%r3) /* IACKR register value. */ + lwz %r3, 0(%r3) + mtCTR %r3 /* Software handler address. */ + + /* Restoring pre-IRQ MSR register value.*/ + mfSRR1 %r0 +#if !PPC_USE_IRQ_PREEMPTION + /* No preemption, keeping EE disabled.*/ + se_bclri %r0, 16 /* EE = bit 16. */ +#endif + mtMSR %r0 + + /* Exectes the software handler.*/ + bctrl + +#if PPC_USE_IRQ_PREEMPTION + /* Prevents preemption again.*/ + wrteei 0 +#endif + + /* Informs the INTC that the interrupt has been served.*/ + mbar 0 + lis %r3, INTC_EOIR_ADDR@h + ori %r3, %r3, INTC_EOIR_ADDR@l + stw %r3, 0(%r3) /* Writing any value should do. */ + + /* Common IVOR epilogue code, context restore.*/ + .globl _ivor_exit +_ivor_exit: + /* Decreasing the SPGR0 register.*/ + mfspr %r0, 272 + eaddi %r0, %r0, -1 + mtspr 272, %r0 + +#if CH_DBG_STATISTICS + bl _stats_start_measure_crit_thd +#endif +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_lock +#endif + bl chSchIsPreemptionRequired + cmpli cr0, %r3, 0 + beq cr0, .noresch + bl chSchDoReschedule +.noresch: +#if CH_DBG_SYSTEM_STATE_CHECK + bl _dbg_check_unlock +#endif +#if CH_DBG_STATISTICS + bl _stats_stop_measure_crit_thd +#endif + + /* Restoring the external context.*/ +#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI + e_lmvgprw 32(%sp) /* Restores GPR0, GPR3...GPR12. */ + e_lmvsprw 16(%sp) /* Restores CR, LR, CTR, XER. */ + e_lmvsrrw 8(%sp) /* Restores PC, MSR. */ +#else /*!(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + lwz %r3, 36(%sp) /* Restores GPR3...GPR12. */ + lwz %r4, 40(%sp) + lwz %r5, 44(%sp) + lwz %r6, 48(%sp) + lwz %r7, 52(%sp) + lwz %r8, 56(%sp) + lwz %r9, 60(%sp) + lwz %r10, 64(%sp) + lwz %r11, 68(%sp) + lwz %r12, 72(%sp) + lwz %r0, 8(%sp) + mtSRR0 %r0 /* Restores PC. */ + lwz %r0, 12(%sp) + mtSRR1 %r0 /* Restores MSR. */ + lwz %r0, 16(%sp) + mtCR %r0 /* Restores CR. */ + lwz %r0, 20(%sp) + mtLR %r0 /* Restores LR. */ + lwz %r0, 24(%sp) + mtCTR %r0 /* Restores CTR. */ + lwz %r0, 28(%sp) + mtXER %r0 /* Restores XER. */ + lwz %r0, 32(%sp) /* Restores GPR0. */ +#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ + addi %sp, %sp, 80 /* Back to the previous frame. */ + rfi + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/common/ports/e200/compilers/GCC/mk/port.mk b/os/common/ports/e200/compilers/GCC/mk/port.mk new file mode 100644 index 000000000..d22a30c97 --- /dev/null +++ b/os/common/ports/e200/compilers/GCC/mk/port.mk @@ -0,0 +1,8 @@ +# List of the ChibiOS/RT e200 generic port files. +PORTSRC = $(CHIBIOS)/os/common/ports/e200/chcore.c + +PORTASM = $(CHIBIOS)/os/common/ports/e200/compilers/GCC/ivor.s \ + $(CHIBIOS)/os/common/ports/e200/compilers/GCC/chcoreasm.s + +PORTINC = $(CHIBIOS)/os/common/ports/e200 \ + $(CHIBIOS)/os/common/ports/e200/compilers/GCC diff --git a/os/common/ports/readme.txt b/os/common/ports/readme.txt new file mode 100644 index 000000000..71e7249e6 --- /dev/null +++ b/os/common/ports/readme.txt @@ -0,0 +1,3 @@ +All the code contained under ./os/common/ports are RTOS ports compatible +with both RT and NIL. The code is placed under ./os/common in order to +prevent code duplication and disalignments. diff --git a/os/common/ports/templates/chcore.c b/os/common/ports/templates/chcore.c new file mode 100644 index 000000000..ef24978a7 --- /dev/null +++ b/os/common/ports/templates/chcore.c @@ -0,0 +1,79 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file templates/chcore.c + * @brief Port related template code. + * @details This file is a template of the system driver functions provided by + * a port. Some of the following functions may be implemented as + * macros in chcore.h if the implementer decides that there is an + * advantage in doing so, for example because performance concerns. + * + * @addtogroup core + * @details Non portable code templates. + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + * @note This function is usually empty. + */ +void _port_init(void) { +} + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +void _port_switch(thread_t *ntp, thread_t *otp) { +} + +/** @} */ diff --git a/os/common/ports/templates/chcore.h b/os/common/ports/templates/chcore.h new file mode 100644 index 000000000..dc4cdb45f --- /dev/null +++ b/os/common/ports/templates/chcore.h @@ -0,0 +1,452 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file templates/chcore.h + * @brief Port related template macros and structures. + * @details This file is a template of the system driver macros provided by + * a port. + * + * @addtogroup core + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Port Capabilities and Constants + * @{ + */ +/** + * @brief This port supports a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE + +/** + * @brief Natural alignment constant. + * @note It is the minimum alignment for pointer-size variables. + */ +#define PORT_NATURAL_ALIGN sizeof (void *) + +/** + * @brief Stack alignment constant. + * @note It is the alignement required for the stack pointer. + */ +#define PORT_STACK_ALIGN sizeof (stkalign_t) + +/** + * @brief Working Areas alignment constant. + * @note It is the alignment to be enforced for thread working areas. + */ +#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t) +/** @} */ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining an XXX architecture. + */ +#define PORT_ARCHITECTURE_XXX + +/** + * @brief Macro defining the specific XXX architecture. + */ +#define PORT_ARCHITECTURE_XXX_YYY + +/** + * @brief Name of the implemented architecture. + */ +#define PORT_ARCHITECTURE_NAME "XXX Architecture" + +/** + * @brief Compiler name and version. + */ +#if defined(__GNUC__) || defined(__DOXYGEN__) +#define PORT_COMPILER_NAME "GCC " __VERSION__ + +#else +#error "unsupported compiler" +#endif + +/** + * @brief Port-specific information string. + */ +#define PORT_INFO "no info" +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) +#define PORT_IDLE_THREAD_STACK_SIZE 32 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + */ +#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) +#define PORT_INT_REQUIRED_STACK 256 +#endif + +/** + * @brief Enables an alternative timer implementation. + * @details Usually the port uses a timer interface defined in the file + * @p chcore_timer.h, if this option is enabled then the file + * @p chcore_timer_alt.h is included instead. + */ +#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__) +#define PORT_USE_ALT_TIMER FALSE +#endif + +/** + * @brief Enables a "wait for interrupt" instruction in the idle loop. + */ +#if !defined(PORT_XXX_WFI_SLEEP_IDLE) || defined(__DOXYGEN__) +#define PORT_XXX_ENABLE_WFI_IDLE FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Type of stack and memory alignment enforcement. + * @note In this architecture the stack alignment is enforced to 64 bits. + */ +typedef uint64_t stkalign_t; + +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + * @note R2 and R13 are not saved because those are assumed to be immutable + * during the system life cycle. + */ +struct port_extctx { +}; + +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switching. + * @note R2 and R13 are not saved because those are assumed to be immutable + * during the system life cycle. + * @note LR is stored in the caller context so it is not present in this + * structure. + */ +struct port_intctx { +}; + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details This structure usually contains just the saved stack pointer + * defined as a pointer to a @p port_intctx structure. + */ +struct port_context { + struct port_intctx *sp; +}; + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ +} + +/** + * @brief Computes the thread working area global size. + * @note There is no need to perform alignments in this macro. + */ +#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ + sizeof(struct port_extctx) + \ + ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + */ +#define PORT_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_PRIORITY(n) false + +/** + * @brief Priority level verification macro. + */ +#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) false + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) void id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) void id(void) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if !CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) +#define port_switch(ntp, otp) _port_switch(ntp, otp) +#else +#define port_switch(ntp, otp) { \ + register struct port_intctx *sp asm ("%r1"); \ + if ((stkalign_t *)(sp - 1) < otp->stklimit) \ + chSysHalt("stack overflow"); \ + _port_switch(ntp, otp); \ +} +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +#ifdef __cplusplus +extern "C" { +#endif + void _port_init(void); + void _port_switch(thread_t *ntp, thread_t *otp); +#ifdef __cplusplus +} +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + + return 0; +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retval false the word specified a disabled interrupts status. + * @retval true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + (void)sts; + + return false; +} + +/** + * @brief Determines the current execution context. + * + * @return The execution context. + * @retval false not running in ISR mode. + * @retval true running in ISR mode. + */ +static inline bool port_is_isr_context(void) { + + return false; +} + +/** + * @brief Kernel-lock action. + * @details Usually this function just disables interrupts but may perform more + * actions. + */ +static inline void port_lock(void) { + +} + +/** + * @brief Kernel-unlock action. + * @details Usually this function just enables interrupts but may perform more + * actions. + */ +static inline void port_unlock(void) { + +} + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details This function is invoked before invoking I-class APIs from + * interrupt handlers. The implementation is architecture dependent, + * in its simplest form it is void. + */ +static inline void port_lock_from_isr(void) { + +} + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details This function is invoked after invoking I-class APIs from interrupt + * handlers. The implementation is architecture dependent, in its + * simplest form it is void. + */ +static inline void port_unlock_from_isr(void) { + +} + +/** + * @brief Disables all the interrupt sources. + * @note Of course non-maskable interrupt sources are not included. + */ +static inline void port_disable(void) { + +} + +/** + * @brief Disables the interrupt sources below kernel-level priority. + * @note Interrupt sources above kernel level remains enabled. + */ +static inline void port_suspend(void) { + +} + +/** + * @brief Enables all the interrupt sources. + */ +static inline void port_enable(void) { + +} + +/** + * @brief Enters an architecture-dependent IRQ-waiting mode. + * @details The function is meant to return when an interrupt becomes pending. + * The simplest implementation is an empty function or macro but this + * would not take advantage of architecture-specific power saving + * modes. + */ +static inline void port_wait_for_interrupt(void) { + +#if PORT_XXX_ENABLE_WFI_IDLE +#endif +} + +/** + * @brief Returns the current value of the realtime counter. + * + * @return The realtime counter value. + */ +static inline rtcnt_t port_rt_get_counter_value(void) { + + return 0; +} + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module late inclusions. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +#if CH_CFG_ST_TIMEDELTA > 0 +#if !PORT_USE_ALT_TIMER +#include "chcore_timer.h" +#else /* PORT_USE_ALT_TIMER */ +#include "chcore_timer_alt.h" +#endif /* PORT_USE_ALT_TIMER */ +#endif /* CH_CFG_ST_TIMEDELTA > 0 */ + +#endif /* !defined(_FROM_ASM_) */ + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/common/ports/templates/chtypes.h b/os/common/ports/templates/chtypes.h new file mode 100644 index 000000000..56549b36e --- /dev/null +++ b/os/common/ports/templates/chtypes.h @@ -0,0 +1,107 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file templates/chtypes.h + * @brief System types template. + * @details The types defined in this file may change depending on the target + * architecture. You may also try to optimize the size of the various + * types in order to privilege size or performance, be careful in + * doing so. + * + * @addtogroup types + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE (!FALSE) +#endif +/** @} */ + +/** + * @name Kernel types + * @{ + */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Realtime accumulator. */ +typedef uint32_t syssts_t; /**< System status word. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint8_t tslices_t; /**< Thread time slices counter.*/ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Numeric event identifier. */ +typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ +typedef uint32_t eventflags_t; /**< Mask of event flags. */ +typedef int32_t cnt_t; /**< Generic signed counter. */ +typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ +/** @} */ + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Makes functions not inlineable. + * @note If the compiler does not support such attribute then the + * realtime counter precision could be degraded. + */ +#define NOINLINE __attribute__((noinline)) + +/** + * @brief Optimized thread function declaration macro. + */ +#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg) + +/** + * @brief Packed variable specifier. + */ +#define PACKED_VAR __attribute__((packed)) + +/** + * @brief Memory alignment enforcement for variables. + */ +#define ALIGNED_VAR(n) __attribute__((aligned(n))) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/common/startup/ARM/compilers/GCC/mk/startup_lpc214x.mk b/os/common/startup/ARM/compilers/GCC/mk/startup_lpc214x.mk index 4f1af1875..baf301a34 100644 --- a/os/common/startup/ARM/compilers/GCC/mk/startup_lpc214x.mk +++ b/os/common/startup/ARM/compilers/GCC/mk/startup_lpc214x.mk @@ -1,9 +1,9 @@ # List of the ChibiOS generic LPC214x file. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/crt1.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARM/compilers/GCC/crt1.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/ARM/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARM/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/ARM/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/ARM/devices/LPC214x +STARTUPINC = ${CHIBIOS}/os/common/startup/ARM/devices/LPC214x -STARTUPLD = ${CHIBIOS}/os/common/ports/ARM/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/ARM/compilers/GCC/ld diff --git a/os/common/startup/ARM/compilers/GCC/rules.ld b/os/common/startup/ARM/compilers/GCC/rules.ld index 6bda5170c..82d1c3270 100644 --- a/os/common/startup/ARM/compilers/GCC/rules.ld +++ b/os/common/startup/ARM/compilers/GCC/rules.ld @@ -117,6 +117,7 @@ SECTIONS { . = ALIGN(8); __stacks_base__ = .; + __main_thread_stack_base__ = .; . += __stacks_total_size__; . = ALIGN(8); __stacks_end__ = .; diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_k20x.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_k20x.mk index b7ea0f3be..0b723f929 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_k20x.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_k20x.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic K20x startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/K20x \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/KINETIS +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/K20x \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/KINETIS -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_kl2x.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_kl2x.mk index a073da004..8b743ec46 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_kl2x.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_kl2x.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic KL2x startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/KL2x \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/KINETIS +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/KL2x \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/KINETIS -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk index e705bd70f..466a58606 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f0xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32F0xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32F0xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32F0xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F0xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32F0xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk index 748075f99..f6c169973 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f1xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32F1xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32F1xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32F1xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F1xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32F1xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk index 9789041c2..8dc97e3ec 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f2xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32F2xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32F2xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32F2xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F2xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32F2xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk index 6968d34a3..bd16abfe5 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f3xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32F3xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32F3xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32F3xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F3xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32F3xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk index 28744ffb5..3083b1372 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f4xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32F4xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32F4xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32F4xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F4xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32F4xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk index b2a8b1f56..ed18f97ee 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32f7xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32F7xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32F7xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32F7xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32F7xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32F7xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk index 24c1ef054..3726c1711 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l0xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32L0xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v6m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32L0xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32L0xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32L0xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32L0xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk index fcd588a9b..63fadc95d 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l1xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32L1xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32L1xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32L1xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32L1xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32L1xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk index a8a3ec441..3c062b821 100644 --- a/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk +++ b/os/common/startup/ARMCMx/compilers/GCC/mk/startup_stm32l4xx.mk @@ -1,12 +1,12 @@ # List of the ChibiOS generic STM32L4xx startup and CMSIS files. -STARTUPSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt1.c \ - $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c +STARTUPSRC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt1.c \ + $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/vectors.c -STARTUPASM = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +STARTUPASM = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/crt0_v7m.s -STARTUPINC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC \ - $(CHIBIOS)/os/common/ports/ARMCMx/devices/STM32L4xx \ - $(CHIBIOS)/os/ext/CMSIS/include \ - $(CHIBIOS)/os/ext/CMSIS/ST/STM32L4xx +STARTUPINC = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC \ + $(CHIBIOS)/os/common/startup/ARMCMx/devices/STM32L4xx \ + $(CHIBIOS)/os/common/ext/CMSIS/include \ + $(CHIBIOS)/os/common/ext/CMSIS/ST/STM32L4xx -STARTUPLD = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/ld +STARTUPLD = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc560bcxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc560bcxx.mk index 2e067b149..6ca606b50 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc560bcxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc560bcxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z0 SPC560BCxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560BCxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC560BCxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560BCxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC560BCxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc560bxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc560bxx.mk index 5cfc4a81e..56a4a9813 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc560bxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc560bxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z0 SPC560Bxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560Bxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC560Bxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560Bxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC560Bxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc560dxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc560dxx.mk index 4e8b633fd..0c5574013 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc560dxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc560dxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z0 SPC560Dxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560Dxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC560Dxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560Dxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC560Dxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc560pxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc560pxx.mk index 72a62d787..fee580672 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc560pxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc560pxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z0 SPC560Pxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560Pxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC560Pxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560Pxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC560Pxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc563mxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc563mxx.mk index 92af14e4c..61f786043 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc563mxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc563mxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z3 SPC563Mxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC563Mxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC563Mxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC563Mxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC563Mxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc564axx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc564axx.mk index a903aa8ff..976ae6dd1 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc564axx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc564axx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z4 SPC564Axx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC564Axx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC564Axx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC564Axx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC564Axx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc56ecxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc56ecxx.mk index d2377e57f..e08bfd6de 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc56ecxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc56ecxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z4 SPC56ECxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC56ECxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC56ECxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC56ECxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC56ECxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/common/startup/e200/compilers/GCC/mk/startup_spc56elxx.mk b/os/common/startup/e200/compilers/GCC/mk/startup_spc56elxx.mk index 40753b63f..8eae8535a 100644 --- a/os/common/startup/e200/compilers/GCC/mk/startup_spc56elxx.mk +++ b/os/common/startup/e200/compilers/GCC/mk/startup_spc56elxx.mk @@ -1,11 +1,11 @@ # List of the ChibiOS e200z4 SPC56ELxx startup files. STARTUPSRC = -STARTUPASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC56ELxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s +STARTUPASM = $(CHIBIOS)/os/common/startup/e200/devices/SPC56ELxx/boot.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/vectors.s \ + $(CHIBIOS)/os/common/startup/e200/compilers/GCC/crt0.s -STARTUPINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC56ELxx +STARTUPINC = ${CHIBIOS}/os/common/startup/e200/compilers/GCC \ + ${CHIBIOS}/os/common/startup/e200/devices/SPC56ELxx -STARTUPLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld +STARTUPLD = ${CHIBIOS}/os/common/startup/e200/compilers/GCC/ld diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h new file mode 100644 index 000000000..168709049 --- /dev/null +++ b/os/nil/include/ch.h @@ -0,0 +1,1003 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file nil.h + * @brief Nil RTOS main header file. + * @details This header includes all the required kernel headers so it is the + * only header you usually need to include in your application. + * + * @addtogroup NIL_KERNEL + * @{ + */ + +#ifndef _NIL_H_ +#define _NIL_H_ + +/** + * @brief Type of a structure representing a thread. + * @note It is required as an early definition. + */ +typedef struct nil_thread thread_t; + +#include "nilconf.h" +#include "niltypes.h" +#include "nilcore.h" + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @brief ChibiOS/NIL identification macro. + */ +#define _CHIBIOS_NIL_ + +/** + * @brief Stable release flag. + */ +#define CH_KERNEL_STABLE 0 + +/** + * @name ChibiOS/NIL version identification + * @{ + */ +/** + * @brief Kernel version string. + */ +#define CH_KERNEL_VERSION "1.1.1" + +/** + * @brief Kernel version major number. + */ +#define CH_KERNEL_MAJOR 1 + +/** + * @brief Kernel version minor number. + */ +#define CH_KERNEL_MINOR 1 + +/** + * @brief Kernel version patch number. + */ +#define CH_KERNEL_PATCH 1 +/** @} */ + +/** + * @name Wakeup messages + * @{ + */ +#define MSG_OK (msg_t)0 /**< @brief OK wakeup message. */ +#define MSG_TIMEOUT (msg_t)-1 /**< @brief Wake-up caused by + a timeout condition. */ +#define MSG_RESET (msg_t)-2 /**< @brief Wake-up caused by + a reset condition. */ +/** @} */ + +/** + * @name Special time constants + * @{ + */ +/** + * @brief Zero time specification for some functions with a timeout + * specification. + * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter, + * see the specific function documentation. + */ +#define TIME_IMMEDIATE ((systime_t)-1) + +/** + * @brief Infinite time specification for all functions with a timeout + * specification. + */ +#define TIME_INFINITE ((systime_t)0) +/** @} */ + +/** + * @name Thread state related macros + * @{ + */ +#define NIL_STATE_READY (tstate_t)0 /**< @brief Thread ready or + executing. */ +#define NIL_STATE_SLEEPING (tstate_t)1 /**< @brief Thread sleeping. */ +#define NIL_STATE_SUSP (tstate_t)2 /**< @brief Thread suspended. */ +#define NIL_STATE_WTSEM (tstate_t)3 /**< @brief On semaphore. */ +#define NIL_STATE_WTOREVT (tstate_t)4 /**< @brief Waiting for events. */ +#define NIL_THD_IS_READY(tr) ((tr)->state == NIL_STATE_READY) +#define NIL_THD_IS_SLEEPING(tr) ((tr)->state == NIL_STATE_SLEEPING) +#define NIL_THD_IS_SUSP(tr) ((tr)->state == NIL_STATE_SUSP) +#define NIL_THD_IS_WTSEM(tr) ((tr)->state == NIL_STATE_WTSEM) +#define NIL_THD_IS_WTOREVT(tr) ((tr)->state == NIL_STATE_WTOREVT) +/** @} */ + +/** + * @name Events related macros + * @{ + */ +/** + * @brief All events allowed mask. + */ +#define ALL_EVENTS ((eventmask_t)-1) + +/** + * @brief Returns an event mask from an event identifier. + */ +#define EVENT_MASK(eid) ((eventmask_t)(1 << (eid))) +/** @} */ + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Number of user threads in the application. + * @note This number is not inclusive of the idle thread which is + * implicitly handled. + */ +#if !defined(NIL_CFG_NUM_THREADS) || defined(__DOXYGEN__) +#define NIL_CFG_NUM_THREADS 2 +#endif + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#if !defined(NIL_CFG_ST_RESOLUTION) || defined(__DOXYGEN__) +#define NIL_CFG_ST_RESOLUTION 32 +#endif + +/** + * @brief System tick frequency. + * @note This value together with the @p NIL_CFG_ST_RESOLUTION + * option defines the maximum amount of time allowed for + * timeouts. + */ +#if !defined(NIL_CFG_ST_FREQUENCY) || defined(__DOXYGEN__) +#define NIL_CFG_ST_FREQUENCY 100 +#endif + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#if !defined(NIL_CFG_ST_TIMEDELTA) || defined(__DOXYGEN__) +#define NIL_CFG_ST_TIMEDELTA 0 +#endif + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#if !defined(NIL_CFG_USE_EVENTS) || defined(__DOXYGEN__) +#define NIL_CFG_USE_EVENTS TRUE +#endif + +/** + * @brief System assertions. + */ +#if !defined(NIL_CFG_ENABLE_ASSERTS) || defined(__DOXYGEN__) +#define NIL_CFG_ENABLE_ASSERTS FALSE +#endif + +/** + * @brief Stack check. + */ +#if !defined(NIL_CFG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) +#define NIL_CFG_ENABLE_STACK_CHECK FALSE +#endif + +/** + * @brief System initialization hook. + */ +#if !defined(NIL_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__) +#define NIL_CFG_SYSTEM_INIT_HOOK() {} +#endif + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#if !defined(NIL_CFG_THREAD_EXT_FIELDS) || defined(__DOXYGEN__) +#define NIL_CFG_THREAD_EXT_FIELDS +#endif + +/** + * @brief Threads initialization hook. + */ +#if !defined(NIL_CFG_THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__) +#define NIL_CFG_THREAD_EXT_INIT_HOOK(tr) {} +#endif + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#if !defined(NIL_CFG_IDLE_ENTER_HOOK) || defined(__DOXYGEN__) +#define NIL_CFG_IDLE_ENTER_HOOK() {} +#endif + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#if !defined(NIL_CFG_IDLE_LEAVE_HOOK) || defined(__DOXYGEN__) +#define NIL_CFG_IDLE_LEAVE_HOOK() {} +#endif + +/** + * @brief System halt hook. + */ +#if !defined(NIL_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) +#define NIL_CFG_SYSTEM_HALT_HOOK(reason) {} +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if NIL_CFG_NUM_THREADS < 1 +#error "at least one thread must be defined" +#endif + +#if NIL_CFG_NUM_THREADS > 12 +#error "Nil is not recommended for thread-intensive applications, consider" \ + "ChibiOS/RT instead" +#endif + +#if (NIL_CFG_ST_RESOLUTION != 16) && (NIL_CFG_ST_RESOLUTION != 32) +#error "invalid NIL_CFG_ST_RESOLUTION specified, must be 16 or 32" +#endif + +#if NIL_CFG_ST_FREQUENCY <= 0 +#error "invalid NIL_CFG_ST_FREQUENCY specified, must be greated than zero" +#endif + +#if (NIL_CFG_ST_TIMEDELTA < 0) || (NIL_CFG_ST_TIMEDELTA == 1) +#error "invalid NIL_CFG_ST_TIMEDELTA specified, must " \ + "be zero or greater than one" +#endif + +#if (NIL_CFG_ENABLE_ASSERTS == TRUE) || (NIL_CFG_ENABLE_STACK_CHECK == TRUE) +#define NIL_DBG_ENABLED TRUE +#else +#define NIL_DBG_ENABLED FALSE +#endif + +/** Boundaries of the idle thread boundaries, only required if stack checking + is enabled.*/ +#if (NIL_CFG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__) +extern stkalign_t __main_thread_stack_base__, __main_thread_stack_end__; + +#define THD_IDLE_BASE (&__main_thread_stack_base__) +#define THD_IDLE_END (&__main_thread_stack_end__) +#else +#define THD_IDLE_BASE NULL +#define THD_IDLE_END NULL +#endif + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type of internal context structure. + */ +typedef struct port_intctx intctx_t; + +/** + * @brief Type of a structure representing a semaphore. + */ +typedef struct nil_semaphore semaphore_t; + +/** + * @brief Structure representing a counting semaphore. + */ +struct nil_semaphore { + volatile cnt_t cnt; /**< @brief Semaphore counter. */ +}; + +/** + * @brief Thread function. + */ +typedef void (*tfunc_t)(void *p); + +/** + * @brief Type of a structure representing a thread static configuration. + */ +typedef struct nil_thread_cfg thread_config_t; + +/** + * @brief Structure representing a thread static configuration. + */ +struct nil_thread_cfg { + stkalign_t *wbase; /**< @brief Thread working area base. */ + stkalign_t *wend; /**< @brief Thread working area end. */ + const char *namep; /**< @brief Thread name, for debugging. */ + tfunc_t funcp; /**< @brief Thread function. */ + void *arg; /**< @brief Thread function argument. */ +}; + +/** + * @brief Type of a thread reference. + */ +typedef thread_t * thread_reference_t; + +/** + * @brief Structure representing a thread. + */ +struct nil_thread { + intctx_t *ctxp; /**< @brief Pointer to internal context. */ + tstate_t state; /**< @brief Thread state. */ + /* Note, the following union contains a pointer while the thread is in a + sleeping state (!NIL_THD_IS_READY()) else contains the wake-up message.*/ + union { + msg_t msg; /**< @brief Wake-up message. */ + void *p; /**< @brief Generic pointer. */ + thread_reference_t *trp; /**< @brief Pointer to thread reference. */ + semaphore_t *semp; /**< @brief Pointer to semaphore. */ +#if (NIL_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) + eventmask_t ewmask; /**< @brief Enabled events mask. */ +#endif + } u1; + volatile systime_t timeout;/**< @brief Timeout counter, zero + if disabled. */ +#if (NIL_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) + eventmask_t epmask; /**< @brief Pending events mask. */ +#endif +#if (NIL_CFG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__) + stkalign_t *stklim;/**< @brief Thread stack boundary. */ +#endif + /* Optional extra fields.*/ + NIL_CFG_THREAD_EXT_FIELDS +}; + +/** + * @brief Type of a structure representing the system. + */ +typedef struct nil_system nil_system_t; + +/** + * @brief System data structure. + * @note This structure contain all the data areas used by the OS except + * stacks. + */ +struct nil_system { + /** + * @brief Pointer to the running thread. + */ + thread_t *current; + /** + * @brief Pointer to the next thread to be executed. + * @note This pointer must point at the same thread pointed by @p current + * or to an higher priority thread if a switch is required. + */ + thread_t *next; +#if (NIL_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__) + /** + * @brief System time. + */ + volatile systime_t systime; +#endif +#if (NIL_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__) + /** + * @brief System time of the last tick event. + */ + systime_t lasttime; + /** + * @brief Time of the next scheduled tick event. + */ + systime_t nexttime; +#endif + /** + * @brief Thread structures for all the defined threads. + */ + thread_t threads[NIL_CFG_NUM_THREADS + 1]; +#if (NIL_DBG_ENABLED == TRUE) || defined(__DOXYGEN__) + /** + * @brief Panic message. + * @note This field is only present if some debug options have been + * activated. + * @note Accesses to this pointer must never be optimized out so the + * field itself is declared volatile. + */ + const char * volatile dbg_panic_msg; +#endif +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @name Threads tables definition macros + * @{ + */ +/** + * @brief Start of user threads table. + */ +#define THD_TABLE_BEGIN \ + const thread_config_t nil_thd_configs[NIL_CFG_NUM_THREADS + 1] = { + +/** + * @brief Entry of user threads table + */ +#define THD_TABLE_ENTRY(wap, name, funcp, arg) \ + {wap, ((stkalign_t *)(wap)) + (sizeof (wap) / sizeof(stkalign_t)), \ + name, funcp, arg}, + +/** + * @brief End of user threads table. + */ +#define THD_TABLE_END \ + {THD_IDLE_BASE, THD_IDLE_END, "idle", NULL, NULL} \ +}; +/** @} */ + +/** + * @name Working Areas and Alignment + */ +/** + * @brief Enforces a correct alignment for a stack area size value. + * + * @param[in] n the stack size to be aligned to the next stack + * alignment boundary + * @return The aligned stack size. + * + * @api + */ +#define THD_ALIGN_STACK_SIZE(n) \ + ((((n) - 1U) | (sizeof(stkalign_t) - 1U)) + 1U) + +/** + * @brief Calculates the total Working Area size. + * + * @param[in] n the stack size to be assigned to the thread + * @return The total used memory in bytes. + * + * @api + */ +#define THD_WORKING_AREA_SIZE(n) \ + THD_ALIGN_STACK_SIZE(PORT_WA_SIZE(n)) + +/** + * @brief Static working area allocation. + * @details This macro is used to allocate a static thread working area + * aligned as both position and size. + * + * @param[in] s the name to be assigned to the stack array + * @param[in] n the stack size to be assigned to the thread + * + * @api + */ +#define THD_WORKING_AREA(s, n) \ + stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof(stkalign_t)] +/** @} */ + +/** + * @name Threads abstraction macros + */ +/** + * @brief Thread declaration macro. + * @note Thread declarations should be performed using this macro because + * the port layer could define optimizations for thread functions. + */ +#define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg) +/** @} */ + +/** + * @name ISRs abstraction macros + */ +/** + * @brief Priority level validation macro. + * @details This macro determines if the passed value is a valid priority + * level for the underlying architecture. + * + * @param[in] prio the priority level + * @return Priority range result. + * @retval false if the priority is invalid or if the architecture + * does not support priorities. + * @retval true if the priority is valid. + */ +#if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__) +#define CH_IRQ_IS_VALID_PRIORITY(prio) \ + PORT_IRQ_IS_VALID_PRIORITY(prio) +#else +#define CH_IRQ_IS_VALID_PRIORITY(prio) false +#endif + +/** + * @brief Priority level validation macro. + * @details This macro determines if the passed value is a valid priority + * level that cannot preempt the kernel critical zone. + * + * @param[in] prio the priority level + * @return Priority range result. + * @retval false if the priority is invalid or if the architecture + * does not support priorities. + * @retval true if the priority is valid. + */ +#if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__) +#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \ + PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio) +#else +#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false +#endif + +/** + * @brief IRQ handler enter code. + * @note Usually IRQ handlers functions are also declared naked. + * @note On some architectures this macro can be empty. + * + * @special + */ +#define CH_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE() + +/** + * @brief IRQ handler exit code. + * @note Usually IRQ handlers function are also declared naked. + * + * @special + */ +#define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE() + +/** + * @brief Standard normal IRQ handler declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + * + * @special + */ +#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) +/** @} */ + +/** + * @name Fast ISRs abstraction macros + */ +/** + * @brief Standard fast IRQ handler declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + * @note Not all architectures support fast interrupts. + * + * @special + */ +#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id) +/** @} */ + +/** + * @name Time conversion utilities + * @{ + */ +/** + * @brief Seconds to system ticks. + * @details Converts from seconds to system ticks number. + * @note The result is rounded upward to the next tick boundary. + * + * @param[in] sec number of seconds + * @return The number of ticks. + * + * @api + */ +#define S2ST(sec) \ + ((systime_t)((uint32_t)(sec) * (uint32_t)NIL_CFG_ST_FREQUENCY)) + +/** + * @brief Milliseconds to system ticks. + * @details Converts from milliseconds to system ticks number. + * @note The result is rounded upward to the next tick boundary. + * + * @param[in] msec number of milliseconds + * @return The number of ticks. + * + * @api + */ +#define MS2ST(msec) \ + ((systime_t)(((((uint32_t)(msec)) * \ + ((uint32_t)NIL_CFG_ST_FREQUENCY)) + 999UL) / 1000UL)) + +/** + * @brief Microseconds to system ticks. + * @details Converts from microseconds to system ticks number. + * @note The result is rounded upward to the next tick boundary. + * + * @param[in] usec number of microseconds + * @return The number of ticks. + * + * @api + */ +#define US2ST(usec) \ + ((systime_t)(((((uint32_t)(usec)) * \ + ((uint32_t)NIL_CFG_ST_FREQUENCY)) + 999999UL) / 1000000UL)) +/** @} */ + +/** + * @name Time conversion utilities for the realtime counter + * @{ + */ +/** + * @brief Seconds to realtime counter. + * @details Converts from seconds to realtime counter cycles. + * @note The macro assumes that @p freq >= @p 1. + * + * @param[in] freq clock frequency, in Hz, of the realtime counter + * @param[in] sec number of seconds + * @return The number of cycles. + * + * @api + */ +#define S2RTC(freq, sec) ((freq) * (sec)) + +/** + * @brief Milliseconds to realtime counter. + * @details Converts from milliseconds to realtime counter cycles. + * @note The result is rounded upward to the next millisecond boundary. + * @note The macro assumes that @p freq >= @p 1000. + * + * @param[in] freq clock frequency, in Hz, of the realtime counter + * @param[in] msec number of milliseconds + * @return The number of cycles. + * + * @api + */ +#define MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec)) + +/** + * @brief Microseconds to realtime counter. + * @details Converts from microseconds to realtime counter cycles. + * @note The result is rounded upward to the next microsecond boundary. + * @note The macro assumes that @p freq >= @p 1000000. + * + * @param[in] freq clock frequency, in Hz, of the realtime counter + * @param[in] usec number of microseconds + * @return The number of cycles. + * + * @api + */ +#define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec)) +/** @} */ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Returns the current value of the system real time counter. + * @note This function is only available if the port layer supports the + * option @p PORT_SUPPORTS_RT. + * + * @return The value of the system realtime counter of + * type rtcnt_t. + * + * @xclass + */ +#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__) +#define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value() +#endif + +/** + * @brief Enters the kernel lock mode. + * + * @special + */ +#define chSysDisable() port_disable() + +/** + * @brief Enters the kernel lock mode. + * + * @special + */ +#define chSysEnable() port_enable() + +/** + * @brief Enters the kernel lock state. + * + * @special + */ +#define chSysLock() port_lock() + +/** + * @brief Leaves the kernel lock state. + * + * @special + */ +#define chSysUnlock() port_unlock() + +/** + * @brief Enters the kernel lock state from within an interrupt handler. + * @note This API may do nothing on some architectures, it is required + * because on ports that support preemptable interrupt handlers + * it is required to raise the interrupt mask to the same level of + * the system mutual exclusion zone.
+ * It is good practice to invoke this API before invoking any I-class + * syscall from an interrupt handler. + * @note This API must be invoked exclusively from interrupt handlers. + * + * @special + */ +#define chSysLockFromISR() port_lock_from_isr() + +/** + * @brief Leaves the kernel lock state from within an interrupt handler. + * + * @note This API may do nothing on some architectures, it is required + * because on ports that support preemptable interrupt handlers + * it is required to raise the interrupt mask to the same level of + * the system mutual exclusion zone.
+ * It is good practice to invoke this API after invoking any I-class + * syscall from an interrupt handler. + * @note This API must be invoked exclusively from interrupt handlers. + * + * @special + */ +#define chSysUnlockFromISR() port_unlock_from_isr() + +/** + * @brief Evaluates if a reschedule is required. + * + * @retval true if there is a thread that must go in running state + * immediately. + * @retval false if preemption is not required. + * + * @iclass + */ +#define chSchIsRescRequiredI() ((bool)(nil.current != nil.next)) + +/** + * @brief Returns a pointer to the current @p thread_t. + * + * @xclass + */ +#define chThdGetSelfX() nil.current + +/** + * @brief Delays the invoking thread for the specified number of seconds. + * @note The specified time is rounded up to a value allowed by the real + * system clock. + * @note The maximum specified value is implementation dependent. + * + * @param[in] sec time in seconds, must be different from zero + * + * @api + */ +#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec)) + +/** + * @brief Delays the invoking thread for the specified number of + * milliseconds. + * @note The specified time is rounded up to a value allowed by the real + * system clock. + * @note The maximum specified value is implementation dependent. + * + * @param[in] msec time in milliseconds, must be different from zero + * + * @api + */ +#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec)) + +/** + * @brief Delays the invoking thread for the specified number of + * microseconds. + * @note The specified time is rounded up to a value allowed by the real + * system clock. + * @note The maximum specified value is implementation dependent. + * + * @param[in] usec time in microseconds, must be different from zero + * + * @api + */ +#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec)) + +/** + * @brief Suspends the invoking thread for the specified time. + * + * @param[in] timeout the delay in system ticks + * + * @sclass + */ +#define chThdSleepS(timeout) (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, timeout) + +/** + * @brief Suspends the invoking thread until the system time arrives to the + * specified value. + * + * @param[in] abstime absolute system time + * + * @sclass + */ +#define chThdSleepUntilS(abstime) \ + (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, (abstime) - \ + chVTGetSystemTimeX()) + +/** + * @brief Initializes a semaphore with the specified counter value. + * + * @param[out] sp pointer to a @p semaphore_t structure + * @param[in] n initial value of the semaphore counter. Must be + * non-negative. + * + * @init + */ +#define chSemObjectInit(sp, n) ((sp)->cnt = n) + +/** + * @brief Performs a wait operation on a semaphore. + * + * @param[in] sp pointer to a @p semaphore_t structure + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the + * semaphore has been signaled. + * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset(). + * + * @api + */ +#define chSemWait(sp) chSemWaitTimeout(sp, TIME_INFINITE) + +/** + * @brief Performs a wait operation on a semaphore. + * + * @param[in] sp pointer to a @p semaphore_t structure + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the + * semaphore has been signaled. + * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset(). + * + * @sclass + */ +#define chSemWaitS(sp) chSemWaitTimeoutS(sp, TIME_INFINITE) + +/** + * @brief Returns the semaphore counter current value. + * + * @iclass + */ +#define chSemGetCounterI(sp) ((sp)->cnt) + +/** + * @brief Current system time. + * @details Returns the number of system ticks since the @p chSysInit() + * invocation. + * @note The counter can reach its maximum and then restart from zero. + * @note This function can be called from any context but its atomicity + * is not guaranteed on architectures whose word size is less than + * @p systime_t size. + * + * @return The system time in ticks. + * + * @xclass + */ +#if (NIL_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__) +#define chVTGetSystemTimeX() (nil.systime) +#else +#define chVTGetSystemTimeX() port_timer_get_time() +#endif + +/** + * @brief Returns the elapsed time since the specified start time. + * + * @param[in] start start time + * @return The elapsed time. + * + * @xclass + */ +#define chVTTimeElapsedSinceX(start) \ + ((systime_t)(chVTGetSystemTimeX() - (start))) + +/** + * @brief Checks if the specified time is within the specified time window. + * @note When start==end then the function returns always true because the + * whole time range is specified. + * @note This function can be called from any context. + * + * @param[in] time the time to be verified + * @param[in] start the start of the time window (inclusive) + * @param[in] end the end of the time window (non inclusive) + * @retval true current time within the specified time window. + * @retval false current time not within the specified time window. + * + * @xclass + */ +#define chVTIsTimeWithinX(time, start, end) \ + ((bool)((systime_t)((time) - (start)) < (systime_t)((end) - (start)))) + +/** + * @brief Condition assertion. + * @details If the condition check fails then the kernel panics with a + * message and halts. + * @note The condition is tested only if the @p NIL_CFG_ENABLE_ASSERTS + * switch is specified in @p nilconf.h else the macro does nothing. + * @note The remark string is not currently used except for putting a + * comment in the code about the assertion. + * + * @param[in] c the condition to be verified to be true + * @param[in] r a remark string + * + * @api + */ +#if !defined(chDbgAssert) +#define chDbgAssert(c, r) do { \ + /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \ + if (NIL_CFG_ENABLE_ASSERTS != FALSE) { \ + if (!(c)) { \ + /*lint -restore*/ \ + chSysHalt(__func__); \ + } \ + } \ +} while (false) +#endif /* !defined(chDbgAssert) */ +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern nil_system_t nil; +extern const thread_config_t nil_thd_configs[NIL_CFG_NUM_THREADS + 1]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void chSysInit(void); + void chSysHalt(const char *reason); + void chSysTimerHandlerI(void); + void chSysUnconditionalLock(void); + void chSysUnconditionalUnlock(void); + syssts_t chSysGetStatusAndLockX(void); + bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end); + void chSysPolledDelayX(rtcnt_t cycles); + void chSysRestoreStatusX(syssts_t sts); + thread_t *chSchReadyI(thread_t *tp, msg_t msg); + void chSchRescheduleS(void); + msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout); + msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout); + void chThdResumeI(thread_reference_t *trp, msg_t msg); + void chThdSleep(systime_t timeout); + void chThdSleepUntil(systime_t abstime); + msg_t chSemWaitTimeout(semaphore_t *sp, systime_t timeout); + msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout); + void chSemSignal(semaphore_t *sp); + void chSemSignalI(semaphore_t *sp); + void chSemReset(semaphore_t *sp, cnt_t n); + void chSemResetI(semaphore_t *sp, cnt_t n); +#if NIL_CFG_USE_EVENTS == TRUE + void chEvtSignal(thread_t *tp, eventmask_t mask); + void chEvtSignalI(thread_t *tp, eventmask_t mask); + eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t timeout); + eventmask_t chEvtWaitAnyTimeoutS(eventmask_t mask, systime_t timeout); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _NIL_H_ */ + +/** @} */ diff --git a/os/nil/include/nil.h b/os/nil/include/nil.h deleted file mode 100644 index 168709049..000000000 --- a/os/nil/include/nil.h +++ /dev/null @@ -1,1003 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file nil.h - * @brief Nil RTOS main header file. - * @details This header includes all the required kernel headers so it is the - * only header you usually need to include in your application. - * - * @addtogroup NIL_KERNEL - * @{ - */ - -#ifndef _NIL_H_ -#define _NIL_H_ - -/** - * @brief Type of a structure representing a thread. - * @note It is required as an early definition. - */ -typedef struct nil_thread thread_t; - -#include "nilconf.h" -#include "niltypes.h" -#include "nilcore.h" - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @brief ChibiOS/NIL identification macro. - */ -#define _CHIBIOS_NIL_ - -/** - * @brief Stable release flag. - */ -#define CH_KERNEL_STABLE 0 - -/** - * @name ChibiOS/NIL version identification - * @{ - */ -/** - * @brief Kernel version string. - */ -#define CH_KERNEL_VERSION "1.1.1" - -/** - * @brief Kernel version major number. - */ -#define CH_KERNEL_MAJOR 1 - -/** - * @brief Kernel version minor number. - */ -#define CH_KERNEL_MINOR 1 - -/** - * @brief Kernel version patch number. - */ -#define CH_KERNEL_PATCH 1 -/** @} */ - -/** - * @name Wakeup messages - * @{ - */ -#define MSG_OK (msg_t)0 /**< @brief OK wakeup message. */ -#define MSG_TIMEOUT (msg_t)-1 /**< @brief Wake-up caused by - a timeout condition. */ -#define MSG_RESET (msg_t)-2 /**< @brief Wake-up caused by - a reset condition. */ -/** @} */ - -/** - * @name Special time constants - * @{ - */ -/** - * @brief Zero time specification for some functions with a timeout - * specification. - * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter, - * see the specific function documentation. - */ -#define TIME_IMMEDIATE ((systime_t)-1) - -/** - * @brief Infinite time specification for all functions with a timeout - * specification. - */ -#define TIME_INFINITE ((systime_t)0) -/** @} */ - -/** - * @name Thread state related macros - * @{ - */ -#define NIL_STATE_READY (tstate_t)0 /**< @brief Thread ready or - executing. */ -#define NIL_STATE_SLEEPING (tstate_t)1 /**< @brief Thread sleeping. */ -#define NIL_STATE_SUSP (tstate_t)2 /**< @brief Thread suspended. */ -#define NIL_STATE_WTSEM (tstate_t)3 /**< @brief On semaphore. */ -#define NIL_STATE_WTOREVT (tstate_t)4 /**< @brief Waiting for events. */ -#define NIL_THD_IS_READY(tr) ((tr)->state == NIL_STATE_READY) -#define NIL_THD_IS_SLEEPING(tr) ((tr)->state == NIL_STATE_SLEEPING) -#define NIL_THD_IS_SUSP(tr) ((tr)->state == NIL_STATE_SUSP) -#define NIL_THD_IS_WTSEM(tr) ((tr)->state == NIL_STATE_WTSEM) -#define NIL_THD_IS_WTOREVT(tr) ((tr)->state == NIL_STATE_WTOREVT) -/** @} */ - -/** - * @name Events related macros - * @{ - */ -/** - * @brief All events allowed mask. - */ -#define ALL_EVENTS ((eventmask_t)-1) - -/** - * @brief Returns an event mask from an event identifier. - */ -#define EVENT_MASK(eid) ((eventmask_t)(1 << (eid))) -/** @} */ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Number of user threads in the application. - * @note This number is not inclusive of the idle thread which is - * implicitly handled. - */ -#if !defined(NIL_CFG_NUM_THREADS) || defined(__DOXYGEN__) -#define NIL_CFG_NUM_THREADS 2 -#endif - -/** - * @brief System time counter resolution. - * @note Allowed values are 16 or 32 bits. - */ -#if !defined(NIL_CFG_ST_RESOLUTION) || defined(__DOXYGEN__) -#define NIL_CFG_ST_RESOLUTION 32 -#endif - -/** - * @brief System tick frequency. - * @note This value together with the @p NIL_CFG_ST_RESOLUTION - * option defines the maximum amount of time allowed for - * timeouts. - */ -#if !defined(NIL_CFG_ST_FREQUENCY) || defined(__DOXYGEN__) -#define NIL_CFG_ST_FREQUENCY 100 -#endif - -/** - * @brief Time delta constant for the tick-less mode. - * @note If this value is zero then the system uses the classic - * periodic tick. This value represents the minimum number - * of ticks that is safe to specify in a timeout directive. - * The value one is not valid, timeouts are rounded up to - * this value. - */ -#if !defined(NIL_CFG_ST_TIMEDELTA) || defined(__DOXYGEN__) -#define NIL_CFG_ST_TIMEDELTA 0 -#endif - -/** - * @brief Events Flags APIs. - * @details If enabled then the event flags APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#if !defined(NIL_CFG_USE_EVENTS) || defined(__DOXYGEN__) -#define NIL_CFG_USE_EVENTS TRUE -#endif - -/** - * @brief System assertions. - */ -#if !defined(NIL_CFG_ENABLE_ASSERTS) || defined(__DOXYGEN__) -#define NIL_CFG_ENABLE_ASSERTS FALSE -#endif - -/** - * @brief Stack check. - */ -#if !defined(NIL_CFG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) -#define NIL_CFG_ENABLE_STACK_CHECK FALSE -#endif - -/** - * @brief System initialization hook. - */ -#if !defined(NIL_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_SYSTEM_INIT_HOOK() {} -#endif - -/** - * @brief Threads descriptor structure extension. - * @details User fields added to the end of the @p thread_t structure. - */ -#if !defined(NIL_CFG_THREAD_EXT_FIELDS) || defined(__DOXYGEN__) -#define NIL_CFG_THREAD_EXT_FIELDS -#endif - -/** - * @brief Threads initialization hook. - */ -#if !defined(NIL_CFG_THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_THREAD_EXT_INIT_HOOK(tr) {} -#endif - -/** - * @brief Idle thread enter hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to activate a power saving mode. - */ -#if !defined(NIL_CFG_IDLE_ENTER_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_IDLE_ENTER_HOOK() {} -#endif - -/** - * @brief Idle thread leave hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to deactivate a power saving mode. - */ -#if !defined(NIL_CFG_IDLE_LEAVE_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_IDLE_LEAVE_HOOK() {} -#endif - -/** - * @brief System halt hook. - */ -#if !defined(NIL_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_SYSTEM_HALT_HOOK(reason) {} -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if NIL_CFG_NUM_THREADS < 1 -#error "at least one thread must be defined" -#endif - -#if NIL_CFG_NUM_THREADS > 12 -#error "Nil is not recommended for thread-intensive applications, consider" \ - "ChibiOS/RT instead" -#endif - -#if (NIL_CFG_ST_RESOLUTION != 16) && (NIL_CFG_ST_RESOLUTION != 32) -#error "invalid NIL_CFG_ST_RESOLUTION specified, must be 16 or 32" -#endif - -#if NIL_CFG_ST_FREQUENCY <= 0 -#error "invalid NIL_CFG_ST_FREQUENCY specified, must be greated than zero" -#endif - -#if (NIL_CFG_ST_TIMEDELTA < 0) || (NIL_CFG_ST_TIMEDELTA == 1) -#error "invalid NIL_CFG_ST_TIMEDELTA specified, must " \ - "be zero or greater than one" -#endif - -#if (NIL_CFG_ENABLE_ASSERTS == TRUE) || (NIL_CFG_ENABLE_STACK_CHECK == TRUE) -#define NIL_DBG_ENABLED TRUE -#else -#define NIL_DBG_ENABLED FALSE -#endif - -/** Boundaries of the idle thread boundaries, only required if stack checking - is enabled.*/ -#if (NIL_CFG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__) -extern stkalign_t __main_thread_stack_base__, __main_thread_stack_end__; - -#define THD_IDLE_BASE (&__main_thread_stack_base__) -#define THD_IDLE_END (&__main_thread_stack_end__) -#else -#define THD_IDLE_BASE NULL -#define THD_IDLE_END NULL -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type of internal context structure. - */ -typedef struct port_intctx intctx_t; - -/** - * @brief Type of a structure representing a semaphore. - */ -typedef struct nil_semaphore semaphore_t; - -/** - * @brief Structure representing a counting semaphore. - */ -struct nil_semaphore { - volatile cnt_t cnt; /**< @brief Semaphore counter. */ -}; - -/** - * @brief Thread function. - */ -typedef void (*tfunc_t)(void *p); - -/** - * @brief Type of a structure representing a thread static configuration. - */ -typedef struct nil_thread_cfg thread_config_t; - -/** - * @brief Structure representing a thread static configuration. - */ -struct nil_thread_cfg { - stkalign_t *wbase; /**< @brief Thread working area base. */ - stkalign_t *wend; /**< @brief Thread working area end. */ - const char *namep; /**< @brief Thread name, for debugging. */ - tfunc_t funcp; /**< @brief Thread function. */ - void *arg; /**< @brief Thread function argument. */ -}; - -/** - * @brief Type of a thread reference. - */ -typedef thread_t * thread_reference_t; - -/** - * @brief Structure representing a thread. - */ -struct nil_thread { - intctx_t *ctxp; /**< @brief Pointer to internal context. */ - tstate_t state; /**< @brief Thread state. */ - /* Note, the following union contains a pointer while the thread is in a - sleeping state (!NIL_THD_IS_READY()) else contains the wake-up message.*/ - union { - msg_t msg; /**< @brief Wake-up message. */ - void *p; /**< @brief Generic pointer. */ - thread_reference_t *trp; /**< @brief Pointer to thread reference. */ - semaphore_t *semp; /**< @brief Pointer to semaphore. */ -#if (NIL_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) - eventmask_t ewmask; /**< @brief Enabled events mask. */ -#endif - } u1; - volatile systime_t timeout;/**< @brief Timeout counter, zero - if disabled. */ -#if (NIL_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) - eventmask_t epmask; /**< @brief Pending events mask. */ -#endif -#if (NIL_CFG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__) - stkalign_t *stklim;/**< @brief Thread stack boundary. */ -#endif - /* Optional extra fields.*/ - NIL_CFG_THREAD_EXT_FIELDS -}; - -/** - * @brief Type of a structure representing the system. - */ -typedef struct nil_system nil_system_t; - -/** - * @brief System data structure. - * @note This structure contain all the data areas used by the OS except - * stacks. - */ -struct nil_system { - /** - * @brief Pointer to the running thread. - */ - thread_t *current; - /** - * @brief Pointer to the next thread to be executed. - * @note This pointer must point at the same thread pointed by @p current - * or to an higher priority thread if a switch is required. - */ - thread_t *next; -#if (NIL_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__) - /** - * @brief System time. - */ - volatile systime_t systime; -#endif -#if (NIL_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__) - /** - * @brief System time of the last tick event. - */ - systime_t lasttime; - /** - * @brief Time of the next scheduled tick event. - */ - systime_t nexttime; -#endif - /** - * @brief Thread structures for all the defined threads. - */ - thread_t threads[NIL_CFG_NUM_THREADS + 1]; -#if (NIL_DBG_ENABLED == TRUE) || defined(__DOXYGEN__) - /** - * @brief Panic message. - * @note This field is only present if some debug options have been - * activated. - * @note Accesses to this pointer must never be optimized out so the - * field itself is declared volatile. - */ - const char * volatile dbg_panic_msg; -#endif -}; - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @name Threads tables definition macros - * @{ - */ -/** - * @brief Start of user threads table. - */ -#define THD_TABLE_BEGIN \ - const thread_config_t nil_thd_configs[NIL_CFG_NUM_THREADS + 1] = { - -/** - * @brief Entry of user threads table - */ -#define THD_TABLE_ENTRY(wap, name, funcp, arg) \ - {wap, ((stkalign_t *)(wap)) + (sizeof (wap) / sizeof(stkalign_t)), \ - name, funcp, arg}, - -/** - * @brief End of user threads table. - */ -#define THD_TABLE_END \ - {THD_IDLE_BASE, THD_IDLE_END, "idle", NULL, NULL} \ -}; -/** @} */ - -/** - * @name Working Areas and Alignment - */ -/** - * @brief Enforces a correct alignment for a stack area size value. - * - * @param[in] n the stack size to be aligned to the next stack - * alignment boundary - * @return The aligned stack size. - * - * @api - */ -#define THD_ALIGN_STACK_SIZE(n) \ - ((((n) - 1U) | (sizeof(stkalign_t) - 1U)) + 1U) - -/** - * @brief Calculates the total Working Area size. - * - * @param[in] n the stack size to be assigned to the thread - * @return The total used memory in bytes. - * - * @api - */ -#define THD_WORKING_AREA_SIZE(n) \ - THD_ALIGN_STACK_SIZE(PORT_WA_SIZE(n)) - -/** - * @brief Static working area allocation. - * @details This macro is used to allocate a static thread working area - * aligned as both position and size. - * - * @param[in] s the name to be assigned to the stack array - * @param[in] n the stack size to be assigned to the thread - * - * @api - */ -#define THD_WORKING_AREA(s, n) \ - stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof(stkalign_t)] -/** @} */ - -/** - * @name Threads abstraction macros - */ -/** - * @brief Thread declaration macro. - * @note Thread declarations should be performed using this macro because - * the port layer could define optimizations for thread functions. - */ -#define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg) -/** @} */ - -/** - * @name ISRs abstraction macros - */ -/** - * @brief Priority level validation macro. - * @details This macro determines if the passed value is a valid priority - * level for the underlying architecture. - * - * @param[in] prio the priority level - * @return Priority range result. - * @retval false if the priority is invalid or if the architecture - * does not support priorities. - * @retval true if the priority is valid. - */ -#if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__) -#define CH_IRQ_IS_VALID_PRIORITY(prio) \ - PORT_IRQ_IS_VALID_PRIORITY(prio) -#else -#define CH_IRQ_IS_VALID_PRIORITY(prio) false -#endif - -/** - * @brief Priority level validation macro. - * @details This macro determines if the passed value is a valid priority - * level that cannot preempt the kernel critical zone. - * - * @param[in] prio the priority level - * @return Priority range result. - * @retval false if the priority is invalid or if the architecture - * does not support priorities. - * @retval true if the priority is valid. - */ -#if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__) -#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \ - PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio) -#else -#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false -#endif - -/** - * @brief IRQ handler enter code. - * @note Usually IRQ handlers functions are also declared naked. - * @note On some architectures this macro can be empty. - * - * @special - */ -#define CH_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE() - -/** - * @brief IRQ handler exit code. - * @note Usually IRQ handlers function are also declared naked. - * - * @special - */ -#define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE() - -/** - * @brief Standard normal IRQ handler declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - * - * @special - */ -#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) -/** @} */ - -/** - * @name Fast ISRs abstraction macros - */ -/** - * @brief Standard fast IRQ handler declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - * @note Not all architectures support fast interrupts. - * - * @special - */ -#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id) -/** @} */ - -/** - * @name Time conversion utilities - * @{ - */ -/** - * @brief Seconds to system ticks. - * @details Converts from seconds to system ticks number. - * @note The result is rounded upward to the next tick boundary. - * - * @param[in] sec number of seconds - * @return The number of ticks. - * - * @api - */ -#define S2ST(sec) \ - ((systime_t)((uint32_t)(sec) * (uint32_t)NIL_CFG_ST_FREQUENCY)) - -/** - * @brief Milliseconds to system ticks. - * @details Converts from milliseconds to system ticks number. - * @note The result is rounded upward to the next tick boundary. - * - * @param[in] msec number of milliseconds - * @return The number of ticks. - * - * @api - */ -#define MS2ST(msec) \ - ((systime_t)(((((uint32_t)(msec)) * \ - ((uint32_t)NIL_CFG_ST_FREQUENCY)) + 999UL) / 1000UL)) - -/** - * @brief Microseconds to system ticks. - * @details Converts from microseconds to system ticks number. - * @note The result is rounded upward to the next tick boundary. - * - * @param[in] usec number of microseconds - * @return The number of ticks. - * - * @api - */ -#define US2ST(usec) \ - ((systime_t)(((((uint32_t)(usec)) * \ - ((uint32_t)NIL_CFG_ST_FREQUENCY)) + 999999UL) / 1000000UL)) -/** @} */ - -/** - * @name Time conversion utilities for the realtime counter - * @{ - */ -/** - * @brief Seconds to realtime counter. - * @details Converts from seconds to realtime counter cycles. - * @note The macro assumes that @p freq >= @p 1. - * - * @param[in] freq clock frequency, in Hz, of the realtime counter - * @param[in] sec number of seconds - * @return The number of cycles. - * - * @api - */ -#define S2RTC(freq, sec) ((freq) * (sec)) - -/** - * @brief Milliseconds to realtime counter. - * @details Converts from milliseconds to realtime counter cycles. - * @note The result is rounded upward to the next millisecond boundary. - * @note The macro assumes that @p freq >= @p 1000. - * - * @param[in] freq clock frequency, in Hz, of the realtime counter - * @param[in] msec number of milliseconds - * @return The number of cycles. - * - * @api - */ -#define MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec)) - -/** - * @brief Microseconds to realtime counter. - * @details Converts from microseconds to realtime counter cycles. - * @note The result is rounded upward to the next microsecond boundary. - * @note The macro assumes that @p freq >= @p 1000000. - * - * @param[in] freq clock frequency, in Hz, of the realtime counter - * @param[in] usec number of microseconds - * @return The number of cycles. - * - * @api - */ -#define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec)) -/** @} */ - -/** - * @name Macro Functions - * @{ - */ -/** - * @brief Returns the current value of the system real time counter. - * @note This function is only available if the port layer supports the - * option @p PORT_SUPPORTS_RT. - * - * @return The value of the system realtime counter of - * type rtcnt_t. - * - * @xclass - */ -#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__) -#define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value() -#endif - -/** - * @brief Enters the kernel lock mode. - * - * @special - */ -#define chSysDisable() port_disable() - -/** - * @brief Enters the kernel lock mode. - * - * @special - */ -#define chSysEnable() port_enable() - -/** - * @brief Enters the kernel lock state. - * - * @special - */ -#define chSysLock() port_lock() - -/** - * @brief Leaves the kernel lock state. - * - * @special - */ -#define chSysUnlock() port_unlock() - -/** - * @brief Enters the kernel lock state from within an interrupt handler. - * @note This API may do nothing on some architectures, it is required - * because on ports that support preemptable interrupt handlers - * it is required to raise the interrupt mask to the same level of - * the system mutual exclusion zone.
- * It is good practice to invoke this API before invoking any I-class - * syscall from an interrupt handler. - * @note This API must be invoked exclusively from interrupt handlers. - * - * @special - */ -#define chSysLockFromISR() port_lock_from_isr() - -/** - * @brief Leaves the kernel lock state from within an interrupt handler. - * - * @note This API may do nothing on some architectures, it is required - * because on ports that support preemptable interrupt handlers - * it is required to raise the interrupt mask to the same level of - * the system mutual exclusion zone.
- * It is good practice to invoke this API after invoking any I-class - * syscall from an interrupt handler. - * @note This API must be invoked exclusively from interrupt handlers. - * - * @special - */ -#define chSysUnlockFromISR() port_unlock_from_isr() - -/** - * @brief Evaluates if a reschedule is required. - * - * @retval true if there is a thread that must go in running state - * immediately. - * @retval false if preemption is not required. - * - * @iclass - */ -#define chSchIsRescRequiredI() ((bool)(nil.current != nil.next)) - -/** - * @brief Returns a pointer to the current @p thread_t. - * - * @xclass - */ -#define chThdGetSelfX() nil.current - -/** - * @brief Delays the invoking thread for the specified number of seconds. - * @note The specified time is rounded up to a value allowed by the real - * system clock. - * @note The maximum specified value is implementation dependent. - * - * @param[in] sec time in seconds, must be different from zero - * - * @api - */ -#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec)) - -/** - * @brief Delays the invoking thread for the specified number of - * milliseconds. - * @note The specified time is rounded up to a value allowed by the real - * system clock. - * @note The maximum specified value is implementation dependent. - * - * @param[in] msec time in milliseconds, must be different from zero - * - * @api - */ -#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec)) - -/** - * @brief Delays the invoking thread for the specified number of - * microseconds. - * @note The specified time is rounded up to a value allowed by the real - * system clock. - * @note The maximum specified value is implementation dependent. - * - * @param[in] usec time in microseconds, must be different from zero - * - * @api - */ -#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec)) - -/** - * @brief Suspends the invoking thread for the specified time. - * - * @param[in] timeout the delay in system ticks - * - * @sclass - */ -#define chThdSleepS(timeout) (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, timeout) - -/** - * @brief Suspends the invoking thread until the system time arrives to the - * specified value. - * - * @param[in] abstime absolute system time - * - * @sclass - */ -#define chThdSleepUntilS(abstime) \ - (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, (abstime) - \ - chVTGetSystemTimeX()) - -/** - * @brief Initializes a semaphore with the specified counter value. - * - * @param[out] sp pointer to a @p semaphore_t structure - * @param[in] n initial value of the semaphore counter. Must be - * non-negative. - * - * @init - */ -#define chSemObjectInit(sp, n) ((sp)->cnt = n) - -/** - * @brief Performs a wait operation on a semaphore. - * - * @param[in] sp pointer to a @p semaphore_t structure - * @return A message specifying how the invoking thread has been - * released from the semaphore. - * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the - * semaphore has been signaled. - * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset(). - * - * @api - */ -#define chSemWait(sp) chSemWaitTimeout(sp, TIME_INFINITE) - -/** - * @brief Performs a wait operation on a semaphore. - * - * @param[in] sp pointer to a @p semaphore_t structure - * @return A message specifying how the invoking thread has been - * released from the semaphore. - * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the - * semaphore has been signaled. - * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset(). - * - * @sclass - */ -#define chSemWaitS(sp) chSemWaitTimeoutS(sp, TIME_INFINITE) - -/** - * @brief Returns the semaphore counter current value. - * - * @iclass - */ -#define chSemGetCounterI(sp) ((sp)->cnt) - -/** - * @brief Current system time. - * @details Returns the number of system ticks since the @p chSysInit() - * invocation. - * @note The counter can reach its maximum and then restart from zero. - * @note This function can be called from any context but its atomicity - * is not guaranteed on architectures whose word size is less than - * @p systime_t size. - * - * @return The system time in ticks. - * - * @xclass - */ -#if (NIL_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__) -#define chVTGetSystemTimeX() (nil.systime) -#else -#define chVTGetSystemTimeX() port_timer_get_time() -#endif - -/** - * @brief Returns the elapsed time since the specified start time. - * - * @param[in] start start time - * @return The elapsed time. - * - * @xclass - */ -#define chVTTimeElapsedSinceX(start) \ - ((systime_t)(chVTGetSystemTimeX() - (start))) - -/** - * @brief Checks if the specified time is within the specified time window. - * @note When start==end then the function returns always true because the - * whole time range is specified. - * @note This function can be called from any context. - * - * @param[in] time the time to be verified - * @param[in] start the start of the time window (inclusive) - * @param[in] end the end of the time window (non inclusive) - * @retval true current time within the specified time window. - * @retval false current time not within the specified time window. - * - * @xclass - */ -#define chVTIsTimeWithinX(time, start, end) \ - ((bool)((systime_t)((time) - (start)) < (systime_t)((end) - (start)))) - -/** - * @brief Condition assertion. - * @details If the condition check fails then the kernel panics with a - * message and halts. - * @note The condition is tested only if the @p NIL_CFG_ENABLE_ASSERTS - * switch is specified in @p nilconf.h else the macro does nothing. - * @note The remark string is not currently used except for putting a - * comment in the code about the assertion. - * - * @param[in] c the condition to be verified to be true - * @param[in] r a remark string - * - * @api - */ -#if !defined(chDbgAssert) -#define chDbgAssert(c, r) do { \ - /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \ - if (NIL_CFG_ENABLE_ASSERTS != FALSE) { \ - if (!(c)) { \ - /*lint -restore*/ \ - chSysHalt(__func__); \ - } \ - } \ -} while (false) -#endif /* !defined(chDbgAssert) */ -/** @} */ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -extern nil_system_t nil; -extern const thread_config_t nil_thd_configs[NIL_CFG_NUM_THREADS + 1]; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - void chSysInit(void); - void chSysHalt(const char *reason); - void chSysTimerHandlerI(void); - void chSysUnconditionalLock(void); - void chSysUnconditionalUnlock(void); - syssts_t chSysGetStatusAndLockX(void); - bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end); - void chSysPolledDelayX(rtcnt_t cycles); - void chSysRestoreStatusX(syssts_t sts); - thread_t *chSchReadyI(thread_t *tp, msg_t msg); - void chSchRescheduleS(void); - msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout); - msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout); - void chThdResumeI(thread_reference_t *trp, msg_t msg); - void chThdSleep(systime_t timeout); - void chThdSleepUntil(systime_t abstime); - msg_t chSemWaitTimeout(semaphore_t *sp, systime_t timeout); - msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout); - void chSemSignal(semaphore_t *sp); - void chSemSignalI(semaphore_t *sp); - void chSemReset(semaphore_t *sp, cnt_t n); - void chSemResetI(semaphore_t *sp, cnt_t n); -#if NIL_CFG_USE_EVENTS == TRUE - void chEvtSignal(thread_t *tp, eventmask_t mask); - void chEvtSignalI(thread_t *tp, eventmask_t mask); - eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t timeout); - eventmask_t chEvtWaitAnyTimeoutS(eventmask_t mask, systime_t timeout); -#endif -#ifdef __cplusplus -} -#endif - -#endif /* _NIL_H_ */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk b/os/nil/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk deleted file mode 100644 index 6fa7d52ea..000000000 --- a/os/nil/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk +++ /dev/null @@ -1,8 +0,0 @@ -# List of the ChibiOS/NIL ARMv6M generic port files. -PORTSRC = $(CHIBIOS)/os/nil/ports/ARMCMx/nilcore.c \ - $(CHIBIOS)/os/nil/ports/ARMCMx/nilcore_v6m.c - -PORTASM = $(CHIBIOS)/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s - -PORTINC = $(CHIBIOS)/os/nil/ports/ARMCMx \ - $(CHIBIOS)/os/nil/ports/ARMCMx/compilers/GCC diff --git a/os/nil/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk b/os/nil/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk deleted file mode 100644 index 3e9c30125..000000000 --- a/os/nil/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk +++ /dev/null @@ -1,8 +0,0 @@ -# List of the ChibiOS/NIL ARMv7M generic port files. -PORTSRC = $(CHIBIOS)/os/nil/ports/ARMCMx/nilcore.c \ - $(CHIBIOS)/os/nil/ports/ARMCMx/nilcore_v7m.c - -PORTASM = $(CHIBIOS)/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v7m.s - -PORTINC = $(CHIBIOS)/os/nil/ports/ARMCMx \ - $(CHIBIOS)/os/nil/ports/ARMCMx/compilers/GCC diff --git a/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s b/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s deleted file mode 100644 index 68862f96e..000000000 --- a/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s +++ /dev/null @@ -1,124 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ARMCMx/compilers/GCC/nilcoreasm_v6m.s - * @brief ARMv6-M architecture port low level code. - * - * @addtogroup ARMCMx_GCC_CORE - * @{ - */ - -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 -#endif - -#define _FROM_ASM_ -#include "nilconf.h" -#include "nilcore.h" - -#if !defined(__DOXYGEN__) - - .set CONTEXT_OFFSET, 0 - .set SCB_ICSR, 0xE000ED04 - .set ICSR_PENDSVSET, 0x10000000 - .set ICSR_NMIPENDSET, 0x80000000 - - .cpu cortex-m0 - .fpu softvfp - - .thumb - .text - -/*--------------------------------------------------------------------------* - * Performs a context switch between two threads. - *--------------------------------------------------------------------------*/ - .thumb_func - .globl _port_switch -_port_switch: - push {r4, r5, r6, r7, lr} - mov r4, r8 - mov r5, r9 - mov r6, r10 - mov r7, r11 - push {r4, r5, r6, r7} - - mov r3, sp - str r3, [r1, #CONTEXT_OFFSET] - ldr r3, [r0, #CONTEXT_OFFSET] - mov sp, r3 - - pop {r4, r5, r6, r7} - mov r8, r4 - mov r9, r5 - mov r10, r6 - mov r11, r7 - pop {r4, r5, r6, r7, pc} - -/*--------------------------------------------------------------------------* - * Start a thread by invoking its work function. - * - * Threads execution starts here, the code leaves the system critical zone - * and then jumps into the thread function passed in register R4. The - * register R5 contains the thread parameter. The function chThdExit() is - * called on thread function return. - *--------------------------------------------------------------------------*/ - .thumb_func - .globl _port_thread_start -_port_thread_start: - cpsie i - mov r0, r5 - blx r4 - mov r3, #0 - bl chSysHalt - -/*--------------------------------------------------------------------------* - * Post-IRQ switch code. - * - * Exception handlers return here for context switching. - *--------------------------------------------------------------------------*/ - .thumb_func - .globl _port_switch_from_isr -_port_switch_from_isr: - bl chSchRescheduleS - .globl _port_exit_from_isr -_port_exit_from_isr: - ldr r2, .L2 - ldr r3, .L3 - str r3, [r2, #0] -#if CORTEX_ALTERNATE_SWITCH - cpsie i -#endif -.L1: b .L1 - - .align 2 -.L2: .word SCB_ICSR -#if CORTEX_ALTERNATE_SWITCH -.L3: .word ICSR_PENDSVSET -#else -.L3: .word ICSR_NMIPENDSET -#endif - -#endif /* !defined(__DOXYGEN__) */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v7m.s b/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v7m.s deleted file mode 100644 index a98802798..000000000 --- a/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v7m.s +++ /dev/null @@ -1,130 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ARMCMx/compilers/GCC/nilcoreasm_v7m.s - * @brief ARMv7-M architecture port low level code. - * - * @addtogroup ARMCMx_GCC_CORE - * @{ - */ - -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 -#endif - -#define _FROM_ASM_ -#include "nilconf.h" -#include "nilcore.h" - -#if !defined(__DOXYGEN__) - - .set CONTEXT_OFFSET, 0 - .set SCB_ICSR, 0xE000ED04 - .set ICSR_PENDSVSET, 0x10000000 - - .syntax unified - .cpu cortex-m4 -#if CORTEX_USE_FPU - .fpu fpv4-sp-d16 -#else - .fpu softvfp -#endif - - .thumb - .text - -/*--------------------------------------------------------------------------* - * Performs a context switch between two threads. - *--------------------------------------------------------------------------*/ - .thumb_func - .globl _port_switch -_port_switch: - push {r4, r5, r6, r7, r8, r9, r10, r11, lr} -#if CORTEX_USE_FPU - vpush {s16-s31} -#endif - - str sp, [r1, #CONTEXT_OFFSET] -#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \ - ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4)) - /* Workaround for ARM errata 752419, only applied if - condition exists for it to be triggered.*/ - ldr r3, [r0, #CONTEXT_OFFSET] - mov sp, r3 -#else - ldr sp, [r0, #CONTEXT_OFFSET] -#endif - -#if CORTEX_USE_FPU - vpop {s16-s31} -#endif - pop {r4, r5, r6, r7, r8, r9, r10, r11, pc} - -/*--------------------------------------------------------------------------* - * Start a thread by invoking its work function. - * - * Threads execution starts here, the code leaves the system critical zone - * and then jumps into the thread function passed in register R4. The - * register R5 contains the thread parameter. The function chThdExit() is - * called on thread function return. - *--------------------------------------------------------------------------*/ - .thumb_func - .globl _port_thread_start -_port_thread_start: -#if !CORTEX_SIMPLIFIED_PRIORITY - movs r3, #0 - msr BASEPRI, r3 -#else /* CORTEX_SIMPLIFIED_PRIORITY */ - cpsie i -#endif /* CORTEX_SIMPLIFIED_PRIORITY */ - mov r0, r5 - blx r4 - mov r3, #0 - bl chSysHalt - -/*--------------------------------------------------------------------------* - * Post-IRQ switch code. - * - * Exception handlers return here for context switching. - *--------------------------------------------------------------------------*/ - .thumb_func - .globl _port_switch_from_isr -_port_switch_from_isr: - bl chSchRescheduleS - .globl _port_exit_from_isr -_port_exit_from_isr: -#if CORTEX_SIMPLIFIED_PRIORITY - movw r3, #:lower16:SCB_ICSR - movt r3, #:upper16:SCB_ICSR - mov r2, ICSR_PENDSVSET - str r2, [r3, #0] - cpsie i -#else /* !CORTEX_SIMPLIFIED_PRIORITY */ - svc #0 -#endif /* !CORTEX_SIMPLIFIED_PRIORITY */ -.L1: b .L1 - -#endif /* !defined(__DOXYGEN__) */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h deleted file mode 100644 index 402110096..000000000 --- a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ARMCMx/compilers/GCC/niltypes.h - * @brief ARM Cortex-Mx port system types. - * - * @addtogroup ARMCMx_GCC_CORE - * @{ - */ - -#ifndef _NILTYPES_H_ -#define _NILTYPES_H_ - -#include -#include -#include - -/** - * @name Common constants - */ -/** - * @brief Generic 'false' boolean constant. - */ -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -/** - * @brief Generic 'true' boolean constant. - */ -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 -#endif -/** @} */ - -typedef uint32_t syssts_t; /**< System status word. */ -typedef uint32_t rtcnt_t; /**< Realtime counter. */ -typedef uint8_t tstate_t; /**< Thread state. */ -typedef int32_t msg_t; /**< Inter-thread message. */ -typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ -typedef int32_t cnt_t; /**< Generic signed counter. */ -typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ - -/** - * @brief Type of system time. - */ -#if (NIL_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__) -typedef uint32_t systime_t; -#else -typedef uint16_t systime_t; -#endif - -/** - * @brief ROM constant modifier. - * @note It is set to use the "const" keyword in this port. - */ -#define ROMCONST const - -/** - * @brief Makes functions not inlineable. - * @note If the compiler does not support such attribute then the - * realtime counter precision could be degraded. - */ -#define NOINLINE __attribute__((noinline)) - -/** - * @brief Optimized thread function declaration macro. - */ -#define PORT_THD_FUNCTION(tname, arg) \ - __attribute__((noreturn)) void tname(void *arg) - -/** - * @brief Packed variable specifier. - */ -#define PACKED_VAR __attribute__((packed)) - -#endif /* _NILTYPES_H_ */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore.c b/os/nil/ports/ARMCMx/nilcore.c deleted file mode 100644 index 7d7738029..000000000 --- a/os/nil/ports/ARMCMx/nilcore.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ARMCMx/nilcore.c - * @brief ARM Cortex-Mx port code. - * - * @addtogroup ARMCMx_CORE - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore.h b/os/nil/ports/ARMCMx/nilcore.h deleted file mode 100644 index 21b5a0535..000000000 --- a/os/nil/ports/ARMCMx/nilcore.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ARMCMx/nilcore.h - * @brief ARM Cortex-Mx port macros and structures. - * - * @addtogroup ARMCMx_CORE - * @{ - */ - -#ifndef _NILCORE_H_ -#define _NILCORE_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @name Architecture and Compiler - * @{ - */ -/** - * @brief Macro defining a generic ARM architecture. - */ -#define PORT_ARCHITECTURE_ARM - -/* The following code is not processed when the file is included from an - asm module because those intrinsic macros are not necessarily defined - by the assembler too.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Compiler name and version. - */ -#if defined(__GNUC__) || defined(__DOXYGEN__) -#define PORT_COMPILER_NAME "GCC " __VERSION__ - -#elif defined(__ICCARM__) -#define PORT_COMPILER_NAME "IAR" - -#elif defined(__CC_ARM) -#define PORT_COMPILER_NAME "RVCT" - -#else -#error "unsupported compiler" -#endif - -#endif /* !defined(_FROM_ASM_) */ - -/** @} */ - -/* Inclusion of the Cortex-Mx implementation specific parameters.*/ -#include "cmparams.h" - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Enables an alternative timer implementation. - * @details Usually the port uses a timer interface defined in the file - * @p nilcore_timer.h, if this option is enabled then the file - * @p nilcore_timer_alt.h is included instead. - */ -#if !defined(PORT_USE_ALT_TIMER) -#define PORT_USE_ALT_TIMER FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Type of a generic ARM register. - */ -typedef void *regarm_t; - -/** - * @brief Type of stack and memory alignment enforcement. - * @note In this architecture the stack alignment is enforced to 64 bits, - * 32 bits alignment is supported by hardware but deprecated by ARM, - * the implementation choice is to not offer the option. - */ -typedef uint64_t stkalign_t; - -/* The following declarations are there just for Doxygen documentation, the - real declarations are inside the sub-headers being specific for the - sub-architectures.*/ -#if defined(__DOXYGEN__) -/** - * @brief Interrupt saved context. - * @details This structure represents the stack frame saved during a - * preemption-capable interrupt handler. - * @note It is implemented to match the Cortex-Mx exception context. - */ -struct port_extctx {}; - -/** - * @brief System saved context. - * @details This structure represents the inner stack frame during a context - * switch. - */ -struct port_intctx {}; -#endif /* defined(__DOXYGEN__) */ - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Total priority levels. - */ -#define CORTEX_PRIORITY_LEVELS (1U << CORTEX_PRIORITY_BITS) - -/** - * @brief Minimum priority level. - * @details This minimum priority level is calculated from the number of - * priority bits supported by the specific Cortex-Mx implementation. - */ -#define CORTEX_MINIMUM_PRIORITY (CORTEX_PRIORITY_LEVELS - 1) - -/** - * @brief Maximum priority level. - * @details The maximum allowed priority level is always zero. - */ -#define CORTEX_MAXIMUM_PRIORITY 0U - -/** - * @brief Priority level to priority mask conversion macro. - */ -#define CORTEX_PRIO_MASK(n) \ - ((n) << (8U - (unsigned)CORTEX_PRIORITY_BITS)) - -/** - * @brief Priority level verification macro. - */ -#define PORT_IRQ_IS_VALID_PRIORITY(n) \ - (((n) >= 0U) && ((n) < CORTEX_PRIORITY_LEVELS)) - -/** - * @brief Priority level verification macro. - */ -#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \ - (((n) >= CORTEX_MAX_KERNEL_PRIORITY) && ((n) < CORTEX_PRIORITY_LEVELS)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/* Includes the sub-architecture-specific part.*/ -#if (CORTEX_MODEL == 0) || (CORTEX_MODEL == 1) -#include "nilcore_v6m.h" -#elif (CORTEX_MODEL == 3) || (CORTEX_MODEL == 4) || (CORTEX_MODEL == 7) -#include "nilcore_v7m.h" -#else -#error "unknown Cortex-M variant" -#endif - -#if !defined(_FROM_ASM_) - -#if NIL_CFG_ST_TIMEDELTA > 0 -#if PORT_USE_ALT_TIMER == FALSE -#include "nilcore_timer.h" -#else /* PORT_USE_ALT_TIMER != FALSE */ -#include "nilcore_timer_alt.h" -#endif /* PORT_USE_ALT_TIMER != FALSE */ -#endif /* NIL_CFG_ST_TIMEDELTA > 0 */ - -#endif /* !defined(_FROM_ASM_) */ - -#endif /* _NILCORE_H_ */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_timer.h b/os/nil/ports/ARMCMx/nilcore_timer.h deleted file mode 100644 index 2c7c98cf6..000000000 --- a/os/nil/ports/ARMCMx/nilcore_timer.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ARMCMx/nilcore_timer.h - * @brief System timer header file. - * - * @addtogroup ARMCMx_TIMER - * @{ - */ - -#ifndef _NILCORE_TIMER_H_ -#define _NILCORE_TIMER_H_ - -/* This is the only header in the HAL designed to be include-able alone.*/ -#include "st.h" - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * - * @param[in] time the time to be set for the first alarm - * - * @notapi - */ -static inline void port_timer_start_alarm(systime_t time) { - - stStartAlarm(time); -} - -/** - * @brief Stops the alarm interrupt. - * - * @notapi - */ -static inline void port_timer_stop_alarm(void) { - - stStopAlarm(); -} - -/** - * @brief Sets the alarm time. - * - * @param[in] time the time to be set for the next alarm - * - * @notapi - */ -static inline void port_timer_set_alarm(systime_t time) { - - stSetAlarm(time); -} - -/** - * @brief Returns the system time. - * - * @return The system time. - * - * @notapi - */ -static inline systime_t port_timer_get_time(void) { - - return stGetCounter(); -} - -/** - * @brief Returns the current alarm time. - * - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t port_timer_get_alarm(void) { - - return stGetAlarm(); -} - -#endif /* _NILCORE_TIMER_H_ */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v6m.c b/os/nil/ports/ARMCMx/nilcore_v6m.c deleted file mode 100644 index 791062db3..000000000 --- a/os/nil/ports/ARMCMx/nilcore_v6m.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file nilcore_v6m.c - * @brief ARMv6-M architecture port code. - * - * @addtogroup ARMCMx_V6M_CORE - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module interrupt handlers. */ -/*===========================================================================*/ - -#if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__) -/** - * @brief NMI vector. - * @details The NMI vector is used for exception mode re-entering after a - * context switch. - */ -/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ -void NMI_Handler(void) { -/*lint -restore*/ - - /* The port_extctx structure is pointed by the PSP register.*/ - struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); - - /* Discarding the current exception context and positioning the stack to - point to the real one.*/ - ctxp++; - - /* Writing back the modified PSP value.*/ - __set_PSP((uint32_t)ctxp); - - /* Restoring the normal interrupts status.*/ - port_unlock_from_isr(); -} -#endif /* !CORTEX_ALTERNATE_SWITCH */ - -#if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__) -/** - * @brief PendSV vector. - * @details The PendSV vector is used for exception mode re-entering after a - * context switch. - */ -/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ -void PendSV_Handler(void) { -/*lint -restore*/ - - /* The port_extctx structure is pointed by the PSP register.*/ - struct port_extctx *ctxp = (struct port_extctx *)__get_PSP(); - - /* Discarding the current exception context and positioning the stack to - point to the real one.*/ - ctxp++; - - /* Writing back the modified PSP value.*/ - __set_PSP((uint32_t)ctxp); -} -#endif /* CORTEX_ALTERNATE_SWITCH */ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief IRQ epilogue code. - * - * @param[in] lr value of the @p LR register on ISR entry - */ -void _port_irq_epilogue(regarm_t lr) { - - if (lr != (regarm_t)0xFFFFFFF1U) { - struct port_extctx *ctxp; - - port_lock_from_isr(); - - /* The extctx structure is pointed by the PSP register.*/ - ctxp = (struct port_extctx *)__get_PSP(); - - /* Adding an artificial exception return context, there is no need to - populate it fully.*/ - ctxp--; - - /* Writing back the modified PSP value.*/ - __set_PSP((uint32_t)ctxp); - - /* Setting up a fake XPSR register value.*/ - ctxp->xpsr = (regarm_t)0x01000000; - - /* The exit sequence is different depending on if a preemption is - required or not.*/ - if (chSchIsRescRequiredI()) { - /* Preemption is required we need to enforce a context switch.*/ - ctxp->pc = (regarm_t)_port_switch_from_isr; - } - else { - /* Preemption not required, we just need to exit the exception - atomically.*/ - ctxp->pc = (regarm_t)_port_exit_from_isr; - } - - /* Note, returning without unlocking is intentional, this is done in - order to keep the rest of the context switch atomic.*/ - } -} - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v6m.h b/os/nil/ports/ARMCMx/nilcore_v6m.h deleted file mode 100644 index 3a500d2b0..000000000 --- a/os/nil/ports/ARMCMx/nilcore_v6m.h +++ /dev/null @@ -1,406 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chcore_v6m.h - * @brief ARMv6-M architecture port macros and structures. - * - * @addtogroup ARMCMx_V6M_CORE - * @{ - */ - -#ifndef _CHCORE_V6M_H_ -#define _CHCORE_V6M_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @brief This port does not support a realtime counter. - */ -#define PORT_SUPPORTS_RT FALSE - -/** - * @brief PendSV priority level. - * @note This priority is enforced to be equal to @p 0, - * this handler always has the highest priority that cannot preempt - * the kernel. - */ -#define CORTEX_PRIORITY_PENDSV 0 - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Stack size for the system idle thread. - * @details This size depends on the idle thread implementation, usually - * the idle thread should take no more space than those reserved - * by @p PORT_INT_REQUIRED_STACK. - * @note In this port it is set to 16 because the idle thread does have - * a stack frame when compiling without optimizations. You may - * reduce this value to zero when compiling with optimizations. - */ -#if !defined(PORT_IDLE_THREAD_STACK_SIZE) -#define PORT_IDLE_THREAD_STACK_SIZE 16 -#endif - -/** - * @brief Per-thread stack overhead for interrupts servicing. - * @details This constant is used in the calculation of the correct working - * area size. - * @note In this port this value is conservatively set to 32 because the - * function @p chSchDoReschedule() can have a stack frame, especially - * with compiler optimizations disabled. The value can be reduced - * when compiler optimizations are enabled. - */ -#if !defined(PORT_INT_REQUIRED_STACK) -#define PORT_INT_REQUIRED_STACK 32 -#endif - -/** - * @brief Enables the use of the WFI instruction in the idle thread loop. - */ -#if !defined(CORTEX_ENABLE_WFI_IDLE) -#define CORTEX_ENABLE_WFI_IDLE FALSE -#endif - -/** - * @brief Alternate preemption method. - * @details Activating this option will make the Kernel use the PendSV - * handler for preemption instead of the NMI handler. - */ -#ifndef CORTEX_ALTERNATE_SWITCH -#define CORTEX_ALTERNATE_SWITCH FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** - * @name Architecture and Compiler - * @{ - */ -#if ((CORTEX_MODEL == 0) && !defined(__CORE_CM0PLUS_H_DEPENDANT)) || \ - defined(__DOXYGEN__) -/** - * @brief Macro defining the specific ARM architecture. - */ -#define PORT_ARCHITECTURE_ARM_v6M - -/** - * @brief Name of the implemented architecture. - */ -#define PORT_ARCHITECTURE_NAME "ARMv6-M" - -/** - * @brief Name of the architecture variant. - */ -#define PORT_CORE_VARIANT_NAME "Cortex-M0" - -#elif (CORTEX_MODEL == 0) && defined(__CORE_CM0PLUS_H_DEPENDANT) -#define PORT_ARCHITECTURE_ARM_v6M -#define PORT_ARCHITECTURE_NAME "ARMv6-M" -#define PORT_CORE_VARIANT_NAME "Cortex-M0+" -#endif - -/** - * @brief Port-specific information string. - */ -#if (CORTEX_ALTERNATE_SWITCH == FALSE) || defined(__DOXYGEN__) -#define PORT_INFO "Preemption through NMI" -#else -#define PORT_INFO "Preemption through PendSV" -#endif -/** @} */ - -/** - * @brief Maximum usable priority for normal ISRs. - */ -#if (CORTEX_ALTERNATE_SWITCH == TRUE) || defined(__DOXYGEN__) -#define CORTEX_MAX_KERNEL_PRIORITY 1 -#else -#define CORTEX_MAX_KERNEL_PRIORITY 0 -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -#if !defined(_FROM_ASM_) - - /* The documentation of the following declarations is in chconf.h in order - to not have duplicated structure names into the documentation.*/ -#if !defined(__DOXYGEN__) -struct port_extctx { - regarm_t r0; - regarm_t r1; - regarm_t r2; - regarm_t r3; - regarm_t r12; - regarm_t lr_thd; - regarm_t pc; - regarm_t xpsr; -}; - -struct port_intctx { - regarm_t r8; - regarm_t r9; - regarm_t r10; - regarm_t r11; - regarm_t r4; - regarm_t r5; - regarm_t r6; - regarm_t r7; - regarm_t lr; -}; -#endif /* !defined(__DOXYGEN__) */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Platform dependent thread stack setup. - * @details This code usually setup the context switching frame represented - * by an @p port_intctx structure. - */ -#define PORT_SETUP_CONTEXT(tp, wend, pf, arg) { \ - (tp)->ctxp = (struct port_intctx *)((uint8_t *)(wend) - \ - sizeof(struct port_intctx)); \ - (tp)->ctxp->r4 = (regarm_t)(pf); \ - (tp)->ctxp->r5 = (regarm_t)(arg); \ - (tp)->ctxp->lr = (regarm_t)_port_thread_start; \ -} - -/** - * @brief Computes the thread working area global size. - * @note There is no need to perform alignments in this macro. - */ -#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ - sizeof(struct port_extctx) + \ - ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) - -/** - * @brief IRQ prologue code. - * @details This macro must be inserted at the start of all IRQ handlers - * enabled to invoke system APIs. - */ -#if defined(__GNUC__) || defined(__DOXYGEN__) -#define PORT_IRQ_PROLOGUE() \ - regarm_t _saved_lr = (regarm_t)__builtin_return_address(0) -#elif defined(__ICCARM__) -#define PORT_IRQ_PROLOGUE() \ - regarm_t _saved_lr = (regarm_t)__get_LR() -#elif defined(__CC_ARM) -#define PORT_IRQ_PROLOGUE() \ - regarm_t _saved_lr = (regarm_t)__return_address() -#endif - -/** - * @brief IRQ epilogue code. - * @details This macro must be inserted at the end of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) - -/** - * @brief IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_IRQ_HANDLER(id) void id(void) - -/** - * @brief Fast IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_FAST_IRQ_HANDLER(id) void id(void) - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - * - * @param[in] ntp the thread to be switched in - * @param[in] otp the thread to be switched out - */ -#if (NIL_CFG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__) -#define port_switch(ntp, otp) _port_switch(ntp, otp) -#else -#define port_switch(ntp, otp) { \ - struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ - if ((stkalign_t *)(r13 - 1) < (otp)->stklim) { \ - chSysHalt("stack overflow"); \ - } \ - _port_switch(ntp, otp); \ -} -#endif - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void _port_irq_epilogue(regarm_t lr); - void _port_switch_from_isr(void); - void _port_exit_from_isr(void); - void _port_switch(thread_t *ntp, thread_t *otp); - void _port_thread_start(void); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Port-related initialization code. - */ -static inline void port_init(void) { - - NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); -} - -/** - * @brief Returns a word encoding the current interrupts status. - * - * @return The interrupts status. - */ -static inline syssts_t port_get_irq_status(void) { - - return (syssts_t)__get_PRIMASK(); -} - -/** - * @brief Checks the interrupt status. - * - * @param[in] sts the interrupt status word - * - * @return The interrupt status. - * @retvel false the word specified a disabled interrupts status. - * @retvel true the word specified an enabled interrupts status. - */ -static inline bool port_irq_enabled(syssts_t sts) { - - return (sts & (syssts_t)1) == (syssts_t)0; -} - -/** - * @brief Determines the current execution context. - * - * @return The execution context. - * @retval false not running in ISR mode. - * @retval true running in ISR mode. - */ -static inline bool port_is_isr_context(void) { - - return (bool)((__get_IPSR() & 0x1FFU) != 0U); -} - -/** - * @brief Kernel-lock action. - * @details In this port this function disables interrupts globally. - */ -static inline void port_lock(void) { - - __disable_irq(); -} - -/** - * @brief Kernel-unlock action. - * @details In this port this function enables interrupts globally. - */ -static inline void port_unlock(void) { - - __enable_irq(); -} - -/** - * @brief Kernel-lock action from an interrupt handler. - * @details In this port this function disables interrupts globally. - * @note Same as @p port_lock() in this port. - */ -static inline void port_lock_from_isr(void) { - - port_lock(); -} - -/** - * @brief Kernel-unlock action from an interrupt handler. - * @details In this port this function enables interrupts globally. - * @note Same as @p port_lock() in this port. - */ -static inline void port_unlock_from_isr(void) { - - port_unlock(); -} - -/** - * @brief Disables all the interrupt sources. - */ -static inline void port_disable(void) { - - __disable_irq(); -} - -/** - * @brief Disables the interrupt sources below kernel-level priority. - */ -static inline void port_suspend(void) { - - __disable_irq(); -} - -/** - * @brief Enables all the interrupt sources. - */ -static inline void port_enable(void) { - - __enable_irq(); -} - -/** - * @brief Enters an architecture-dependent IRQ-waiting mode. - * @details The function is meant to return when an interrupt becomes pending. - * The simplest implementation is an empty function or macro but this - * would not take advantage of architecture-specific power saving - * modes. - * @note Implemented as an inlined @p WFI instruction. - */ -static inline void port_wait_for_interrupt(void) { - -#if CORTEX_ENABLE_WFI_IDLE == TRUE - __WFI(); -#endif -} - -#endif /* _FROM_ASM_ */ - -#endif /* _CHCORE_V6M_H_ */ - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v7m.c b/os/nil/ports/ARMCMx/nilcore_v7m.c deleted file mode 100644 index c381fc3ef..000000000 --- a/os/nil/ports/ARMCMx/nilcore_v7m.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file nilcore_v7m.c - * @brief ARMv7-M architecture port code. - * - * @addtogroup ARMCMx_V7M_CORE - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module interrupt handlers. */ -/*===========================================================================*/ - -#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) -/** - * @brief SVC vector. - * @details The SVC vector is used for exception mode re-entering after a - * context switch. - * @note The PendSV vector is only used in advanced kernel mode. - */ -/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ -void SVC_Handler(void) { -/*lint -restore*/ - struct port_extctx *ctxp; - -#if CORTEX_USE_FPU == TRUE - /* Enforcing unstacking of the FP part of the context.*/ - FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; -#endif - - /* The port_extctx structure is pointed by the PSP register.*/ - ctxp = (struct port_extctx *)__get_PSP(); - - /* Discarding the current exception context and positioning the stack to - point to the real one.*/ - ctxp++; - - /* Restoring real position of the original stack frame.*/ - __set_PSP((uint32_t)ctxp); - - /* Restoring the normal interrupts status.*/ - port_unlock_from_isr(); -} -#endif /* CORTEX_SIMPLIFIED_PRIORITY == FALSE */ - -#if (CORTEX_SIMPLIFIED_PRIORITY == TRUE) || defined(__DOXYGEN__) -/** - * @brief PendSV vector. - * @details The PendSV vector is used for exception mode re-entering after a - * context switch. - * @note The PendSV vector is only used in compact kernel mode. - */ -/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ -void PendSV_Handler(void) { -/*lint -restore*/ - struct port_extctx *ctxp; - -#if CORTEX_USE_FPU == TRUE - /* Enforcing unstacking of the FP part of the context.*/ - FPU->FPCCR &= ~FPU_FPCCR_LSPACT_Msk; -#endif - - /* The port_extctx structure is pointed by the PSP register.*/ - ctxp = (struct port_extctx *)__get_PSP(); - - /* Discarding the current exception context and positioning the stack to - point to the real one.*/ - ctxp++; - - /* Writing back the modified PSP value.*/ - __set_PSP((uint32_t)ctxp); -} -#endif /* CORTEX_SIMPLIFIED_PRIORITY == TRUE */ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Exception exit redirection to _port_switch_from_isr(). - */ -void _port_irq_epilogue(void) { - - port_lock_from_isr(); - if ((SCB->ICSR & SCB_ICSR_RETTOBASE_Msk) != 0U) { - struct port_extctx *ctxp; - -#if CORTEX_USE_FPU == TRUE - /* Enforcing a lazy FPU state save by accessing the FPCSR register.*/ - (void) __get_FPSCR(); -#endif - - /* The port_extctx structure is pointed by the PSP register.*/ - ctxp = (struct port_extctx *)__get_PSP(); - - /* Adding an artificial exception return context, there is no need to - populate it fully.*/ - ctxp--; - - /* Setting up a fake XPSR register value.*/ - ctxp->xpsr = (regarm_t)0x01000000; - - /* Writing back the modified PSP value.*/ - __set_PSP((uint32_t)ctxp); - - /* The exit sequence is different depending on if a preemption is - required or not.*/ - if (chSchIsRescRequiredI()) { - /* Preemption is required we need to enforce a context switch.*/ - ctxp->pc = (regarm_t)_port_switch_from_isr; - } - else { - /* Preemption not required, we just need to exit the exception - atomically.*/ - ctxp->pc = (regarm_t)_port_exit_from_isr; - } - - /* Note, returning without unlocking is intentional, this is done in - order to keep the rest of the context switch atomic.*/ - return; - } - port_unlock_from_isr(); -} - -/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v7m.h b/os/nil/ports/ARMCMx/nilcore_v7m.h deleted file mode 100644 index c9ffe87b8..000000000 --- a/os/nil/ports/ARMCMx/nilcore_v7m.h +++ /dev/null @@ -1,576 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file chcore_v7m.h - * @brief ARMv7-M architecture port macros and structures. - * - * @addtogroup ARMCMx_V7M_CORE - * @{ - */ - -#ifndef _NILCORE_V7M_H_ -#define _NILCORE_V7M_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @brief This port supports a realtime counter. - */ -#define PORT_SUPPORTS_RT TRUE - -/** - * @brief Disabled value for BASEPRI register. - */ -#define CORTEX_BASEPRI_DISABLED 0U - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Stack size for the system idle thread. - * @details This size depends on the idle thread implementation, usually - * the idle thread should take no more space than those reserved - * by @p PORT_INT_REQUIRED_STACK. - * @note In this port it is set to 16 because the idle thread does have - * a stack frame when compiling without optimizations. You may - * reduce this value to zero when compiling with optimizations. - */ -#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) -#define PORT_IDLE_THREAD_STACK_SIZE 16 -#endif - -/** - * @brief Per-thread stack overhead for interrupts servicing. - * @details This constant is used in the calculation of the correct working - * area size. - * @note In this port this value is conservatively set to 32 because the - * function @p chSchDoReschedule() can have a stack frame, especially - * with compiler optimizations disabled. The value can be reduced - * when compiler optimizations are enabled. - */ -#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) -#define PORT_INT_REQUIRED_STACK 32 -#endif - -/** - * @brief Enables the use of the WFI instruction in the idle thread loop. - */ -#if !defined(CORTEX_ENABLE_WFI_IDLE) -#define CORTEX_ENABLE_WFI_IDLE FALSE -#endif - -/** - * @brief FPU support in context switch. - * @details Activating this option activates the FPU support in the kernel. - */ -#if !defined(CORTEX_USE_FPU) -#define CORTEX_USE_FPU CORTEX_HAS_FPU -#elif (CORTEX_USE_FPU == TRUE) && (CORTEX_HAS_FPU == FALSE) -/* This setting requires an FPU presence check in case it is externally - redefined.*/ -#error "the selected core does not have an FPU" -#endif - -/** - * @brief Simplified priority handling flag. - * @details Activating this option makes the Kernel work in compact mode. - * In compact mode interrupts are disabled globally instead of - * raising the priority mask to some intermediate level. - */ -#if !defined(CORTEX_SIMPLIFIED_PRIORITY) -#define CORTEX_SIMPLIFIED_PRIORITY FALSE -#endif - -/** - * @brief SVCALL handler priority. - * @note The default SVCALL handler priority is defaulted to - * @p CORTEX_MAXIMUM_PRIORITY+1, this reserves the - * @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts - * priority level. - */ -#if !defined(CORTEX_PRIORITY_SVCALL) -#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1U) -#elif !PORT_IRQ_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL) -/* If it is externally redefined then better perform a validity check on it.*/ -#error "invalid priority level specified for CORTEX_PRIORITY_SVCALL" -#endif - -/** - * @brief NVIC VTOR initialization expression. - */ -#if !defined(CORTEX_VTOR_INIT) || defined(__DOXYGEN__) -#define CORTEX_VTOR_INIT 0x00000000U -#endif - -/** - * @brief NVIC PRIGROUP initialization expression. - * @details The default assigns all available priority bits as preemption - * priority with no sub-priority. - */ -#if !defined(CORTEX_PRIGROUP_INIT) || defined(__DOXYGEN__) -#define CORTEX_PRIGROUP_INIT (7 - CORTEX_PRIORITY_BITS) -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** - * @name Architecture and Compiler - * @{ - */ -#if (CORTEX_MODEL == 3) || defined(__DOXYGEN__) -/** - * @brief Macro defining the specific ARM architecture. - */ -#define PORT_ARCHITECTURE_ARM_v7M - -/** - * @brief Name of the implemented architecture. - */ -#define PORT_ARCHITECTURE_NAME "ARMv7-M" - -/** - * @brief Name of the architecture variant. - */ -#define PORT_CORE_VARIANT_NAME "Cortex-M3" - -#elif (CORTEX_MODEL == 4) -#define PORT_ARCHITECTURE_ARM_v7ME -#define PORT_ARCHITECTURE_NAME "ARMv7E-M" -#if CORTEX_USE_FPU -#define PORT_CORE_VARIANT_NAME "Cortex-M4F" -#else -#define PORT_CORE_VARIANT_NAME "Cortex-M4" -#endif - -#elif (CORTEX_MODEL == 7) -#define PORT_ARCHITECTURE_ARM_v7ME -#define PORT_ARCHITECTURE_NAME "ARMv7E-M" -#if CORTEX_USE_FPU -#define PORT_CORE_VARIANT_NAME "Cortex-M7F" -#else -#define PORT_CORE_VARIANT_NAME "Cortex-M7" -#endif -#endif - -/** - * @brief Port-specific information string. - */ -#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) -#define PORT_INFO "Advanced kernel mode" -#else -#define PORT_INFO "Compact kernel mode" -#endif -/** @} */ - -#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) -/** - * @brief Maximum usable priority for normal ISRs. - */ -#define CORTEX_MAX_KERNEL_PRIORITY (CORTEX_PRIORITY_SVCALL + 1U) - -/** - * @brief BASEPRI level within kernel lock. - */ -#define CORTEX_BASEPRI_KERNEL \ - CORTEX_PRIO_MASK(CORTEX_MAX_KERNEL_PRIORITY) -#else - -#define CORTEX_MAX_KERNEL_PRIORITY 0U -#endif - -/** - * @brief PendSV priority level. - * @note This priority is enforced to be equal to - * @p CORTEX_MAX_KERNEL_PRIORITY, this handler always have the - * highest priority that cannot preempt the kernel. - */ -#define CORTEX_PRIORITY_PENDSV CORTEX_MAX_KERNEL_PRIORITY - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/* The documentation of the following declarations is in chconf.h in order - to not have duplicated structure names into the documentation.*/ -#if !defined(__DOXYGEN__) -struct port_extctx { - regarm_t r0; - regarm_t r1; - regarm_t r2; - regarm_t r3; - regarm_t r12; - regarm_t lr_thd; - regarm_t pc; - regarm_t xpsr; -#if CORTEX_USE_FPU - regarm_t s0; - regarm_t s1; - regarm_t s2; - regarm_t s3; - regarm_t s4; - regarm_t s5; - regarm_t s6; - regarm_t s7; - regarm_t s8; - regarm_t s9; - regarm_t s10; - regarm_t s11; - regarm_t s12; - regarm_t s13; - regarm_t s14; - regarm_t s15; - regarm_t fpscr; - regarm_t reserved; -#endif /* CORTEX_USE_FPU */ -}; - -struct port_intctx { -#if CORTEX_USE_FPU - regarm_t s16; - regarm_t s17; - regarm_t s18; - regarm_t s19; - regarm_t s20; - regarm_t s21; - regarm_t s22; - regarm_t s23; - regarm_t s24; - regarm_t s25; - regarm_t s26; - regarm_t s27; - regarm_t s28; - regarm_t s29; - regarm_t s30; - regarm_t s31; -#endif /* CORTEX_USE_FPU */ - regarm_t r4; - regarm_t r5; - regarm_t r6; - regarm_t r7; - regarm_t r8; - regarm_t r9; - regarm_t r10; - regarm_t r11; - regarm_t lr; -}; -#endif /* !defined(__DOXYGEN__) */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Platform dependent part of the @p chThdCreateI() API. - * @details This code usually setup the context switching frame represented - * by an @p port_intctx structure. - */ -#define PORT_SETUP_CONTEXT(tp, wend, pf, arg) { \ - (tp)->ctxp = (struct port_intctx *)((uint8_t *)(wend) - \ - sizeof(struct port_intctx)); \ - (tp)->ctxp->r4 = (regarm_t)(pf); \ - (tp)->ctxp->r5 = (regarm_t)(arg); \ - (tp)->ctxp->lr = (regarm_t)_port_thread_start; \ -} - -/** - * @brief Computes the thread working area global size. - * @note There is no need to perform alignments in this macro. - */ -#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ - sizeof(struct port_extctx) + \ - ((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK))) - -/** - * @brief IRQ prologue code. - * @details This macro must be inserted at the start of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_PROLOGUE() - -/** - * @brief IRQ epilogue code. - * @details This macro must be inserted at the end of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_EPILOGUE() _port_irq_epilogue() - -/** - * @brief IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_IRQ_HANDLER(id) void id(void) - -/** - * @brief Fast IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_FAST_IRQ_HANDLER(id) void id(void) - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - * - * @param[in] ntp the thread to be switched in - * @param[in] otp the thread to be switched out - */ -#if (NIL_CFG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__) -#define port_switch(ntp, otp) _port_switch(ntp, otp) -#else -#define port_switch(ntp, otp) { \ - struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \ - if ((stkalign_t *)(r13 - 1) < (otp)->stklim) { \ - chSysHalt("stack overflow"); \ - } \ - _port_switch(ntp, otp); \ -} -#endif - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void _port_irq_epilogue(void); - void _port_switch(thread_t *ntp, thread_t *otp); - void _port_thread_start(void); - void _port_switch_from_isr(void); - void _port_exit_from_isr(void); -#ifdef __cplusplus -} -#endif - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Port-related initialization code. - */ -static inline void port_init(void) { - - /* Initialization of the vector table and priority related settings.*/ - SCB->VTOR = CORTEX_VTOR_INIT; - - /* Initializing priority grouping.*/ - NVIC_SetPriorityGrouping(CORTEX_PRIGROUP_INIT); - - /* DWT cycle counter enable.*/ - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; -#if CORTEX_MODEL == 7 - DWT->LAR = 0xC5ACCE55U; -#endif - DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; - - /* Initialization of the system vectors used by the port.*/ -#if CORTEX_SIMPLIFIED_PRIORITY == FALSE - NVIC_SetPriority(SVCall_IRQn, CORTEX_PRIORITY_SVCALL); -#endif - NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); -} - -/** - * @brief Returns a word encoding the current interrupts status. - * - * @return The interrupts status. - */ -static inline syssts_t port_get_irq_status(void) { - syssts_t sts; - -#if CORTEX_SIMPLIFIED_PRIORITY == FALSE - sts = (syssts_t)__get_BASEPRI(); -#else /* CORTEX_SIMPLIFIED_PRIORITY */ - sts = (syssts_t)__get_PRIMASK(); -#endif /* CORTEX_SIMPLIFIED_PRIORITY */ - return sts; -} - -/** - * @brief Checks the interrupt status. - * - * @param[in] sts the interrupt status word - * - * @return The interrupt status. - * @retvel false the word specified a disabled interrupts status. - * @retvel true the word specified an enabled interrupts status. - */ -static inline bool port_irq_enabled(syssts_t sts) { - -#if CORTEX_SIMPLIFIED_PRIORITY == FALSE - return sts == (syssts_t)CORTEX_BASEPRI_DISABLED; -#else /* CORTEX_SIMPLIFIED_PRIORITY */ - return (sts & (syssts_t)1) == (syssts_t)0; -#endif /* CORTEX_SIMPLIFIED_PRIORITY */ -} - -/** - * @brief Determines the current execution context. - * - * @return The execution context. - * @retval false not running in ISR mode. - * @retval true running in ISR mode. - */ -static inline bool port_is_isr_context(void) { - - return (bool)((__get_IPSR() & 0x1FFU) != 0U); -} - -/** - * @brief Kernel-lock action. - * @details In this port this function raises the base priority to kernel - * level. - */ -static inline void port_lock(void) { - -#if CORTEX_SIMPLIFIED_PRIORITY == FALSE -#if defined(__CM7_REV) -#if __CM7_REV == 0 - __disable_irq(); -#endif -#endif - __set_BASEPRI(CORTEX_BASEPRI_KERNEL); -#if defined(__CM7_REV) -#if __CM7_REV == 0 - __enable_irq(); -#endif -#endif -#else /* CORTEX_SIMPLIFIED_PRIORITY */ - __disable_irq(); -#endif /* CORTEX_SIMPLIFIED_PRIORITY */ -} - -/** - * @brief Kernel-unlock action. - * @details In this port this function lowers the base priority to user - * level. - */ -static inline void port_unlock(void) { - -#if CORTEX_SIMPLIFIED_PRIORITY == FALSE - __set_BASEPRI(CORTEX_BASEPRI_DISABLED); -#else /* CORTEX_SIMPLIFIED_PRIORITY */ - __enable_irq(); -#endif /* CORTEX_SIMPLIFIED_PRIORITY */ -} - -/** - * @brief Kernel-lock action from an interrupt handler. - * @details In this port this function raises the base priority to kernel - * level. - * @note Same as @p port_lock() in this port. - */ -static inline void port_lock_from_isr(void) { - - port_lock(); -} - -/** - * @brief Kernel-unlock action from an interrupt handler. - * @details In this port this function lowers the base priority to user - * level. - * @note Same as @p port_unlock() in this port. - */ -static inline void port_unlock_from_isr(void) { - - port_unlock(); -} - -/** - * @brief Disables all the interrupt sources. - * @note In this port it disables all the interrupt sources by raising - * the priority mask to level 0. - */ -static inline void port_disable(void) { - - __disable_irq(); -} - -/** - * @brief Disables the interrupt sources below kernel-level priority. - * @note Interrupt sources above kernel level remains enabled. - * @note In this port it raises/lowers the base priority to kernel level. - */ -static inline void port_suspend(void) { - -#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) - __set_BASEPRI(CORTEX_BASEPRI_KERNEL); - __enable_irq(); -#else - __disable_irq(); -#endif -} - -/** - * @brief Enables all the interrupt sources. - * @note In this port it lowers the base priority to user level. - */ -static inline void port_enable(void) { - -#if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) - __set_BASEPRI(CORTEX_BASEPRI_DISABLED); -#endif - __enable_irq(); -} - -/** - * @brief Enters an architecture-dependent IRQ-waiting mode. - * @details The function is meant to return when an interrupt becomes pending. - * The simplest implementation is an empty function or macro but this - * would not take advantage of architecture-specific power saving - * modes. - * @note Implemented as an inlined @p WFI instruction. - */ -static inline void port_wait_for_interrupt(void) { - -#if CORTEX_ENABLE_WFI_IDLE == TRUE - __WFI(); -#endif -} - -/** - * @brief Returns the current value of the realtime counter. - * - * @return The realtime counter value. - */ -static inline rtcnt_t port_rt_get_counter_value(void) { - - return DWT->CYCCNT; -} - -#endif /* !defined(_FROM_ASM_) */ - -#endif /* _NILCORE_V7M_H_ */ - -/** @} */ diff --git a/os/nil/ports/AVR/compilers/GCC/mk/port.mk b/os/nil/ports/AVR/compilers/GCC/mk/port.mk deleted file mode 100644 index 0eaec1a5f..000000000 --- a/os/nil/ports/AVR/compilers/GCC/mk/port.mk +++ /dev/null @@ -1,7 +0,0 @@ -# List of the ChibiOS/RT AVR port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/AVR/nilcore.c - -PORTASM = - -PORTINC = ${CHIBIOS}/os/nil/ports/AVR \ - ${CHIBIOS}/os/nil/ports/AVR/compilers/GCC diff --git a/os/nil/ports/AVR/compilers/GCC/niltypes.h b/os/nil/ports/AVR/compilers/GCC/niltypes.h deleted file mode 100644 index 3e2e941fa..000000000 --- a/os/nil/ports/AVR/compilers/GCC/niltypes.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file AVR/compilers/GCC/niltypes.h - * @brief AVR port system types. - * - * @addtogroup AVR_CORE - * @{ - */ - -#ifndef _NILTYPES_H_ -#define _NILTYPES_H_ - -#include -#include -#include - -/** - * @name Common constants - */ -/** - * @brief Generic 'false' boolean constant. - */ -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -/** - * @brief Generic 'true' boolean constant. - */ -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE (!FALSE) -#endif -/** @} */ - -typedef uint8_t syssts_t; /**< System status word. */ -typedef uint16_t rtcnt_t; /**< Realtime counter. */ -typedef uint8_t tstate_t; /**< Thread state. */ -typedef int16_t msg_t; /**< Inter-thread message. */ -typedef uint8_t eventmask_t; /**< Mask of event identifiers. */ -typedef int8_t cnt_t; /**< Generic signed counter. */ -typedef uint8_t ucnt_t; /**< Generic unsigned counter. */ - -/** - * @brief Type of system time. - */ -#if (NIL_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__) -typedef uint32_t systime_t; -#else -typedef uint16_t systime_t; -#endif - -/** - * @brief ROM constant modifier. - * @note It is set to use the "const" keyword in this port. - */ -#define ROMCONST const - -/** - * @brief Makes functions not inlineable. - * @note If the compiler does not support such attribute then the - * realtime counter precision could be degraded. - */ -#define NOINLINE __attribute__((noinline)) - -/** - * @brief Optimized thread function declaration macro. - */ -#define PORT_THD_FUNCTION(tname, arg) \ - __attribute__((noreturn)) void tname(void *arg) - -/** - * @brief Packed variable specifier. - */ -#define PACKED_VAR __attribute__((packed)) - -#endif /* _NILTYPES_H_ */ - -/** @} */ diff --git a/os/nil/ports/AVR/nilcore.c b/os/nil/ports/AVR/nilcore.c deleted file mode 100644 index 83fe441df..000000000 --- a/os/nil/ports/AVR/nilcore.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file AVR/nilcore.c - * @brief AVR port code. - * - * @addtogroup AVR_CORE - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - * @note The function is declared as a weak symbol, it is possible to - * redefine it in your application code. - * - * @param[in] ntp the thread to be switched in - * @param[in] otp the thread to be switched out - */ -#if !defined(__DOXYGEN__) -__attribute__((naked, weak)) -#endif -void _port_switch(thread_t *ntp, thread_t *otp) { - - asm volatile ("push r2"); - asm volatile ("push r3"); - asm volatile ("push r4"); - asm volatile ("push r5"); - asm volatile ("push r6"); - asm volatile ("push r7"); - asm volatile ("push r8"); - asm volatile ("push r9"); - asm volatile ("push r10"); - asm volatile ("push r11"); - asm volatile ("push r12"); - asm volatile ("push r13"); - asm volatile ("push r14"); - asm volatile ("push r15"); - asm volatile ("push r16"); - asm volatile ("push r17"); - asm volatile ("push r28"); - asm volatile ("push r29"); - - asm volatile ("movw r30, r22"); - asm volatile ("in r0, 0x3d"); - asm volatile ("std Z+0, r0"); - asm volatile ("in r0, 0x3e"); - asm volatile ("std Z+1, r0"); - - asm volatile ("movw r30, r24"); - asm volatile ("ldd r0, Z+0"); - asm volatile ("out 0x3d, r0"); - asm volatile ("ldd r0, Z+1"); - asm volatile ("out 0x3e, r0"); - - asm volatile ("pop r29"); - asm volatile ("pop r28"); - asm volatile ("pop r17"); - asm volatile ("pop r16"); - asm volatile ("pop r15"); - asm volatile ("pop r14"); - asm volatile ("pop r13"); - asm volatile ("pop r12"); - asm volatile ("pop r11"); - asm volatile ("pop r10"); - asm volatile ("pop r9"); - asm volatile ("pop r8"); - asm volatile ("pop r7"); - asm volatile ("pop r6"); - asm volatile ("pop r5"); - asm volatile ("pop r4"); - asm volatile ("pop r3"); - asm volatile ("pop r2"); - asm volatile ("ret"); -} - -/** - * @brief Start a thread by invoking its work function. - * @details If the work function returns @p chThdExit() is automatically - * invoked. - */ -void _port_thread_start(void) { - - chSysUnlock(); - asm volatile ("movw r24, r4"); - asm volatile ("movw r30, r2"); - asm volatile ("icall"); - chSysHalt(0); -} - -/** @} */ diff --git a/os/nil/ports/AVR/nilcore.h b/os/nil/ports/AVR/nilcore.h deleted file mode 100644 index 4d3122c22..000000000 --- a/os/nil/ports/AVR/nilcore.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file AVR/nilcore.h - * @brief AVR port macros and structures. - * - * @addtogroup AVR_CORE - * @{ - */ - -#ifndef _NILCORE_H_ -#define _NILCORE_H_ - -#include -#include - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @name Architecture and Compiler - * @{ - */ -/** - * @brief Macro defining the port architecture. - */ -#define PORT_ARCHITECTURE_AVR - -/** - * @brief Name of the implemented architecture. - */ -#define PORT_ARCHITECTURE_NAME "AVR" - -/** - * @brief Name of the architecture variant. - */ -#define PORT_CORE_VARIANT_NAME "MegaAVR" - -/** - * @brief Compiler name and version. - */ -#if defined(__GNUC__) || defined(__DOXYGEN__) -#define PORT_COMPILER_NAME "GCC " __VERSION__ - -#else -#error "unsupported compiler" -#endif - -/** - * @brief Port-specific information string. - */ -#define PORT_INFO "16 bits code addressing" - -/** - * @brief This port supports a realtime counter. - */ -#define PORT_SUPPORTS_RT FALSE -/** @} */ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Stack size for the system idle thread. - * @details This size depends on the idle thread implementation, usually - * the idle thread should take no more space than those reserved - * by @p PORT_INT_REQUIRED_STACK. - * @note In this port it is set to 8. - */ -#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) -#define PORT_IDLE_THREAD_STACK_SIZE 8 -#endif - -/** - * @brief Per-thread stack overhead for interrupts servicing. - * @details This constant is used in the calculation of the correct working - * area size. - * @note In this port the default is 32 bytes per thread. - */ -#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) -#define PORT_INT_REQUIRED_STACK 32 -#endif - -/** - * @brief Enables an alternative timer implementation. - * @details Usually the port uses a timer interface defined in the file - * @p nilcore_timer.h, if this option is enabled then the file - * @p nilcore_timer_alt.h is included instead. - */ -#if !defined(PORT_USE_ALT_TIMER) -#define PORT_USE_ALT_TIMER FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Type of stack and memory alignment enforcement. - */ -typedef uint8_t stkalign_t; - -/** - * @brief System saved context. - * @details This structure represents the inner stack frame during a context - * switching. - */ -struct port_intctx { - uint8_t _next; - uint8_t r29; - uint8_t r28; - uint8_t r17; - uint8_t r16; - uint8_t r15; - uint8_t r14; - uint8_t r13; - uint8_t r12; - uint8_t r11; - uint8_t r10; - uint8_t r9; - uint8_t r8; - uint8_t r7; - uint8_t r6; - uint8_t r5; - uint8_t r4; - uint8_t r3; - uint8_t r2; -#ifdef __AVR_3_BYTE_PC__ - uint8_t pcx; -#endif - uint8_t pcl; - uint8_t pch; -}; - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Platform dependent thread stack setup. - * @details This code usually setup the context switching frame represented - * by an @p port_intctx structure. - */ -#ifdef __AVR_3_BYTE_PC__ -#define PORT_SETUP_CONTEXT(tp, wend, pf, arg) { \ - (tp)->ctxp = (struct port_intctx*)(((uint8_t *)(wend)) - \ - sizeof(struct port_intctx)); \ - (tp)->ctxp->r2 = (int)pf; \ - (tp)->ctxp->r3 = (int)pf >> 8; \ - (tp)->ctxp->r4 = (int)arg; \ - (tp)->ctxp->r5 = (int)arg >> 8; \ - (tp)->ctxp->pcx = (int)0; \ - (tp)->ctxp->pcl = (int)_port_thread_start >> 8; \ - (tp)->ctxp->pch = (int)_port_thread_start; \ -} -#else /* __AVR_3_BYTE_PC__ */ -#define PORT_SETUP_CONTEXT(tp, wend, pf, arg) { \ - (tp)->ctxp = (struct port_intctx*)(((uint8_t *)(wend)) - \ - sizeof(struct port_intctx)); \ - (tp)->ctxp->r2 = (int)pf; \ - (tp)->ctxp->r3 = (int)pf >> 8; \ - (tp)->ctxp->r4 = (int)arg; \ - (tp)->ctxp->r5 = (int)arg >> 8; \ - (tp)->ctxp->pcl = (int)_port_thread_start >> 8; \ - (tp)->ctxp->pch = (int)_port_thread_start; \ -} -#endif /* __AVR_3_BYTE_PC__ */ -/** - * @brief Computes the thread working area global size. - * @note There is no need to perform alignments in this macro. - */ -#define PORT_WA_SIZE(n) ((sizeof(struct port_intctx) - 1) + \ - (n) + (PORT_INT_REQUIRED_STACK)) - -/** - * @brief IRQ prologue code. - * @details This macro must be inserted at the start of all IRQ handlers - * enabled to invoke system APIs. - * @note This code tricks the compiler to save all the specified registers - * by "touching" them. - */ -#define PORT_IRQ_PROLOGUE() { \ - asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \ - "r25", "r26", "r27", "r30", "r31"); \ -} - -/** - * @brief IRQ epilogue code. - * @details This macro must be inserted at the end of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_EPILOGUE() chSchRescheduleS() - -/** - * @brief IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_IRQ_HANDLER(id) ISR(id) - -/** - * @brief Fast IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_FAST_IRQ_HANDLER(id) ISR(id) - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - * - * @param[in] ntp the thread to be switched in - * @param[in] otp the thread to be switched out - */ -#define port_switch(ntp, otp) _port_switch(ntp, otp) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -#ifdef __cplusplus -extern "C" { -#endif - void _port_irq_epilogue(void); - void _port_switch(thread_t *ntp, thread_t *otp); - void _port_thread_start(void); -#ifdef __cplusplus -} -#endif - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Port-related initialization code. - */ -static inline void port_init(void) { - -} - -/** - * @brief Returns a word encoding the current interrupts status. - * - * @return The interrupts status. - */ -static inline syssts_t port_get_irq_status(void) { - - return 0; -} - -/** - * @brief Checks the interrupt status. - * - * @param[in] sts the interrupt status word - * - * @return The interrupt status. - * @retvel false the word specified a disabled interrupts status. - * @retvel true the word specified an enabled interrupts status. - */ -static inline bool port_irq_enabled(syssts_t sts) { - - return false; -} - -/** - * @brief Determines the current execution context. - * - * @return The execution context. - * @retval false not running in ISR mode. - * @retval true running in ISR mode. - */ -static inline bool port_is_isr_context(void) { - - return false; -} - -/** - * @brief Kernel-lock action. - */ -static inline void port_lock(void) { - - asm volatile ("cli" : : : "memory"); -} - -/** - * @brief Kernel-unlock action. - */ -static inline void port_unlock(void) { - - asm volatile ("sei" : : : "memory"); -} - -/** - * @brief Kernel-lock action from an interrupt handler. - * @note This function is empty in this port. - */ -static inline void port_lock_from_isr(void) { - -} - -/** - * @brief Kernel-unlock action from an interrupt handler. - * @note This function is empty in this port. - */ -static inline void port_unlock_from_isr(void) { - -} - -/** - * @brief Disables all the interrupt sources. - */ -static inline void port_disable(void) { - - asm volatile ("cli" : : : "memory"); -} - -/** - * @brief Disables the interrupt sources below kernel-level priority. - */ -static inline void port_suspend(void) { - - asm volatile ("cli" : : : "memory"); -} - -/** - * @brief Enables all the interrupt sources. - */ -static inline void port_enable(void) { - - asm volatile ("sei" : : : "memory"); -} - -/** - * @brief Enters an architecture-dependent IRQ-waiting mode. - * @details The function is meant to return when an interrupt becomes pending. - * The simplest implementation is an empty function or macro but this - * would not take advantage of architecture-specific power saving - * modes. - */ -static inline void port_wait_for_interrupt(void) { - - asm volatile ("sleep" : : : "memory"); -} - -/** - * @brief Returns the current value of the realtime counter. - * - * @return The realtime counter value. - */ -static inline rtcnt_t port_rt_get_counter_value(void) { - - return 0; -} - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module late inclusions. */ -/*===========================================================================*/ - -#if !defined(_FROM_ASM_) - -#if NIL_CFG_ST_TIMEDELTA > 0 -#if !PORT_USE_ALT_TIMER -#include "nilcore_timer.h" -#else /* PORT_USE_ALT_TIMER */ -#include "nilcore_timer_alt.h" -#endif /* PORT_USE_ALT_TIMER */ -#endif /* NIL_CFG_ST_TIMEDELTA > 0 */ - -#endif /* !defined(_FROM_ASM_) */ - -#endif /* _NILCORE_H_ */ - -/** @} */ diff --git a/os/nil/ports/AVR/nilcore_timer.h b/os/nil/ports/AVR/nilcore_timer.h deleted file mode 100644 index fc00cf50f..000000000 --- a/os/nil/ports/AVR/nilcore_timer.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file AVR/nilcore_timer.h - * @brief System timer header file. - * - * @addtogroup AVR_TIMER - * @{ - */ - -#ifndef _NILCORE_TIMER_H_ -#define _NILCORE_TIMER_H_ - -/* This is the only header in the HAL designed to be include-able alone.*/ -#include "st.h" - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * - * @param[in] time the time to be set for the first alarm - * - * @notapi - */ -static inline void port_timer_start_alarm(systime_t time) { - - stStartAlarm(time); -} - -/** - * @brief Stops the alarm interrupt. - * - * @notapi - */ -static inline void port_timer_stop_alarm(void) { - - stStopAlarm(); -} - -/** - * @brief Sets the alarm time. - * - * @param[in] time the time to be set for the next alarm - * - * @notapi - */ -static inline void port_timer_set_alarm(systime_t time) { - - stSetAlarm(time); -} - -/** - * @brief Returns the system time. - * - * @return The system time. - * - * @notapi - */ -static inline systime_t port_timer_get_time(void) { - - return stGetCounter(); -} - -/** - * @brief Returns the current alarm time. - * - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t port_timer_get_alarm(void) { - - return stGetAlarm(); -} - -#endif /* _NILCORE_TIMER_H_ */ - -/** @} */ diff --git a/os/nil/ports/e200/compilers/GCC/ivor.s b/os/nil/ports/e200/compilers/GCC/ivor.s deleted file mode 100644 index 8bd687c0a..000000000 --- a/os/nil/ports/e200/compilers/GCC/ivor.s +++ /dev/null @@ -1,234 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ivor.s - * @brief Kernel ISRs. - * - * @addtogroup PPC_GCC_CORE - * @{ - */ - -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 -#endif - -/* - * Imports the PPC configuration headers. - */ -#define _FROM_ASM_ -#include "nilconf.h" -#include "nilcore.h" - -#if !defined(__DOXYGEN__) - - .section .handlers, "ax" - -#if PPC_SUPPORTS_DECREMENTER - /* - * _IVOR10 handler (Book-E decrementer). - */ - .align 4 - .globl _IVOR10 - .type _IVOR10, @function -_IVOR10: - /* Saving the external context (port_extctx structure).*/ - stwu %sp, -80(%sp) -#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI - e_stmvsrrw 8(%sp) /* Saves PC, MSR. */ - e_stmvsprw 16(%sp) /* Saves CR, LR, CTR, XER. */ - e_stmvgprw 32(%sp) /* Saves GPR0, GPR3...GPR12. */ -#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ - stw %r0, 32(%sp) /* Saves GPR0. */ - mfSRR0 %r0 - stw %r0, 8(%sp) /* Saves PC. */ - mfSRR1 %r0 - stw %r0, 12(%sp) /* Saves MSR. */ - mfCR %r0 - stw %r0, 16(%sp) /* Saves CR. */ - mfLR %r0 - stw %r0, 20(%sp) /* Saves LR. */ - mfCTR %r0 - stw %r0, 24(%sp) /* Saves CTR. */ - mfXER %r0 - stw %r0, 28(%sp) /* Saves XER. */ - stw %r3, 36(%sp) /* Saves GPR3...GPR12. */ - stw %r4, 40(%sp) - stw %r5, 44(%sp) - stw %r6, 48(%sp) - stw %r7, 52(%sp) - stw %r8, 56(%sp) - stw %r9, 60(%sp) - stw %r10, 64(%sp) - stw %r11, 68(%sp) - stw %r12, 72(%sp) -#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ - - /* Increasing the SPGR0 register.*/ - mfspr %r0, 272 - eaddi %r0, %r0, 1 - mtspr 272, %r0 - - /* Reset DIE bit in TSR register.*/ - lis %r3, 0x0800 /* DIS bit mask. */ - mtspr 336, %r3 /* TSR register. */ - - /* Restoring pre-IRQ MSR register value.*/ - mfSRR1 %r0 -#if !PPC_USE_IRQ_PREEMPTION - /* No preemption, keeping EE disabled.*/ - se_bclri %r0, 16 /* EE = bit 16. */ -#endif - mtMSR %r0 - - /* System tick handler invocation.*/ - bl chSysTimerHandlerI - -#if PPC_USE_IRQ_PREEMPTION - /* Prevents preemption again.*/ - wrteei 0 -#endif - - /* Jumps to the common IVOR epilogue code.*/ - b _ivor_exit -#endif /* PPC_SUPPORTS_DECREMENTER */ - - /* - * _IVOR4 handler (Book-E external interrupt). - */ - .align 4 - .globl _IVOR4 - .type _IVOR4, @function -_IVOR4: - /* Saving the external context (port_extctx structure).*/ - stwu %sp, -80(%sp) -#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI - e_stmvsrrw 8(%sp) /* Saves PC, MSR. */ - e_stmvsprw 16(%sp) /* Saves CR, LR, CTR, XER. */ - e_stmvgprw 32(%sp) /* Saves GPR0, GPR3...GPR12. */ -#else /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ - stw %r0, 32(%sp) /* Saves GPR0. */ - mfSRR0 %r0 - stw %r0, 8(%sp) /* Saves PC. */ - mfSRR1 %r0 - stw %r0, 12(%sp) /* Saves MSR. */ - mfCR %r0 - stw %r0, 16(%sp) /* Saves CR. */ - mfLR %r0 - stw %r0, 20(%sp) /* Saves LR. */ - mfCTR %r0 - stw %r0, 24(%sp) /* Saves CTR. */ - mfXER %r0 - stw %r0, 28(%sp) /* Saves XER. */ - stw %r3, 36(%sp) /* Saves GPR3...GPR12. */ - stw %r4, 40(%sp) - stw %r5, 44(%sp) - stw %r6, 48(%sp) - stw %r7, 52(%sp) - stw %r8, 56(%sp) - stw %r9, 60(%sp) - stw %r10, 64(%sp) - stw %r11, 68(%sp) - stw %r12, 72(%sp) -#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ - - /* Increasing the SPGR0 register.*/ - mfspr %r0, 272 - eaddi %r0, %r0, 1 - mtspr 272, %r0 - - /* Software vector address from the INTC register.*/ - lis %r3, INTC_IACKR_ADDR@h - ori %r3, %r3, INTC_IACKR_ADDR@l - lwz %r3, 0(%r3) /* IACKR register value. */ - lwz %r3, 0(%r3) - mtCTR %r3 /* Software handler address. */ - - /* Restoring pre-IRQ MSR register value.*/ - mfSRR1 %r0 -#if !PPC_USE_IRQ_PREEMPTION - /* No preemption, keeping EE disabled.*/ - se_bclri %r0, 16 /* EE = bit 16. */ -#endif - mtMSR %r0 - - /* Exectes the software handler.*/ - bctrl - -#if PPC_USE_IRQ_PREEMPTION - /* Prevents preemption again.*/ - wrteei 0 -#endif - - /* Informs the INTC that the interrupt has been served.*/ - mbar 0 - lis %r3, INTC_EOIR_ADDR@h - ori %r3, %r3, INTC_EOIR_ADDR@l - stw %r3, 0(%r3) /* Writing any value should do. */ - - /* Common IVOR epilogue code, context restore.*/ - .globl _ivor_exit -_ivor_exit: - /* Decreasing the SPGR0 register.*/ - mfspr %r0, 272 - eaddi %r0, %r0, -1 - mtspr 272, %r0 - - bl chSchRescheduleS - - /* Restoring the external context.*/ -#if PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI - e_lmvgprw 32(%sp) /* Restores GPR0, GPR3...GPR12. */ - e_lmvsprw 16(%sp) /* Restores CR, LR, CTR, XER. */ - e_lmvsrrw 8(%sp) /* Restores PC, MSR. */ -#else /*!(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ - lwz %r3, 36(%sp) /* Restores GPR3...GPR12. */ - lwz %r4, 40(%sp) - lwz %r5, 44(%sp) - lwz %r6, 48(%sp) - lwz %r7, 52(%sp) - lwz %r8, 56(%sp) - lwz %r9, 60(%sp) - lwz %r10, 64(%sp) - lwz %r11, 68(%sp) - lwz %r12, 72(%sp) - lwz %r0, 8(%sp) - mtSRR0 %r0 /* Restores PC. */ - lwz %r0, 12(%sp) - mtSRR1 %r0 /* Restores MSR. */ - lwz %r0, 16(%sp) - mtCR %r0 /* Restores CR. */ - lwz %r0, 20(%sp) - mtLR %r0 /* Restores LR. */ - lwz %r0, 24(%sp) - mtCTR %r0 /* Restores CTR. */ - lwz %r0, 28(%sp) - mtXER %r0 /* Restores XER. */ - lwz %r0, 32(%sp) /* Restores GPR0. */ -#endif /* !(PPC_USE_VLE && PPC_SUPPORTS_VLE_MULTI) */ - addi %sp, %sp, 80 /* Back to the previous frame. */ - rfi - -#endif /* !defined(__DOXYGEN__) */ - -/** @} */ diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc560bcxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc560bcxx.mk deleted file mode 100644 index 050076219..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc560bcxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z0 SPC560BCxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560BCxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560BCxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc560bxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc560bxx.mk deleted file mode 100644 index 6089f4743..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc560bxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z0 SPC560Bxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560Bxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560Bxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc560dxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc560dxx.mk deleted file mode 100644 index 91176f87b..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc560dxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z0 SPC560Dxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560Dxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560Dxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc560pxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc560pxx.mk deleted file mode 100644 index 9342310aa..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc560pxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z0 SPC560Pxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC560Pxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC560Pxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc563mxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc563mxx.mk deleted file mode 100644 index febbf22a8..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc563mxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z3 SPC563Mxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC563Mxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC563Mxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc564axx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc564axx.mk deleted file mode 100644 index 31b25c692..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc564axx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z4 SPC564Axx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC564Axx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC564Axx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc56ecxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc56ecxx.mk deleted file mode 100644 index 84ada33e1..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc56ecxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z4 SPC56ECxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC56ECxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC56ECxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc56elxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc56elxx.mk deleted file mode 100644 index a913240e3..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc56elxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z4 SPC56ELxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC56ELxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC56ELxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/mk/port_spc57emxx.mk b/os/nil/ports/e200/compilers/GCC/mk/port_spc57emxx.mk deleted file mode 100644 index 669d371ea..000000000 --- a/os/nil/ports/e200/compilers/GCC/mk/port_spc57emxx.mk +++ /dev/null @@ -1,14 +0,0 @@ -# List of the ChibiOS/NIL e200z4 SPC57EMxx port files. -PORTSRC = ${CHIBIOS}/os/nil/ports/e200/nilcore.c - -PORTASM = $(CHIBIOS)/os/common/ports/e200/devices/SPC57EMxx/boot.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/vectors.s \ - $(CHIBIOS)/os/common/ports/e200/compilers/GCC/crt0.s \ - $(CHIBIOS)/os/nil/ports/e200/compilers/GCC/ivor.s - -PORTINC = ${CHIBIOS}/os/common/ports/e200/compilers/GCC \ - ${CHIBIOS}/os/common/ports/e200/devices/SPC57EMxx \ - ${CHIBIOS}/os/nil/ports/e200 \ - ${CHIBIOS}/os/nil/ports/e200/compilers/GCC - -PORTLD = ${CHIBIOS}/os/common/ports/e200/compilers/GCC/ld diff --git a/os/nil/ports/e200/compilers/GCC/niltypes.h b/os/nil/ports/e200/compilers/GCC/niltypes.h deleted file mode 100644 index 587beb26e..000000000 --- a/os/nil/ports/e200/compilers/GCC/niltypes.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file e200/compilers/GCC/niltypes.h - * @brief Power e200 port system types. - * - * @addtogroup PPC_GCC_CORE - * @{ - */ - -#ifndef _NILTYPES_H_ -#define _NILTYPES_H_ - -#include -#include -#include - -/** - * @name Common constants - */ -/** - * @brief Generic 'false' boolean constant. - */ -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -/** - * @brief Generic 'true' boolean constant. - */ -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE (!FALSE) -#endif -/** @} */ - -typedef uint32_t syssts_t; /**< System status word. */ -typedef uint32_t rtcnt_t; /**< Realtime counter. */ -typedef uint8_t tstate_t; /**< Thread state. */ -typedef int32_t msg_t; /**< Inter-thread message. */ -typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ -typedef int32_t cnt_t; /**< Generic signed counter. */ -typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ - -/** - * @brief Type of system time. - */ -#if (NIL_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__) -typedef uint32_t systime_t; -#else -typedef uint16_t systime_t; -#endif - -/** - * @brief ROM constant modifier. - * @note It is set to use the "const" keyword in this port. - */ -#define ROMCONST const - -/** - * @brief Makes functions not inlineable. - * @note If the compiler does not support such attribute then the - * realtime counter precision could be degraded. - */ -#define NOINLINE __attribute__((noinline)) - -/** - * @brief Optimized thread function declaration macro. - */ -#define PORT_THD_FUNCTION(tname, arg) \ - __attribute__((noreturn)) void tname(void *arg) - -/** - * @brief Packed variable specifier. - */ -#define PACKED_VAR __attribute__((packed)) - -#endif /* _NILTYPES_H_ */ - -/** @} */ diff --git a/os/nil/ports/e200/nilcore.c b/os/nil/ports/e200/nilcore.c deleted file mode 100644 index 4e4510bab..000000000 --- a/os/nil/ports/e200/nilcore.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file templates/nilcore.c - * @brief Port code. - * - * @addtogroup NIL_CORE - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - */ -#if !defined(__DOXYGEN__) -__attribute__((naked)) -#endif -void port_dummy1(void) { - - asm (".global _port_switch"); - asm ("_port_switch:"); - asm ("subi %sp, %sp, 80"); /* Size of the intctx structure. */ - asm ("mflr %r0"); - asm ("stw %r0, 84(%sp)"); /* LR into the caller frame. */ - asm ("mfcr %r0"); - asm ("stw %r0, 0(%sp)"); /* CR. */ - asm ("stmw %r14, 4(%sp)"); /* GPR14...GPR31. */ - - asm ("stw %sp, 0(%r4)"); /* Store swapped-out stack. */ - asm ("lwz %sp, 0(%r3)"); /* Load swapped-in stack. */ - - asm ("lmw %r14, 4(%sp)"); /* GPR14...GPR31. */ - asm ("lwz %r0, 0(%sp)"); /* CR. */ - asm ("mtcr %r0"); - asm ("lwz %r0, 84(%sp)"); /* LR from the caller frame. */ - asm ("mtlr %r0"); - asm ("addi %sp, %sp, 80"); /* Size of the intctx structure. */ - asm ("blr"); -} - -/** - * @brief Start a thread by invoking its work function. - * @details If the work function returns @p chThdExit() is automatically - * invoked. - */ -#if !defined(__DOXYGEN__) -__attribute__((naked)) -#endif -void port_dummy2(void) { - - asm (".global _port_thread_start"); - asm ("_port_thread_start:"); - chSysUnlock(); - asm ("mr %r3, %r31"); /* Thread parameter. */ - asm ("mtctr %r30"); - asm ("bctrl"); /* Invoke thread function. */ - asm ("li %r0, 0"); - asm ("bl chSysHalt"); /* Thread termination on exit. */ -} - -/** @} */ diff --git a/os/nil/ports/e200/nilcore.h b/os/nil/ports/e200/nilcore.h deleted file mode 100644 index ac5a32433..000000000 --- a/os/nil/ports/e200/nilcore.h +++ /dev/null @@ -1,555 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file templates/nilcore.h - * @brief Port macros and structures. - * - * @addtogroup NIL_CORE - * @{ - */ - -#ifndef _NILCORE_H_ -#define _NILCORE_H_ - -#include "intc.h" - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @name Architecture and Compiler - * @{ - */ -/** - * @brief Macro defining an PPC architecture. - */ -#define PORT_ARCHITECTURE_PPC - -/** - * @brief Macro defining the specific PPC architecture. - */ -#define PORT_ARCHITECTURE_PPC_E200 - -/** - * @brief Name of the implemented architecture. - */ -#define PORT_ARCHITECTURE_NAME "Power Architecture" - -/** - * @brief Compiler name and version. - */ -#if defined(__GNUC__) || defined(__DOXYGEN__) -#define PORT_COMPILER_NAME "GCC " __VERSION__ - -#else -#error "unsupported compiler" -#endif - -/** - * @brief This port supports a realtime counter. - */ -#define PORT_SUPPORTS_RT FALSE -/** @} */ - -/** - * @name E200 core variants - * @{ - */ -#define PPC_VARIANT_e200z0 200 -#define PPC_VARIANT_e200z2 202 -#define PPC_VARIANT_e200z3 203 -#define PPC_VARIANT_e200z4 204 -/** @} */ - -/* Inclusion of the PPC implementation specific parameters.*/ -#include "ppcparams.h" -#include "vectors.h" - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Per-thread stack overhead for interrupts servicing. - * @details This constant is used in the calculation of the correct working - * area size. - */ -#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) -#define PORT_INT_REQUIRED_STACK 256 -#endif - -/** - * @brief Enables an alternative timer implementation. - * @details Usually the port uses a timer interface defined in the file - * @p nilcore_timer.h, if this option is enabled then the file - * @p nilcore_timer_alt.h is included instead. - */ -#if !defined(PORT_USE_ALT_TIMER) || defined(__DOXYGEN__) -#define PORT_USE_ALT_TIMER FALSE -#endif - -/** - * @brief Use VLE instruction set. - * @note This parameter is usually set in the Makefile. - */ -#if !defined(PPC_USE_VLE) || defined(__DOXYGEN__) -#define PPC_USE_VLE TRUE -#endif - -/** - * @brief Enables the use of the @p WFI instruction. - */ -#if !defined(PPC_ENABLE_WFI_IDLE) || defined(__DOXYGEN__) -#define PPC_ENABLE_WFI_IDLE FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if PPC_USE_VLE && !PPC_SUPPORTS_VLE -#error "the selected MCU does not support VLE instructions set" -#endif - -#if !PPC_USE_VLE && !PPC_SUPPORTS_BOOKE -#error "the selected MCU does not support BookE instructions set" -#endif - -/** - * @brief Name of the architecture variant. - */ -#if (PPC_VARIANT == PPC_VARIANT_e200z0) || defined(__DOXYGEN__) -#define PORT_CORE_VARIANT_NAME "e200z0" -#elif PPC_VARIANT == PPC_VARIANT_e200z2 -#define PORT_CORE_VARIANT_NAME "e200z2" -#elif PPC_VARIANT == PPC_VARIANT_e200z3 -#define PORT_CORE_VARIANT_NAME "e200z3" -#elif PPC_VARIANT == PPC_VARIANT_e200z4 -#define PORT_CORE_VARIANT_NAME "e200z4" -#else -#error "unknown or unsupported PowerPC variant specified" -#endif - -/** - * @brief Port-specific information string. - */ -#if PPC_USE_VLE -#define PORT_INFO "VLE mode" -#else -#define PORT_INFO "Book-E mode" -#endif - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Type of stack and memory alignment enforcement. - */ -typedef uint64_t stkalign_t; - -/** - * @brief Generic PPC register. - */ -typedef void *regppc_t; - -/** - * @brief Mandatory part of a stack frame. - */ -struct port_eabi_frame { - uint32_t slink; /**< Stack back link. */ - uint32_t shole; /**< Stack hole for LR storage. */ -}; - -/** - * @brief Interrupt saved context. - * @details This structure represents the stack frame saved during a - * preemption-capable interrupt handler. - * @note R2 and R13 are not saved because those are assumed to be immutable - * during the system life cycle. - */ -struct port_extctx { - struct port_eabi_frame frame; - /* Start of the e_stmvsrrw frame (offset 8).*/ - regppc_t pc; - regppc_t msr; - /* Start of the e_stmvsprw frame (offset 16).*/ - regppc_t cr; - regppc_t lr; - regppc_t ctr; - regppc_t xer; - /* Start of the e_stmvgprw frame (offset 32).*/ - regppc_t r0; - regppc_t r3; - regppc_t r4; - regppc_t r5; - regppc_t r6; - regppc_t r7; - regppc_t r8; - regppc_t r9; - regppc_t r10; - regppc_t r11; - regppc_t r12; - regppc_t padding; - }; - -/** - * @brief System saved context. - * @details This structure represents the inner stack frame during a context - * switching. - * @note R2 and R13 are not saved because those are assumed to be immutable - * during the system life cycle. - * @note LR is stored in the caller context so it is not present in this - * structure. - */ -struct port_intctx { - regppc_t cr; /* Part of it is not volatile... */ - regppc_t r14; - regppc_t r15; - regppc_t r16; - regppc_t r17; - regppc_t r18; - regppc_t r19; - regppc_t r20; - regppc_t r21; - regppc_t r22; - regppc_t r23; - regppc_t r24; - regppc_t r25; - regppc_t r26; - regppc_t r27; - regppc_t r28; - regppc_t r29; - regppc_t r30; - regppc_t r31; - regppc_t padding; -}; - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Platform dependent thread stack setup. - * @details This code usually setup the context switching frame represented - * by an @p port_intctx structure. - */ -#define PORT_SETUP_CONTEXT(tp, wend, pf, arg) { \ - uint8_t *sp = (uint8_t *)(wend) - \ - sizeof(struct port_eabi_frame); \ - ((struct port_eabi_frame *)sp)->slink = 0; \ - ((struct port_eabi_frame *)sp)->shole = (uint32_t)_port_thread_start; \ - (tp)->ctxp = (struct port_intctx *)(sp - sizeof(struct port_intctx)); \ - (tp)->ctxp->r31 = (regppc_t)(arg); \ - (tp)->ctxp->r30 = (regppc_t)(pf); \ -} - -/** - * @brief Computes the thread working area global size. - * @note There is no need to perform alignments in this macro. - */ -#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ - sizeof(struct port_extctx) + \ - (n) + (PORT_INT_REQUIRED_STACK)) - -/** - * @brief IRQ prologue code. - * @details This macro must be inserted at the start of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_PROLOGUE() - -/** - * @brief IRQ epilogue code. - * @details This macro must be inserted at the end of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_EPILOGUE() - -/** - * @brief IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_IRQ_HANDLER(id) void id(void) - -/** - * @brief Fast IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_FAST_IRQ_HANDLER(id) void id(void) - -/** - * @brief Priority level verification macro. - */ -#define PORT_IRQ_IS_VALID_PRIORITY(n) \ - (((n) >= 0U) && ((n) < INTC_PRIORITY_LEVELS)) - -/** - * @brief Priority level verification macro. - */ -#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) \ - (((n) >= 0U) && ((n) < INTC_PRIORITY_LEVELS)) - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - * - * @param[in] ntp the thread to be switched in - * @param[in] otp the thread to be switched out - */ -#if !NIL_CFG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) -#define port_switch(ntp, otp) _port_switch(ntp, otp) -#else -#define port_switch(ntp, otp) { \ - register struct port_intctx *sp asm ("%r1"); \ - if ((stkalign_t *)(sp - 1) < otp->stklim) \ - chSysHalt("stack overflow"); \ - _port_switch(ntp, otp); \ -} -#endif - -/** - * @brief Writes to a special register. - * - * @param[in] spr special register number - * @param[in] val value to be written, must be an automatic variable - */ -#define port_write_spr(spr, val) \ - asm volatile ("mtspr %[p0], %[p1]" : : [p0] "n" (spr), [p1] "r" (val)) - -/** - * @brief Writes to a special register. - * - * @param[in] spr special register number - * @param[in] val returned value, must be an automatic variable - */ -#define port_read_spr(spr, val) \ - asm volatile ("mfspr %[p0], %[p1]" : [p0] "=r" (val) : [p1] "n" (spr)) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -#ifdef __cplusplus -extern "C" { -#endif - void _port_switch(thread_t *ntp, thread_t *otp); - void _port_thread_start(void); -#ifdef __cplusplus -} -#endif - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Port-related initialization code. - */ -static inline void port_init(void) { - uint32_t n; - unsigned i; - - /* Initializing the SPRG0 register to zero, it is required for interrupts - handling.*/ - n = 0; - port_write_spr(272, n); - -#if PPC_SUPPORTS_IVORS - /* The CPU supports IVOR registers, the kernel requires IVOR4 and IVOR10 - and the initialization is performed here.*/ - asm volatile ("li %%r3, _IVOR4@l \t\n" - "mtIVOR4 %%r3 \t\n" - "li %%r3, _IVOR10@l \t\n" - "mtIVOR10 %%r3" : : : "r3", "memory"); -#endif - - /* INTC initialization, software vector mode, 4 bytes vectors, starting - at priority 0.*/ - INTC_BCR = 0; - for (i = 0; i < PPC_CORE_NUMBER; i++) { - INTC_CPR(i) = 0; - INTC_IACKR(i) = (uint32_t)_vectors; - } -} - -/** - * @brief Returns a word encoding the current interrupts status. - * - * @return The interrupts status. - */ -static inline syssts_t port_get_irq_status(void) { - uint32_t sts; - - asm volatile ("mfmsr %[p0]" : [p0] "=r" (sts) :); - return sts; -} - -/** - * @brief Checks the interrupt status. - * - * @param[in] sts the interrupt status word - * - * @return The interrupt status. - * @retvel false the word specified a disabled interrupts status. - * @retvel true the word specified an enabled interrupts status. - */ -static inline bool port_irq_enabled(syssts_t sts) { - - return (bool)((sts & (1 << 15)) != 0); -} - -/** - * @brief Determines the current execution context. - * - * @return The execution context. - * @retval false not running in ISR mode. - * @retval true running in ISR mode. - */ -static inline bool port_is_isr_context(void) { - uint32_t sprg0; - - /* The SPRG0 register is increased before entering interrupt handlers and - decreased at the end.*/ - port_read_spr(272, sprg0); - return (bool)(sprg0 > 0); -} - -/** - * @brief Kernel-lock action. - */ -static inline void port_lock(void) { - - asm volatile ("wrteei 0" : : : "memory"); -} - -/** - * @brief Kernel-unlock action. - */ -static inline void port_unlock(void) { - - asm volatile("wrteei 1" : : : "memory"); -} - -/** - * @brief Kernel-lock action from an interrupt handler. - */ -static inline void port_lock_from_isr(void) { - -} - -/** - * @brief Kernel-unlock action from an interrupt handler. - */ -static inline void port_unlock_from_isr(void) { - -} - -/** - * @brief Disables all the interrupt sources. - */ -static inline void port_disable(void) { - - asm volatile ("wrteei 0" : : : "memory"); -} - -/** - * @brief Disables the interrupt sources below kernel-level priority. - */ -static inline void port_suspend(void) { - - asm volatile ("wrteei 0" : : : "memory"); -} - -/** - * @brief Enables all the interrupt sources. - */ -static inline void port_enable(void) { - - asm volatile ("wrteei 1" : : : "memory"); -} - -/** - * @brief Enters an architecture-dependent IRQ-waiting mode. - * @details The function is meant to return when an interrupt becomes pending. - * The simplest implementation is an empty function or macro but this - * would not take advantage of architecture-specific power saving - * modes. - */ -static inline void port_wait_for_interrupt(void) { - -#if PPC_ENABLE_WFI_IDLE - asm volatile ("wait" : : : "memory"); -#endif -} - -/** - * @brief Returns the current value of the realtime counter. - * - * @return The realtime counter value. - */ -static inline rtcnt_t port_rt_get_counter_value(void) { - - return 0; -} - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module late inclusions. */ -/*===========================================================================*/ - -#if !defined(_FROM_ASM_) - -#if NIL_CFG_ST_TIMEDELTA > 0 -#if !PORT_USE_ALT_TIMER -#include "nilcore_timer.h" -#else /* PORT_USE_ALT_TIMER */ -#include "nilcore_timer_alt.h" -#endif /* PORT_USE_ALT_TIMER */ -#endif /* NIL_CFG_ST_TIMEDELTA > 0 */ - -#endif /* !defined(_FROM_ASM_) */ - -#endif /* _NILCORE_H_ */ - -/** @} */ diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c new file mode 100644 index 000000000..0db75db37 --- /dev/null +++ b/os/nil/src/ch.c @@ -0,0 +1,840 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file nil.c + * @brief Nil RTOS main source file. + * + * @addtogroup NIL_KERNEL + * @{ + */ + +#include "nil.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/** + * @brief System data structures. + */ +nil_system_t nil; + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module interrupt handlers. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** + * @brief Initializes the kernel. + * @details Initializes the kernel structures, the current instructions flow + * becomes the idle thread upon return. The idle thread must not + * invoke any kernel primitive able to change state to not runnable. + * @note This function assumes that the @p nil global variable has been + * zeroed by the runtime environment. If this is not the case then + * make sure to clear it before calling this function. + * + * @special + */ +void chSysInit(void) { + thread_t *tp; + const thread_config_t *tcp; + + /* Port layer initialization.*/ + port_init(); + + /* System initialization hook.*/ + NIL_CFG_SYSTEM_INIT_HOOK(); + + /* Iterates through the list of defined threads.*/ + tp = &nil.threads[0]; + tcp = nil_thd_configs; + while (tp < &nil.threads[NIL_CFG_NUM_THREADS]) { +#if NIL_CFG_ENABLE_STACK_CHECK + tp->stklim = (stkalign_t *)tcp->wbase; +#endif + + /* Port dependent thread initialization.*/ + PORT_SETUP_CONTEXT(tp, tcp->wend, tcp->funcp, tcp->arg); + + /* Initialization hook.*/ + NIL_CFG_THREAD_EXT_INIT_HOOK(tp); + + tp++; + tcp++; + } + +#if NIL_CFG_ENABLE_STACK_CHECK + /* The idle thread is a special case because its stack is set up by the + runtime environment.*/ + tp->stklim = THD_IDLE_BASE; +#endif + + /* Runs the highest priority thread, the current one becomes the idle + thread.*/ + nil.current = nil.next = nil.threads; + port_switch(nil.current, tp); + + /* Interrupts enabled for the idle thread.*/ + chSysEnable(); +} + +/** + * @brief Halts the system. + * @details This function is invoked by the operating system when an + * unrecoverable error is detected, for example because a programming + * error in the application code that triggers an assertion while + * in debug mode. + * @note Can be invoked from any system state. + * + * @param[in] reason pointer to an error string + * + * @special + */ +void chSysHalt(const char *reason) { + + port_disable(); + +#if NIL_DBG_ENABLED + nil.dbg_panic_msg = reason; +#else + (void)reason; +#endif + + NIL_CFG_SYSTEM_HALT_HOOK(reason); + + /* Harmless infinite loop.*/ + while (true) { + } +} + +/** + * @brief Time management handler. + * @note This handler has to be invoked by a periodic ISR in order to + * reschedule the waiting threads. + * + * @iclass + */ +void chSysTimerHandlerI(void) { + +#if NIL_CFG_ST_TIMEDELTA == 0 + thread_t *tp = &nil.threads[0]; + nil.systime++; + do { + /* Is the thread in a wait state with timeout?.*/ + if (tp->timeout > (systime_t)0) { + + chDbgAssert(!NIL_THD_IS_READY(tp), "is ready"); + + /* Did the timer reach zero?*/ + if (--tp->timeout == (systime_t)0) { + /* Timeout on semaphores requires a special handling because the + semaphore counter must be incremented.*/ + /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ + if (NIL_THD_IS_WTSEM(tp)) { + tp->u1.semp->cnt++; + } + else if (NIL_THD_IS_SUSP(tp)) { + *tp->u1.trp = NULL; + } + /*lint -restore*/ + (void) chSchReadyI(tp, MSG_TIMEOUT); + } + } + /* Lock released in order to give a preemption chance on those + architectures supporting IRQ preemption.*/ + chSysUnlockFromISR(); + tp++; + chSysLockFromISR(); + } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]); +#else + thread_t *tp = &nil.threads[0]; + systime_t next = (systime_t)0; + + chDbgAssert(nil.nexttime == port_timer_get_alarm(), "time mismatch"); + + do { + /* Is the thread in a wait state with timeout?.*/ + if (tp->timeout > (systime_t)0) { + + chDbgAssert(!NIL_THD_IS_READY(tp), "is ready"); + chDbgAssert(tp->timeout >= (nil.nexttime - nil.lasttime), "skipped one"); + + tp->timeout -= nil.nexttime - nil.lasttime; + if (tp->timeout == (systime_t)0) { + /* Timeout on semaphores requires a special handling because the + semaphore counter must be incremented.*/ + /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ + if (NIL_THD_IS_WTSEM(tp)) { + tp->u1.semp->cnt++; + } + else if (NIL_THD_IS_SUSP(tp)) { + *tp->u1.trp = NULL; + } + /*lint -restore*/ + (void) chSchReadyI(tp, MSG_TIMEOUT); + } + else { + if (tp->timeout <= (systime_t)(next - (systime_t)1)) { + next = tp->timeout; + } + } + } + /* Lock released in order to give a preemption chance on those + architectures supporting IRQ preemption.*/ + chSysUnlockFromISR(); + tp++; + chSysLockFromISR(); + } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]); + nil.lasttime = nil.nexttime; + if (next > (systime_t)0) { + nil.nexttime += next; + port_timer_set_alarm(nil.nexttime); + } + else { + /* No tick event needed.*/ + port_timer_stop_alarm(); + } +#endif +} + +/** + * @brief Unconditionally enters the kernel lock state. + * @note Can be called without previous knowledge of the current lock state. + * The final state is "s-locked". + * + * @special + */ +void chSysUnconditionalLock(void) { + + if (port_irq_enabled(port_get_irq_status())) { + chSysLock(); + } +} + +/** + * @brief Unconditionally leaves the kernel lock state. + * @note Can be called without previous knowledge of the current lock state. + * The final state is "normal". + * + * @special + */ +void chSysUnconditionalUnlock(void) { + + if (!port_irq_enabled(port_get_irq_status())) { + chSysUnlock(); + } +} + +/** + * @brief Returns the execution status and enters a critical zone. + * @details This functions enters into a critical zone and can be called + * from any context. Because its flexibility it is less efficient + * than @p chSysLock() which is preferable when the calling context + * is known. + * @post The system is in a critical zone. + * + * @return The previous system status, the encoding of this + * status word is architecture-dependent and opaque. + * + * @xclass + */ +syssts_t chSysGetStatusAndLockX(void) { + + syssts_t sts = port_get_irq_status(); + if (port_irq_enabled(sts)) { + if (port_is_isr_context()) { + chSysLockFromISR(); + } + else { + chSysLock(); + } + } + return sts; +} + +/** + * @brief Restores the specified execution status and leaves a critical zone. + * @note A call to @p chSchRescheduleS() is automatically performed + * if exiting the critical zone and if not in ISR context. + * + * @param[in] sts the system status to be restored. + * + * @xclass + */ +void chSysRestoreStatusX(syssts_t sts) { + + if (port_irq_enabled(sts)) { + if (port_is_isr_context()) { + chSysUnlockFromISR(); + } + else { + chSchRescheduleS(); + chSysUnlock(); + } + } +} + +#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Realtime window test. + * @details This function verifies if the current realtime counter value + * lies within the specified range or not. The test takes care + * of the realtime counter wrapping to zero on overflow. + * @note When start==end then the function returns always true because the + * whole time range is specified. + * @note This function is only available if the port layer supports the + * option @p PORT_SUPPORTS_RT. + * + * @param[in] cnt the counter value to be tested + * @param[in] start the start of the time window (inclusive) + * @param[in] end the end of the time window (non inclusive) + * @retval true current time within the specified time window. + * @retval false current time not within the specified time window. + * + * @xclass + */ +bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end) { + + return (bool)((cnt - start) < (end - start)); +} + +/** + * @brief Polled delay. + * @note The real delay is always few cycles in excess of the specified + * value. + * @note This function is only available if the port layer supports the + * option @p PORT_SUPPORTS_RT. + * + * @param[in] cycles number of cycles + * + * @xclass + */ +void chSysPolledDelayX(rtcnt_t cycles) { + rtcnt_t start = chSysGetRealtimeCounterX(); + rtcnt_t end = start + cycles; + + while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) { + } +} +#endif /* PORT_SUPPORTS_RT == TRUE */ + +/** + * @brief Makes the specified thread ready for execution. + * + * @param[in] tp pointer to the @p thread_t object + * @param[in] msg the wakeup message + * + * @return The same reference passed as parameter. + */ +thread_t *chSchReadyI(thread_t *tp, msg_t msg) { + + chDbgAssert((tp >= nil.threads) && + (tp < &nil.threads[NIL_CFG_NUM_THREADS]), + "pointer out of range"); + chDbgAssert(!NIL_THD_IS_READY(tp), "already ready"); + chDbgAssert(nil.next <= nil.current, "priority ordering"); + + tp->u1.msg = msg; + tp->state = NIL_STATE_READY; + tp->timeout = (systime_t)0; + if (tp < nil.next) { + nil.next = tp; + } + return tp; +} + +/** + * @brief Reschedules if needed. + * + * @sclass + */ +void chSchRescheduleS(void) { + + if (chSchIsRescRequiredI()) { + thread_t *otp = nil.current; + + nil.current = nil.next; + if (otp == &nil.threads[NIL_CFG_NUM_THREADS]) { + NIL_CFG_IDLE_LEAVE_HOOK(); + } + port_switch(nil.next, otp); + } +} + +/** + * @brief Puts the current thread to sleep into the specified state with + * timeout specification. + * @details The thread goes into a sleeping state, if it is not awakened + * explicitly within the specified system time then it is forcibly + * awakened with a @p NIL_MSG_TMO low level message. + * + * @param[in] newstate the new thread state or a semaphore pointer + * @param[in] timeout the number of ticks before the operation timeouts. + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The wakeup message. + * @retval NIL_MSG_TMO if a timeout occurred. + * + * @sclass + */ +msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) { + thread_t *ntp, *otp = nil.current; + + chDbgAssert(otp != &nil.threads[NIL_CFG_NUM_THREADS], + "idle cannot sleep"); + + /* Storing the wait object for the current thread.*/ + otp->state = newstate; + +#if NIL_CFG_ST_TIMEDELTA > 0 + if (timeout != TIME_INFINITE) { + systime_t abstime; + + /* TIMEDELTA makes sure to have enough time to reprogram the timer + before the free-running timer counter reaches the selected timeout.*/ + if (timeout < (systime_t)NIL_CFG_ST_TIMEDELTA) { + timeout = (systime_t)NIL_CFG_ST_TIMEDELTA; + } + + /* Absolute time of the timeout event.*/ + abstime = chVTGetSystemTimeX() + timeout; + + if (nil.lasttime == nil.nexttime) { + /* Special case, first thread asking for a timeout.*/ + port_timer_start_alarm(abstime); + nil.nexttime = abstime; + } + else { + /* Special case, there are already other threads with a timeout + activated, evaluating the order.*/ + if (chVTIsTimeWithinX(abstime, nil.lasttime, nil.nexttime)) { + port_timer_set_alarm(abstime); + nil.nexttime = abstime; + } + } + + /* Timeout settings.*/ + otp->timeout = abstime - nil.lasttime; + } +#else + + /* Timeout settings.*/ + otp->timeout = timeout; +#endif + + /* Scanning the whole threads array.*/ + ntp = nil.threads; + while (true) { + /* Is this thread ready to execute?*/ + if (NIL_THD_IS_READY(ntp)) { + nil.current = nil.next = ntp; + if (ntp == &nil.threads[NIL_CFG_NUM_THREADS]) { + NIL_CFG_IDLE_ENTER_HOOK(); + } + port_switch(ntp, otp); + return nil.current->u1.msg; + } + + /* Points to the next thread in lowering priority order.*/ + ntp++; + chDbgAssert(ntp <= &nil.threads[NIL_CFG_NUM_THREADS], + "pointer out of range"); + } +} + +/** + * @brief Sends the current thread sleeping and sets a reference variable. + * @note This function must reschedule, it can only be called from thread + * context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The wake up message. + * + * @sclass + */ +msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) { + + chDbgAssert(*trp == NULL, "not NULL"); + + *trp = nil.current; + nil.current->u1.trp = trp; + return chSchGoSleepTimeoutS(NIL_STATE_SUSP, timeout); +} + +/** + * @brief Wakes up a thread waiting on a thread reference object. + * @note This function must not reschedule because it can be called from + * ISR context. + * + * @param[in] trp a pointer to a thread reference object + * @param[in] msg the message code + * + * @iclass + */ +void chThdResumeI(thread_reference_t *trp, msg_t msg) { + + if (*trp != NULL) { + thread_reference_t tr = *trp; + + chDbgAssert(NIL_THD_IS_SUSP(tr), "not suspended"); + + *trp = NULL; + (void) chSchReadyI(tr, msg); + } +} + +/** + * @brief Suspends the invoking thread for the specified time. + * + * @param[in] timeout the delay in system ticks + * + * @api + */ +void chThdSleep(systime_t timeout) { + + chSysLock(); + chThdSleepS(timeout); + chSysUnlock(); +} + +/** + * @brief Suspends the invoking thread until the system time arrives to the + * specified value. + * + * @param[in] abstime absolute system time + * + * @api + */ +void chThdSleepUntil(systime_t abstime) { + + chSysLock(); + chThdSleepUntilS(abstime); + chSysUnlock(); +} + +/** + * @brief Performs a wait operation on a semaphore with timeout specification. + * + * @param[in] sp pointer to a @p semaphore_t structure + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the + * semaphore has been signaled. + * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset(). + * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within + * the specified timeout. + * + * @api + */ +msg_t chSemWaitTimeout(semaphore_t *sp, systime_t timeout) { + msg_t msg; + + chSysLock(); + msg = chSemWaitTimeoutS(sp, timeout); + chSysUnlock(); + + return msg; +} + +/** + * @brief Performs a wait operation on a semaphore with timeout specification. + * + * @param[in] sp pointer to a @p semaphore_t structure + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return A message specifying how the invoking thread has been + * released from the semaphore. + * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the + * semaphore has been signaled. + * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset(). + * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within + * the specified timeout. + * + * @sclass + */ +msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) { + + /* Note, the semaphore counter is a volatile variable so accesses are + manually optimized.*/ + cnt_t cnt = sp->cnt; + if (cnt <= (cnt_t)0) { + if (TIME_IMMEDIATE == timeout) { + return MSG_TIMEOUT; + } + sp->cnt = cnt - (cnt_t)1; + nil.current->u1.semp = sp; + return chSchGoSleepTimeoutS(NIL_STATE_WTSEM, timeout); + } + sp->cnt = cnt - (cnt_t)1; + return MSG_OK; +} + +/** + * @brief Performs a signal operation on a semaphore. + * @post This function does not reschedule so a call to a rescheduling + * function must be performed before unlocking the kernel. Note that + * interrupt handlers always reschedule on exit so an explicit + * reschedule must not be performed in ISRs. + * + * @param[in] sp pointer to a @p semaphore_t structure + * + * @api + */ +void chSemSignal(semaphore_t *sp) { + + chSysLock(); + chSemSignalI(sp); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Performs a signal operation on a semaphore. + * @post This function does not reschedule so a call to a rescheduling + * function must be performed before unlocking the kernel. Note that + * interrupt handlers always reschedule on exit so an explicit + * reschedule must not be performed in ISRs. + * + * @param[in] sp pointer to a @p semaphore_t structure + * + * @iclass + */ +void chSemSignalI(semaphore_t *sp) { + + if (++sp->cnt <= (cnt_t)0) { + thread_reference_t tr = nil.threads; + while (true) { + /* Is this thread waiting on this semaphore?*/ + if (tr->u1.semp == sp) { + + chDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); + + (void) chSchReadyI(tr, MSG_OK); + return; + } + tr++; + + chDbgAssert(tr < &nil.threads[NIL_CFG_NUM_THREADS], + "pointer out of range"); + } + } +} + +/** + * @brief Performs a reset operation on the semaphore. + * @post After invoking this function all the threads waiting on the + * semaphore, if any, are released and the semaphore counter is set + * to the specified, non negative, value. + * @post This function does not reschedule so a call to a rescheduling + * function must be performed before unlocking the kernel. Note that + * interrupt handlers always reschedule on exit so an explicit + * reschedule must not be performed in ISRs. + * + * @param[in] sp pointer to a @p semaphore_t structure + * @param[in] n the new value of the semaphore counter. The value must + * be non-negative. + * + * @api + */ +void chSemReset(semaphore_t *sp, cnt_t n) { + + chSysLock(); + chSemResetI(sp, n); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Performs a reset operation on the semaphore. + * @post After invoking this function all the threads waiting on the + * semaphore, if any, are released and the semaphore counter is set + * to the specified, non negative, value. + * @post This function does not reschedule so a call to a rescheduling + * function must be performed before unlocking the kernel. Note that + * interrupt handlers always reschedule on exit so an explicit + * reschedule must not be performed in ISRs. + * + * @param[in] sp pointer to a @p semaphore_t structure + * @param[in] n the new value of the semaphore counter. The value must + * be non-negative. + * + * @iclass + */ +void chSemResetI(semaphore_t *sp, cnt_t n) { + thread_t *tp; + cnt_t cnt; + + cnt = sp->cnt; + sp->cnt = n; + tp = nil.threads; + while (cnt < (cnt_t)0) { + + chDbgAssert(tp < &nil.threads[NIL_CFG_NUM_THREADS], + "pointer out of range"); + + /* Is this thread waiting on this semaphore?*/ + if (tp->u1.semp == sp) { + + chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting"); + + cnt++; + (void) chSchReadyI(tp, MSG_RESET); + } + tp++; + } +} + +#if (NIL_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Adds a set of event flags directly to the specified @p thread_t. + * + * @param[in] tp the thread to be signaled + * @param[in] mask the event flags set to be ORed + * + * @api + */ +void chEvtSignal(thread_t *tp, eventmask_t mask) { + + chSysLock(); + chEvtSignalI(tp, mask); + chSchRescheduleS(); + chSysUnlock(); +} + +/** + * @brief Adds a set of event flags directly to the specified @p thread_t. + * @post This function does not reschedule so a call to a rescheduling + * function must be performed before unlocking the kernel. Note that + * interrupt handlers always reschedule on exit so an explicit + * reschedule must not be performed in ISRs. + * + * @param[in] tp the thread to be signaled + * @param[in] mask the event flags set to be ORed + * + * @iclass + */ +void chEvtSignalI(thread_t *tp, eventmask_t mask) { + + tp->epmask |= mask; + if (NIL_THD_IS_WTOREVT(tp) && + ((tp->epmask & tp->u1.ewmask) != (eventmask_t)0)) { + (void) chSchReadyI(tp, MSG_OK); + } +} + +/** + * @brief Waits for any of the specified events. + * @details The function waits for any event among those specified in + * @p mask to become pending then the events are cleared and + * returned. + * + * @param[in] mask mask of the event flags that the function should wait + * for, @p ALL_EVENTS enables all the events + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The mask of the served and cleared events. + * @retval 0 if the operation has timed out. + * + * @api + */ +eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t timeout) { + eventmask_t m; + + chSysLock(); + m = chEvtWaitAnyTimeoutS(mask, timeout); + chSysUnlock(); + + return m; +} + +/** + * @brief Waits for any of the specified events. + * @details The function waits for any event among those specified in + * @p mask to become pending then the events are cleared and + * returned. + * + * @param[in] mask mask of the event flags that the function should wait + * for, @p ALL_EVENTS enables all the events + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The mask of the served and cleared events. + * @retval 0 if the operation has timed out. + * + * @sclass + */ +eventmask_t chEvtWaitAnyTimeoutS(eventmask_t mask, systime_t timeout) { + thread_t *ctp = nil.current; + eventmask_t m; + + if ((m = (ctp->epmask & mask)) == (eventmask_t)0) { + if (TIME_IMMEDIATE == timeout) { + chSysUnlock(); + + return (eventmask_t)0; + } + ctp->u1.ewmask = mask; + if (chSchGoSleepTimeoutS(NIL_STATE_WTOREVT, timeout) < MSG_OK) { + chSysUnlock(); + + return (eventmask_t)0; + } + m = ctp->epmask & mask; + } + ctp->epmask &= ~m; + + return m; +} +#endif /* NIL_CFG_USE_EVENTS == TRUE */ + +/** @} */ diff --git a/os/nil/src/nil.c b/os/nil/src/nil.c deleted file mode 100644 index 0db75db37..000000000 --- a/os/nil/src/nil.c +++ /dev/null @@ -1,840 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file nil.c - * @brief Nil RTOS main source file. - * - * @addtogroup NIL_KERNEL - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/** - * @brief System data structures. - */ -nil_system_t nil; - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the kernel. - * @details Initializes the kernel structures, the current instructions flow - * becomes the idle thread upon return. The idle thread must not - * invoke any kernel primitive able to change state to not runnable. - * @note This function assumes that the @p nil global variable has been - * zeroed by the runtime environment. If this is not the case then - * make sure to clear it before calling this function. - * - * @special - */ -void chSysInit(void) { - thread_t *tp; - const thread_config_t *tcp; - - /* Port layer initialization.*/ - port_init(); - - /* System initialization hook.*/ - NIL_CFG_SYSTEM_INIT_HOOK(); - - /* Iterates through the list of defined threads.*/ - tp = &nil.threads[0]; - tcp = nil_thd_configs; - while (tp < &nil.threads[NIL_CFG_NUM_THREADS]) { -#if NIL_CFG_ENABLE_STACK_CHECK - tp->stklim = (stkalign_t *)tcp->wbase; -#endif - - /* Port dependent thread initialization.*/ - PORT_SETUP_CONTEXT(tp, tcp->wend, tcp->funcp, tcp->arg); - - /* Initialization hook.*/ - NIL_CFG_THREAD_EXT_INIT_HOOK(tp); - - tp++; - tcp++; - } - -#if NIL_CFG_ENABLE_STACK_CHECK - /* The idle thread is a special case because its stack is set up by the - runtime environment.*/ - tp->stklim = THD_IDLE_BASE; -#endif - - /* Runs the highest priority thread, the current one becomes the idle - thread.*/ - nil.current = nil.next = nil.threads; - port_switch(nil.current, tp); - - /* Interrupts enabled for the idle thread.*/ - chSysEnable(); -} - -/** - * @brief Halts the system. - * @details This function is invoked by the operating system when an - * unrecoverable error is detected, for example because a programming - * error in the application code that triggers an assertion while - * in debug mode. - * @note Can be invoked from any system state. - * - * @param[in] reason pointer to an error string - * - * @special - */ -void chSysHalt(const char *reason) { - - port_disable(); - -#if NIL_DBG_ENABLED - nil.dbg_panic_msg = reason; -#else - (void)reason; -#endif - - NIL_CFG_SYSTEM_HALT_HOOK(reason); - - /* Harmless infinite loop.*/ - while (true) { - } -} - -/** - * @brief Time management handler. - * @note This handler has to be invoked by a periodic ISR in order to - * reschedule the waiting threads. - * - * @iclass - */ -void chSysTimerHandlerI(void) { - -#if NIL_CFG_ST_TIMEDELTA == 0 - thread_t *tp = &nil.threads[0]; - nil.systime++; - do { - /* Is the thread in a wait state with timeout?.*/ - if (tp->timeout > (systime_t)0) { - - chDbgAssert(!NIL_THD_IS_READY(tp), "is ready"); - - /* Did the timer reach zero?*/ - if (--tp->timeout == (systime_t)0) { - /* Timeout on semaphores requires a special handling because the - semaphore counter must be incremented.*/ - /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ - if (NIL_THD_IS_WTSEM(tp)) { - tp->u1.semp->cnt++; - } - else if (NIL_THD_IS_SUSP(tp)) { - *tp->u1.trp = NULL; - } - /*lint -restore*/ - (void) chSchReadyI(tp, MSG_TIMEOUT); - } - } - /* Lock released in order to give a preemption chance on those - architectures supporting IRQ preemption.*/ - chSysUnlockFromISR(); - tp++; - chSysLockFromISR(); - } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]); -#else - thread_t *tp = &nil.threads[0]; - systime_t next = (systime_t)0; - - chDbgAssert(nil.nexttime == port_timer_get_alarm(), "time mismatch"); - - do { - /* Is the thread in a wait state with timeout?.*/ - if (tp->timeout > (systime_t)0) { - - chDbgAssert(!NIL_THD_IS_READY(tp), "is ready"); - chDbgAssert(tp->timeout >= (nil.nexttime - nil.lasttime), "skipped one"); - - tp->timeout -= nil.nexttime - nil.lasttime; - if (tp->timeout == (systime_t)0) { - /* Timeout on semaphores requires a special handling because the - semaphore counter must be incremented.*/ - /*lint -save -e9013 [15.7] There is no else because it is not needed.*/ - if (NIL_THD_IS_WTSEM(tp)) { - tp->u1.semp->cnt++; - } - else if (NIL_THD_IS_SUSP(tp)) { - *tp->u1.trp = NULL; - } - /*lint -restore*/ - (void) chSchReadyI(tp, MSG_TIMEOUT); - } - else { - if (tp->timeout <= (systime_t)(next - (systime_t)1)) { - next = tp->timeout; - } - } - } - /* Lock released in order to give a preemption chance on those - architectures supporting IRQ preemption.*/ - chSysUnlockFromISR(); - tp++; - chSysLockFromISR(); - } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]); - nil.lasttime = nil.nexttime; - if (next > (systime_t)0) { - nil.nexttime += next; - port_timer_set_alarm(nil.nexttime); - } - else { - /* No tick event needed.*/ - port_timer_stop_alarm(); - } -#endif -} - -/** - * @brief Unconditionally enters the kernel lock state. - * @note Can be called without previous knowledge of the current lock state. - * The final state is "s-locked". - * - * @special - */ -void chSysUnconditionalLock(void) { - - if (port_irq_enabled(port_get_irq_status())) { - chSysLock(); - } -} - -/** - * @brief Unconditionally leaves the kernel lock state. - * @note Can be called without previous knowledge of the current lock state. - * The final state is "normal". - * - * @special - */ -void chSysUnconditionalUnlock(void) { - - if (!port_irq_enabled(port_get_irq_status())) { - chSysUnlock(); - } -} - -/** - * @brief Returns the execution status and enters a critical zone. - * @details This functions enters into a critical zone and can be called - * from any context. Because its flexibility it is less efficient - * than @p chSysLock() which is preferable when the calling context - * is known. - * @post The system is in a critical zone. - * - * @return The previous system status, the encoding of this - * status word is architecture-dependent and opaque. - * - * @xclass - */ -syssts_t chSysGetStatusAndLockX(void) { - - syssts_t sts = port_get_irq_status(); - if (port_irq_enabled(sts)) { - if (port_is_isr_context()) { - chSysLockFromISR(); - } - else { - chSysLock(); - } - } - return sts; -} - -/** - * @brief Restores the specified execution status and leaves a critical zone. - * @note A call to @p chSchRescheduleS() is automatically performed - * if exiting the critical zone and if not in ISR context. - * - * @param[in] sts the system status to be restored. - * - * @xclass - */ -void chSysRestoreStatusX(syssts_t sts) { - - if (port_irq_enabled(sts)) { - if (port_is_isr_context()) { - chSysUnlockFromISR(); - } - else { - chSchRescheduleS(); - chSysUnlock(); - } - } -} - -#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__) -/** - * @brief Realtime window test. - * @details This function verifies if the current realtime counter value - * lies within the specified range or not. The test takes care - * of the realtime counter wrapping to zero on overflow. - * @note When start==end then the function returns always true because the - * whole time range is specified. - * @note This function is only available if the port layer supports the - * option @p PORT_SUPPORTS_RT. - * - * @param[in] cnt the counter value to be tested - * @param[in] start the start of the time window (inclusive) - * @param[in] end the end of the time window (non inclusive) - * @retval true current time within the specified time window. - * @retval false current time not within the specified time window. - * - * @xclass - */ -bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end) { - - return (bool)((cnt - start) < (end - start)); -} - -/** - * @brief Polled delay. - * @note The real delay is always few cycles in excess of the specified - * value. - * @note This function is only available if the port layer supports the - * option @p PORT_SUPPORTS_RT. - * - * @param[in] cycles number of cycles - * - * @xclass - */ -void chSysPolledDelayX(rtcnt_t cycles) { - rtcnt_t start = chSysGetRealtimeCounterX(); - rtcnt_t end = start + cycles; - - while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) { - } -} -#endif /* PORT_SUPPORTS_RT == TRUE */ - -/** - * @brief Makes the specified thread ready for execution. - * - * @param[in] tp pointer to the @p thread_t object - * @param[in] msg the wakeup message - * - * @return The same reference passed as parameter. - */ -thread_t *chSchReadyI(thread_t *tp, msg_t msg) { - - chDbgAssert((tp >= nil.threads) && - (tp < &nil.threads[NIL_CFG_NUM_THREADS]), - "pointer out of range"); - chDbgAssert(!NIL_THD_IS_READY(tp), "already ready"); - chDbgAssert(nil.next <= nil.current, "priority ordering"); - - tp->u1.msg = msg; - tp->state = NIL_STATE_READY; - tp->timeout = (systime_t)0; - if (tp < nil.next) { - nil.next = tp; - } - return tp; -} - -/** - * @brief Reschedules if needed. - * - * @sclass - */ -void chSchRescheduleS(void) { - - if (chSchIsRescRequiredI()) { - thread_t *otp = nil.current; - - nil.current = nil.next; - if (otp == &nil.threads[NIL_CFG_NUM_THREADS]) { - NIL_CFG_IDLE_LEAVE_HOOK(); - } - port_switch(nil.next, otp); - } -} - -/** - * @brief Puts the current thread to sleep into the specified state with - * timeout specification. - * @details The thread goes into a sleeping state, if it is not awakened - * explicitly within the specified system time then it is forcibly - * awakened with a @p NIL_MSG_TMO low level message. - * - * @param[in] newstate the new thread state or a semaphore pointer - * @param[in] timeout the number of ticks before the operation timeouts. - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The wakeup message. - * @retval NIL_MSG_TMO if a timeout occurred. - * - * @sclass - */ -msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout) { - thread_t *ntp, *otp = nil.current; - - chDbgAssert(otp != &nil.threads[NIL_CFG_NUM_THREADS], - "idle cannot sleep"); - - /* Storing the wait object for the current thread.*/ - otp->state = newstate; - -#if NIL_CFG_ST_TIMEDELTA > 0 - if (timeout != TIME_INFINITE) { - systime_t abstime; - - /* TIMEDELTA makes sure to have enough time to reprogram the timer - before the free-running timer counter reaches the selected timeout.*/ - if (timeout < (systime_t)NIL_CFG_ST_TIMEDELTA) { - timeout = (systime_t)NIL_CFG_ST_TIMEDELTA; - } - - /* Absolute time of the timeout event.*/ - abstime = chVTGetSystemTimeX() + timeout; - - if (nil.lasttime == nil.nexttime) { - /* Special case, first thread asking for a timeout.*/ - port_timer_start_alarm(abstime); - nil.nexttime = abstime; - } - else { - /* Special case, there are already other threads with a timeout - activated, evaluating the order.*/ - if (chVTIsTimeWithinX(abstime, nil.lasttime, nil.nexttime)) { - port_timer_set_alarm(abstime); - nil.nexttime = abstime; - } - } - - /* Timeout settings.*/ - otp->timeout = abstime - nil.lasttime; - } -#else - - /* Timeout settings.*/ - otp->timeout = timeout; -#endif - - /* Scanning the whole threads array.*/ - ntp = nil.threads; - while (true) { - /* Is this thread ready to execute?*/ - if (NIL_THD_IS_READY(ntp)) { - nil.current = nil.next = ntp; - if (ntp == &nil.threads[NIL_CFG_NUM_THREADS]) { - NIL_CFG_IDLE_ENTER_HOOK(); - } - port_switch(ntp, otp); - return nil.current->u1.msg; - } - - /* Points to the next thread in lowering priority order.*/ - ntp++; - chDbgAssert(ntp <= &nil.threads[NIL_CFG_NUM_THREADS], - "pointer out of range"); - } -} - -/** - * @brief Sends the current thread sleeping and sets a reference variable. - * @note This function must reschedule, it can only be called from thread - * context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The wake up message. - * - * @sclass - */ -msg_t chThdSuspendTimeoutS(thread_reference_t *trp, systime_t timeout) { - - chDbgAssert(*trp == NULL, "not NULL"); - - *trp = nil.current; - nil.current->u1.trp = trp; - return chSchGoSleepTimeoutS(NIL_STATE_SUSP, timeout); -} - -/** - * @brief Wakes up a thread waiting on a thread reference object. - * @note This function must not reschedule because it can be called from - * ISR context. - * - * @param[in] trp a pointer to a thread reference object - * @param[in] msg the message code - * - * @iclass - */ -void chThdResumeI(thread_reference_t *trp, msg_t msg) { - - if (*trp != NULL) { - thread_reference_t tr = *trp; - - chDbgAssert(NIL_THD_IS_SUSP(tr), "not suspended"); - - *trp = NULL; - (void) chSchReadyI(tr, msg); - } -} - -/** - * @brief Suspends the invoking thread for the specified time. - * - * @param[in] timeout the delay in system ticks - * - * @api - */ -void chThdSleep(systime_t timeout) { - - chSysLock(); - chThdSleepS(timeout); - chSysUnlock(); -} - -/** - * @brief Suspends the invoking thread until the system time arrives to the - * specified value. - * - * @param[in] abstime absolute system time - * - * @api - */ -void chThdSleepUntil(systime_t abstime) { - - chSysLock(); - chThdSleepUntilS(abstime); - chSysUnlock(); -} - -/** - * @brief Performs a wait operation on a semaphore with timeout specification. - * - * @param[in] sp pointer to a @p semaphore_t structure - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return A message specifying how the invoking thread has been - * released from the semaphore. - * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the - * semaphore has been signaled. - * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset(). - * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within - * the specified timeout. - * - * @api - */ -msg_t chSemWaitTimeout(semaphore_t *sp, systime_t timeout) { - msg_t msg; - - chSysLock(); - msg = chSemWaitTimeoutS(sp, timeout); - chSysUnlock(); - - return msg; -} - -/** - * @brief Performs a wait operation on a semaphore with timeout specification. - * - * @param[in] sp pointer to a @p semaphore_t structure - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return A message specifying how the invoking thread has been - * released from the semaphore. - * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the - * semaphore has been signaled. - * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset(). - * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within - * the specified timeout. - * - * @sclass - */ -msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) { - - /* Note, the semaphore counter is a volatile variable so accesses are - manually optimized.*/ - cnt_t cnt = sp->cnt; - if (cnt <= (cnt_t)0) { - if (TIME_IMMEDIATE == timeout) { - return MSG_TIMEOUT; - } - sp->cnt = cnt - (cnt_t)1; - nil.current->u1.semp = sp; - return chSchGoSleepTimeoutS(NIL_STATE_WTSEM, timeout); - } - sp->cnt = cnt - (cnt_t)1; - return MSG_OK; -} - -/** - * @brief Performs a signal operation on a semaphore. - * @post This function does not reschedule so a call to a rescheduling - * function must be performed before unlocking the kernel. Note that - * interrupt handlers always reschedule on exit so an explicit - * reschedule must not be performed in ISRs. - * - * @param[in] sp pointer to a @p semaphore_t structure - * - * @api - */ -void chSemSignal(semaphore_t *sp) { - - chSysLock(); - chSemSignalI(sp); - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Performs a signal operation on a semaphore. - * @post This function does not reschedule so a call to a rescheduling - * function must be performed before unlocking the kernel. Note that - * interrupt handlers always reschedule on exit so an explicit - * reschedule must not be performed in ISRs. - * - * @param[in] sp pointer to a @p semaphore_t structure - * - * @iclass - */ -void chSemSignalI(semaphore_t *sp) { - - if (++sp->cnt <= (cnt_t)0) { - thread_reference_t tr = nil.threads; - while (true) { - /* Is this thread waiting on this semaphore?*/ - if (tr->u1.semp == sp) { - - chDbgAssert(NIL_THD_IS_WTSEM(tr), "not waiting"); - - (void) chSchReadyI(tr, MSG_OK); - return; - } - tr++; - - chDbgAssert(tr < &nil.threads[NIL_CFG_NUM_THREADS], - "pointer out of range"); - } - } -} - -/** - * @brief Performs a reset operation on the semaphore. - * @post After invoking this function all the threads waiting on the - * semaphore, if any, are released and the semaphore counter is set - * to the specified, non negative, value. - * @post This function does not reschedule so a call to a rescheduling - * function must be performed before unlocking the kernel. Note that - * interrupt handlers always reschedule on exit so an explicit - * reschedule must not be performed in ISRs. - * - * @param[in] sp pointer to a @p semaphore_t structure - * @param[in] n the new value of the semaphore counter. The value must - * be non-negative. - * - * @api - */ -void chSemReset(semaphore_t *sp, cnt_t n) { - - chSysLock(); - chSemResetI(sp, n); - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Performs a reset operation on the semaphore. - * @post After invoking this function all the threads waiting on the - * semaphore, if any, are released and the semaphore counter is set - * to the specified, non negative, value. - * @post This function does not reschedule so a call to a rescheduling - * function must be performed before unlocking the kernel. Note that - * interrupt handlers always reschedule on exit so an explicit - * reschedule must not be performed in ISRs. - * - * @param[in] sp pointer to a @p semaphore_t structure - * @param[in] n the new value of the semaphore counter. The value must - * be non-negative. - * - * @iclass - */ -void chSemResetI(semaphore_t *sp, cnt_t n) { - thread_t *tp; - cnt_t cnt; - - cnt = sp->cnt; - sp->cnt = n; - tp = nil.threads; - while (cnt < (cnt_t)0) { - - chDbgAssert(tp < &nil.threads[NIL_CFG_NUM_THREADS], - "pointer out of range"); - - /* Is this thread waiting on this semaphore?*/ - if (tp->u1.semp == sp) { - - chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting"); - - cnt++; - (void) chSchReadyI(tp, MSG_RESET); - } - tp++; - } -} - -#if (NIL_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Adds a set of event flags directly to the specified @p thread_t. - * - * @param[in] tp the thread to be signaled - * @param[in] mask the event flags set to be ORed - * - * @api - */ -void chEvtSignal(thread_t *tp, eventmask_t mask) { - - chSysLock(); - chEvtSignalI(tp, mask); - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Adds a set of event flags directly to the specified @p thread_t. - * @post This function does not reschedule so a call to a rescheduling - * function must be performed before unlocking the kernel. Note that - * interrupt handlers always reschedule on exit so an explicit - * reschedule must not be performed in ISRs. - * - * @param[in] tp the thread to be signaled - * @param[in] mask the event flags set to be ORed - * - * @iclass - */ -void chEvtSignalI(thread_t *tp, eventmask_t mask) { - - tp->epmask |= mask; - if (NIL_THD_IS_WTOREVT(tp) && - ((tp->epmask & tp->u1.ewmask) != (eventmask_t)0)) { - (void) chSchReadyI(tp, MSG_OK); - } -} - -/** - * @brief Waits for any of the specified events. - * @details The function waits for any event among those specified in - * @p mask to become pending then the events are cleared and - * returned. - * - * @param[in] mask mask of the event flags that the function should wait - * for, @p ALL_EVENTS enables all the events - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The mask of the served and cleared events. - * @retval 0 if the operation has timed out. - * - * @api - */ -eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t timeout) { - eventmask_t m; - - chSysLock(); - m = chEvtWaitAnyTimeoutS(mask, timeout); - chSysUnlock(); - - return m; -} - -/** - * @brief Waits for any of the specified events. - * @details The function waits for any event among those specified in - * @p mask to become pending then the events are cleared and - * returned. - * - * @param[in] mask mask of the event flags that the function should wait - * for, @p ALL_EVENTS enables all the events - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The mask of the served and cleared events. - * @retval 0 if the operation has timed out. - * - * @sclass - */ -eventmask_t chEvtWaitAnyTimeoutS(eventmask_t mask, systime_t timeout) { - thread_t *ctp = nil.current; - eventmask_t m; - - if ((m = (ctp->epmask & mask)) == (eventmask_t)0) { - if (TIME_IMMEDIATE == timeout) { - chSysUnlock(); - - return (eventmask_t)0; - } - ctp->u1.ewmask = mask; - if (chSchGoSleepTimeoutS(NIL_STATE_WTOREVT, timeout) < MSG_OK) { - chSysUnlock(); - - return (eventmask_t)0; - } - m = ctp->epmask & mask; - } - ctp->epmask &= ~m; - - return m; -} -#endif /* NIL_CFG_USE_EVENTS == TRUE */ - -/** @} */ diff --git a/os/nil/templates/chconf.h b/os/nil/templates/chconf.h new file mode 100644 index 000000000..234705f7e --- /dev/null +++ b/os/nil/templates/chconf.h @@ -0,0 +1,274 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef _CHCONF_H_ +#define _CHCONF_H_ + +#define _CHIBIOS_NIL_CONF_ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Number of user threads in the application. + * @note This number is not inclusive of the idle thread which is + * Implicitly handled. + */ +#define CH_CFG_NUM_THREADS 3 + +/** @} */ + +/*===========================================================================*/ +/** + * @name System timer settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @note This value together with the @p CH_CFG_ST_RESOLUTION + * option defines the maximum amount of time allowed for + * timeouts. + */ +#define CH_CFG_ST_FREQUENCY 1000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 0 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note Feature not currently implemented. + * @note The default is @p FALSE. + */ +#define CH_CFG_USE_MUTEXES FALSE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note Feature not currently implemented. + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK TRUE + +/** + * @brief Debug option, parameters checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS TRUE + +/** + * @brief System assertions. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS TRUE + +/** + * @brief Stack check. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_STACK_CHECK TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System initialization hook. + */ +#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__) +#define CH_CFG_SYSTEM_INIT_HOOK() { \ +} +#endif + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXT_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + */ +#define CH_CFG_THREAD_EXT_INIT_HOOK(tr) { \ + /* Add custom threads initialization code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ +} + +/** + * @brief System halt hook. + */ +#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ +} +#endif + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in nilcore.h). */ +/*===========================================================================*/ + +#endif /* _CHCONF_H_ */ + +/** @} */ diff --git a/os/nil/templates/nilconf.h b/os/nil/templates/nilconf.h deleted file mode 100644 index c89fd61aa..000000000 --- a/os/nil/templates/nilconf.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/** - * @file nilconf.h - * @brief Configuration file template. - * @details A copy of this file must be placed in each project directory, it - * contains the application specific kernel settings. - * - * @addtogroup NIL_CONFIG - * @details Kernel related settings and hooks. - * @{ - */ - -#ifndef _NILCONF_H_ -#define _NILCONF_H_ - -/*===========================================================================*/ -/** - * @name Kernel parameters and options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Number of user threads in the application. - * @note This number is not inclusive of the idle thread which is - * Implicitly handled. - */ -#define NIL_CFG_NUM_THREADS 1 - -/** @} */ - -/*===========================================================================*/ -/** - * @name System timer settings - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System time counter resolution. - * @note Allowed values are 16 or 32 bits. - */ -#define NIL_CFG_ST_RESOLUTION 32 - -/** - * @brief System tick frequency. - * @note This value together with the @p NIL_CFG_ST_RESOLUTION - * option defines the maximum amount of time allowed for - * timeouts. - */ -#define NIL_CFG_ST_FREQUENCY 50000 - -/** - * @brief Time delta constant for the tick-less mode. - * @note If this value is zero then the system uses the classic - * periodic tick. This value represents the minimum number - * of ticks that is safe to specify in a timeout directive. - * The value one is not valid, timeouts are rounded up to - * this value. - */ -#define NIL_CFG_ST_TIMEDELTA 2 - -/** @} */ - -/*===========================================================================*/ -/** - * @name Subsystem options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Events Flags APIs. - * @details If enabled then the event flags APIs are included in the kernel. - * - * @note The default is @p TRUE. - */ -#define NIL_CFG_USE_EVENTS TRUE - -/** @} */ - -/*===========================================================================*/ -/** - * @name Debug options - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System assertions. - */ -#define NIL_CFG_ENABLE_ASSERTS FALSE - -/** - * @brief Stack check. - */ -#define NIL_CFG_ENABLE_STACK_CHECK FALSE - -/** @} */ - -/*===========================================================================*/ -/** - * @name Kernel hooks - * @{ - */ -/*===========================================================================*/ - -/** - * @brief System initialization hook. - */ -#if !defined(NIL_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_SYSTEM_INIT_HOOK() { \ -} -#endif - -/** - * @brief Threads descriptor structure extension. - * @details User fields added to the end of the @p thread_t structure. - */ -#define NIL_CFG_THREAD_EXT_FIELDS \ - /* Add threads custom fields here.*/ - -/** - * @brief Threads initialization hook. - */ -#define NIL_CFG_THREAD_EXT_INIT_HOOK(tr) { \ - /* Add custom threads initialization code here.*/ \ -} - -/** - * @brief Idle thread enter hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to activate a power saving mode. - */ -#define NIL_CFG_IDLE_ENTER_HOOK() { \ -} - -/** - * @brief Idle thread leave hook. - * @note This hook is invoked within a critical zone, no OS functions - * should be invoked from here. - * @note This macro can be used to deactivate a power saving mode. - */ -#define NIL_CFG_IDLE_LEAVE_HOOK() { \ -} - -/** - * @brief System halt hook. - */ -#if !defined(NIL_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) -#define NIL_CFG_SYSTEM_HALT_HOOK(reason) { \ -} -#endif - -/** @} */ - -/*===========================================================================*/ -/* Port-specific settings (override port settings defaulted in nilcore.h). */ -/*===========================================================================*/ - -#endif /* _NILCONF_H_ */ - -/** @} */ diff --git a/os/nil/templates/nilcore.c b/os/nil/templates/nilcore.c deleted file mode 100644 index 7bbb020fa..000000000 --- a/os/nil/templates/nilcore.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file templates/nilcore.c - * @brief Port code. - * - * @addtogroup NIL_CORE - * @{ - */ - -#include "nil.h" - -/*===========================================================================*/ -/* Module local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module exported functions. */ -/*===========================================================================*/ - -/** @} */ diff --git a/os/nil/templates/nilcore.h b/os/nil/templates/nilcore.h deleted file mode 100644 index 1aad42ddc..000000000 --- a/os/nil/templates/nilcore.h +++ /dev/null @@ -1,379 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file templates/nilcore.h - * @brief Port macros and structures. - * - * @addtogroup NIL_CORE - * @{ - */ - -#ifndef _NILCORE_H_ -#define _NILCORE_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/** - * @name Architecture and Compiler - * @{ - */ -/** - * @brief Macro defining the port architecture. - */ -#define PORT_ARCHITECTURE_XXX - -/** - * @brief Name of the implemented architecture. - */ -#define PORT_ARCHITECTURE_NAME "XXX" - -/** - * @brief Name of the architecture variant. - */ -#define PORT_CORE_VARIANT_NAME "XXXX-Y" - -/** - * @brief Compiler name and version. - */ -#if defined(__GNUC__) || defined(__DOXYGEN__) -#define PORT_COMPILER_NAME "GCC " __VERSION__ - -#else -#error "unsupported compiler" -#endif - -/** - * @brief Port-specific information string. - */ -#define PORT_INFO "port description" - -/** - * @brief This port supports a realtime counter. - */ -#define PORT_SUPPORTS_RT FALSE -/** @} */ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Per-thread stack overhead for interrupts servicing. - * @details This constant is used in the calculation of the correct working - * area size. - */ -#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) -#define PORT_INT_REQUIRED_STACK 32 -#endif - -/** - * @brief Enables an alternative timer implementation. - * @details Usually the port uses a timer interface defined in the file - * @p nilcore_timer.h, if this option is enabled then the file - * @p nilcore_timer_alt.h is included instead. - */ -#if !defined(PORT_USE_ALT_TIMER) -#define PORT_USE_ALT_TIMER FALSE -#endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Type of stack and memory alignment enforcement. - */ -typedef uint64_t stkalign_t; - -/** - * @brief Interrupt saved context. - * @details This structure represents the stack frame saved during a - * preemption-capable interrupt handler. - */ -struct port_extctx { - uint32_t reg1; - uint32_t reg2; -}; - -/** - * @brief System saved context. - * @details This structure represents the inner stack frame during a context - * switch. - */ -struct port_intctx { - uint32_t reg3; - uint32_t reg4; -}; - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/** - * @brief Platform dependent thread stack setup. - * @details This code usually setup the context switching frame represented - * by an @p port_intctx structure. - */ -#define PORT_SETUP_CONTEXT(tp, wend, pf, arg) do { \ - (void)(tp); \ - (void)(wend); \ - (void)(pf); \ - (void)(arg); \ -} while (false) - -/** - * @brief Computes the thread working area global size. - * @note There is no need to perform alignments in this macro. - */ -#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \ - sizeof(struct port_extctx) + \ - (size_t)(n) + \ - (size_t)(PORT_INT_REQUIRED_STACK)) - -/** - * @brief Priority level verification macro. - */ -#define PORT_IRQ_IS_VALID_PRIORITY(n) false - -/** - * @brief Priority level verification macro. - */ -#define PORT_IRQ_IS_VALID_KERNEL_PRIORITY(n) false - -/** - * @brief IRQ prologue code. - * @details This macro must be inserted at the start of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_PROLOGUE() - -/** - * @brief IRQ epilogue code. - * @details This macro must be inserted at the end of all IRQ handlers - * enabled to invoke system APIs. - */ -#define PORT_IRQ_EPILOGUE() _port_irq_epilogue() - -/** - * @brief IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_IRQ_HANDLER(id) void id(void) - -/** - * @brief Fast IRQ handler function declaration. - * @note @p id can be a function name or a vector number depending on the - * port implementation. - */ -#define PORT_FAST_IRQ_HANDLER(id) void id(void) - -/** - * @brief Performs a context switch between two threads. - * @details This is the most critical code in any port, this function - * is responsible for the context switch between 2 threads. - * @note The implementation of this code affects directly the context - * switch performance so optimize here as much as you can. - * - * @param[in] ntp the thread to be switched in - * @param[in] otp the thread to be switched out - */ -#define port_switch(ntp, otp) do { \ - (void)ntp; \ - (void)otp; \ - /*_port_switch(ntp, otp)*/ \ -} while (false) - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -#ifdef __cplusplus -extern "C" { -#endif - void _port_irq_epilogue(void); - void _port_switch(thread_t *ntp, thread_t *otp); - void _port_thread_start(void); -#ifdef __cplusplus -} -#endif - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/* The following code is not processed when the file is included from an - asm module.*/ -#if !defined(_FROM_ASM_) - -/** - * @brief Port-related initialization code. - */ -static inline void port_init(void) { - -} - -/** - * @brief Returns a word encoding the current interrupts status. - * - * @return The interrupts status. - */ -static inline syssts_t port_get_irq_status(void) { - - return (syssts_t)0; -} - -/** - * @brief Checks the interrupt status. - * - * @param[in] sts the interrupt status word - * - * @return The interrupt status. - * @retval false the word specified a disabled interrupts status. - * @retval true the word specified an enabled interrupts status. - */ -static inline bool port_irq_enabled(syssts_t sts) { - - (void)sts; - - return false; -} - -/** - * @brief Determines the current execution context. - * - * @return The execution context. - * @retval false not running in ISR mode. - * @retval true running in ISR mode. - */ -static inline bool port_is_isr_context(void) { - - return false; -} - -/** - * @brief Kernel-lock action. - */ -static inline void port_lock(void) { - -} - -/** - * @brief Kernel-unlock action. - */ -static inline void port_unlock(void) { - -} - -/** - * @brief Kernel-lock action from an interrupt handler. - */ -static inline void port_lock_from_isr(void) { - -} - -/** - * @brief Kernel-unlock action from an interrupt handler. - */ -static inline void port_unlock_from_isr(void) { - -} - -/** - * @brief Disables all the interrupt sources. - */ -static inline void port_disable(void) { - -} - -/** - * @brief Disables the interrupt sources below kernel-level priority. - */ -static inline void port_suspend(void) { - -} - -/** - * @brief Enables all the interrupt sources. - */ -static inline void port_enable(void) { - -} - -/** - * @brief Enters an architecture-dependent IRQ-waiting mode. - * @details The function is meant to return when an interrupt becomes pending. - * The simplest implementation is an empty function or macro but this - * would not take advantage of architecture-specific power saving - * modes. - */ -static inline void port_wait_for_interrupt(void) { - -} - -/** - * @brief Returns the current value of the realtime counter. - * - * @return The realtime counter value. - */ -static inline rtcnt_t port_rt_get_counter_value(void) { - - return (rtcnt_t)0; -} - -#endif /* !defined(_FROM_ASM_) */ - -/*===========================================================================*/ -/* Module late inclusions. */ -/*===========================================================================*/ - -#if !defined(_FROM_ASM_) - -#if NIL_CFG_ST_TIMEDELTA > 0 -#if PORT_USE_ALT_TIMER == FALSE -#include "nilcore_timer.h" -#else -#include "nilcore_timer_alt.h" -#endif -#endif /* NIL_CFG_ST_TIMEDELTA > 0 */ - -#endif /* !defined(_FROM_ASM_) */ - -#endif /* _NILCORE_H_ */ - -/** @} */ diff --git a/os/nil/templates/nilcore_timer.h b/os/nil/templates/nilcore_timer.h deleted file mode 100644 index 6eab4dd40..000000000 --- a/os/nil/templates/nilcore_timer.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file templates/nilcore_timer.h - * @brief System timer header file. - * - * @addtogroup NIL_TIMER - * @{ - */ - -#ifndef _NILCORE_TIMER_H_ -#define _NILCORE_TIMER_H_ - -/*===========================================================================*/ -/* Module constants. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module pre-compile time settings. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module data structures and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module macros. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Module inline functions. */ -/*===========================================================================*/ - -/** - * @brief Starts the alarm. - * @note Makes sure that no spurious alarms are triggered after - * this call. - * - * @param[in] abstime the time to be set for the first alarm - * - * @notapi - */ -static inline void port_timer_start_alarm(systime_t abstime) { - - (void)abstime; -} - -/** - * @brief Stops the alarm interrupt. - * - * @notapi - */ -static inline void port_timer_stop_alarm(void) { - -} - -/** - * @brief Sets the alarm time. - * - * @param[in] abstime the time to be set for the next alarm - * - * @notapi - */ -static inline void port_timer_set_alarm(systime_t abstime) { - - (void)abstime; -} - -/** - * @brief Returns the system time. - * - * @return The system time. - * - * @notapi - */ -static inline systime_t port_timer_get_time(void) { - - return (systime_t)0; -} - -/** - * @brief Returns the current alarm time. - * - * @return The currently set alarm time. - * - * @notapi - */ -static inline systime_t port_timer_get_alarm(void) { - - return (systime_t)0; -} - -#endif /* _NILCORE_TIMER_H_ */ - -/** @} */ diff --git a/os/nil/templates/niltypes.h b/os/nil/templates/niltypes.h deleted file mode 100644 index 16043831b..000000000 --- a/os/nil/templates/niltypes.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - - This file is part of ChibiOS. - - ChibiOS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file templates/niltypes.h - * @brief Port system types. - * - * @addtogroup NIL_TYPES - * @{ - */ - -#ifndef _NILTYPES_H_ -#define _NILTYPES_H_ - -#include -#include -#include - -/** - * @name Common constants - */ -/** - * @brief Generic 'false' boolean constant. - */ -#if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 -#endif - -/** - * @brief Generic 'true' boolean constant. - */ -#if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 -#endif -/** @} */ - -typedef uint32_t syssts_t; /**< System status word. */ -typedef uint32_t rtcnt_t; /**< Realtime counter. */ -typedef uint8_t tstate_t; /**< Thread state. */ -typedef int32_t msg_t; /**< Inter-thread message. */ -typedef uint32_t eventmask_t; /**< Mask of event identifiers. */ -typedef int32_t cnt_t; /**< Generic signed counter. */ -typedef uint32_t ucnt_t; /**< Generic unsigned counter. */ - -/** - * @brief Type of system time. - */ -#if (NIL_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__) -typedef uint32_t systime_t; -#else -typedef uint16_t systime_t; -#endif - -/** - * @brief ROM constant modifier. - * @note It is set to use the "const" keyword in this port. - */ -#define ROMCONST const - -/** - * @brief Makes functions not inlineable. - * @note If the compiler does not support such attribute then the - * realtime counter precision could be degraded. - */ -#define NOINLINE __attribute__((noinline)) - -/** - * @brief Optimized thread function declaration macro. - */ -#define PORT_THD_FUNCTION(tname, arg) \ - __attribute__((noreturn)) void tname(void *arg) - -/** - * @brief Packed variable specifier. - */ -#define PACKED_VAR __attribute__((packed)) - -#endif /* _NILTYPES_H_ */ - -/** @} */ -- cgit v1.2.3