aboutsummaryrefslogtreecommitdiffstats
path: root/os/common/ports/ARMCMx
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2016-02-16 09:59:21 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2016-02-16 09:59:21 +0000
commit641f2c372605cf405f0dda8536b45a78e0e5e2e2 (patch)
treef120afff37ef959b367a6023749700d5b618beff /os/common/ports/ARMCMx
parent5e24a813bef8d7ac5ca79fe9079db0fc2d2bb8b2 (diff)
downloadChibiOS-641f2c372605cf405f0dda8536b45a78e0e5e2e2.tar.gz
ChibiOS-641f2c372605cf405f0dda8536b45a78e0e5e2e2.tar.bz2
ChibiOS-641f2c372605cf405f0dda8536b45a78e0e5e2e2.zip
Tree reorganization.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8899 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/common/ports/ARMCMx')
-rw-r--r--os/common/ports/ARMCMx/chcore.c54
-rw-r--r--os/common/ports/ARMCMx/chcore.h215
-rw-r--r--os/common/ports/ARMCMx/chcore_timer.h124
-rw-r--r--os/common/ports/ARMCMx/chcore_v6m.c147
-rw-r--r--os/common/ports/ARMCMx/chcore_v6m.h440
-rw-r--r--os/common/ports/ARMCMx/chcore_v7m.c168
-rw-r--r--os/common/ports/ARMCMx/chcore_v7m.h698
-rw-r--r--os/common/ports/ARMCMx/cmsis_os/cmsis_os.c554
-rw-r--r--os/common/ports/ARMCMx/cmsis_os/cmsis_os.h520
-rw-r--r--os/common/ports/ARMCMx/cmsis_os/cmsis_os.mk4
-rw-r--r--os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s152
-rw-r--r--os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.s164
-rw-r--r--os/common/ports/ARMCMx/compilers/GCC/chtypes.h103
-rw-r--r--os/common/ports/ARMCMx/compilers/GCC/mk/port_v6m.mk8
-rw-r--r--os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk8
-rw-r--r--os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v6m.s142
-rw-r--r--os/common/ports/ARMCMx/compilers/IAR/chcoreasm_v7m.s150
-rw-r--r--os/common/ports/ARMCMx/compilers/IAR/chtypes.h98
-rw-r--r--os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v6m.s139
-rw-r--r--os/common/ports/ARMCMx/compilers/RVCT/chcoreasm_v7m.s148
-rw-r--r--os/common/ports/ARMCMx/compilers/RVCT/chtypes.h98
-rw-r--r--os/common/ports/ARMCMx/mpu.h208
22 files changed, 4342 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <b>directly</b> 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <b>directly</b> 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 <http://www.gnu.org/licenses/>.
+*/
+/*
+ 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 <string.h>
+
+/*===========================================================================*/
+/* 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 <http://www.gnu.org/licenses/>.
+*/
+/*
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/compilers/GCC/chtypes.h
+ * @brief ARM Cortex-Mx port system types.
+ *
+ * @addtogroup ARMCMx_GCC_CORE
+ * @{
+ */
+
+#ifndef _CHTYPES_H_
+#define _CHTYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/compilers/IAR/chtypes.h
+ * @brief ARM Cortex-Mx port system types.
+ *
+ * @addtogroup ARMCMx_IAR_CORE
+ * @{
+ */
+
+#ifndef _CHTYPES_H_
+#define _CHTYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file ARMCMx/compilers/RVCT/chtypes.h
+ * @brief ARM Cortex-Mx port system types.
+ *
+ * @addtogroup ARMCMx_RVCT_CORE
+ * @{
+ */
+
+#ifndef _CHTYPES_H_
+#define _CHTYPES_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * @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_ */
+
+/** @} */