diff options
Diffstat (limited to 'os')
| -rw-r--r-- | os/ports/GCC/ARMCM3/chcore.h | 8 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/LPC11xx/port.mk | 5 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/STM32F10x/port.mk | 1 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/chcore.c | 155 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/chcore.h | 375 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/chcore_v6m.c | 152 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/chcore_v6m.h | 271 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/chcore_v7m.c | 178 | ||||
| -rw-r--r-- | os/ports/GCC/ARMCMx/chcore_v7m.h | 313 | 
9 files changed, 965 insertions, 493 deletions
diff --git a/os/ports/GCC/ARMCM3/chcore.h b/os/ports/GCC/ARMCM3/chcore.h index b844fbffb..ac8ab021b 100644 --- a/os/ports/GCC/ARMCM3/chcore.h +++ b/os/ports/GCC/ARMCM3/chcore.h @@ -34,13 +34,6 @@  /* Port constants.                                                           */
  /*===========================================================================*/
 -/**
 - * @brief   Port implementing a exception mode context switching.
 - * @details This macro can be used to differentiate this port from the other
 - *          Cortex-Mx port which defines @p CORTEX_PORT_MODE_EXOSWITCH.
 - */
 -#define CORTEX_PORT_MODE_ENDOSWITCH
 -
  #define CORTEX_M0               0       /**< @brief Cortex-M0 variant.      */
  #define CORTEX_M1               1       /**< @brief Cortex-M1 variant.      */
  #define CORTEX_M3               3       /**< @brief Cortex-M3 variant.      */
 @@ -55,7 +48,6 @@  #error "unknown or unsupported Cortex-M model"
  #endif
 -
  /*===========================================================================*/
  /* Port derived parameters.                                                  */
  /*===========================================================================*/
 diff --git a/os/ports/GCC/ARMCMx/LPC11xx/port.mk b/os/ports/GCC/ARMCMx/LPC11xx/port.mk index dfbb01b16..3935b9195 100644 --- a/os/ports/GCC/ARMCMx/LPC11xx/port.mk +++ b/os/ports/GCC/ARMCMx/LPC11xx/port.mk @@ -1,7 +1,8 @@  # List of the ChibiOS/RT Cortex-M0 LPC111x port files.
  PORTSRC = ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \
 -          ${CHIBIOS}/os/ports/GCC/ARMCMx/nvic.c
 -#          ${CHIBIOS}/os/ports/GCC/ARMCMx/cmsis/core_cm0.c
 +          ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v6m.c \
 +          ${CHIBIOS}/os/ports/GCC/ARMCMx/nvic.c \
 +          ${CHIBIOS}/os/ports/GCC/ARMCMx/cmsis/core_cm0.c
  PORTASM = ${CHIBIOS}/os/ports/GCC/ARMCMx/crt0.s
 diff --git a/os/ports/GCC/ARMCMx/STM32F10x/port.mk b/os/ports/GCC/ARMCMx/STM32F10x/port.mk index 739f031f8..02cbe871a 100644 --- a/os/ports/GCC/ARMCMx/STM32F10x/port.mk +++ b/os/ports/GCC/ARMCMx/STM32F10x/port.mk @@ -1,5 +1,6 @@  # List of the ChibiOS/RT Cortex-M3 STM32 port files.
  PORTSRC = ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore.c \
 +          ${CHIBIOS}/os/ports/GCC/ARMCMx/chcore_v7m.c \
            ${CHIBIOS}/os/ports/GCC/ARMCMx/nvic.c \
            ${CHIBIOS}/os/ports/GCC/ARMCMx/cmsis/core_cm3.c
 diff --git a/os/ports/GCC/ARMCMx/chcore.c b/os/ports/GCC/ARMCMx/chcore.c index 908f0b5a6..24a9d7f7a 100644 --- a/os/ports/GCC/ARMCMx/chcore.c +++ b/os/ports/GCC/ARMCMx/chcore.c @@ -26,17 +26,6 @@   */
  #include "ch.h"
 -#include "nvic.h"
 -
 -/**
 - * @brief   PC register temporary storage.
 - */
 -regarm_t _port_saved_pc;
 -
 -/**
 - * @brief	IRQ nesting counter. - */
 -unsigned _port_irq_nesting;
  /**
   * @brief   Halts the system.
 @@ -53,148 +42,4 @@ void port_halt(void) {    }
  }
 -/**
 - * @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.
 - */
 -#if !defined(__DOXYGEN__)
 -__attribute__((naked))
 -#endif
 -void _port_switch_from_irq(void) {
 -  /* Note, saves r4 to make space for the PC.*/
 -#if defined(CH_ARCHITECTURE_ARM_v6M)
 -  asm volatile ("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]");
 -#elif defined(CH_ARCHITECTURE_ARM_v7M)
 -  asm volatile ("push    {r0, r1, r2, r3, r4}                   \n\t"   \
 -                "mrs     r0, APSR                               \n\t"   \
 -                "push    {r0, r12, 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]");
 -#endif
 -
 -  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.*/
 -#if defined(CH_ARCHITECTURE_ARM_v6M)
 -  asm volatile ("pop     {r0, r1, r2}                           \n\t"   \
 -                "mov     r12, r1                                \n\t"   \
 -                "msr     APSR, r0                               \n\t"   \
 -                "mov     lr, r2");
 -#elif defined(CH_ARCHITECTURE_ARM_v7M)
 -  asm volatile ("pop     {r0, r12, lr}                          \n\t"   \
 -                "msr     APSR, r0");
 -#endif
 -#if CORTEX_USE_BASEPRI
 -  asm volatile ("mov     r0, #0                                 \n\t"   \
 -                "msr     BASEPRI, r0");
 -#else /* !CORTEX_USE_BASEPRI */
 -  asm volatile ("cpsie   i");
 -#endif /* !CORTEX_USE_BASEPRI */
 -  asm volatile ("pop     {r0, r1, r2, r3, pc}");
 -}
 -
 -#if defined(CH_ARCHITECTURE_ARM_v6M)
 -#define PUSH_CONTEXT(sp) {                                              \
 -  asm volatile ("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 volatile ("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}" :  : "r" (sp));          \
 -}
 -#elif defined(CH_ARCHITECTURE_ARM_v7M)
 -#define PUSH_CONTEXT(sp) {                                              \
 -  asm volatile ("push    {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t"); \
 -}
 -
 -#define POP_CONTEXT(sp) {                                               \
 -  asm volatile ("pop     {r4, r5, r6, r7, r8, r9, r10, r11, pc} \n\t"   \
 -                :  : "r" (sp));                                         \
 -}
 -#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 <b>directly</b> the context
 - *          switch performance so optimize here as much as you can.
 - *
 - * @param[in] ntp       the thread to be switched in
 - * @param[in] otp       the thread to be switched out
 - */
 -#if !defined(__DOXYGEN__)
 -__attribute__((naked))
 -#endif
 -void port_switch(Thread *ntp, Thread *otp) {
 -  register struct intctx *r13 asm ("r13");
 -
 -  /* 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);
 -
 -  otp->p_ctx.r13 = r13;
 -  r13 = ntp->p_ctx.r13;
 -
 -  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 volatile ("mov     r0, r5                                 \n\t"   \
 -                "blx     r4                                     \n\t"   \
 -                "bl      chThdExit");
 -}
 -
  /** @} */
 diff --git a/os/ports/GCC/ARMCMx/chcore.h b/os/ports/GCC/ARMCMx/chcore.h index e627fcf8f..5d45b00fd 100644 --- a/os/ports/GCC/ARMCMx/chcore.h +++ b/os/ports/GCC/ARMCMx/chcore.h @@ -34,13 +34,6 @@  /* Port constants.                                                           */
  /*===========================================================================*/
 -/**
 - * @brief   Port implementing a process mode context switching.
 - * @details This macro can be used to differentiate this port from the other
 - *          Cortex-Mx port which defines @p CORTEX_PORT_MODE_ENDOSWITCH.
 - */
 -#define CORTEX_PORT_MODE_EXOSWITCH
 -
  #define CORTEX_M0               0       /**< @brief Cortex-M0 variant.      */
  #define CORTEX_M1               1       /**< @brief Cortex-M1 variant.      */
  #define CORTEX_M3               3       /**< @brief Cortex-M3 variant.      */
 @@ -62,16 +55,6 @@  /*===========================================================================*/
  /**
 - * @brief   Priority masking support.
 - */
 -#if (CORTEX_MODEL == CORTEX_M3) || (CORTEX_MODEL == CORTEX_M4) ||           \
 -    defined(__DOXYGEN__)
 -#define CORTEX_SUPPORTS_BASEPRI TRUE
 -#else
 -#define CORTEX_SUPPORTS_BASEPRI FALSE
 -#endif
 -
 -/**
   * @brief   Total priority levels.
   */
  #define CORTEX_PRIORITY_LEVELS  (1 << CORTEX_PRIORITY_BITS)
 @@ -89,6 +72,11 @@   */
  #define CORTEX_MAXIMUM_PRIORITY 0
 +/**
 + * @brief   Disabled value for BASEPRI register. + */
 +#define CORTEX_BASEPRI_DISABLED 0
 +
  /*===========================================================================*/
  /* Port macros.                                                              */
  /*===========================================================================*/
 @@ -117,8 +105,8 @@  /**
   * @brief   SYSTICK handler priority.
 - * @note    The default priority is calculated as the priority level in
 - *          the middle of the numeric priorities range.
 + * @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)
 @@ -130,44 +118,48 @@  #endif
  /**
 - * @brief   Priority masking support.
 - * @details The ARMv7-M architecture is capable to mask only interrupt
 - *          priorities below or equal to a certain specified priority
 - *          mask. If this option is enabled all the priorities above
 - *          @p CORTEX_BASEPRI_KERNEL (lower numeric values) are not
 - *          affected by the kernel locks and can operate with minimum
 - *          latency.<br>
 - *          This option makes the kernel code a bit larger and slower, if
 - *          your application does not need fast interrups it is recommended
 - *          to keep this option disabled.
 + * @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.
   */
 -#if CORTEX_SUPPORTS_BASEPRI || defined(__DOXYGEN__)
 -#if !defined(CORTEX_USE_BASEPRI) || defined(__DOXYGEN__)
 -#define CORTEX_USE_BASEPRI      FALSE
 -#endif /* !defined(CORTEX_USE_BASEPRI) */
 -#else /* !CORTEX_SUPPORTS_BASEPRI */
 -#if defined(CORTEX_USE_BASEPRI) && CORTEX_USE_BASEPRI
 -#error "BASEPRI priority masking register not supported in this architecture"
 +#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    In the ARMv7-M port this value should be not changed from the
 + *          minimum priority level.
 + * @note    The PENDSV vector is only used in the ARMv7-M port, it is available
 + *          to user in the ARMv6-M port.
 + */
 +#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
 -#define CORTEX_USE_BASEPRI      FALSE
 -#endif /* !CORTEX_SUPPORTS_BASEPRI */
 -#if CORTEX_USE_BASEPRI || defined(__DOXYGEN__)
  /**
   * @brief   BASEPRI level within kernel lock.
 - * @details Priority levels higher than this one (lower numeric values) are
 - *          unaffected by kernel locks and can be classified as fast
 - *          interrupt sources, see @ref interrupt_classes.
 - * @note    This constant is defined only if the @p CORTEX_USE_BASEPRI port
 - *          option is enabled.
 - * @note    The default setting reserves just the highest priority level
 - *          (@p CORTEX_MAXIMUM_PRIORITY) for fast interrupts, you may redefine
 - *          this setting in order to reserve more levels.
 + * @note    This value must not mask the SVCALL priority level.
   */
  #ifndef CORTEX_BASEPRI_KERNEL
 -#define CORTEX_BASEPRI_KERNEL   CORTEX_PRIORITY_MASK(CORTEX_MAXIMUM_PRIORITY+1)
 +#define CORTEX_BASEPRI_KERNEL   CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_SVCALL+1)
  #endif
 -#endif /* CORTEX_USE_BASEPRI */
  /*===========================================================================*/
  /* Port exported info.                                                       */
 @@ -225,294 +217,21 @@ typedef uint32_t stkalign_t;   */
  typedef void *regarm_t;
 -/**
 - * @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.
 - */
 -#if defined(CH_ARCHITECTURE_ARM_v6M)
 -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;
 -};
 -#elif defined(CH_ARCHITECTURE_ARM_v7M)
 -struct intctx {
 -  regarm_t      r4;
 -  regarm_t      r5;
 -  regarm_t      r6;
 -  regarm_t      r7;
 -  regarm_t      r8;
 -  regarm_t      r9;
 -  regarm_t      r10;
 -  regarm_t      r11;
 -  regarm_t      lr;
 -};
 -#endif
 -#endif
 -
  #if !defined(__DOXYGEN__)
  /**
   * @brief   Platform dependent part of the @p Thread structure.
 - * @details In the Cortex-Mx port this structure just holds a pointer to the
 - *          @p intctx structure representing the stack pointer at the time
 - *          of the context switch.
 + * @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   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 = pf;                                                   \
 -  tp->p_ctx.r13->r5 = arg;                                                  \
 -  tp->p_ctx.r13->lr = _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   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)];
 -
 -/**
 - * @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() {                                               \
 -  chSysLockFromIsr();                                                       \
 -  _port_irq_nesting++;                                                      \
 -  chSysUnlockFromIsr();                                                     \
 -}
 -
 -/**
 - * @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() {                                               \
 -  chSysLockFromIsr();                                                       \
 -  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;                                                                 \
 -  }                                                                         \
 -  chSysUnlockFromIsr();                                                     \
 -}
 -
 -/**
 - * @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   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.
 - */
 -#if CORTEX_USE_BASEPRI
 -#define port_lock() {                                                       \
 -  register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL;                 \
 -  asm volatile ("msr     BASEPRI, %0" : : "r" (tmp));                       \
 -}
 -#else /* !CORTEX_USE_BASEPRI */
 -#define port_lock() asm volatile ("cpsid   i")
 -#endif /* !CORTEX_USE_BASEPRI */
 -
 -/**
 - * @brief   Kernel-unlock action.
 - * @details Usually this function just disables interrupts but may perform
 - *          more actions.
 - */
 -#if CORTEX_USE_BASEPRI
 -#define port_unlock() {                                                     \
 -  register uint32_t tmp asm ("r3") = 0;                                     \
 -  asm volatile ("msr     BASEPRI, %0" : : "r" (tmp));                       \
 -}
 -#else /* !CORTEX_USE_BASEPRI */
 -#define port_unlock() asm volatile ("cpsie   i")
 -#endif /* !CORTEX_USE_BASEPRI */
 -
 -/**
 - * @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.
 - */
 -#if CORTEX_USE_BASEPRI
 -#define port_suspend() {                                                    \
 -  register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL;                 \
 -  asm volatile ("msr     BASEPRI, %0                    \n\t"               \
 -                "cpsie   i" : : "r" (tmp));                                 \
 -}
 -#else /* !CORTEX_USE_BASEPRI */
 -#define port_suspend() asm volatile ("cpsid   i")
 -#endif /* !CORTEX_USE_BASEPRI */
 -
 -/**
 - * @brief   Enables all the interrupt sources.
 - */
 -#if CORTEX_USE_BASEPRI
 -#define port_enable() {                                                     \
 -  register uint32_t tmp asm ("r3") = 0;                                     \
 -  asm volatile ("msr     BASEPRI, %0                    \n\t"               \
 -                "cpsie   i" : : "r" (tmp));                                 \
 -}
 -#else /* !CORTEX_USE_BASEPRI */
 -#define port_enable() asm volatile ("cpsie   i")
 -#endif /* !CORTEX_USE_BASEPRI */
 -
 -/**
 - * @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
 -}
 +#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/GCC/ARMCMx/chcore_v6m.c b/os/ports/GCC/ARMCMx/chcore_v6m.c new file mode 100644 index 000000000..8f8a0a100 --- /dev/null +++ b/os/ports/GCC/ARMCMx/chcore_v6m.c @@ -0,0 +1,152 @@ +/*
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @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.
 + */
 +#if !defined(__DOXYGEN__)
 +__attribute__((naked))
 +#endif
 +void _port_switch_from_irq(void) {
 +  /* Note, saves r4 to make space for the PC.*/
 +  asm volatile ("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 volatile ("pop     {r0, r1, r2}                           \n\t"   \
 +                "mov     r12, r1                                \n\t"   \
 +                "msr     APSR, r0                               \n\t"   \
 +                "mov     lr, r2                                 \n\t"   \
 +                "pop     {r0, r1, r2, r3, pc}");
 +}
 +
 +#define PUSH_CONTEXT(sp) {                                              \
 +  asm volatile ("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 volatile ("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}" :  : "r" (sp));          \
 +}
 +
 +/**
 + * @brief   Performs a context switch between two threads.
 + * @details This is the most critical code in any port, this function
 + *          is responsible for the context switch between 2 threads.
 + * @note    The implementation of this code affects <b>directly</b> the context
 + *          switch performance so optimize here as much as you can.
 + *
 + * @param[in] ntp       the thread to be switched in
 + * @param[in] otp       the thread to be switched out
 + */
 +#if !defined(__DOXYGEN__)
 +__attribute__((naked))
 +#endif
 +void port_switch(Thread *ntp, Thread *otp) {
 +  register struct intctx *r13 asm ("r13");
 +
 +  /* 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);
 +
 +  otp->p_ctx.r13 = r13;
 +  r13 = ntp->p_ctx.r13;
 +
 +  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 volatile ("mov     r0, r5                                 \n\t"   \
 +                "blx     r4                                     \n\t"   \
 +                "bl      chThdExit");
 +}
 +
 +/** @} */
 diff --git a/os/ports/GCC/ARMCMx/chcore_v6m.h b/os/ports/GCC/ARMCMx/chcore_v6m.h new file mode 100644 index 000000000..7aff774bc --- /dev/null +++ b/os/ports/GCC/ARMCMx/chcore_v6m.h @@ -0,0 +1,271 @@ +/*
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @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 = pf;                                                   \
 +  tp->p_ctx.r13->r5 = arg;                                                  \
 +  tp->p_ctx.r13->lr = _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   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)];
 +
 +/**
 + * @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() {                                               \
 +  chSysLockFromIsr();                                                       \
 +  _port_irq_nesting++;                                                      \
 +  chSysUnlockFromIsr();                                                     \
 +}
 +
 +/**
 + * @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() {                                               \
 +  chSysLockFromIsr();                                                       \
 +  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;                                                                 \
 +  }                                                                         \
 +  chSysUnlockFromIsr();                                                     \
 +}
 +
 +/**
 + * @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   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/GCC/ARMCMx/chcore_v7m.c b/os/ports/GCC/ARMCMx/chcore_v7m.c new file mode 100644 index 000000000..e5df0d296 --- /dev/null +++ b/os/ports/GCC/ARMCMx/chcore_v7m.c @@ -0,0 +1,178 @@ +/*
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @file    ARMCMx/chcore_v7m.c
 + * @brief   ARMv7-M architecture port code.
 + *
 + * @addtogroup ARMCMx_V7M_CORE
 + * @{
 + */
 +
 +#include "ch.h"
 +
 +#if !CH_OPTIMIZE_SPEED
 +void _port_lock(void) {
 +  register uint32_t tmp asm ("r3") = BASEPRI_KERNEL;
 +  asm volatile ("msr     BASEPRI, %0" : : "r" (tmp));
 +}
 +
 +void _port_unlock(void) {
 +  register uint32_t tmp asm ("r3") = BASEPRI_USER;
 +  asm volatile ("msr     BASEPRI, %0" : : "r" (tmp));
 +}
 +#endif
 +
 +/**
 + * @brief   System Timer vector.
 + * @details This interrupt is used as system tick.
 + * @note    The timer must be initialized in the startup code.
 + */
 +void SysTickVector(void) {
 +
 +  chSysLockFromIsr();
 +  chSysTimerHandlerI();
 +  if (chSchIsRescRequiredExI())
 +    SCB_ICSR = ICSR_PENDSVSET;
 +  chSysUnlockFromIsr();
 +}
 +
 +#if CORTEX_MODEL == CORTEX_M0
 +#define PUSH_CONTEXT(sp, prio) {                                        \
 +  asm volatile ("mrs     %0, PSP                                \n\t"   \
 +                "sub     %0, %0, #40                            \n\t"   \
 +                "stmia   %0!, {r3-r7}                           \n\t"   \
 +                "sub     %0, %0, #20                            \n\t"   \
 +                "mov     r3, r8                                 \n\t"   \
 +                "str     r3, [%0, #20]                          \n\t"   \
 +                "mov     r3, r9                                 \n\t"   \
 +                "str     r3, [%0, #24]                          \n\t"   \
 +                "mov     r3, r10                                \n\t"   \
 +                "str     r3, [%0, #28]                          \n\t"   \
 +                "mov     r3, r11                                \n\t"   \
 +                "str     r3, [%0, #32]                          \n\t"   \
 +                "mov     r3, lr                                 \n\t"   \
 +                "str     r3, [%0, #36]                          \n\t"   \
 +                : "=r" (sp) : "r" (sp), "r" (prio));                    \
 +}
 +
 +#define POP_CONTEXT(sp) {                                               \
 +  asm volatile ("ldr     r3, [%0, #20]                          \n\t"   \
 +                "mov     r8, r3                                 \n\t"   \
 +                "ldr     r3, [%0, #24]                          \n\t"   \
 +                "mov     r9, r3                                 \n\t"   \
 +                "ldr     r3, [%0, #28]                          \n\t"   \
 +                "mov     r10, r3                                \n\t"   \
 +                "ldr     r3, [%0, #32]                          \n\t"   \
 +                "mov     r11, r3                                \n\t"   \
 +                "ldr     r3, [%0, #36]                          \n\t"   \
 +                "mov     lr, r3                                 \n\t"   \
 +                "ldmia   %0!, {r3-r7}                           \n\t"   \
 +                "add     %0, %0, #20                            \n\t"   \
 +                "msr     PSP, %0                                \n\t"   \
 +                "msr     BASEPRI, r3                            \n\t"   \
 +                "bx      lr" : "=r" (sp) : "r" (sp));                   \
 +}
 +#else /* CORTEX_MODEL != CORTEX_M0 */
 +#if !defined(CH_CURRP_REGISTER_CACHE)
 +#define PUSH_CONTEXT(sp, prio) {                                        \
 +  asm volatile ("mrs     %0, PSP                                \n\t"   \
 +                "stmdb   %0!, {r3-r11,lr}" :                            \
 +                "=r" (sp) : "r" (sp), "r" (prio));                      \
 +}
 +
 +#define POP_CONTEXT(sp) {                                               \
 +  asm volatile ("ldmia   %0!, {r3-r11, lr}                      \n\t"   \
 +                "msr     PSP, %0                                \n\t"   \
 +                "msr     BASEPRI, r3                            \n\t"   \
 +                "bx      lr" : "=r" (sp) : "r" (sp));                   \
 +}
 +#else /* defined(CH_CURRP_REGISTER_CACHE) */
 +#define PUSH_CONTEXT(sp, prio) {                                        \
 +  asm volatile ("mrs     %0, PSP                                \n\t"   \
 +                "stmdb   %0!, {r3-r6,r8-r11, lr}" :                     \
 +                "=r" (sp) : "r" (sp), "r" (prio));                      \
 +}
 +
 +#define POP_CONTEXT(sp) {                                               \
 +  asm volatile ("ldmia   %0!, {r3-r6,r8-r11, lr}                \n\t"   \
 +                "msr     PSP, %0                                \n\t"   \
 +                "msr     BASEPRI, r3                            \n\t"   \
 +                "bx      lr" : "=r" (sp) : "r" (sp));                   \
 +}
 +#endif /* defined(CH_CURRP_REGISTER_CACHE) */
 +#endif /* CORTEX_MODEL != CORTEX_M0 */
 +
 +/**
 + * @brief   SVC vector.
 + * @details The SVC vector is used for commanded context switch. Structures
 + *          @p intctx are saved and restored from the process stacks of the
 + *          switched threads.
 + *
 + * @param[in] ntp       the thread to be switched it
 + * @param[in] otp       the thread to be switched out
 + */
 +#if !defined(__DOXYGEN__)
 +__attribute__((naked))
 +#endif
 +void SVCallVector(Thread *ntp, Thread *otp) {
 +  register struct intctx *sp_thd asm("r2");
 +  register uint32_t prio asm ("r3");
 +
 +  asm volatile ("mrs     r3, BASEPRI" : "=r" (prio) : );
 +  PUSH_CONTEXT(sp_thd, prio)
 +
 +  otp->p_ctx.r13 = sp_thd;
 +  sp_thd = ntp->p_ctx.r13;
 +
 +  POP_CONTEXT(sp_thd)
 +}
 +
 +/**
 + * @brief   Preemption code.
 + */
 +#if !defined(__DOXYGEN__)
 +__attribute__((naked))
 +#endif
 +void PendSVVector(void) {
 +  register struct intctx *sp_thd asm("r2");
 +  register uint32_t prio asm ("r3");
 +  Thread *otp, *ntp;
 +
 +  chSysLockFromIsr();
 +
 +  prio = CORTEX_BASEPRI_DISABLED;
 +  PUSH_CONTEXT(sp_thd, prio)
 +
 +  (otp = currp)->p_ctx.r13 = sp_thd;
 +  ntp = fifo_remove(&rlist.r_queue);
 +  setcurrp(ntp);
 +  ntp->p_state = THD_STATE_CURRENT;
 +  chSchReadyI(otp);
 +#if CH_TIME_QUANTUM > 0
 +  /* Set the round-robin time quantum.*/
 +  rlist.r_preempt = CH_TIME_QUANTUM;
 +#endif
 +  chDbgTrace(otp);
 +  sp_thd = ntp->p_ctx.r13;
 +
 +  POP_CONTEXT(sp_thd)
 +}
 +
 +/** @} */
 diff --git a/os/ports/GCC/ARMCMx/chcore_v7m.h b/os/ports/GCC/ARMCMx/chcore_v7m.h new file mode 100644 index 000000000..804f6357e --- /dev/null +++ b/os/ports/GCC/ARMCMx/chcore_v7m.h @@ -0,0 +1,313 @@ +/*
 +    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 <http://www.gnu.org/licenses/>.
 +*/
 +
 +/**
 + * @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    This structure is empty in this port.
 + */
 +struct extctx {
 +};
 +#endif
 +
 +#if !defined(__DOXYGEN__)
 +/**
 + * @brief   System saved context.
 + * @details This structure represents the inner stack frame during a context
 + *          switching.
 + */
 +struct intctx {
 +  regarm_t      basepri;
 +  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_exc;
 +  /* Start of the hardware saved frame.*/
 +  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
 +
 +/**
 + * @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->basepri = CORTEX_BASEPRI_DISABLED;                     \
 +  tp->p_ctx.r13->lr_exc = (regarm_t)0xFFFFFFFD;                         \
 +  tp->p_ctx.r13->r0 = arg;                                              \
 +  tp->p_ctx.r13->lr_thd = chThdExit;                                    \
 +  tp->p_ctx.r13->pc = pf;                                               \
 +  tp->p_ctx.r13->xpsr = (regarm_t)0x01000000;                           \
 +}
 +
 +/**
 + * @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   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)];
 +
 +/**
 + * @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() {                                           \
 +  chSysLockFromIsr();                                                   \
 +  if (chSchIsRescRequiredI())                                           \
 +    SCB_ICSR = ICSR_PENDSVSET;                                          \
 +  chSysUnlockFromIsr();                                                 \
 +}
 +
 +/**
 + * @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   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_PENDSV,                              \
 +    CORTEX_PRIORITY_MASK(CORTEX_PRIORITY_PENDSV));                          \
 +  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.
 + */
 +#if CH_OPTIMIZE_SPEED
 +#define port_lock() {                                                   \
 +  register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL;             \
 +  asm volatile ("msr     BASEPRI, %0" : : "r" (tmp));                   \
 +}
 +#else
 +#define port_lock() {                                                   \
 +  asm volatile ("bl      _port_lock" : : : "r3", "lr");                 \
 +}
 +#endif
 +
 +/**
 + * @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 kernel level.
 + */
 +#if CH_OPTIMIZE_SPEED
 +#define port_unlock() {                                                 \
 +  register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_DISABLED;           \
 +  asm volatile ("msr     BASEPRI, %0" : : "r" (tmp));                   \
 +}
 +#else
 +#define port_unlock() {                                                 \
 +  asm volatile ("bl      _port_unlock" : : : "r3", "lr");               \
 +}
 +#endif
 +
 +/**
 + * @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() asm volatile ("cpsid   i")
 +
 +/**
 + * @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() {                                                \
 +  register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_KERNEL;             \
 +  asm volatile ("msr     BASEPRI, %0                    \n\t"           \
 +                "cpsie   i" : : "r" (tmp));                             \
 +}
 +
 +/**
 + * @brief   Enables all the interrupt sources.
 + * @note    In this port it lowers the base priority to user level.
 + */
 +#define port_enable() {                                                 \
 +  register uint32_t tmp asm ("r3") = CORTEX_BASEPRI_DISABLED;           \
 +  asm volatile ("msr     BASEPRI, %0                    \n\t"           \
 +                "cpsie   i" : : "r" (tmp));                             \
 +}
 +
 +/**
 + * @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
 +
 +/**
 + * @brief   Performs a context switch between two threads.
 + * @details This is the most critical code in any port, this function
 + *          is responsible for the context switch between 2 threads.
 + * @note    The implementation of this code affects <b>directly</b> the context
 + *          switch performance so optimize here as much as you can.
 + * @note    Implemented as inlined code for performance reasons.
 + *
 + * @param[in] ntp       the thread to be switched in
 + * @param[in] otp       the thread to be switched out
 + */
 +static INLINE Thread *port_switch(Thread *ntp, Thread *otp) {
 +  register Thread *_ntp asm ("r0") = (ntp);
 +  register Thread *_otp asm ("r1") = (otp);
 +#if CH_DBG_ENABLE_STACK_CHECK
 +  register char *sp asm ("sp");
 +  if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp)
 +    asm volatile ("movs    r0, #0                               \n\t"
 +                  "b       chDbgPanic");
 +#endif /* CH_DBG_ENABLE_STACK_CHECK */
 +  asm volatile ("svc     #0" : : "r" (_otp), "r" (_ntp) : "memory");
 +  return _otp;
 +}
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +  void port_halt(void);
 +#if !CH_OPTIMIZE_SPEED
 +  void _port_lock(void);
 +  void _port_unlock(void);
 +#endif
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif /* _CHCORE_V7M_H_ */
 +
 +/** @} */
  | 
