From 975780704949e2ed551c3e50a81ea5e45d28a0af Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 14 Dec 2010 22:27:09 +0000 Subject: Added working prototype Cortex-Mx port for IAR compiler and related demo for STM32. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2479 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ports/IAR/ARMCMx/STM32/cmparams.h | 56 +++++++ os/ports/IAR/ARMCMx/STM32/vectors.s | 308 +++++++++++++++++++++++++++++++++++ os/ports/IAR/ARMCMx/chcore.c | 45 +++++ os/ports/IAR/ARMCMx/chcore.h | 265 ++++++++++++++++++++++++++++++ os/ports/IAR/ARMCMx/chcore_v6m.c | 146 +++++++++++++++++ os/ports/IAR/ARMCMx/chcore_v6m.h | 260 +++++++++++++++++++++++++++++ os/ports/IAR/ARMCMx/chcore_v7m.c | 46 ++++++ os/ports/IAR/ARMCMx/chcore_v7m.h | 256 +++++++++++++++++++++++++++++ os/ports/IAR/ARMCMx/chcoreasm_v7m.s | 134 +++++++++++++++ os/ports/IAR/ARMCMx/chtypes.h | 80 +++++++++ os/ports/IAR/ARMCMx/cstartup.s | 67 ++++++++ os/ports/IAR/ARMCMx/nvic.c | 75 +++++++++ os/ports/IAR/ARMCMx/nvic.h | 192 ++++++++++++++++++++++ 13 files changed, 1930 insertions(+) create mode 100644 os/ports/IAR/ARMCMx/STM32/cmparams.h create mode 100644 os/ports/IAR/ARMCMx/STM32/vectors.s create mode 100644 os/ports/IAR/ARMCMx/chcore.c create mode 100644 os/ports/IAR/ARMCMx/chcore.h create mode 100644 os/ports/IAR/ARMCMx/chcore_v6m.c create mode 100644 os/ports/IAR/ARMCMx/chcore_v6m.h create mode 100644 os/ports/IAR/ARMCMx/chcore_v7m.c create mode 100644 os/ports/IAR/ARMCMx/chcore_v7m.h create mode 100644 os/ports/IAR/ARMCMx/chcoreasm_v7m.s create mode 100644 os/ports/IAR/ARMCMx/chtypes.h create mode 100644 os/ports/IAR/ARMCMx/cstartup.s create mode 100644 os/ports/IAR/ARMCMx/nvic.c create mode 100644 os/ports/IAR/ARMCMx/nvic.h (limited to 'os') diff --git a/os/ports/IAR/ARMCMx/STM32/cmparams.h b/os/ports/IAR/ARMCMx/STM32/cmparams.h new file mode 100644 index 000000000..de07b7c67 --- /dev/null +++ b/os/ports/IAR/ARMCMx/STM32/cmparams.h @@ -0,0 +1,56 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 STM32/cmparams.h + * @brief ARM Cortex-M3 parameters for the STM32. + * + * @defgroup ARMCMx_STM32 STM32 Specific Parameters + * @ingroup ARMCMx_SPECIFIC + * @details This file contains the Cortex-M3 specific parameters for the + * STM32 platform. + * @{ + */ + +#ifndef _CMPARAMS_H_ +#define _CMPARAMS_H_ + +/** + * @brief Cortex core model. + */ +#define CORTEX_MODEL CORTEX_M3 + +/** + * @brief Systick unit presence. + */ +#define CORTEX_HAS_ST TRUE + +/** + * @brief Memory Protection unit presence. + */ +#define CORTEX_HAS_MPU FALSE + +/** + * @brief Number of bits in priority masks. + */ +#define CORTEX_PRIORITY_BITS 4 + +#endif /* _CMPARAMS_H_ */ + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/STM32/vectors.s b/os/ports/IAR/ARMCMx/STM32/vectors.s new file mode 100644 index 000000000..6e7cf9229 --- /dev/null +++ b/os/ports/IAR/ARMCMx/STM32/vectors.s @@ -0,0 +1,308 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + +#if !defined(STM32F10X_LD) && !defined(STM32F10X_LD_VL) && \ + !defined(STM32F10X_MD) && !defined(STM32F10X_MD_VL) && \ + !defined(STM32F10X_HD) && !defined(STM32F10X_XL) && \ + !defined(STM32F10X_CL) +#include "board.h" +#endif + + MODULE ?vectors + + AAPCS INTERWORK, VFP_COMPATIBLE, RWPI_COMPATIBLE + PRESERVE8 + + SECTION CSTACK:DATA:NOROOT(3) + SECTION .intvec:CODE:NOROOT(2) + + EXTERN __iar_program_start + PUBLIC __vector_table + + DATA + +__vector_table: + DCD SFE(CSTACK) + DCD __iar_program_start + DCD NMIVector + DCD HardFaultVector + DCD MemManageVector + DCD BusFaultVector + DCD UsageFaultVector + DCD Vector1C + DCD Vector20 + DCD Vector24 + DCD Vector28 + DCD SVCallVector + DCD DebugMonitorVector + DCD Vector34 + DCD PendSVVector + DCD SysTickVector + DCD Vector40 + DCD Vector44 + DCD Vector48 + DCD Vector4C + DCD Vector50 + DCD Vector54 + DCD Vector58 + DCD Vector5C + DCD Vector60 + DCD Vector64 + DCD Vector68 + DCD Vector6C + DCD Vector70 + DCD Vector74 + DCD Vector78 + DCD Vector7C + DCD Vector80 + DCD Vector84 + DCD Vector88 + DCD Vector8C + DCD Vector90 + DCD Vector94 + DCD Vector98 + DCD Vector9C + DCD VectorA0 + DCD VectorA4 + DCD VectorA8 + DCD VectorAC + DCD VectorB0 + DCD VectorB4 + DCD VectorB8 + DCD VectorBC + DCD VectorC0 + DCD VectorC4 + DCD VectorC8 + DCD VectorCC + DCD VectorD0 + DCD VectorD4 + DCD VectorD8 + DCD VectorDC + DCD VectorE0 + DCD VectorE4 + DCD VectorE8 +#if defined(STM32F10X_MD_VL) || defined(STM32F10X_HD) || \ + defined(STM32F10X_XL) || defined(STM32F10X_CL) + DCD VectorEC + DCD VectorF0 + DCD VectorF4 +#endif +#if defined(STM32F10X_HD) || defined(STM32F10X_XL) || defined(STM32F10X_CL) + DCD VectorF8 + DCD VectorFC + DCD Vector100 + DCD Vector104 + DCD Vector108 + DCD Vector10C + DCD Vector110 + DCD Vector114 + DCD Vector118 + DCD Vector11C + DCD Vector120 + DCD Vector124 + DCD Vector128 + DCD Vector12C +#endif +#if defined(STM32F10X_CL) + DCD Vector130 + DCD Vector134 + DCD Vector138 + DCD Vector13C + DCD Vector140 + DCD Vector144 + DCD Vector148 + DCD Vector14C +#endif + +/* + * Default interrupt handlers. + */ + PUBWEAK NMIVector + PUBWEAK HardFaultVector + PUBWEAK MemManageVector + PUBWEAK BusFaultVector + PUBWEAK UsageFaultVector + PUBWEAK Vector1C + PUBWEAK Vector20 + PUBWEAK Vector24 + PUBWEAK Vector28 + PUBWEAK SVCallVector + PUBWEAK DebugMonitorVector + PUBWEAK Vector34 + PUBWEAK PendSVVector + PUBWEAK SysTickVector + PUBWEAK Vector40 + PUBWEAK Vector44 + PUBWEAK Vector48 + PUBWEAK Vector4C + PUBWEAK Vector50 + PUBWEAK Vector54 + PUBWEAK Vector58 + PUBWEAK Vector5C + PUBWEAK Vector60 + PUBWEAK Vector64 + PUBWEAK Vector68 + PUBWEAK Vector6C + PUBWEAK Vector70 + PUBWEAK Vector74 + PUBWEAK Vector78 + PUBWEAK Vector7C + PUBWEAK Vector80 + PUBWEAK Vector84 + PUBWEAK Vector88 + PUBWEAK Vector8C + PUBWEAK Vector90 + PUBWEAK Vector94 + PUBWEAK Vector98 + PUBWEAK Vector9C + PUBWEAK VectorA0 + PUBWEAK VectorA4 + PUBWEAK VectorA8 + PUBWEAK VectorAC + PUBWEAK VectorB0 + PUBWEAK VectorB4 + PUBWEAK VectorB8 + PUBWEAK VectorBC + PUBWEAK VectorC0 + PUBWEAK VectorC4 + PUBWEAK VectorC8 + PUBWEAK VectorCC + PUBWEAK VectorD0 + PUBWEAK VectorD4 + PUBWEAK VectorD8 + PUBWEAK VectorDC + PUBWEAK VectorE0 + PUBWEAK VectorE4 + PUBWEAK VectorE8 + PUBWEAK VectorEC + PUBWEAK VectorF0 + PUBWEAK VectorF4 + PUBWEAK VectorF8 + PUBWEAK VectorFC + PUBWEAK Vector100 + PUBWEAK Vector104 + PUBWEAK Vector108 + PUBWEAK Vector10C + PUBWEAK Vector110 + PUBWEAK Vector114 + PUBWEAK Vector118 + PUBWEAK Vector11C + PUBWEAK Vector120 + PUBWEAK Vector124 + PUBWEAK Vector128 + PUBWEAK Vector12C + PUBWEAK Vector130 + PUBWEAK Vector134 + PUBWEAK Vector138 + PUBWEAK Vector13C + PUBWEAK Vector140 + PUBWEAK Vector144 + PUBWEAK Vector148 + PUBWEAK Vector14C + PUBLIC _unhandled_exception + + SECTION .text:CODE:REORDER(1) + THUMB + +NMIVector +HardFaultVector +MemManageVector +BusFaultVector +UsageFaultVector +Vector1C +Vector20 +Vector24 +Vector28 +SVCallVector +DebugMonitorVector +Vector34 +PendSVVector +SysTickVector +Vector40 +Vector44 +Vector48 +Vector4C +Vector50 +Vector54 +Vector58 +Vector5C +Vector60 +Vector64 +Vector68 +Vector6C +Vector70 +Vector74 +Vector78 +Vector7C +Vector80 +Vector84 +Vector88 +Vector8C +Vector90 +Vector94 +Vector98 +Vector9C +VectorA0 +VectorA4 +VectorA8 +VectorAC +VectorB0 +VectorB4 +VectorB8 +VectorBC +VectorC0 +VectorC4 +VectorC8 +VectorCC +VectorD0 +VectorD4 +VectorD8 +VectorDC +VectorE0 +VectorE4 +VectorE8 +VectorEC +VectorF0 +VectorF4 +VectorF8 +VectorFC +Vector100 +Vector104 +Vector108 +Vector10C +Vector110 +Vector114 +Vector118 +Vector11C +Vector120 +Vector124 +Vector128 +Vector12C +Vector130 +Vector134 +Vector138 +Vector13C +Vector140 +Vector144 +Vector148 +Vector14C +_unhandled_exception + b _unhandled_exception + + END diff --git a/os/ports/IAR/ARMCMx/chcore.c b/os/ports/IAR/ARMCMx/chcore.c new file mode 100644 index 000000000..2f2122ae4 --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcore.c @@ -0,0 +1,45 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 IAR/ARMCMx/chcore.c + * @brief ARM Cortex-Mx port code. + * + * @addtogroup IAR_ARMCMx_CORE + * @{ + */ + +#include "ch.h" + +/** + * @brief Halts the system. + * @note The function is declared as a weak symbol, it is possible + * to redefine it in your application code. + */ +#if !defined(__DOXYGEN__) +__weak +#endif +void port_halt(void) { + + port_disable(); + while (TRUE) { + } +} + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore.h b/os/ports/IAR/ARMCMx/chcore.h new file mode 100644 index 000000000..2acba58a8 --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcore.h @@ -0,0 +1,265 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 IAR/ARMCMx/chcore.h + * @brief ARM Cortex-Mx port macros and structures. + * + * @addtogroup IAR_ARMCMx_CORE + * @{ + */ + +#ifndef _CHCORE_H_ +#define _CHCORE_H_ + +#include + +#include "nvic.h" + +/*===========================================================================*/ +/* Port constants. */ +/*===========================================================================*/ + +#define CORTEX_M0 0 /**< @brief Cortex-M0 variant. */ +#define CORTEX_M1 1 /**< @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" + +/* Cortex model check, only M0 and M3 supported right now.*/ +#if (CORTEX_MODEL == CORTEX_M0) || (CORTEX_MODEL == CORTEX_M3) +#elif (CORTEX_MODEL == CORTEX_M1) || (CORTEX_MODEL == CORTEX_M4) +#warning "untested Cortex-M model" +#else +#error "unknown or unsupported Cortex-M model" +#endif + +/*===========================================================================*/ +/* Port statically derived parameters. */ +/*===========================================================================*/ + +/** + * @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 Disabled value for BASEPRI register. + * @note ARMv7-M architecture only. + */ +#define CORTEX_BASEPRI_DISABLED 0 + +/*===========================================================================*/ +/* Port macros. */ +/*===========================================================================*/ + +/** + * @brief Priority level verification macro. + */ +#define CORTEX_IS_VALID_PRIORITY(n) \ + (((n) >= 0) && ((n) < CORTEX_PRIORITY_LEVELS)) + +/** + * @brief Priority level to priority mask conversion macro. + */ +#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS)) + +/*===========================================================================*/ +/* Port configurable parameters. */ +/*===========================================================================*/ + +/** + * @brief Enables the use of the WFI instruction in the idle thread loop. + */ +#ifndef CORTEX_ENABLE_WFI_IDLE +#define CORTEX_ENABLE_WFI_IDLE FALSE +#endif + +/** + * @brief SYSTICK handler priority. + * @note The default SYSTICK handler priority is calculated as the priority + * level in the middle of the numeric priorities range. + */ +#ifndef CORTEX_PRIORITY_SYSTICK +#define CORTEX_PRIORITY_SYSTICK (CORTEX_PRIORITY_LEVELS >> 1) +#else +/* If it is externally redefined then better perform a validity check on it.*/ +#if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SYSTICK) +#error "invalid priority level specified for CORTEX_PRIORITY_SYSTICK" +#endif +#endif + +/** + * @brief SVCALL handler priority. + * @note The default SVCALL handler priority is calculated as + * @p CORTEX_MAXIMUM_PRIORITY+1, in the ARMv7-M port this reserves + * the @p CORTEX_MAXIMUM_PRIORITY priority level as fast interrupts + * priority level. + * @note The SVCALL vector is only used in the ARMv7-M port, it is available + * to user in the ARMv6-M port. + */ +#ifndef CORTEX_PRIORITY_SVCALL +#define CORTEX_PRIORITY_SVCALL (CORTEX_MAXIMUM_PRIORITY + 1) +#else +/* If it is externally redefined then better perform a validity check on it.*/ +#if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_SVCALL) +#error "invalid priority level specified for CORTEX_PRIORITY_SVCALL" +#endif +#endif + +/** + * @brief PENDSV handler priority. + * @note The default PENDSV handler priority is set at the + * @p CORTEX_MINIMUM_PRIORITY priority level. + * @note The PENDSV vector is only used in the ARMv7-M legacy port, it is + * available to user in the ARMv6-M and ARMv7-M ports. + * @note In the ARMv7-M legacy port this value should be not changed from + * the minimum priority level. + */ +#ifndef CORTEX_PRIORITY_PENDSV +#define CORTEX_PRIORITY_PENDSV CORTEX_MINIMUM_PRIORITY +#else +/* If it is externally redefined then better perform a validity check on it.*/ +#if !CORTEX_IS_VALID_PRIORITY(CORTEX_PRIORITY_PENDSV) +#error "invalid priority level specified for CORTEX_PRIORITY_PENDSV" +#endif +#endif + +/** + * @brief BASEPRI level within kernel lock. + * @note This value must not mask the SVCALL priority level or the + * kernel would hard fault. + * @note ARMv7-M architecture only. + */ +#ifndef CORTEX_BASEPRI_KERNEL +#define CORTEX_BASEPRI_KERNEL CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL+1) +#endif + +/*===========================================================================*/ +/* Port exported info. */ +/*===========================================================================*/ + +/** + * @brief Macro defining a generic ARM architecture. + */ +#define CH_ARCHITECTURE_ARM + +#if defined(__DOXYGEN__) +/** + * @brief Macro defining the specific ARM architecture. + */ +#define CH_ARCHITECTURE_ARM_vxm + +/** + * @brief Name of the implemented architecture. + */ +#define CH_ARCHITECTURE_NAME "ARMvx-M" + +/** + * @brief Name of the architecture variant (optional). + */ +#define CH_CORE_VARIANT_NAME "Cortex-Mx" +#elif CORTEX_MODEL == CORTEX_M4 +#define CH_ARCHITECTURE_ARM_v7M +#define CH_ARCHITECTURE_NAME "ARMv7-ME" +#define CH_CORE_VARIANT_NAME "Cortex-M4" +#elif CORTEX_MODEL == CORTEX_M3 +#define CH_ARCHITECTURE_ARM_v7M +#define CH_ARCHITECTURE_NAME "ARMv7-M" +#define CH_CORE_VARIANT_NAME "Cortex-M3" +#elif CORTEX_MODEL == CORTEX_M1 +#define CH_ARCHITECTURE_ARM_v6M +#define CH_ARCHITECTURE_NAME "ARMv6-M" +#define CH_CORE_VARIANT_NAME "Cortex-M1" +#elif CORTEX_MODEL == CORTEX_M0 +#define CH_ARCHITECTURE_ARM_v6M +#define CH_ARCHITECTURE_NAME "ARMv6-M" +#define CH_CORE_VARIANT_NAME "Cortex-M0" +#endif + +/*===========================================================================*/ +/* Port implementation part (common). */ +/*===========================================================================*/ + +/** + * @brief 32 bits stack and memory alignment enforcement. + */ +typedef uint32_t stkalign_t; + +/** + * @brief Generic ARM register. + */ +typedef void *regarm_t; + +#if !defined(__DOXYGEN__) +/** + * @brief Platform dependent part of the @p Thread structure. + * @details In this port the structure just holds a pointer to the @p intctx + * structure representing the stack pointer at context switch time. + */ +struct context { + struct intctx *r13; +}; +#endif + +/** + * @brief Enforces a correct alignment for a stack area size value. + */ +#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1) + +/** + * @brief Computes the thread working area global size. + */ +#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \ + sizeof(struct intctx) + \ + sizeof(struct extctx) + \ + (n) + (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. + */ +#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)] + +/* Includes the architecture-specific implementation part.*/ +#if defined(CH_ARCHITECTURE_ARM_v6M) +#include "chcore_v6m.h" +#elif defined(CH_ARCHITECTURE_ARM_v7M) +#include "chcore_v7m.h" +#endif + +#endif /* _CHCORE_H_ */ + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore_v6m.c b/os/ports/IAR/ARMCMx/chcore_v6m.c new file mode 100644 index 000000000..4f8bdf02a --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcore_v6m.c @@ -0,0 +1,146 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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" + +/** + * @brief PC register temporary storage. + */ +regarm_t _port_saved_pc; + +/** + * @brief IRQ nesting counter. + */ +unsigned _port_irq_nesting; + +/** + * @brief System Timer vector. + * @details This interrupt is used as system tick. + * @note The timer must be initialized in the startup code. + */ +CH_IRQ_HANDLER(SysTickVector) { + + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + chSysTimerHandlerI(); + chSysUnlockFromIsr(); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief Post-IRQ switch code. + * @details On entry the stack and the registers are restored by the exception + * return, the PC value is stored in @p _port_saved_pc, the interrupts + * are disabled. + */ +void _port_switch_from_irq(void) { + /* Note, saves r4 to make space for the PC.*/ + asm ("push {r0, r1, r2, r3, r4} \n\t" + "mrs r0, APSR \n\t" + "mov r1, r12 \n\t" + "push {r0, r1, lr} \n\t" + "ldr r0, =_port_saved_pc \n\t" + "ldr r0, [r0] \n\t" + "add r0, r0, #1 \n\t" + "str r0, [sp, #28]"); + + chSchDoRescheduleI(); + + /* Note, the last registers are restored alone after re-enabling the + interrupts in order to minimize the (very remote and unlikely) + possibility that the stack is filled by continuous and saturating + interrupts that would not allow that last words to be pulled out of + the stack.*/ + asm ("pop {r0, r1, r2} \n\t" + "mov r12, r1 \n\t" + "msr APSR, r0 \n\t" + "mov lr, r2 \n\t" + "cpsie i \n\t" + "pop {r0, r1, r2, r3, pc}"); +} + +#define PUSH_CONTEXT(sp) { \ + asm ("push {r4, r5, r6, r7, lr} \n\t" \ + "mov r4, r8 \n\t" \ + "mov r5, r9 \n\t" \ + "mov r6, r10 \n\t" \ + "mov r7, r11 \n\t" \ + "push {r4, r5, r6, r7}"); \ +} + +#define POP_CONTEXT(sp) { \ + asm ("pop {r4, r5, r6, r7} \n\t" \ + "mov r8, r4 \n\t" \ + "mov r9, r5 \n\t" \ + "mov r10, r6 \n\t" \ + "mov r11, r7 \n\t" \ + "pop {r4, r5, r6, r7, pc}"); \ +} + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +void port_switch(Thread *ntp, Thread *otp) { + + /* Stack overflow check, if enabled.*/ +#if CH_DBG_ENABLE_STACK_CHECK + if ((void *)(r13 - 1) < (void *)(otp + 1)) + asm volatile ("movs r0, #0 \n\t" + "b chDbgPanic"); +#endif /* CH_DBG_ENABLE_STACK_CHECK */ + + PUSH_CONTEXT(r13); + + asm ("str sp, [r1, #12] \n\t" + "ldr sp, [r0, #12]"); + + POP_CONTEXT(r13); +} + +/** + * @brief Start a thread by invoking its work function. + * @details If the work function returns @p chThdExit() is automatically + * invoked. + */ +void _port_thread_start(void) { + + port_unlock(); + asm ("mov r0, r5 \n\t" + "blx r4 \n\t" + "bl chThdExit"); +} + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore_v6m.h b/os/ports/IAR/ARMCMx/chcore_v6m.h new file mode 100644 index 000000000..92a667e3d --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcore_v6m.h @@ -0,0 +1,260 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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_ + +/*===========================================================================*/ +/* Port implementation part. */ +/*===========================================================================*/ + +/** + * @brief Cortex-Mx exception context. + */ +struct cmxctx { + 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 !defined(__DOXYGEN__) +/** + * @brief Interrupt saved context. + * @details This structure represents the stack frame saved during a + * preemption-capable interrupt handler. + */ +struct extctx { + regarm_t xpsr; + regarm_t r12; + regarm_t lr; + regarm_t r0; + regarm_t r1; + regarm_t r2; + regarm_t r3; + regarm_t pc; +}; +#endif + +#if !defined(__DOXYGEN__) +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switching. + */ +struct 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 + +/** + * @brief Platform dependent part of the @p chThdInit() API. + * @details This code usually setup the context switching frame represented + * by an @p intctx structure. + */ +#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ + tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \ + wsize - \ + sizeof(struct intctx)); \ + tp->p_ctx.r13->r4 = (void *)pf; \ + tp->p_ctx.r13->r5 = arg; \ + tp->p_ctx.r13->lr = (void *)_port_thread_start; \ +} + +/** + * @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 INT_REQUIRED_STACK. + * @note In this port it is set to 4 because the idle thread does have + * a stack frame when compiling without optimizations. + */ +#ifndef IDLE_THREAD_STACK_SIZE +#define IDLE_THREAD_STACK_SIZE 4 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * This value can be zero on those architecture where there is a + * separate interrupt stack and the stack space between @p intctx and + * @p extctx is known to be zero. + * @note This port requires some extra stack space for interrupt handling + * representing the frame of the function @p chSchDoRescheduleI(). + */ +#ifndef INT_REQUIRED_STACK +#define INT_REQUIRED_STACK 8 +#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() { \ + port_lock_from_isr(); \ + _port_irq_nesting++; \ + port_unlock_from_isr(); \ +} + +/** + * @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_lock_from_isr(); \ + if ((--_port_irq_nesting == 0) && chSchIsRescRequiredExI()) { \ + register struct cmxctx *ctxp; \ + \ + asm volatile ("mrs %0, PSP" : "=r" (ctxp) : ); \ + _port_saved_pc = ctxp->pc; \ + ctxp->pc = _port_switch_from_irq; \ + return; \ + } \ + port_unlock_from_isr(); \ +} + +/** + * @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 Port-related initialization code. + */ +#define port_init() { \ + _port_irq_nesting = 0; \ + SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \ + NVICSetSystemHandlerPriority(HANDLER_SYSTICK, \ + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \ +} + +/** + * @brief Kernel-lock action. + * @details Usually this function just disables interrupts but may perform + * more actions. + */ +#define port_lock() asm volatile ("cpsid i") + +/** + * @brief Kernel-unlock action. + * @details Usually this function just disables interrupts but may perform + * more actions. + */ +#define port_unlock() asm volatile ("cpsie i") + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details This function is invoked before invoking I-class APIs from + * interrupt handlers. The implementation is architecture dependent, + * in its simplest form it is void. + * @note Same as @p port_lock() in this port. + */ +#define port_lock_from_isr() port_lock() + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details This function is invoked after invoking I-class APIs from interrupt + * handlers. The implementation is architecture dependent, in its + * simplest form it is void. + * @note Same as @p port_lock() in this port. + */ +#define port_unlock_from_isr() port_unlock() + +/** + * @brief Disables all the interrupt sources. + */ +#define port_disable() asm volatile ("cpsid i") + +/** + * @brief Disables the interrupt sources below kernel-level priority. + */ +#define port_suspend() asm volatile ("cpsid i") + +/** + * @brief Enables all the interrupt sources. + */ +#define port_enable() asm volatile ("cpsie i") + +/** + * @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. + */ +#if CORTEX_ENABLE_WFI_IDLE || defined(__DOXYGEN__) +#define port_wait_for_interrupt() asm volatile ("wfi") +#else +#define port_wait_for_interrupt() +#endif + +#if !defined(__DOXYGEN__) +extern regarm_t _port_saved_pc; +extern unsigned _port_irq_nesting; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void port_halt(void); + void port_switch(Thread *ntp, Thread *otp); + void _port_switch_from_irq(void); + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +#endif /* _CHCORE_V6M_H_ */ + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore_v7m.c b/os/ports/IAR/ARMCMx/chcore_v7m.c new file mode 100644 index 000000000..fe267b9e9 --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcore_v7m.c @@ -0,0 +1,46 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 IAR/ARMCMx/chcore_v7m.c + * @brief ARMv7-M architecture port code. + * + * @addtogroup IAR_ARMCMx_V7M_CORE + * @{ + */ + +#include "ch.h" + +/** + * @brief System Timer vector. + * @details This interrupt is used as system tick. + * @note The timer must be initialized in the startup code. + */ +CH_IRQ_HANDLER(SysTickVector) { + + CH_IRQ_PROLOGUE(); + + chSysLockFromIsr(); + chSysTimerHandlerI(); + chSysUnlockFromIsr(); + + CH_IRQ_EPILOGUE(); +} + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/chcore_v7m.h b/os/ports/IAR/ARMCMx/chcore_v7m.h new file mode 100644 index 000000000..aa00a8afd --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcore_v7m.h @@ -0,0 +1,256 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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_v7m.h + * @brief ARMv7-M architecture port macros and structures. + * + * @addtogroup ARMCMx_V7M_CORE + * @{ + */ + +#ifndef _CHCORE_V7M_H_ +#define _CHCORE_V7M_H_ + +/*===========================================================================*/ +/* Port implementation part. */ +/*===========================================================================*/ + +#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 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; +}; +#endif + +#if !defined(__DOXYGEN__) +/** + * @brief System saved context. + * @details This structure represents the inner stack frame during a context + * switching. + */ +struct intctx { + regarm_t r4; + regarm_t r5; + regarm_t r6; +#ifndef CH_CURRP_REGISTER_CACHE + regarm_t r7; +#endif + regarm_t r8; + regarm_t r9; + regarm_t r10; + regarm_t r11; + regarm_t lr; +}; +#endif + +/** + * @brief Platform dependent part of the @p chThdInit() API. + * @details This code usually setup the context switching frame represented + * by an @p intctx structure. + */ +#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \ + tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \ + wsize - \ + sizeof(struct intctx)); \ + tp->p_ctx.r13->r4 = (void *)pf; \ + tp->p_ctx.r13->r5 = arg; \ + tp->p_ctx.r13->lr = (void *)_port_thread_start; \ +} + +/** + * @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 INT_REQUIRED_STACK. + * @note In this port it is set to 4 because the idle thread does have + * a stack frame when compiling without optimizations. + */ +#ifndef IDLE_THREAD_STACK_SIZE +#define IDLE_THREAD_STACK_SIZE 4 +#endif + +/** + * @brief Per-thread stack overhead for interrupts servicing. + * @details This constant is used in the calculation of the correct working + * area size. + * This value can be zero on those architecture where there is a + * separate interrupt stack and the stack space between @p intctx and + * @p extctx is known to be zero. + * @note This port requires no extra stack space for interrupt handling. + */ +#ifndef INT_REQUIRED_STACK +#define INT_REQUIRED_STACK 0 +#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 Port-related initialization code. + */ +#define port_init() { \ + SCB_AIRCR = AIRCR_VECTKEY | AIRCR_PRIGROUP(0); \ + NVICSetSystemHandlerPriority(HANDLER_SVCALL, \ + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL)); \ + NVICSetSystemHandlerPriority(HANDLER_SYSTICK, \ + CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SYSTICK)); \ +} + +/** + * @brief Kernel-lock action. + * @details Usually this function just disables interrupts but may perform + * more actions. + * @note In this port this it raises the base priority to kernel level. + */ +#define port_lock() __set_BASEPRI(CORTEX_BASEPRI_KERNEL) + +/** + * @brief Kernel-unlock action. + * @details Usually this function just disables interrupts but may perform + * more actions. + * @note In this port this it lowers the base priority to user level. + */ +#define port_unlock() __set_BASEPRI(CORTEX_BASEPRI_DISABLED) + +/** + * @brief Kernel-lock action from an interrupt handler. + * @details This function is invoked before invoking I-class APIs from + * interrupt handlers. The implementation is architecture dependent, + * in its simplest form it is void. + * @note Same as @p port_lock() in this port. + */ +#define port_lock_from_isr() port_lock() + +/** + * @brief Kernel-unlock action from an interrupt handler. + * @details This function is invoked after invoking I-class APIs from interrupt + * handlers. The implementation is architecture dependent, in its + * simplest form it is void. + * @note Same as @p port_unlock() in this port. + */ +#define port_unlock_from_isr() port_unlock() + +/** + * @brief Disables all the interrupt sources. + * @note Of course non maskable interrupt sources are not included. + * @note In this port it disables all the interrupt sources by raising + * the priority mask to level 0. + */ +#define port_disable() __disable_interrupt() + +/** + * @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. + */ +#define port_suspend() { \ + __set_BASEPRI(CORTEX_BASEPRI_KERNEL); \ + __enable_interrupt(); \ +} + +/** + * @brief Enables all the interrupt sources. + * @note In this port it lowers the base priority to user level. + */ +#define port_enable() { \ + __set_BASEPRI(CORTEX_BASEPRI_DISABLED); \ + __enable_interrupt(); \ +} + +/** + * @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. + */ +#if CORTEX_ENABLE_WFI_IDLE || defined(__DOXYGEN__) +#define port_wait_for_interrupt() +#else +#define port_wait_for_interrupt() +#endif + +/** + * @brief Performs a context switch between two threads. + * @details This is the most critical code in any port, this function + * is responsible for the context switch between 2 threads. + * @note The implementation of this code affects directly the context + * switch performance so optimize here as much as you can. + * + * @param[in] ntp the thread to be switched in + * @param[in] otp the thread to be switched out + */ +#define port_switch(ntp, otp) _port_switch(ntp, otp) + +#ifdef __cplusplus +extern "C" { +#endif + void port_halt(void); + void _port_switch(Thread *ntp, Thread *otp); + void _port_irq_epilogue(void); + void _port_switch_from_isr(void); + void _port_thread_start(void); +#ifdef __cplusplus +} +#endif + +#endif /* _CHCORE_V7M_H_ */ + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/chcoreasm_v7m.s b/os/ports/IAR/ARMCMx/chcoreasm_v7m.s new file mode 100644 index 000000000..cfb35f3cc --- /dev/null +++ b/os/ports/IAR/ARMCMx/chcoreasm_v7m.s @@ -0,0 +1,134 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 . +*/ + + MODULE ?chcoreasm_v7m + + AAPCS INTERWORK, VFP_COMPATIBLE + PRESERVE8 + +/* + * Imports the Cortex-Mx parameters header and performs the same calculations + * done in chcore.h. + */ +#include "cmparams.h" + +#define CORTEX_PRIORITY_MASK(n) ((n) << (8 - CORTEX_PRIORITY_BITS)) + +#ifndef CORTEX_PRIORITY_SVCALL +#define CORTEX_PRIORITY_SVCALL 1 +#endif + +#ifndef CORTEX_BASEPRI_KERNEL +#define CORTEX_BASEPRI_KERNEL CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL+1) +#endif + +#define CORTEX_BASEPRI_DISABLED 0 + +EXTCTX_SIZE SET 32 +CONTEXT_OFFSET SET 12 +SCB_ICSR SET 0xE000ED04 +ICSR_RETTOBASE SET 0x00000800 + + SECTION .text:CODE:NOROOT(2) + + EXTERN chThdExit + EXTERN chSchIsRescRequiredExI + EXTERN chSchDoRescheduleI + + THUMB + +/* + * Performs a context switch between two threads. + */ + PUBLIC _port_switch +_port_switch: + push {r4, r5, r6, r7, r8, r9, r10, r11, lr} + str sp, [r1, #CONTEXT_OFFSET] + ldr sp, [r0, #CONTEXT_OFFSET] + 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: + movs r3, #CORTEX_BASEPRI_DISABLED + msr BASEPRI, r3 + mov r0, r5 + blx r4 + bl chThdExit + +/* + * Post-IRQ switch code. + * Exception handlers return here for context switching. + */ + PUBLIC _port_switch_from_isr +_port_switch_from_isr: + bl chSchDoRescheduleI + svc #0 + +/* + * Reschedule verification and setup after an IRQ. + */ + PUBLIC _port_irq_epilogue +_port_irq_epilogue: + movs r3, #CORTEX_BASEPRI_KERNEL + msr BASEPRI, r3 + mov r3, #LWRD SCB_ICSR + movt r3, #HWRD SCB_ICSR + ldr r3, [r3, #0] + tst r3, #ICSR_RETTOBASE + bne .L7 + movs r3, #CORTEX_BASEPRI_DISABLED + msr BASEPRI, r3 + bx lr +.L7: + push {r3, lr} + bl chSchIsRescRequiredExI + cmp r0, #0 + beq .L4 + mrs r3, PSP + subs r3, r3, #EXTCTX_SIZE + msr PSP, r3 + ldr r2, =_port_switch_from_isr + str r2, [r3, #24] + mov r2, #0x01000000 + str r2, [r3, #28] + pop {r3, pc} +.L4: + movs r3, #CORTEX_BASEPRI_DISABLED + msr BASEPRI, r3 + pop {r3, pc} + +/* + * SVC vector. + * Discarding the current exception context and positioning the stack to + * point to the real one. + */ + PUBLIC SVCallVector +SVCallVector: + mrs r3, PSP + adds r3, r3, #EXTCTX_SIZE + msr PSP, r3 + movs r3, #CORTEX_BASEPRI_DISABLED + msr BASEPRI, r3 + bx lr + + END diff --git a/os/ports/IAR/ARMCMx/chtypes.h b/os/ports/IAR/ARMCMx/chtypes.h new file mode 100644 index 000000000..4020b95b5 --- /dev/null +++ b/os/ports/IAR/ARMCMx/chtypes.h @@ -0,0 +1,80 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 IAR/ARMCMx/chtypes.h + * @brief ARM Cortex-Mx port system types. + * + * @addtogroup IAR_ARMCMx_CORE + * @{ + */ + +#ifndef _CHTYPES_H_ +#define _CHTYPES_H_ + +#define __need_NULL +#define __need_size_t +#define __need_ptrdiff_t +#include + +#include + +typedef int32_t bool_t; /**< Fast boolean type. */ +typedef uint8_t tmode_t; /**< Thread flags. */ +typedef uint8_t tstate_t; /**< Thread state. */ +typedef uint8_t trefs_t; /**< Thread references counter. */ +typedef uint32_t tprio_t; /**< Thread priority. */ +typedef int32_t msg_t; /**< Inter-thread message. */ +typedef int32_t eventid_t; /**< Event Id. */ +typedef uint32_t eventmask_t; /**< Events mask. */ +typedef uint32_t systime_t; /**< System time. */ +typedef int32_t cnt_t; /**< Resources counter. */ + +/** + * @brief Inline function modifier. + */ +#define INLINE inline + +/** + * @brief ROM constant modifier. + * @note It is set to use the "const" keyword in this port. + */ +#define ROMCONST const + +/** + * @brief Packed structure modifier (within). + * @note It uses the "packed" GCC attribute. + */ +#define PACK_STRUCT_STRUCT __attribute__((packed)) + +/** + * @brief Packed structure modifier (before). + * @note Empty in this port. + */ +#define PACK_STRUCT_BEGIN + +/** + * @brief Packed structure modifier (after). + * @note Empty in this port. + */ +#define PACK_STRUCT_END + +#endif /* _CHTYPES_H_ */ + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/cstartup.s b/os/ports/IAR/ARMCMx/cstartup.s new file mode 100644 index 000000000..97757362a --- /dev/null +++ b/os/ports/IAR/ARMCMx/cstartup.s @@ -0,0 +1,67 @@ +/************************************************** + * + * Part one of the system initialization code, contains low-level + * initialization, plain thumb variant. + * + * Copyright 2008 IAR Systems. All rights reserved. + * + * $Revision: 34775 $ + * + **************************************************/ + +; +; The modules in this file are included in the libraries, and may be replaced +; by any user-defined modules that define the PUBLIC symbol _program_start or +; a user defined start symbol. +; To override the cstartup defined in the library, simply add your modified +; version to the workbench project. +; +; The vector table is normally located at address 0. +; When debugging in RAM, it can be located in RAM, aligned to at least 2^6. +; The name "__vector_table" has special meaning for C-SPY: +; it is where the SP start value is found, and the NVIC vector +; table register (VTOR) is initialized to this address if != 0. +; +; Cortex-M version +; + + MODULE ?cstartup + +CONTROL_MODE_PRIVILEGED SET 0 +CONTROL_MODE_UNPRIVILEGED SET 1 +CONTROL_USE_MSP SET 0 +CONTROL_USE_PSP SET 2 + + AAPCS INTERWORK, VFP_COMPATIBLE, ROPI + PRESERVE8 + + SECTION PSTACK:DATA:NOROOT(3) + SECTION .intvec:CODE:NOROOT(3) + + PUBLIC __iar_program_start + EXTERN __cmain + EXTERN __vector_table + EXTWEAK __iar_init_core + EXTWEAK __iar_init_vfp + + SECTION .text:CODE:REORDER(2) + THUMB +__iar_program_start: + cpsid i + ldr r0, =sfe(PSTACK) + msr PSP, r0 + movs r0, #CONTROL_MODE_PRIVILEGED | CONTROL_USE_PSP + msr CONTROL, r0 + isb + bl hwinit0 + bl __iar_init_core + bl __iar_init_vfp + bl __cmain + + PUBWEAK hwinit0 +hwinit0 + bx lr + + REQUIRE __vector_table + + END diff --git a/os/ports/IAR/ARMCMx/nvic.c b/os/ports/IAR/ARMCMx/nvic.c new file mode 100644 index 000000000..93dbd6ba4 --- /dev/null +++ b/os/ports/IAR/ARMCMx/nvic.c @@ -0,0 +1,75 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 IAR/ARMCMx/nvic.c + * @brief Cortex-Mx NVIC support code. + * + * @addtogroup IAR_ARMCMx_NVIC + * @{ + */ + +#include "ch.h" +#include "nvic.h" + +/** + * @brief Sets the priority of an interrupt handler and enables it. + * + * @param n the interrupt number + * @param prio the interrupt priority mask + * + * @note The parameters are not tested for correctness. + */ +void NVICEnableVector(uint32_t n, uint32_t prio) { + unsigned sh = (n & 3) << 3; + + NVIC_IPR(n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh); + NVIC_ICPR(n >> 5) = 1 << (n & 0x1F); + NVIC_ISER(n >> 5) = 1 << (n & 0x1F); +} + +/** + * @brief Disables an interrupt handler. + * + * @param n the interrupt number + * + * @note The parameters are not tested for correctness. + */ +void NVICDisableVector(uint32_t n) { + unsigned sh = (n & 3) << 3; + + NVIC_ICER(n >> 5) = 1 << (n & 0x1F); + NVIC_IPR(n >> 2) = NVIC_IPR(n >> 2) & ~(0xFF << sh); +} + +/** + * @brief Changes the priority of a system handler. + * + * @param handler the system handler number + * @param prio the system handler priority mask + * @note The parameters are not tested for correctness. + */ +void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio) { + unsigned sh = (handler & 3) * 8; + + SCB_SHPR(handler >> 2) = (SCB_SHPR(handler >> 2) & + ~(0xFF << sh)) | (prio << sh); +} + +/** @} */ diff --git a/os/ports/IAR/ARMCMx/nvic.h b/os/ports/IAR/ARMCMx/nvic.h new file mode 100644 index 000000000..321a0ed7b --- /dev/null +++ b/os/ports/IAR/ARMCMx/nvic.h @@ -0,0 +1,192 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 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 IAR/ARMCMx/nvic.h + * @brief Cortex-Mx NVIC support macros and structures. + * + * @addtogroup IAR_ARMCMx_NVIC + * @{ + */ + +#ifndef _NVIC_H_ +#define _NVIC_H_ + +/* + * System vector constants for @p NVICSetSystemHandlerPriority(). + */ +#define HANDLER_MEM_MANAGE 0 /**< MEM MANAGE vector id. */ +#define HANDLER_BUS_FAULT 1 /**< BUS FAULT vector id. */ +#define HANDLER_USAGE_FAULT 2 /**< USAGE FAULT vector id. */ +#define HANDLER_RESERVED_3 3 +#define HANDLER_RESERVED_4 4 +#define HANDLER_RESERVED_5 5 +#define HANDLER_RESERVED_6 6 +#define HANDLER_SVCALL 7 /**< SVCALL vector id. */ +#define HANDLER_DEBUG_MONITOR 8 /**< DEBUG MONITOR vector id. */ +#define HANDLER_RESERVED_9 9 +#define HANDLER_PENDSV 10 /**< PENDSV vector id. */ +#define HANDLER_SYSTICK 11 /**< SYS TCK vector id. */ + +typedef volatile uint8_t IOREG8; /**< 8 bits I/O register type. */ +typedef volatile uint32_t IOREG32; /**< 32 bits I/O register type. */ + +/** + * @brief NVIC ITCR register. + */ +#define NVIC_ITCR (*((IOREG32 *)0xE000E004)) + +/** + * @brief NVIC STIR register. + */ +#define NVIC_STIR (*((IOREG32 *)0xE000EF00)) + +/** + * @brief Structure representing the SYSTICK I/O space. + */ +typedef struct { + IOREG32 CSR; + IOREG32 RVR; + IOREG32 CVR; + IOREG32 CBVR; +} CM3_ST; + +/** + * @brief SYSTICK peripheral base address. + */ +#define STBase ((CM3_ST *)0xE000E010) +#define ST_CSR (STBase->CSR) +#define ST_RVR (STBase->RVR) +#define ST_CVR (STBase->CVR) +#define ST_CBVR (STBase->CBVR) + +#define CSR_ENABLE_MASK (0x1 << 0) +#define ENABLE_OFF_BITS (0 << 0) +#define ENABLE_ON_BITS (1 << 0) +#define CSR_TICKINT_MASK (0x1 << 1) +#define TICKINT_DISABLED_BITS (0 << 1) +#define TICKINT_ENABLED_BITS (1 << 1) +#define CSR_CLKSOURCE_MASK (0x1 << 2) +#define CLKSOURCE_EXT_BITS (0 << 2) +#define CLKSOURCE_CORE_BITS (1 << 2) +#define CSR_COUNTFLAG_MASK (0x1 << 16) + +#define RVR_RELOAD_MASK (0xFFFFFF << 0) + +#define CVR_CURRENT_MASK (0xFFFFFF << 0) + +#define CBVR_TENMS_MASK (0xFFFFFF << 0) +#define CBVR_SKEW_MASK (0x1 << 30) +#define CBVR_NOREF_MASK (0x1 << 31) + +/** + * @brief Structure representing the NVIC I/O space. + */ +typedef struct { + IOREG32 ISER[8]; + IOREG32 unused1[24]; + IOREG32 ICER[8]; + IOREG32 unused2[24]; + IOREG32 ISPR[8]; + IOREG32 unused3[24]; + IOREG32 ICPR[8]; + IOREG32 unused4[24]; + IOREG32 IABR[8]; + IOREG32 unused5[56]; + IOREG32 IPR[60]; +} CM3_NVIC; + +/** + * @brief NVIC peripheral base address. + */ +#define NVICBase ((CM3_NVIC *)0xE000E100) +#define NVIC_ISER(n) (NVICBase->ISER[n]) +#define NVIC_ICER(n) (NVICBase->ICER[n]) +#define NVIC_ISPR(n) (NVICBase->ISPR[n]) +#define NVIC_ICPR(n) (NVICBase->ICPR[n]) +#define NVIC_IABR(n) (NVICBase->IABR[n]) +#define NVIC_IPR(n) (NVICBase->IPR[n]) + +/** + * @brief Structure representing the System Control Block I/O space. + */ +typedef struct { + IOREG32 CPUID; + IOREG32 ICSR; + IOREG32 VTOR; + IOREG32 AIRCR; + IOREG32 SCR; + IOREG32 CCR; + IOREG32 SHPR[3]; + IOREG32 SHCSR; + IOREG32 CFSR; + IOREG32 HFSR; + IOREG32 DFSR; + IOREG32 MMFAR; + IOREG32 BFAR; + IOREG32 AFSR; +} CM3_SCB; + +/** + * @brief SCB peripheral base address. + */ +#define SCBBase ((CM3_SCB *)0xE000ED00) +#define SCB_CPUID (SCBBase->CPUID) +#define SCB_ICSR (SCBBase->ICSR) +#define SCB_VTOR (SCBBase->VTOR) +#define SCB_AIRCR (SCBBase->AIRCR) +#define SCB_SCR (SCBBase->SCR) +#define SCB_CCR (SCBBase->CCR) +#define SCB_SHPR(n) (SCBBase->SHPR[n]) +#define SCB_SHCSR (SCBBase->SHCSR) +#define SCB_CFSR (SCBBase->CFSR) +#define SCB_HFSR (SCBBase->HFSR) +#define SCB_DFSR (SCBBase->DFSR) +#define SCB_MMFAR (SCBBase->MMFAR) +#define SCB_BFAR (SCBBase->BFAR) +#define SCB_AFSR (SCBBase->AFSR) + +#define ICSR_VECTACTIVE_MASK (0x1FF << 0) +#define ICSR_RETTOBASE (0x1 << 11) +#define ICSR_VECTPENDING_MASK (0x1FF << 12) +#define ICSR_ISRPENDING (0x1 << 22) +#define ICSR_ISRPREEMPT (0x1 << 23) +#define ICSR_PENDSTCLR (0x1 << 25) +#define ICSR_PENDSTSET (0x1 << 26) +#define ICSR_PENDSVCLR (0x1 << 27) +#define ICSR_PENDSVSET (0x1 << 28) +#define ICSR_NMIPENDSET (0x1 << 31) + +#define AIRCR_VECTKEY 0x05FA0000 +#define AIRCR_PRIGROUP_MASK (0x7 << 8) +#define AIRCR_PRIGROUP(n) ((n) << 8) + +#ifdef __cplusplus +extern "C" { +#endif + void NVICEnableVector(uint32_t n, uint32_t prio); + void NVICDisableVector(uint32_t n); + void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio); +#ifdef __cplusplus +} +#endif + +#endif /* _NVIC_H_ */ + +/** @} */ -- cgit v1.2.3