diff --git a/os/nil/ports/ARMCMx/compilers/GCC/mk/port_stm32f0xx.mk b/os/nil/ports/ARMCMx/compilers/GCC/mk/port_stm32f0xx.mk new file mode 100644 index 000000000..6e63c076c --- /dev/null +++ b/os/nil/ports/ARMCMx/compilers/GCC/mk/port_stm32f0xx.mk @@ -0,0 +1,15 @@ +# List of the ChibiOS/NIL Cortex-M0 STM32F0xx port files. +PORTSRC = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/crt0.c \ + $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/vectors.c \ + ${CHIBIOS}/os/nil/ports/ARMCMx/nilcore.c \ + ${CHIBIOS}/os/nil/ports/ARMCMx/nilcore_v6m.c + +PORTASM = $(CHIBIOS)/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s + +PORTINC = ${CHIBIOS}/os/ext/CMSIS/include \ + ${CHIBIOS}/os/ext/CMSIS/ST \ + ${CHIBIOS}/os/common/ports/ARMCMx/devices/STM32F0xx \ + ${CHIBIOS}/os/nil/ports/ARMCMx \ + ${CHIBIOS}/os/nil/ports/ARMCMx/compilers/GCC + +PORTLD = ${CHIBIOS}/os/common/ports/ARMCMx/compilers/GCC/ld diff --git a/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s b/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s new file mode 100644 index 000000000..06f7d7cee --- /dev/null +++ b/os/nil/ports/ARMCMx/compilers/GCC/nilcoreasm_v6m.s @@ -0,0 +1,124 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/GCC/nilcoreasm_v6m.s + * @brief ARMv6-M architecture port low level code. + * + * @addtogroup ARMCMx_CORE + * @{ + */ + +#define _FROM_ASM_ +#include "nilconf.h" +#include "nilcore.h" + +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE 1 +#endif + +#if !defined(__DOXYGEN__) + + + .set CONTEXT_OFFSET, 0 + .set SCB_ICSR, 0xE000ED04 + .set ICSR_PENDSVSET, 0x10000000 + .set ICSR_NMIPENDSET, 0x80000000 + + .cpu cortex-m0 + .fpu softvfp + + .thumb + .text + +/*--------------------------------------------------------------------------* + * Performs a context switch between two threads. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_switch +_port_switch: + push {r4, r5, r6, r7, lr} + mov r4, r8 + mov r5, r9 + mov r6, r10 + mov r7, r11 + push {r4, r5, r6, r7} + mov r3, sp + str r3, [r1, #CONTEXT_OFFSET] + ldr r3, [r0, #CONTEXT_OFFSET] + mov sp, r3 + pop {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov r10, r6 + mov r11, r7 + pop {r4, r5, r6, r7, pc} + +/*--------------------------------------------------------------------------* + * Start a thread by invoking its work function. + * + * Threads execution starts here, the code leaves the system critical zone + * and then jumps into the thread function passed in register R4. The + * register R5 contains the thread parameter. The function chThdExit() is + * called on thread function return. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_thread_start +_port_thread_start: + cpsie i + mov r0, r5 + blx r4 + mov r3, #0 + bl nilSysHalt + +/*--------------------------------------------------------------------------* + * Post-IRQ switch code. + * + * Exception handlers return here for context switching. + *--------------------------------------------------------------------------*/ + .thumb_func + .globl _port_switch_from_isr +_port_switch_from_isr: + bl nilSchRescheduleS + .globl _port_exit_from_isr +_port_exit_from_isr: + ldr r2, .L2 + ldr r3, .L3 + str r3, [r2, #0] +#if CORTEX_ALTERNATE_SWITCH + cpsie i +#endif +.L1: b .L1 + + .align 2 +.L2: .word SCB_ICSR +#if CORTEX_ALTERNATE_SWITCH +.L3: .word ICSR_PENDSVSET +#else +.L3: .word ICSR_NMIPENDSET +#endif + +#endif /* !defined(__DOXYGEN__) */ + +/** @} */ diff --git a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h new file mode 100644 index 000000000..bc33d2e10 --- /dev/null +++ b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h @@ -0,0 +1,85 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/GCC/chtypes.h + * @brief ARM Cortex-Mx port system types. + * + * @addtogroup ARMCMx_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#include +#include +#include + +/** + * @name Common constants + */ +/** + * @brief Generic 'false' boolean constant. + */ +#if !defined(FALSE) || defined(__DOXYGEN__) +#define FALSE 0 +#endif + +/** + * @brief Generic 'true' boolean constant. + */ +#if !defined(TRUE) || defined(__DOXYGEN__) +#define TRUE (!FALSE) +#endif +/** @} */ + +typedef uint32_t systime_t; /**< System time. */ +typedef uint32_t rtcnt_t; /**< Realtime counter. */ +typedef uint64_t rttime_t; /**< Time 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)) + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore.c b/os/nil/ports/ARMCMx/nilcore.c new file mode 100644 index 000000000..c66ce160c --- /dev/null +++ b/os/nil/ports/ARMCMx/nilcore.c @@ -0,0 +1,55 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore.c + * @brief ARM Cortex-Mx port code. + * + * @addtogroup ARMCMx_CORE + * @{ + */ + +#include "ch.h" + +/*===========================================================================*/ +/* Module local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module exported functions. */ +/*===========================================================================*/ + +/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore.h b/os/nil/ports/ARMCMx/nilcore.h new file mode 100644 index 000000000..c2eb68078 --- /dev/null +++ b/os/nil/ports/ARMCMx/nilcore.h @@ -0,0 +1,201 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore.h + * @brief ARM Cortex-Mx port macros and structures. + * + * @addtogroup ARMCMx_CORE + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + +/** + * @name Architecture and Compiler + * @{ + */ +/** + * @brief Macro defining a generic ARM architecture. + */ +#define PORT_ARCHITECTURE_ARM + +/** + * @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 +/** @} */ + +/** + * @name Cortex-M variants + * @{ + */ +#define CORTEX_M0 0 /**< @brief Cortex-M0 variant. */ +#define CORTEX_M0PLUS 1 /**< @brief Cortex-M0+ variant. */ +#define CORTEX_M1 2 /**< @brief Cortex-M1 variant. */ +#define CORTEX_M3 3 /**< @brief Cortex-M3 variant. */ +#define CORTEX_M4 4 /**< @brief Cortex-M4 variant. */ +/** @} */ + +/* Inclusion of the Cortex-Mx implementation specific parameters.*/ +#include "cmparams.h" + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/* + * Inclusion of the appropriate CMSIS header for the selected device. + */ +#if CORTEX_MODEL == CORTEX_M0 +#include "core_cm0.h" +#elif CORTEX_MODEL == CORTEX_M0PLUS +#include "core_cm0plus.h" +#elif CORTEX_MODEL == CORTEX_M3 +#include "core_cm3.h" +#elif CORTEX_MODEL == CORTEX_M4 +#include "core_cm4.h" +#else +#error "unknown or unsupported Cortex-M model" +#endif + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module data structures and types. */ +/*===========================================================================*/ + +/* The following code is not processed when the file is included from an + asm module.*/ +#if !defined(_FROM_ASM_) + +/* 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 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; + +/** + * @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 + * switching. + */ +struct port_intctx {}; +#endif /* defined(__DOXYGEN__) */ + +#endif /* !defined(_FROM_ASM_) */ + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Total priority levels. + */ +#define CORTEX_PRIORITY_LEVELS (1 << 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 0 + +/** + * @brief Priority level verification macro. + */ +#define CORTEX_IS_VALID_PRIORITY(n) \ + (((n) >= 0) && ((n) < CORTEX_PRIORITY_LEVELS)) + +/** + * @brief Priority level verification macro. + */ +#define CORTEX_IS_VALID_KERNEL_PRIORITY(n) \ + (((n) >= CORTEX_MAX_KERNEL_PRIORITY) && ((n) < CORTEX_PRIORITY_LEVELS)) + +/** + * @brief Priority level to priority mask conversion macro. + */ +#define CORTEX_PRIO_MASK(n) \ + ((n) << (8 - CORTEX_PRIORITY_BITS)) + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/* Includes the sub-architecture-specific part.*/ +#if (CORTEX_MODEL == CORTEX_M0) || (CORTEX_MODEL == CORTEX_M0PLUS) || \ + (CORTEX_MODEL == CORTEX_M1) +#include "chcore_v6m.h" +#elif (CORTEX_MODEL == CORTEX_M3) || (CORTEX_MODEL == CORTEX_M4) +#include "chcore_v7m.h" +#endif + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_timer.h b/os/nil/ports/ARMCMx/nilcore_timer.h new file mode 100644 index 000000000..1a0f98ac0 --- /dev/null +++ b/os/nil/ports/ARMCMx/nilcore_timer.h @@ -0,0 +1,135 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore_timer.h + * @brief System timer header file. + * + * @addtogroup ARMCMx_TIMER + * @{ + */ + +#ifndef _CHCORE_TIMER_H_ +#define _CHCORE_TIMER_H_ + +#if defined(CH_PORT_DO_NOT_USE_ST) +/* If, for some reason, the use of the HAL-provided ST timer port interface + is not wanted, it is possible to provide the timer interface into a custom + module.*/ +#include "chcore_timer_ext.h" + +#else /* !defined(CH_PORT_DO_NOT_USE_ST) */ + +/* 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. */ +/*===========================================================================*/ + +/** + * @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 + */ +#define port_timer_start_alarm(time) { \ + chDbgAssert(stIsAlarmActive() == false, "already active"); \ + stStartAlarm(time); \ +} + +/** + * @brief Stops the alarm interrupt. + * + * @notapi + */ +#define port_timer_stop_alarm() { \ + chDbgAssert(stIsAlarmActive() != false, "not active"); \ + stStopAlarm(); \ +} + +/** + * @brief Sets the alarm time. + * + * @param[in] time the time to be set for the next alarm + * + * @notapi + */ +#define port_timer_set_alarm(time) { \ + chDbgAssert(stIsAlarmActive() != false, "not active"); \ + stSetAlarm(time); \ +} + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @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 /* !defined(CH_PORT_DO_NOT_USE_ST) */ + +#endif /* _CHCORE_TIMER_H_ */ + +/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v6m.c b/os/nil/ports/ARMCMx/nilcore_v6m.c new file mode 100644 index 000000000..78e796087 --- /dev/null +++ b/os/nil/ports/ARMCMx/nilcore_v6m.c @@ -0,0 +1,144 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore_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 || defined(__DOXYGEN__) +/** + * @brief NMI vector. + * @details The NMI vector is used for exception mode re-entering after a + * context switch. + */ +void NMI_Handler(void) { + + /* 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 || defined(__DOXYGEN__) +/** + * @brief PendSV vector. + * @details The PendSV vector is used for exception mode re-entering after a + * context switch. + */ +void PendSV_Handler(void) { + + /* 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)0xFFFFFFF1) { + struct port_extctx *ctxp; + + port_lock_from_isr(); + + /* The extctx structure is pointed by the PSP register.*/ + ctxp = (struct 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 = (void *)_port_switch_from_isr; + } + else { + /* Preemption not required, we just need to exit the exception + atomically.*/ + ctxp->pc = (void *)_port_exit_from_isr; + } + + /* Note, returning without unlocking is intentional, this is done in + order to keep the rest of the context switch atomic.*/ + } +} + +/** @} */ diff --git a/os/nil/ports/ARMCMx/nilcore_v6m.h b/os/nil/ports/ARMCMx/nilcore_v6m.h new file mode 100644 index 000000000..846378b65 --- /dev/null +++ b/os/nil/ports/ARMCMx/nilcore_v6m.h @@ -0,0 +1,423 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT 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/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ARMCMx/chcore_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 Architecture and Compiler + * @{ + */ +#if (CORTEX_MODEL == CORTEX_M0) || 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 == CORTEX_M0PLUS) +#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 || defined(__DOXYGEN__) +#define PORT_INFO "Preemption through NMI" +#else +#define PORT_INFO "Preemption through PendSV" +#endif +/** @} */ + +/** + * @brief This port does not support a realtime counter. + */ +#define PORT_SUPPORTS_RT FALSE + +/** + * @brief PendSV priority level. + * @note This priority is enforced to be equal to @p 0, + * this handler always has the highest priority that cannot preempt + * the kernel. + */ +#define CORTEX_PRIORITY_PENDSV 0 + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Stack size for the system idle thread. + * @details This size depends on the idle thread implementation, usually + * the idle thread should take no more space than those reserved + * by @p PORT_INT_REQUIRED_STACK. + * @note In this port it is set to 16 because the idle thread does have + * a stack frame when compiling without optimizations. You may + * reduce this value to zero when compiling with optimizations. + */ +#if !defined(PORT_IDLE_THREAD_STACK_SIZE) +#define PORT_IDLE_THREAD_STACK_SIZE 16 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * @note In this port this value is conservatively set to 32 because the + * function @p chSchDoReschedule() can have a stack frame, especially + * with compiler optimizations disabled. The value can be reduced + * when compiler optimizations are enabled. + */ +#if !defined(PORT_INT_REQUIRED_STACK) +#define PORT_INT_REQUIRED_STACK 32 +#endif + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#if !defined(CORTEX_ENABLE_WFI_IDLE) +#define CORTEX_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief Alternate preemption method. + * @details Activating this option will make the Kernel use the PendSV + * handler for preemption instead of the NMI handler. + */ +#ifndef CORTEX_ALTERNATE_SWITCH +#define CORTEX_ALTERNATE_SWITCH FALSE +#endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** + * @brief Maximum usable priority for normal ISRs. + */ +#if CORTEX_ALTERNATE_SWITCH || 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_) + +/** + * @brief Generic ARM register. + */ +typedef void *regarm_t; + + /* The documentation of the following declarations is in chconf.h in order + to not have duplicated structure names into the documentation.*/ +#if !defined(__DOXYGEN__) + +typedef uint64_t stkalign_t; + +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__) */ + +/** + * @brief Platform dependent part of the @p thread_t structure. + * @details In this port the structure just holds a pointer to the + * @p port_intctx structure representing the stack pointer + * at context switch time. + */ +struct context { + struct port_intctx *r13; +}; + +/*===========================================================================*/ +/* Module macros. */ +/*===========================================================================*/ + +/** + * @brief Platform dependent part of the @p chThdCreateI() API. + * @details This code usually setup the context switching frame represented + * by an @p port_intctx structure. + */ +#define PORT_SETUP_CONTEXT(workspace, wsize, pf, arg) { \ + tp->p_ctx.r13 = (struct port_intctx *)((uint8_t *)workspace + \ + wsize - \ + sizeof(struct port_intctx)); \ + tp->p_ctx.r13->r4 = (regarm_t)(pf); \ + tp->p_ctx.r13->r5 = (regarm_t)(arg); \ + tp->p_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) + \ + (n) + (PORT_INT_REQUIRED_STACK)) + +/** + * @brief IRQ prologue code. + * @details This macro must be inserted at the start of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_PROLOGUE() \ + regarm_t _saved_lr; \ + asm volatile ("mov %0, lr" : "=r" (_saved_lr) : : "memory") + +/** + * @brief IRQ epilogue code. + * @details This macro must be inserted at the end of all IRQ handlers + * enabled to invoke system APIs. + */ +#define PORT_IRQ_EPILOGUE() _port_irq_epilogue(_saved_lr) + +/** + * @brief IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_IRQ_HANDLER(id) void id(void) + +/** + * @brief Fast IRQ handler function declaration. + * @note @p id can be a function name or a vector number depending on the + * port implementation. + */ +#define PORT_FAST_IRQ_HANDLER(id) void id(void) + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#if !CH_DBG_ENABLE_STACK_CHECK || 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->p_stklimit) \ + chSysHalt("stack overflow"); \ + _port_switch(ntp, otp); \ +} +#endif + +#if CH_CFG_TIMEDELTA > 0 +#include "chcore_timer.h" +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void port_halt(void); + void _port_irq_epilogue(regarm_t lr); + void _port_switch_from_isr(void); + void _port_exit_from_isr(void); + void _port_switch(thread_t *ntp, thread_t *otp); + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +/*===========================================================================*/ +/* Module inline functions. */ +/*===========================================================================*/ + +/** + * @brief Port-related initialization code. + */ +static inline void port_init(void) { + + NVIC_SetPriority(PendSV_IRQn, CORTEX_PRIORITY_PENDSV); +} + +/** + * @brief Returns a word encoding the current interrupts status. + * + * @return The interrupts status. + */ +static inline syssts_t port_get_irq_status(void) { + + return __get_PRIMASK(); +} + +/** + * @brief Checks the interrupt status. + * + * @param[in] sts the interrupt status word + * + * @return The interrupt status. + * @retvel false the word specified a disabled interrupts status. + * @retvel true the word specified an enabled interrupts status. + */ +static inline bool port_irq_enabled(syssts_t sts) { + + return (sts & 1) == 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() & 0x1FF) != 0); +} + +/** + * @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 + __WFI; +#endif +} + +#endif /* _FROM_ASM_ */ + +#endif /* _CHCORE_V6M_H_ */ + +/** @} */ diff --git a/os/rt/ports/ARMCMx/chcore_v6m.h b/os/rt/ports/ARMCMx/chcore_v6m.h index b39d019e7..846378b65 100644 --- a/os/rt/ports/ARMCMx/chcore_v6m.h +++ b/os/rt/ports/ARMCMx/chcore_v6m.h @@ -19,7 +19,7 @@ */ /** - * @file GCC/ARMCMx/chcore_v6m.h + * @file ARMCMx/chcore_v6m.h * @brief ARMv6-M architecture port macros and structures. * * @addtogroup ARMCMx_V6M_CORE @@ -213,6 +213,7 @@ struct context { /** * @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) + \ diff --git a/os/rt/ports/ARMCMx/chcore_v7m.h b/os/rt/ports/ARMCMx/chcore_v7m.h index 04d2c0240..f4db6f884 100644 --- a/os/rt/ports/ARMCMx/chcore_v7m.h +++ b/os/rt/ports/ARMCMx/chcore_v7m.h @@ -312,6 +312,7 @@ struct context { /** * @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) + \ diff --git a/os/rt/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s b/os/rt/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s index 7fe77c57f..d8f5601db 100644 --- a/os/rt/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s +++ b/os/rt/ports/ARMCMx/compilers/GCC/chcoreasm_v6m.s @@ -19,8 +19,8 @@ */ /** - * @file ARMCMx/GCC/chcoreasm_v7m.s - * @brief ARMv7-M architecture port low level code. + * @file ARMCMx/GCC/chcoreasm_v6m.s + * @brief ARMv6-M architecture port low level code. * * @addtogroup ARMCMx_CORE * @{