git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13496 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
parent
5395751f6c
commit
a0f0a8dc5e
|
@ -589,7 +589,7 @@
|
|||
* @p panic_msg variable set to @p NULL.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_STACK_CHECK)
|
||||
#define CH_DBG_ENABLE_STACK_CHECK TRUE
|
||||
#define CH_DBG_ENABLE_STACK_CHECK FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -26,7 +26,7 @@
|
|||
* This is a periodic thread that does absolutely nothing except flashing
|
||||
* a LED.
|
||||
*/
|
||||
static THD_WORKING_AREA(waThread1, 128);
|
||||
static THD_WORKING_AREA(waThread1, 256);
|
||||
static THD_FUNCTION(Thread1, arg) {
|
||||
|
||||
(void)arg;
|
||||
|
|
|
@ -39,9 +39,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
@ -66,8 +75,8 @@
|
|||
.global _port_switch_arm
|
||||
_port_switch_arm:
|
||||
stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
|
||||
str sp, [r1, #12]
|
||||
ldr sp, [r0, #12]
|
||||
str sp, [r1, #CONTEXT_OFFSET]
|
||||
ldr sp, [r0, #CONTEXT_OFFSET]
|
||||
ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ARMCMAx-TZ/chcore.c
|
||||
* @brief ARMCMAx-TZ port code.
|
||||
*
|
||||
* @addtogroup ARMCMAx-TZ_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/** @} */
|
|
@ -1,547 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ARMCAx-TZ/chcore.h
|
||||
* @brief ARMCAx-TZ architecture port macros and structures.
|
||||
*
|
||||
* @addtogroup ARMCAx-TZ_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHCORE_H
|
||||
#define CHCORE_H
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Port Capabilities and Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief This port supports a realtime counter.
|
||||
*/
|
||||
#define PORT_SUPPORTS_RT TRUE
|
||||
|
||||
/**
|
||||
* @brief Natural alignment constant.
|
||||
* @note It is the minimum alignment for pointer-size variables.
|
||||
*/
|
||||
#define PORT_NATURAL_ALIGN sizeof (void *)
|
||||
|
||||
/**
|
||||
* @brief Stack alignment constant.
|
||||
* @note It is the alignment required for the stack pointer.
|
||||
*/
|
||||
#define PORT_STACK_ALIGN sizeof (stkalign_t)
|
||||
|
||||
/**
|
||||
* @brief Working Areas alignment constant.
|
||||
* @note It is the alignment to be enforced for thread working areas.
|
||||
*/
|
||||
#define PORT_WORKING_AREA_ALIGN sizeof (stkalign_t)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Architecture and Compiler
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Macro defining a generic ARM architecture.
|
||||
*/
|
||||
#define PORT_ARCHITECTURE_ARM_TZ
|
||||
|
||||
/* The following code is not processed when the file is included from an
|
||||
asm module because those intrinsic macros are not necessarily defined
|
||||
by the assembler too.*/
|
||||
#if !defined(_FROM_ASM_)
|
||||
|
||||
/**
|
||||
* @brief Compiler name and version.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__DOXYGEN__)
|
||||
#define PORT_COMPILER_NAME "GCC " __VERSION__
|
||||
|
||||
#else
|
||||
#error "unsupported compiler"
|
||||
#endif
|
||||
|
||||
#endif /* !defined(_FROM_ASM_) */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name ARM variants
|
||||
* @{
|
||||
*/
|
||||
#define ARM_CORE_CORTEX_A5 105
|
||||
#define ARM_CORE_CORTEX_A8 108
|
||||
#define ARM_CORE_CORTEX_A9 109
|
||||
/** @} */
|
||||
|
||||
/* Inclusion of the ARM implementation specific parameters.*/
|
||||
#include "armparams.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables an alternative timer implementation.
|
||||
* @details Usually the port uses a timer interface defined in the file
|
||||
* @p chcore_timer.h, if this option is enabled then the file
|
||||
* @p chcore_timer_alt.h is included instead.
|
||||
*/
|
||||
#if !defined(PORT_USE_ALT_TIMER)
|
||||
#define PORT_USE_ALT_TIMER FALSE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Stack size for the system idle thread.
|
||||
* @details This size depends on the idle thread implementation, usually
|
||||
* the idle thread should take no more space than those reserved
|
||||
* by @p PORT_INT_REQUIRED_STACK.
|
||||
* @note In this port it is set to 32 because the idle thread does have
|
||||
* a stack frame when compiling without optimizations. You may
|
||||
* reduce this value to zero when compiling with optimizations.
|
||||
*/
|
||||
#if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__)
|
||||
#define PORT_IDLE_THREAD_STACK_SIZE 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Per-thread stack overhead for interrupts servicing.
|
||||
* @details This constant is used in the calculation of the correct working
|
||||
* area size.
|
||||
*/
|
||||
#if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__)
|
||||
#define PORT_INT_REQUIRED_STACK 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If enabled allows the idle thread to enter a low power mode.
|
||||
*/
|
||||
#ifndef ARM_ENABLE_WFI_IDLE
|
||||
#define ARM_ENABLE_WFI_IDLE FALSE
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The following code is not processed when the file is included from an
|
||||
asm module.*/
|
||||
#if !defined(_FROM_ASM_)
|
||||
|
||||
/* ARM core check.*/
|
||||
#if (ARM_CORE == ARM_CORE_CORTEX_A5) || defined(__DOXYGEN__)
|
||||
#define PORT_ARCHITECTURE_ARM_ARM7
|
||||
#define PORT_ARCHITECTURE_NAME "ARMv7 (TZ)"
|
||||
#define PORT_CORE_VARIANT_NAME "ARM Cortex-A5"
|
||||
|
||||
#elif ARM_CORE == ARM_CORE_CORTEX_A8
|
||||
#define PORT_ARCHITECTURE_ARM_CORTEXA8
|
||||
#define PORT_ARCHITECTURE_NAME "ARMv7"
|
||||
#define PORT_CORE_VARIANT_NAME "ARM Cortex-A8"
|
||||
|
||||
#elif ARM_CORE == ARM_CORE_CORTEX_A9
|
||||
#define PORT_ARCHITECTURE_ARM_CORTEXA9
|
||||
#define PORT_ARCHITECTURE_NAME "ARMv7"
|
||||
#define PORT_CORE_VARIANT_NAME "ARM Cortex-A9"
|
||||
|
||||
#else
|
||||
#error "unknown or unsupported ARM core"
|
||||
#endif
|
||||
|
||||
#define PORT_INFO "Pure THUMB mode"
|
||||
|
||||
#endif /* !defined(_FROM_ASM_) */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The following code is not processed when the file is included from an
|
||||
asm module.*/
|
||||
#if !defined(_FROM_ASM_)
|
||||
|
||||
/**
|
||||
* @brief Type of stack and memory alignment enforcement.
|
||||
* @note In this architecture the stack alignment is enforced to 64 bits.
|
||||
*/
|
||||
typedef uint64_t stkalign_t;
|
||||
|
||||
/**
|
||||
* @brief Generic ARM register.
|
||||
*/
|
||||
typedef void *regarm_t;
|
||||
|
||||
/**
|
||||
* @brief Interrupt saved context.
|
||||
* @details This structure represents the stack frame saved during an
|
||||
* interrupt handler.
|
||||
*/
|
||||
struct port_extctx {
|
||||
regarm_t spsr_irq;
|
||||
regarm_t lr_irq;
|
||||
regarm_t r0;
|
||||
regarm_t r1;
|
||||
regarm_t r2;
|
||||
regarm_t r3;
|
||||
regarm_t r12;
|
||||
regarm_t lr_usr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief System saved context.
|
||||
* @details This structure represents the inner stack frame during a context
|
||||
* switch.
|
||||
*/
|
||||
struct port_intctx {
|
||||
regarm_t r4;
|
||||
regarm_t r5;
|
||||
regarm_t r6;
|
||||
regarm_t r7;
|
||||
regarm_t r8;
|
||||
regarm_t r9;
|
||||
regarm_t r10;
|
||||
regarm_t r11;
|
||||
regarm_t lr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Platform dependent part of the @p thread_t structure.
|
||||
* @details In this port the structure just holds a pointer to the
|
||||
* @p port_intctx structure representing the stack pointer
|
||||
* at context switch time.
|
||||
*/
|
||||
struct port_context {
|
||||
struct port_intctx *sp;
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Platform dependent part of the @p chThdCreateI() API.
|
||||
* @details This code usually setup the context switching frame represented
|
||||
* by an @p port_intctx structure.
|
||||
*/
|
||||
#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \
|
||||
(tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
|
||||
sizeof (struct port_intctx)); \
|
||||
(tp)->ctx.sp->r4 = (regarm_t)(pf); \
|
||||
(tp)->ctx.sp->r5 = (regarm_t)(arg); \
|
||||
(tp)->ctx.sp->lr = (regarm_t)(_port_thread_start); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Computes the thread working area global size.
|
||||
* @note There is no need to perform alignments in this macro.
|
||||
*/
|
||||
#define PORT_WA_SIZE(n) (sizeof(struct port_intctx) + \
|
||||
sizeof(struct port_extctx) + \
|
||||
((size_t)(n)) + ((size_t)(PORT_INT_REQUIRED_STACK)))
|
||||
|
||||
/**
|
||||
* @brief Static working area allocation.
|
||||
* @details This macro is used to allocate a static thread working area
|
||||
* aligned as both position and size.
|
||||
*
|
||||
* @param[in] s the name to be assigned to the stack array
|
||||
* @param[in] n the stack size to be assigned to the thread
|
||||
*/
|
||||
#define PORT_WORKING_AREA(s, n) \
|
||||
stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)]
|
||||
|
||||
/**
|
||||
* @brief Priority level verification macro.
|
||||
* @todo Add the required parameters to armparams.h.
|
||||
*/
|
||||
#define PORT_IRQ_IS_VALID_PRIORITY(n) false
|
||||
|
||||
/**
|
||||
* @brief IRQ prologue code.
|
||||
* @details This macro must be inserted at the start of all IRQ handlers
|
||||
* enabled to invoke system APIs.
|
||||
*/
|
||||
#define PORT_IRQ_PROLOGUE()
|
||||
|
||||
/**
|
||||
* @brief IRQ epilogue code.
|
||||
* @details This macro must be inserted at the end of all IRQ handlers
|
||||
* enabled to invoke system APIs.
|
||||
*/
|
||||
#define PORT_IRQ_EPILOGUE() return chSchIsPreemptionRequired()
|
||||
|
||||
/**
|
||||
* @brief IRQ handler function declaration.
|
||||
* @note @p id can be a function name or a vector number depending on the
|
||||
* port implementation.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define PORT_IRQ_HANDLER(id) extern "C" bool id(void)
|
||||
#else
|
||||
#define PORT_IRQ_HANDLER(id) bool id(void)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @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) \
|
||||
bool id(void)
|
||||
|
||||
/**
|
||||
* @brief Performs a context switch between two threads.
|
||||
* @details This is the most critical code in any port, this function
|
||||
* is responsible for the context switch between 2 threads.
|
||||
* @note The implementation of this code affects <b>directly</b> the context
|
||||
* switch performance so optimize here as much as you can.
|
||||
* @note Implemented as inlined code for performance reasons.
|
||||
*
|
||||
* @param[in] ntp the thread to be switched in
|
||||
* @param[in] otp the thread to be switched out
|
||||
*/
|
||||
#if defined(THUMB)
|
||||
|
||||
#if CH_DBG_ENABLE_STACK_CHECK == TRUE
|
||||
#define port_switch(ntp, otp) { \
|
||||
register struct port_intctx *r13 asm ("r13"); \
|
||||
if ((stkalign_t *)(r13 - 1) < otp->wabase) \
|
||||
chSysHalt("stack overflow"); \
|
||||
_port_switch_thumb(ntp, otp); \
|
||||
}
|
||||
#else
|
||||
#define port_switch(ntp, otp) _port_switch_thumb(ntp, otp)
|
||||
#endif
|
||||
|
||||
#else /* !defined(THUMB) */
|
||||
|
||||
#if CH_DBG_ENABLE_STACK_CHECK == TRUE
|
||||
#define port_switch(ntp, otp) { \
|
||||
register struct port_intctx *r13 asm ("r13"); \
|
||||
if ((stkalign_t *)(r13 - 1) < otp->wabase) \
|
||||
chSysHalt("stack overflow"); \
|
||||
_port_switch_arm(ntp, otp); \
|
||||
}
|
||||
#else
|
||||
#define port_switch(ntp, otp) _port_switch_arm(ntp, otp)
|
||||
#endif
|
||||
|
||||
#endif /* !defined(THUMB) */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if defined(THUMB_PRESENT)
|
||||
syssts_t _port_get_cpsr(void);
|
||||
#endif
|
||||
#if defined(THUMB)
|
||||
void _port_switch_thumb(thread_t *ntp, thread_t *otp);
|
||||
#else
|
||||
void _port_switch_arm(thread_t *ntp, thread_t *otp);
|
||||
#endif
|
||||
void _port_thread_start(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module inline functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Port-related initialization code.
|
||||
*/
|
||||
static inline void port_init(void) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a word encoding the current interrupts status.
|
||||
*
|
||||
* @return The interrupts status.
|
||||
*/
|
||||
static inline syssts_t port_get_irq_status(void) {
|
||||
syssts_t sts;
|
||||
|
||||
#if defined(THUMB)
|
||||
sts = _port_get_cpsr();
|
||||
#else
|
||||
__asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :);
|
||||
#endif
|
||||
/*lint -save -e530 [9.1] Asm instruction not seen by lint.*/
|
||||
return sts;
|
||||
/*lint -restore*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks the interrupt status.
|
||||
*
|
||||
* @param[in] sts the interrupt status word
|
||||
*
|
||||
* @return The interrupt status.
|
||||
* @retval false the word specified a disabled interrupts status.
|
||||
* @retval true the word specified an enabled interrupts status.
|
||||
*/
|
||||
static inline bool port_irq_enabled(syssts_t sts) {
|
||||
|
||||
return (sts & (syssts_t)0x40) == (syssts_t)0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines the current execution context.
|
||||
*
|
||||
* @return The execution context.
|
||||
* @retval false not running in ISR mode.
|
||||
* @retval true running in ISR mode.
|
||||
*/
|
||||
static inline bool port_is_isr_context(void) {
|
||||
syssts_t sts;
|
||||
|
||||
#if defined(THUMB)
|
||||
sts = _port_get_cpsr();
|
||||
#else
|
||||
__asm volatile ("mrs %[p0], CPSR" : [p0] "=r" (sts) :);
|
||||
#endif
|
||||
|
||||
/*lint -save -e530 [9.1] Asm instruction not seen by lint.*/
|
||||
return (sts & (syssts_t)0x1F) == (syssts_t)0x11;
|
||||
/*lint -restore*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-lock action.
|
||||
* @details In this port it disables the FIQ and keep IRQ state.
|
||||
*/
|
||||
static inline void port_lock(void) {
|
||||
|
||||
__asm volatile ("cpsid if" : : : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-unlock action.
|
||||
* @details In this port it enables the FIQ and IRQ sources.
|
||||
*/
|
||||
static inline void port_unlock(void) {
|
||||
__asm volatile ("cpsie if" : : : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-lock action from an interrupt handler.
|
||||
* @note Empty in this port.
|
||||
*/
|
||||
static inline void port_lock_from_isr(void) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Kernel-unlock action from an interrupt handler.
|
||||
* @note Empty in this port.
|
||||
*/
|
||||
static inline void port_unlock_from_isr(void) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables all the interrupt sources.
|
||||
* @details In this port it disables FIQ sources and keeps IRQ sources
|
||||
* disabled.
|
||||
*/
|
||||
static inline void port_disable(void) {
|
||||
|
||||
__asm volatile ("msr CPSR_c, #0xDF" : : : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the interrupt sources below kernel-level priority.
|
||||
* @note Interrupt sources above kernel level remains enabled.
|
||||
* @note In this port it disables the FIQ and IRQ sources.
|
||||
*/
|
||||
static inline void port_suspend(void) {
|
||||
|
||||
__asm volatile ("msr CPSR_c, #0xDF" : : : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables all the interrupt sources.
|
||||
* @note In this port it enables the FIQ and IRQ sources.
|
||||
*/
|
||||
static inline void port_enable(void) {
|
||||
|
||||
__asm volatile ("msr CPSR_c, #0x1F" : : : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters an architecture-dependent IRQ-waiting mode.
|
||||
* @details The function is meant to return when an interrupt becomes pending.
|
||||
* The simplest implementation is an empty function or macro but this
|
||||
* would not take advantage of architecture-specific power saving
|
||||
* modes.
|
||||
* @note Implemented as an inlined @p WFI instruction.
|
||||
*/
|
||||
static inline void port_wait_for_interrupt(void) {
|
||||
|
||||
asm volatile ("wfi" : : : "memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current value of the realtime counter.
|
||||
*
|
||||
* @return The realtime counter value.
|
||||
*/
|
||||
static inline rtcnt_t port_rt_get_counter_value(void) {
|
||||
|
||||
#if ((ARM_CORE == ARM_CORE_CORTEX_A5) || (ARM_CORE == ARM_CORE_CORTEX_A9) || defined(__DOXYGEN__))
|
||||
|
||||
rtcnt_t cyc;
|
||||
|
||||
__asm volatile("mrc p15, 0, %[p0], c9, c13, 0" : [p0] "=r" (cyc) :);
|
||||
|
||||
return cyc;
|
||||
#else
|
||||
/*
|
||||
* TODO develop same function for ARM_CORE_CORTEX_A8
|
||||
*/
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CH_CFG_ST_TIMEDELTA > 0
|
||||
#if PORT_USE_ALT_TIMER == FALSE
|
||||
#include "chcore_timer.h"
|
||||
#else /* PORT_USE_ALT_TIMER */
|
||||
#include "chcore_timer_alt.h"
|
||||
#endif /* PORT_USE_ALT_TIMER */
|
||||
#endif /* CH_CFG_ST_TIMEDELTA > 0 */
|
||||
|
||||
#endif /* !defined(_FROM_ASM_) */
|
||||
|
||||
#endif /* CHCORE_H */
|
||||
|
||||
/** @} */
|
|
@ -1,126 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chcore_timer.h
|
||||
* @brief System timer header file.
|
||||
*
|
||||
* @addtogroup ARMCMAx-TZ_TIMER
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHCORE_TIMER_H
|
||||
#define CHCORE_TIMER_H
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module inline functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Starts the alarm.
|
||||
* @note Makes sure that no spurious alarms are triggered after
|
||||
* this call.
|
||||
*
|
||||
* @param[in] time the time to be set for the first alarm
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void port_timer_start_alarm(systime_t time) {
|
||||
void stStartAlarm(systime_t time);
|
||||
|
||||
stStartAlarm(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the alarm interrupt.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void port_timer_stop_alarm(void) {
|
||||
void stStopAlarm(void);
|
||||
|
||||
stStopAlarm();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the alarm time.
|
||||
*
|
||||
* @param[in] time the time to be set for the next alarm
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline void port_timer_set_alarm(systime_t time) {
|
||||
void stSetAlarm(systime_t time);
|
||||
|
||||
stSetAlarm(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the system time.
|
||||
*
|
||||
* @return The system time.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline systime_t port_timer_get_time(void) {
|
||||
systime_t stGetCounter(void);
|
||||
|
||||
return stGetCounter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current alarm time.
|
||||
*
|
||||
* @return The currently set alarm time.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
static inline systime_t port_timer_get_alarm(void) {
|
||||
systime_t stGetAlarm(void);
|
||||
|
||||
return stGetAlarm();
|
||||
}
|
||||
|
||||
#endif /* CHCORE_TIMER_H */
|
||||
|
||||
/** @} */
|
|
@ -1,522 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Isidoro Orabona
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chtssi.c
|
||||
* @brief Trusted services related API and definition.
|
||||
*
|
||||
* @addtogroup TSSI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "chtssi.h"
|
||||
#include "ARMCA5.h"
|
||||
#if defined(__GNUC__) || defined(__DOXYGEN__)
|
||||
#include "cmsis_gcc.h"
|
||||
#else
|
||||
#include "cmsis_armcc.h"
|
||||
#endif
|
||||
#include "ccportab.h"
|
||||
#include <string.h>
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local definitions. */
|
||||
/*===========================================================================*/
|
||||
/* Granted timeslices to trusted service. DO NOT modify those values.
|
||||
They have non secure world counterparts.*/
|
||||
typedef enum {
|
||||
TS_TIMEINT_1000_US = 1000,
|
||||
TS_TIMEINT_10000_US = 10000
|
||||
} ts_timeint_t;
|
||||
|
||||
#define LOWORD(in64) ((int64_t)in64 & 0x0FFFFFFFF)
|
||||
#define TS_TIME2I(tmo) \
|
||||
(tmo == TS_TIMEINT_10000_US ? TIME_US2I(TS_TIMEINT_10000_US) : \
|
||||
TIME_US2I(TS_TIMEINT_1000_US))
|
||||
#define FDT_MAGIC 0xd00dfeed
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* If a services file is missing in the user application.*/
|
||||
CC_WEAK ts_state_t ts_state[TS_MAX_SVCS];
|
||||
CC_WEAK const thread_descriptor_t ts_configs[TS_MAX_SVCS];
|
||||
CC_WEAK const fc_descriptor_t ts_fc_configs[1];
|
||||
uint32_t ts_fc_configs_n;
|
||||
|
||||
/* The reference to the suspended NSEC main thread.*/
|
||||
thread_reference_t _ns_thread = NULL;
|
||||
|
||||
/* The services may broadcast and listen event flags via this object.*/
|
||||
EVENTSOURCE_DECL(tsEventSource);
|
||||
|
||||
extern uint32_t __ram0_start__;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
struct fdt_header {
|
||||
uint32_t magic; /* magic word FDT_MAGIC */
|
||||
uint32_t totalsize; /* total size of DT block */
|
||||
uint32_t off_dt_struct; /* offset to structure */
|
||||
uint32_t off_dt_strings; /* offset to strings */
|
||||
uint32_t off_mem_rsvmap; /* offset to memory reserve map */
|
||||
uint32_t version; /* format version */
|
||||
uint32_t last_comp_version; /* last compatible version */
|
||||
|
||||
/* version 2 fields below */
|
||||
uint32_t boot_cpuid_phys; /* Which physical CPU id we're
|
||||
booting on */
|
||||
/* version 3 fields below */
|
||||
uint32_t size_dt_strings; /* size of the strings block */
|
||||
|
||||
/* version 17 fields below */
|
||||
uint32_t size_dt_struct; /* size of the structure block */
|
||||
};
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* The ts module listen to the tsEventSource via this object.*/
|
||||
static event_listener_t tsEventListener;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static inline uint32_t uswap32(uint32_t v)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
__asm volatile ("rev %0, %1" : "=r" (result) : "r" (v));
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool isAddrSpaceValid(uint8_t *addr, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return TRUE;
|
||||
return (bool)((addr - NSEC_MEMORY_START_ADDR) <
|
||||
(NSEC_MEMORY_END_ADDR - NSEC_MEMORY_START_ADDR)) &&
|
||||
(bool)((addr + size - NSEC_MEMORY_START_ADDR) <
|
||||
(NSEC_MEMORY_END_ADDR - NSEC_MEMORY_START_ADDR));
|
||||
}
|
||||
|
||||
static bool isHndlValid(ts_state_t *handle)
|
||||
{
|
||||
if ((handle < TS_STATE(0)) || (handle >= TS_STATE(TS_MAX_SVCS)))
|
||||
return FALSE;
|
||||
if (((char *)handle - (char *)TS_STATE(0)) % sizeof *TS_STATE(0))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ts_state_t *findSvcsEntry(const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TS_MAX_SVCS; ++i) {
|
||||
if (TS_CONF_TABLE(i)->name == NULL)
|
||||
continue;
|
||||
if (!strcmp(TS_CONF_TABLE(i)->name, name))
|
||||
return TS_CONF_TABLE(i)->arg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief The trusted service call entry point.
|
||||
* @pre The foreign interrupts are disabled.
|
||||
* @post A request is passed to the thread registered for the service.
|
||||
* @post The service thread is resumed.
|
||||
*
|
||||
* @param[in] svc_handle the handle of the service to be invoked.
|
||||
* @param[in,out] svc_data service request data, often a reference to a more
|
||||
* complex structure.
|
||||
* @param[in] svc_datalen size of the svc_data memory area.
|
||||
* @param[in] svc_timeout after this time interval, the service execution
|
||||
* will be interrupted. Time is in microseconds.
|
||||
* This interval represents the time slice granted
|
||||
* to the services to continue their work.
|
||||
*
|
||||
* @return A 64bit value. It is the OR of the 32bit service
|
||||
* status combined with a 32bit event mask (in the
|
||||
* hi-word).
|
||||
* The retval values are returned in the lower word
|
||||
* as 32bit int.
|
||||
* @retval SMC_SVC_OK generic success value.
|
||||
* @retval SMC_SVC_INTR call interrupted.
|
||||
* @retval SMC_SVC_BUSY the service has a pending request.
|
||||
* @retval SMC_SVC_INVALID bad parameters.
|
||||
* @retval SMC_SVC_NOENT no such service.
|
||||
* @retval SMC_SVC_BADH bad handle.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
int64_t smcEntry(ts_state_t *svc_handle, ts_params_area_t svc_data,
|
||||
size_t svc_datalen, ts_timeint_t svc_timeout) {
|
||||
ts_state_t *tssp = NULL;
|
||||
msg_t r;
|
||||
|
||||
if (svc_handle == TS_HND_STQRY) {
|
||||
|
||||
/* Internal query status service.*/
|
||||
ts_state_t *tsqryd;
|
||||
|
||||
/* svc_data is the handle of the service to whom 'query' the state.*/
|
||||
tsqryd = (ts_state_t *)svc_data;
|
||||
|
||||
/* handle argument validation.*/
|
||||
if (!isHndlValid(tsqryd))
|
||||
return LOWORD(SMC_SVC_BADH);
|
||||
|
||||
/* if the service has done, return its last status.*/
|
||||
if (tsqryd->ts_thdp != NULL) {
|
||||
r = tsqryd->ts_status;
|
||||
return LOWORD(r);
|
||||
}
|
||||
}
|
||||
else if (svc_handle != TS_HND_IDLE) {
|
||||
if (!isAddrSpaceValid(svc_data, svc_datalen))
|
||||
return LOWORD(SMC_SVC_INVALID);
|
||||
|
||||
uint32_t i = (uint32_t)svc_handle;
|
||||
|
||||
if ((i & TS_FASTCALL_MASK) == TS_FASTCALL_MASK) {
|
||||
|
||||
/* Fast call user service.*/
|
||||
i &= ~TS_FASTCALL_MASK;
|
||||
|
||||
if (i >= ts_fc_configs_n)
|
||||
return LOWORD(SMC_SVC_BADH);
|
||||
|
||||
return TS_FC_CONF_TABLE(i)->funcp(svc_data, svc_datalen);
|
||||
}
|
||||
else if (svc_handle == TS_HND_VERSION) {
|
||||
|
||||
/* Internal get version service.*/
|
||||
return LOWORD(TSSI_VERSION);
|
||||
}
|
||||
else if (svc_handle == TS_HND_DISCOVERY) {
|
||||
|
||||
/* Internal discovery service.*/
|
||||
if (svc_datalen) {
|
||||
*((char *)svc_data + svc_datalen - 1) = '\0';
|
||||
tssp = findSvcsEntry((char *)svc_data);
|
||||
}
|
||||
if (tssp == NULL)
|
||||
return LOWORD(SMC_SVC_NOENT);
|
||||
return LOWORD((int32_t)tssp);
|
||||
}
|
||||
else {
|
||||
|
||||
/* User service.*/
|
||||
if (!isHndlValid(svc_handle))
|
||||
return LOWORD(SMC_SVC_BADH);
|
||||
tssp = svc_handle;
|
||||
|
||||
/* If the service is not waiting requests, it's busy.*/
|
||||
if (tssp->ts_thdp == NULL)
|
||||
return LOWORD(SMC_SVC_BUSY);
|
||||
tssp->ts_datap = svc_data;
|
||||
tssp->ts_datalen = svc_datalen;
|
||||
}
|
||||
}
|
||||
|
||||
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
||||
_dbg_check_lock();
|
||||
#endif
|
||||
|
||||
/* Limit the max timeout interval.*/
|
||||
if (svc_timeout > TS_MAX_TMO)
|
||||
svc_timeout = TS_MAX_TMO;
|
||||
|
||||
if (tssp)
|
||||
chThdResumeS(&tssp->ts_thdp, MSG_OK);
|
||||
r = chThdSuspendTimeoutS(&_ns_thread, TS_TIME2I(svc_timeout));
|
||||
|
||||
/* Map MSG_TIMEOUT to SMC_SVC_INTR.*/
|
||||
if (r == MSG_TIMEOUT)
|
||||
r = SMC_SVC_INTR;
|
||||
|
||||
/* Get and clear any pending event flags.*/
|
||||
eventflags_t f = chEvtGetAndClearFlagsI(&tsEventListener);
|
||||
|
||||
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
||||
_dbg_check_unlock();
|
||||
#endif
|
||||
return LOWORD(r) | ((int64_t)f << 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The calling thread is a service and wait the arrival of
|
||||
* a request.
|
||||
* @post The service object state is filled with the parameters of
|
||||
* the requester.
|
||||
*
|
||||
* @param[in] svcp the service object reference.
|
||||
*
|
||||
* @return The wakeup message.
|
||||
* @retval MSG_OK a new request has to be processed.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t tssiWaitRequest(ts_state_t *svcp)
|
||||
{
|
||||
msg_t r;
|
||||
|
||||
chDbgCheck(svcp != NULL);
|
||||
|
||||
chSysLock();
|
||||
if (_ns_thread) {
|
||||
/* Ack a previous service invocation. Not schedule.*/
|
||||
chThdResumeI(&_ns_thread, SMC_SVC_INTR);
|
||||
}
|
||||
r = chThdSuspendS(&svcp->ts_thdp);
|
||||
chSysUnlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check that the specified memory space is a subspace of
|
||||
* the non secure memory space.
|
||||
*
|
||||
* @param[in] addr start address of the memory space.
|
||||
* @param[in] size size of the memory space.
|
||||
*
|
||||
* @return TRUE, if the space is valid.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
bool tsIsAddrSpaceValid(void *addr, size_t size)
|
||||
{
|
||||
return isAddrSpaceValid((uint8_t *)addr, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the trusted services and jumps in the NSEC world.
|
||||
*
|
||||
* @init
|
||||
*/
|
||||
CC_NO_RETURN void tssiInit(void)
|
||||
{
|
||||
int32_t i;
|
||||
uint32_t d;
|
||||
uint32_t *tt;
|
||||
struct fdt_header *pfdt = (struct fdt_header *)NSEC_MEMORY_START_ADDR;
|
||||
void *moveto = NULL;
|
||||
|
||||
/*
|
||||
* The main DDR memory, PORT0, is divided in 4 region, each 32MB large.
|
||||
* The last region is split in two areas, each 16MB large.
|
||||
* The first 3 region and the lower area of this last region is non secure.
|
||||
* All the rest of the regions space is secured.
|
||||
* The same applies to AESB view of the DDR, PORT1, and LCDC view.
|
||||
*
|
||||
* Those settings depend on the designed memory mapping.
|
||||
*/
|
||||
mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
|
||||
mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
|
||||
mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT2, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
|
||||
mtxSetSlaveRegionSize(MATRIX0, H64MX_SLAVE_DDR_PORT3, MATRIX_AREA_SIZE_32M, REGION_0_MSK);
|
||||
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_32M,
|
||||
REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_32M,
|
||||
REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT2, MATRIX_AREA_SIZE_32M,
|
||||
REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT3, MATRIX_AREA_SIZE_32M,
|
||||
REGION_0_MSK | REGION_1_MSK | REGION_2_MSK);
|
||||
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT0, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT1, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT2, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_DDR_PORT3, MATRIX_AREA_SIZE_16M, REGION_3_MSK);
|
||||
|
||||
mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT0,
|
||||
mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
|
||||
mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
|
||||
mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
|
||||
|
||||
mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT1,
|
||||
mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
|
||||
mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
|
||||
mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
|
||||
|
||||
mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT2,
|
||||
mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
|
||||
mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
|
||||
mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
|
||||
|
||||
mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_DDR_PORT3,
|
||||
mtxRegionLansech(REGION_0, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_3, UPPER_AREA_SECURABLE),
|
||||
mtxRegionRdnsech(REGION_0, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
|
||||
mtxRegionWrnsech(REGION_0, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
|
||||
|
||||
#if !SAMA_USE_SDMMC
|
||||
|
||||
/* Configure the SDMMCx regions as non secure.*/
|
||||
mtxSetSlaveSplitAddr(MATRIX0, H64MX_SLAVE_SDMMC, MATRIX_AREA_SIZE_128M, REGION_1_MSK|REGION_2_MSK);
|
||||
mtxConfigSlaveSec(MATRIX0, H64MX_SLAVE_SDMMC,
|
||||
mtxRegionLansech(REGION_1, UPPER_AREA_SECURABLE) |
|
||||
mtxRegionLansech(REGION_2, UPPER_AREA_SECURABLE),
|
||||
mtxRegionRdnsech(REGION_1, NOT_SECURE_READ) |
|
||||
mtxRegionRdnsech(REGION_2, NOT_SECURE_READ),
|
||||
mtxRegionWrnsech(REGION_1, NOT_SECURE_WRITE) |
|
||||
mtxRegionWrnsech(REGION_2, NOT_SECURE_WRITE));
|
||||
#endif
|
||||
|
||||
/* Mark the whole non secure memory region non executable
|
||||
by the secure side, and set the Non-Secure access bit, so that
|
||||
any access to this region is in the non-secure physical
|
||||
space. This ensures the coherence of the cache between
|
||||
secure and non secure accesses.*/
|
||||
tt = (uint32_t *)(__get_TTBR0() & 0xFFFFC000);
|
||||
for (d = ((uint32_t)NSEC_MEMORY_START_ADDR >> 20);
|
||||
d < ((uint32_t)NSEC_MEMORY_END_ADDR >> 20); d += 1) {
|
||||
MMU_SecureSection(tt + d, NON_SECURE);
|
||||
MMU_XNSection(tt + d, NON_EXECUTE);
|
||||
}
|
||||
|
||||
/* The same, but for the AESB view of the DDR memory region.*/
|
||||
for (d = ((uint32_t)(NSEC_MEMORY_START_ADDR + 0x20000000) >> 20);
|
||||
d < ((uint32_t)(NSEC_MEMORY_END_ADDR + 0x20000000) >> 20); d += 1) {
|
||||
MMU_SecureSection(tt + d, NON_SECURE);
|
||||
MMU_XNSection(tt + d, NON_EXECUTE);
|
||||
}
|
||||
MMU_InvalidateTLB();
|
||||
|
||||
/* Flush the modified MMU table.*/
|
||||
cacheCleanRegion(tt, d * sizeof (uint32_t));
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Make sure that prio is NORMALPRIO.*/
|
||||
chThdSetPriority(NORMALPRIO);
|
||||
|
||||
/* Initialize the services.*/
|
||||
for (i = 0; i < TS_MAX_SVCS; ++i) {
|
||||
if (TS_CONF_TABLE(i)->arg == NULL)
|
||||
continue;
|
||||
|
||||
/* Check that the initialization of the TS_TABLE against TS_STATE_TABLE
|
||||
has been set right.*/
|
||||
if (TS_CONF_TABLE(i)->arg != TS_STATE(i)) {
|
||||
chSysHalt("Bad TS_STATE setting in the services configuration table.");
|
||||
}
|
||||
|
||||
/* Check that the service priority has been set right.*/
|
||||
if ((TS_CONF_TABLE(i)->prio <= NORMALPRIO) ||
|
||||
(TS_CONF_TABLE(i)->prio >= HIGHPRIO)) {
|
||||
chSysHalt("Bad prio setting in the services configuration table.");
|
||||
}
|
||||
|
||||
/* Create the service thread.*/
|
||||
chThdCreate(TS_CONF_TABLE(i));
|
||||
}
|
||||
|
||||
/* Fast call services.*/
|
||||
for (i = 0; TS_FC_CONF_TABLE(i)->name; ++i) {
|
||||
|
||||
/* Check that the 'code' field of the
|
||||
fast call table has been set right.*/
|
||||
if ((TS_FC_CONF_TABLE(i)->code &~ TS_FASTCALL_MASK) != (uint32_t)i) {
|
||||
chSysHalt("Bad 'code' setting in the fast call configuration table.");
|
||||
}
|
||||
}
|
||||
ts_fc_configs_n = i;
|
||||
|
||||
/* Register to the daemon services events. All flags.*/
|
||||
chEvtRegister(&tsEventSource, &tsEventListener, EVT_DAEMON_REQ_ATN);
|
||||
|
||||
/* Now set the priority at the max.*/
|
||||
chThdSetPriority(HIGHPRIO);
|
||||
|
||||
/* Allow non secure access to CP10 and CP11.*/
|
||||
asm volatile (
|
||||
"mrc p15, 0, r0, c1, c1, 2 \n"
|
||||
"orr r0, r0, #0b11<<10 \n"
|
||||
"mcr p15, 0, r0, c1, c1, 2 \n"
|
||||
);
|
||||
|
||||
/* Check if a fdt image exists at the start
|
||||
of the non secure memory region.*/
|
||||
if (uswap32(pfdt->magic) == FDT_MAGIC) {
|
||||
uint32_t fdtsize;
|
||||
|
||||
/* Detected a fdt structure.
|
||||
Move it to the end of non secure area.*/
|
||||
fdtsize = uswap32(pfdt->totalsize);
|
||||
fdtsize = (fdtsize + 4095) &~ 4095;
|
||||
moveto = (void *)(SEC_MEMORY_START_ADDR - fdtsize);
|
||||
memmove(moveto, pfdt, fdtsize);
|
||||
|
||||
/* Invalidate the original fdt image.*/
|
||||
pfdt->magic = 0;
|
||||
}
|
||||
|
||||
/* Jump in the NON SECURE world.
|
||||
This thread becomes the non secure environment as view by
|
||||
the secure world.*/
|
||||
|
||||
/* r2 address of the moved fdt, if any.*/
|
||||
asm volatile (
|
||||
"mov r2, %0 \n" :: "r" (moveto)
|
||||
);
|
||||
|
||||
_ns_trampoline(NSEC_MEMORY_START_ADDR + NSEC_MEMORY_EXE_OFFSET);
|
||||
|
||||
/* It never goes here.*/
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -1,288 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Isidoro Orabona.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file chtssi.h
|
||||
* @brief tssi module macros and structures.
|
||||
*
|
||||
* @addtogroup TSSI
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHTSSI_H
|
||||
#define CHTSSI_H
|
||||
|
||||
#include "ch.h"
|
||||
#include "ccportab.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/* TSSI interface version. This code is returned also at run time by
|
||||
calling the internal service TS_HND_VERSION.*/
|
||||
#define TSSI_VERSION 0x01000000 /* 00 major, 000 minor, 000 build.*/
|
||||
|
||||
/* Service registry errors as returned by smc.*/
|
||||
#define SMC_SVC_OK (int32_t)0 /* No error.*/
|
||||
#define SMC_SVC_INTR (int32_t)-4 /* Service interrupted.*/
|
||||
#define SMC_SVC_NOENT (int32_t)-2 /* No existent service.*/
|
||||
#define SMC_SVC_INVALID (int32_t)-22 /* Invalid service
|
||||
parameter(s).*/
|
||||
#define SMC_SVC_BADH (int32_t)-9 /* Invalid service handle.*/
|
||||
#define SMC_SVC_EXIST (int32_t)-17 /* Service already exists.*/
|
||||
#define SMC_SVC_NHND (int32_t)-23 /* No more services or
|
||||
service resources.*/
|
||||
#define SMC_SVC_BUSY (int32_t)-16 /* Service busy.*/
|
||||
|
||||
/* Special trusted service handles.*/
|
||||
#define TS_HND_TRAMP ((ts_state_t *)0) /* Trampoline service handle.*/
|
||||
#define TS_HND_DISCOVERY ((ts_state_t *)1) /* Discovery service handle.*/
|
||||
#define TS_HND_STQRY ((ts_state_t *)2) /* Query status service handle.*/
|
||||
#define TS_HND_IDLE ((ts_state_t *)3) /* Idle service handle.*/
|
||||
#define TS_HND_VERSION ((ts_state_t *)4) /* Get version service handle.*/
|
||||
|
||||
/* Fast call service bitmask.
|
||||
Service handles that contain this mask access to
|
||||
the fast call table.*/
|
||||
#define TS_FASTCALL_MASK 0xFFFF0000
|
||||
|
||||
/* Services events event mask.*/
|
||||
#define EVT_DAEMON_REQ_ATN EVENT_MASK(0)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name TSSI module settings.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Max number of services.
|
||||
*/
|
||||
#define TS_MAX_SVCS 64
|
||||
|
||||
/**
|
||||
* @brief Max smc call timeout, in microseconds.
|
||||
*/
|
||||
#define TS_MAX_TMO 10000
|
||||
|
||||
/**
|
||||
* @brief Secure and non secure memory address spaces.
|
||||
*/
|
||||
#if !defined(NSEC_MEMORY_START_ADDR)
|
||||
#define NSEC_MEMORY_START_ADDR ((uint8_t *)0x20000000)
|
||||
#endif
|
||||
#if !defined(NSEC_MEMORY_EXE_OFFSET)
|
||||
#define NSEC_MEMORY_EXE_OFFSET ((uint32_t) 0x00000000)
|
||||
#endif
|
||||
#if !defined(NSEC_MEMORY_END_ADDR)
|
||||
#define NSEC_MEMORY_END_ADDR ((uint8_t *)0x27000000)
|
||||
#endif
|
||||
#if !defined(SEC_MEMORY_START_ADDR)
|
||||
#define SEC_MEMORY_START_ADDR ((uint8_t *)0x27000000)
|
||||
#endif
|
||||
#if !defined(SEC_MEMORY_SIZE)
|
||||
#define SEC_MEMORY_SIZE ((size_t)0x1000000)
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module data structures and types. */
|
||||
/*===========================================================================*/
|
||||
typedef uint8_t * ts_params_area_t;
|
||||
|
||||
typedef struct tssi_service_state {
|
||||
uint32_t ts_status;
|
||||
thread_reference_t ts_thdp;
|
||||
ts_params_area_t ts_datap;
|
||||
uint32_t ts_datalen;
|
||||
} ts_state_t;
|
||||
|
||||
/**
|
||||
* @brief Fast call function.
|
||||
*/
|
||||
typedef msg_t (*fcfunc_t)(ts_params_area_t ts_datap, uint32_t ts_datalen);
|
||||
|
||||
/**
|
||||
* @brief Type of a fast call descriptor.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Fast call service name.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/* The code identifying the service.
|
||||
Used for checking purpose, it must correspond to the
|
||||
order that the service lists in the descriptor table.*/
|
||||
uint32_t code;
|
||||
/**
|
||||
* @brief Fast call function pointer.
|
||||
*/
|
||||
fcfunc_t funcp;
|
||||
} fc_descriptor_t;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Services tables definition macros.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Table of the runtime state of the services.
|
||||
*/
|
||||
#define TS_STATE_TABLE \
|
||||
ts_state_t ts_state[TS_MAX_SVCS] = {0};
|
||||
|
||||
/**
|
||||
* @brief Accessor to the runtime state of service i.
|
||||
*/
|
||||
#define TS_STATE(i) (&ts_state[i])
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start of user service table.
|
||||
*/
|
||||
#define TS_CONF_TABLE_BEGIN \
|
||||
const thread_descriptor_t ts_configs[TS_MAX_SVCS] = {
|
||||
|
||||
/**
|
||||
* @brief Entry of user services table.
|
||||
*/
|
||||
#define TS_CONF_TABLE_ENTRY(name, wap, prio, funcp, tsstatep) \
|
||||
{name, wap, ((stkalign_t *)(wap)) + (sizeof (wap) / sizeof(stkalign_t)), \
|
||||
prio, funcp, tsstatep},
|
||||
|
||||
/**
|
||||
* @brief End of user services table.
|
||||
*/
|
||||
#define TS_CONF_TABLE_END \
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Accessor to the service table entry i.
|
||||
*/
|
||||
#define TS_CONF_TABLE(i) (&ts_configs[i])
|
||||
|
||||
/**
|
||||
* @brief Trusted services base prio.
|
||||
*/
|
||||
#define TS_BASE_PRIO (NORMALPRIO+1)
|
||||
|
||||
/**
|
||||
* @brief Set the service status.
|
||||
* @note The service sets the status at a value representing the status
|
||||
* of the completion of the request. This value is
|
||||
* service dependent.
|
||||
*/
|
||||
#define TS_SET_STATUS(svcp, newst) (((ts_state_t *)svcp)->ts_status = newst)
|
||||
|
||||
/**
|
||||
* @brief Get the pointer to the client shared memory.
|
||||
* @note The client sets the data field at the start address
|
||||
* of a shared memory allocated from the non secure memory space.
|
||||
*/
|
||||
#define TS_GET_DATA(svcp) ((char *)((ts_state_t *)svcp)->ts_datap)
|
||||
|
||||
/**
|
||||
* @brief Get the size of the client shared memory.
|
||||
* @note The client sets the datalen field to the size
|
||||
* of a shared memory allocated from the non secure memory space.
|
||||
*/
|
||||
#define TS_GET_DATALEN(svcp) (((ts_state_t *)svcp)->ts_datalen)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Fast call table definition macros.
|
||||
* @note Fast call services run at max priority level, so it is
|
||||
* mandatory that they last less time as possible.
|
||||
* @note Fast call services should be invoked using
|
||||
* the tsInvoke0 function in order to optimize the
|
||||
* performances.
|
||||
* @note Fast call services don't have a runtime state, so
|
||||
* the response management is in charge to the higher levels.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start of user fast call service table.
|
||||
*/
|
||||
#define TS_FC_CONF_TABLE_BEGIN \
|
||||
const fc_descriptor_t ts_fc_configs[] = {
|
||||
|
||||
/**
|
||||
* @brief Entry of user fast call services table.
|
||||
*/
|
||||
#define TS_FC_CONF_TABLE_ENTRY(name, code, funcp) \
|
||||
{name, code, funcp},
|
||||
|
||||
/**
|
||||
* @brief End of user fast call services table.
|
||||
*/
|
||||
#define TS_FC_CONF_TABLE_END \
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Accessor to the fast call service table entry i.
|
||||
*/
|
||||
#define TS_FC_CONF_TABLE(i) (&ts_fc_configs[i])
|
||||
|
||||
/**
|
||||
* @brief Number of entries in the fast call service table.
|
||||
*/
|
||||
#define TS_FC_CONF_TABLE_N (sizeof ts_fc_configs / sizeof ts_fc_configs[0])
|
||||
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern event_source_t tsEventSource;
|
||||
extern ts_state_t ts_state[];
|
||||
extern const thread_descriptor_t ts_configs[];
|
||||
extern thread_reference_t _ns_thread;
|
||||
CC_NO_RETURN void _ns_trampoline(uint8_t *addr);
|
||||
CC_NO_RETURN void tssiInit(void);
|
||||
msg_t tssiWaitRequest(ts_state_t *svcp);
|
||||
bool tsIsAddrSpaceValid(void *addr, size_t size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Module inline functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#endif /* CHTSSI_H */
|
|
@ -1,169 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ARMCMAx-TZ/compilers/GCC/chcoreasm.S
|
||||
* @brief ARMCMAx-TZ architecture port low level code.
|
||||
*
|
||||
* @addtogroup ARMCMAx-TZ_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define _FROM_ASM_
|
||||
#include "chlicense.h"
|
||||
#include "chconf.h"
|
||||
#include "armparams.h"
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
|
||||
/*
|
||||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#define CONTEXT_OFFSET 12
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CONTEXT_OFFSET 0
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
||||
.set MODE_USR, 0x10
|
||||
.set MODE_FIQ, 0x11
|
||||
.set MODE_IRQ, 0x12
|
||||
.set MODE_SVC, 0x13
|
||||
.set MODE_MON, 0x16
|
||||
.set MODE_ABT, 0x17
|
||||
.set MODE_UND, 0x1B
|
||||
.set MODE_SYS, 0x1F
|
||||
|
||||
.set I_BIT, 0x80
|
||||
.set F_BIT, 0x40
|
||||
|
||||
.text
|
||||
|
||||
.balign 16
|
||||
|
||||
.code 32
|
||||
.global _port_switch_arm
|
||||
_port_switch_arm:
|
||||
stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
|
||||
str sp, [r1, #12]
|
||||
ldr sp, [r0, #12]
|
||||
ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
|
||||
|
||||
/*
|
||||
* Common IRQ code. It expects a macro ARM_IRQ_VECTOR_REG with the address
|
||||
* of a register holding the address of the ISR to be invoked, the ISR
|
||||
* then returns in the common epilogue code where the context switch will
|
||||
* be performed, if required.
|
||||
* System stack frame structure after a context switch in the
|
||||
* interrupt handler:
|
||||
*
|
||||
* High +------------+
|
||||
* | LR_USR | -+
|
||||
* | r12 | |
|
||||
* | r3 | |
|
||||
* | r2 | | External context: IRQ handler frame
|
||||
* | r1 | |
|
||||
* | r0 | |
|
||||
* | LR_FIQ | | (user code return address)
|
||||
* | PSR_USR | -+ (user code status)
|
||||
* | .... | <- chSchDoReschedule() stack frame, optimize it for space
|
||||
* | LR | -+ (system code return address)
|
||||
* | r11 | |
|
||||
* | r10 | |
|
||||
* | r9 | |
|
||||
* | r8 | | Internal context: chSysSwitch() frame
|
||||
* | r7 | |
|
||||
* | r6 | |
|
||||
* | r5 | |
|
||||
* SP-> | r4 | -+
|
||||
* Low +------------+
|
||||
*
|
||||
*/
|
||||
.balign 16
|
||||
.code 32
|
||||
.global Fiq_Handler
|
||||
Fiq_Handler:
|
||||
// the fiq is taken locally from secure state
|
||||
// current mode is fiq
|
||||
stmfd sp!, {r0-r3, r12, lr} // save scratch registers and lr
|
||||
ldr r0, =ARM_IRQ_VECTOR_REG
|
||||
ldr r0, [r0]
|
||||
ldr lr, =_fiq_ret_arm // ISR return point.
|
||||
bx r0 // Calling the ISR.
|
||||
_fiq_ret_arm:
|
||||
cmp r0, #0
|
||||
ldmfd sp!, {r0-r3, r12, lr}
|
||||
subeqs pc, lr, #4 // No reschedule, returns.
|
||||
|
||||
// Now the frame is created in the system stack of the current
|
||||
// thread, the IRQ stack is empty.
|
||||
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
||||
stmfd sp!, {r0-r3, r12, lr}
|
||||
msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
|
||||
mrs r0, SPSR
|
||||
mov r1, lr
|
||||
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
||||
stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_FIQ.
|
||||
|
||||
// Context switch.
|
||||
#if CH_DBG_SYSTEM_STATE_CHECK
|
||||
bl _dbg_check_lock
|
||||
#endif
|
||||
bl chSchDoReschedule
|
||||
#if CH_DBG_SYSTEM_STATE_CHECK
|
||||
bl _dbg_check_unlock
|
||||
#endif
|
||||
|
||||
// Re-establish the IRQ conditions again.
|
||||
ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_FIQ.
|
||||
msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
|
||||
msr SPSR_fsxc, r0
|
||||
mov lr, r1
|
||||
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
|
||||
ldmfd sp!, {r0-r3, r12, lr}
|
||||
msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
|
||||
subs pc, lr, #4
|
||||
|
||||
/*
|
||||
* Threads trampoline code.
|
||||
* NOTE: The threads always start in ARM mode.
|
||||
*/
|
||||
.balign 16
|
||||
.code 32
|
||||
.globl _port_thread_start
|
||||
_port_thread_start:
|
||||
#if CH_DBG_SYSTEM_STATE_CHECK
|
||||
bl _dbg_check_unlock
|
||||
#endif
|
||||
msr CPSR_c, #MODE_SYS
|
||||
mov r0, r5
|
||||
mov lr, pc
|
||||
bx r4
|
||||
mov r0, #0 /* MSG_OK */
|
||||
bl chThdExit
|
||||
_zombies: b _zombies
|
||||
|
||||
#endif /* !defined(__DOXYGEN__) */
|
||||
|
||||
/** @} */
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
|
||||
|
||||
This file is part of ChibiOS.
|
||||
|
||||
ChibiOS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
ChibiOS is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ARMCMAx-TZ/compilers/GCC/chtypes.h
|
||||
* @brief ARMCMAx-TZ port system types.
|
||||
*
|
||||
* @addtogroup ARMCMAx-TZ_GCC_CORE
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef CHTYPES_H
|
||||
#define CHTYPES_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* @name Common constants
|
||||
*/
|
||||
/**
|
||||
* @brief Generic 'false' boolean constant.
|
||||
*/
|
||||
#if !defined(FALSE) || defined(__DOXYGEN__)
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Generic 'true' boolean constant.
|
||||
*/
|
||||
#if !defined(TRUE) || defined(__DOXYGEN__)
|
||||
#define TRUE 1
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Kernel types
|
||||
* @{
|
||||
*/
|
||||
typedef uint32_t rtcnt_t; /**< Realtime counter. */
|
||||
typedef uint64_t rttime_t; /**< Realtime accumulator. */
|
||||
typedef uint32_t syssts_t; /**< System status word. */
|
||||
typedef uint8_t tmode_t; /**< Thread flags. */
|
||||
typedef uint8_t tstate_t; /**< Thread state. */
|
||||
typedef uint8_t trefs_t; /**< Thread references counter. */
|
||||
typedef uint8_t tslices_t; /**< Thread time slices counter.*/
|
||||
typedef uint32_t tprio_t; /**< Thread priority. */
|
||||
typedef int32_t msg_t; /**< Inter-thread message. */
|
||||
typedef int32_t eventid_t; /**< Numeric event identifier. */
|
||||
typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
|
||||
typedef uint32_t eventflags_t; /**< Mask of event flags. */
|
||||
typedef int32_t cnt_t; /**< Generic signed counter. */
|
||||
typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief ROM constant modifier.
|
||||
* @note It is set to use the "const" keyword in this port.
|
||||
*/
|
||||
#define ROMCONST const
|
||||
|
||||
/**
|
||||
* @brief Makes functions not inlineable.
|
||||
* @note If the compiler does not support such attribute then some
|
||||
* time-dependent services could be degraded.
|
||||
*/
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
|
||||
/**
|
||||
* @brief Optimized thread function declaration macro.
|
||||
*/
|
||||
#define PORT_THD_FUNCTION(tname, arg) void tname(void *arg)
|
||||
|
||||
/**
|
||||
* @brief Packed variable specifier.
|
||||
*/
|
||||
#define PACKED_VAR __attribute__((packed))
|
||||
|
||||
/**
|
||||
* @brief Memory alignment enforcement for variables.
|
||||
*/
|
||||
#define ALIGNED_VAR(n) __attribute__((aligned(n)))
|
||||
|
||||
/**
|
||||
* @brief Size of a pointer.
|
||||
* @note To be used where the sizeof operator cannot be used, preprocessor
|
||||
* expressions for example.
|
||||
*/
|
||||
#define SIZEOF_PTR 4
|
||||
|
||||
/**
|
||||
* @brief True if alignment is low-high in current architecture.
|
||||
*/
|
||||
#define REVERSE_ORDER 1
|
||||
|
||||
#endif /* CHTYPES_H */
|
||||
|
||||
/** @} */
|
|
@ -1,14 +0,0 @@
|
|||
# List of the ChibiOS/RT ARMCAx-TZ generic port files.
|
||||
PORTSRC = ${CHIBIOS}/os/common/ports/ARMCAx-TZ/chcore.c \
|
||||
${CHIBIOS}/os/common/ports/ARMCAx-TZ/chtssi.c
|
||||
|
||||
PORTASM = $(CHIBIOS)/os/common/ports/ARMCAx-TZ/compilers/GCC/chcoreasm.S \
|
||||
$(CHIBIOS)/os/common/ports/ARMCAx-TZ/compilers/GCC/monitor.S
|
||||
|
||||
PORTINC = ${CHIBIOS}/os/common/ports/ARMCAx-TZ \
|
||||
${CHIBIOS}/os/common/ports/ARMCAx-TZ/compilers/GCC
|
||||
|
||||
# Shared variables
|
||||
ALLXASMSRC += $(PORTASM)
|
||||
ALLCSRC += $(PORTSRC)
|
||||
ALLINC += $(PORTINC)
|
|
@ -1,302 +0,0 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ARMCAx-TZ/compilers/GCC/monitor.S
|
||||
* @brief ARMCAx-TZ monitor code
|
||||
*
|
||||
* @addtogroup ARM_CORE
|
||||
* @{
|
||||
*/
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define _FROM_ASM_
|
||||
#include "chlicense.h"
|
||||
#include "chconf.h"
|
||||
#include "armparams.h"
|
||||
|
||||
/*
|
||||
* We are facing an architecure with security extension exploited.
|
||||
* The following execution paths are taken by the execution units
|
||||
* running in secure state when an irq is fired (sm_irq), and in non-secure
|
||||
* state when a fiq interrupt is fired (sm_fiq).
|
||||
* They originate by the monitor irq/fiq vector and run in monitor mode,
|
||||
* ie in secure state.
|
||||
* It assumes the following, intially set at boot time, or wherever it needs:
|
||||
* SCR.FW == 0 and SCR.FIQ == 1 and SCR.IRQ == 0 in non-secure state,
|
||||
* ie FIQs are taken to monitor mode, IRQs are taken locally
|
||||
* SCR.FW == 0 and SCR.FIQ == 0 and SCR.IRQ == 1 in secure state,
|
||||
* ie FIQs are taken locally, IRQs are taken to monitor mode
|
||||
* MVBAR holds the address of the monitor vectors base.
|
||||
* The code and the stacks memory reside both in secure memory.
|
||||
*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
|
||||
.set MODE_USR, 0x10
|
||||
.set MODE_FIQ, 0x11
|
||||
.set MODE_IRQ, 0x12
|
||||
.set MODE_SVC, 0x13
|
||||
.set MODE_MON, 0x16
|
||||
.set MODE_ABT, 0x17
|
||||
.set MODE_UND, 0x1B
|
||||
.set MODE_SYS, 0x1F
|
||||
|
||||
.set SCR_NS, 0x01
|
||||
.set SCR_IRQ, 0x02
|
||||
.set SCR_FIQ, 0x04
|
||||
.set SCR_EA, 0x08
|
||||
.set SCR_FW, 0x10
|
||||
.set SCR_AW, 0x20
|
||||
|
||||
.set MON_S_SCR, (SCR_IRQ) // (SCR_EA|SCR_IRQ)
|
||||
.set MON_NS_SCR, (SCR_FIQ|SCR_NS)
|
||||
|
||||
.set SMC_SVC_INTR, -4
|
||||
|
||||
.comm sm_secctx, 20*4, 4
|
||||
.comm sm_nsecctx, 20*4, 4
|
||||
|
||||
.global _ns_thread
|
||||
.section .text
|
||||
.code 32
|
||||
.balign 4
|
||||
/*
|
||||
* Helper macros
|
||||
*/
|
||||
/*
|
||||
* Store banked registers in a world area pointed by rm
|
||||
*/
|
||||
.macro sm_store_ooctx_regs rm
|
||||
// cps #MODE_SYS // Assume mode SYS
|
||||
stm \rm!, {sp, lr}
|
||||
cps #MODE_FIQ
|
||||
mrs r12, spsr
|
||||
stm \rm!, {r12, sp, lr}
|
||||
cps #MODE_IRQ
|
||||
mrs r12, spsr
|
||||
stm \rm!, {r12, sp, lr}
|
||||
cps #MODE_ABT
|
||||
mrs r12, spsr
|
||||
stm \rm!, {r12, sp, lr}
|
||||
cps #MODE_SVC
|
||||
mrs r12, spsr
|
||||
stm \rm!, {r12, sp, lr}
|
||||
cps #MODE_UND
|
||||
mrs r12, spsr
|
||||
stm \rm!, {r12, sp, lr}
|
||||
.endm
|
||||
/*
|
||||
* Retrieve banked registers from a world area pointed by rm
|
||||
*/
|
||||
.macro sm_load_ooctx_regs rm
|
||||
// cps #MODE_SYS // Assume mode SYS
|
||||
ldm \rm!, {sp, lr}
|
||||
cps #MODE_FIQ
|
||||
ldm \rm!, {r12, sp, lr}
|
||||
msr spsr_fsxc, r12
|
||||
cps #MODE_IRQ
|
||||
ldm \rm!, {r12, sp, lr}
|
||||
msr spsr_fsxc, r12
|
||||
cps #MODE_ABT
|
||||
ldm \rm!, {r12, sp, lr}
|
||||
msr spsr_fsxc, r12
|
||||
cps #MODE_SVC
|
||||
ldm \rm!, {r12, sp, lr}
|
||||
msr spsr_fsxc, r12
|
||||
cps #MODE_UND
|
||||
ldm \rm!, {r12, sp, lr}
|
||||
msr spsr_fsxc, r12
|
||||
.endm
|
||||
/*
|
||||
* Monitor vectors
|
||||
*/
|
||||
.global _monitor_vectors
|
||||
.balign 32
|
||||
_monitor_vectors:
|
||||
b . // Reset vector, not used
|
||||
b . // Undefined instruction, not used
|
||||
b sm_call // Secure monitor call
|
||||
b . // Prefetch abort, not taken to Monitor mode
|
||||
b . // Data abort, not taken to Monitor mode
|
||||
b . // Reserved
|
||||
b sm_irq // IRQ
|
||||
b sm_fiq // FIQ
|
||||
/*
|
||||
* SMC entry
|
||||
*/
|
||||
sm_call:
|
||||
stmfd sp!, {r4, r12}
|
||||
ldr r12, =MON_S_SCR // enter in the secure world
|
||||
mcr p15, 0, r12, c1, c1, 0
|
||||
ands r0, r0 // OS special service,
|
||||
// 0 == jump trampoline to non secure world
|
||||
// r1 contains the address where it jumps
|
||||
beq 1f
|
||||
|
||||
mrs r4, SPSR
|
||||
mov r12, lr
|
||||
stmfd sp!, {r4, r12} // push r4=spsr_mon, r12=lr_mon.
|
||||
|
||||
cps #MODE_SYS // switch to sys mode, ints disabled
|
||||
ldr r4, =sm_nsecctx
|
||||
sm_store_ooctx_regs r4
|
||||
|
||||
cps #MODE_SYS
|
||||
ldr r4, =sm_secctx
|
||||
sm_load_ooctx_regs r4
|
||||
|
||||
cps #MODE_SYS
|
||||
bl smcEntry // call the C smc handler
|
||||
|
||||
ldr r4, =sm_secctx
|
||||
sm_store_ooctx_regs r4
|
||||
|
||||
cps #MODE_SYS
|
||||
ldr r4, =sm_nsecctx
|
||||
sm_load_ooctx_regs r4
|
||||
|
||||
cps #MODE_MON // switch to monitor mode
|
||||
|
||||
ldmfd sp!, {r4, r12} // pop r4=spsr_mon, r12=lr_mon.
|
||||
msr SPSR_fsxc, r4
|
||||
mov lr, r12
|
||||
|
||||
ldr r12, =MON_NS_SCR // enter in the non-secure world
|
||||
mcr p15, 0, r12, c1, c1, 0
|
||||
ldmfd sp!, {r4, r12}
|
||||
subs pc, lr, #0 // return from smc
|
||||
1:
|
||||
mov lr, r1 // use the address in r1 as return address
|
||||
// in the non secure world
|
||||
ldr r12, =MON_NS_SCR // enter in the non-secure world
|
||||
mcr p15, 0, r12, c1, c1, 0
|
||||
ldmfd sp!, {r4, r12}
|
||||
subs pc, lr, #0 // return from smc
|
||||
|
||||
/*
|
||||
* FIQ entry
|
||||
*
|
||||
* Here the fiq is taken from non-secure state, via the FIQ vector
|
||||
* that is in the monitor vector table.
|
||||
* Current mode is monitor (so current state is secure).
|
||||
* We switch immediately to system mode, enabling FIQ.
|
||||
* The FIQ is then served while the ns_thread is running.
|
||||
* Because the ns_thread has the highest priority, the handler returns here
|
||||
* without scheduling.
|
||||
*/
|
||||
sm_fiq:
|
||||
// check point: SCR.NS == 1
|
||||
stmfd sp!, {r0, r12}
|
||||
ldr r0, =MON_S_SCR // enter in the secure world
|
||||
mcr p15, 0, r0, c1, c1, 0
|
||||
|
||||
cps #MODE_SYS
|
||||
ldr r0, =sm_nsecctx
|
||||
sm_store_ooctx_regs r0
|
||||
|
||||
cps #MODE_SYS
|
||||
ldr r0, =sm_secctx
|
||||
sm_load_ooctx_regs r0
|
||||
|
||||
cpsie f, #MODE_SYS // FIQ enabled, served via base table
|
||||
|
||||
cpsid f, #MODE_SYS // the handler returns here, FIQ disabled.
|
||||
ldr r0, =sm_secctx
|
||||
sm_store_ooctx_regs r0
|
||||
|
||||
cps #MODE_SYS
|
||||
ldr r0, =sm_nsecctx
|
||||
sm_load_ooctx_regs r0
|
||||
|
||||
cps #MODE_MON // switch to monitor mode
|
||||
ldr r0, =MON_NS_SCR // set non-secure SCR before return
|
||||
mcr p15, 0, r0, c1, c1, 0
|
||||
ldmfd sp!, {r0, r12}
|
||||
subs pc, lr, #4 // return into non-secure world
|
||||
/*
|
||||
* IRQ entry
|
||||
*
|
||||
* Here the IRQ is taken from secure state.
|
||||
* Current mode is monitor (so current state is secure),
|
||||
* the previous mode and status is in spsr_mon and
|
||||
* the return address+4 is in lr_mon.
|
||||
* Because we are running in secure state, we are sure that
|
||||
* the main thread is suspended in the smc handler.
|
||||
* The main thread is then resumed with SMC_SVC_INTR
|
||||
* The non secure world has then the responsibility to return into
|
||||
* secure state via a smc.
|
||||
*
|
||||
*/
|
||||
sm_irq:
|
||||
// check point: SCR.NS == 0
|
||||
cps #MODE_SYS
|
||||
stmfd sp!, {r0-r3, r12, lr} // save scratch registers and lr
|
||||
cps #MODE_MON // switch to monitor mode
|
||||
mrs r0, spsr
|
||||
mov r1, lr
|
||||
cps #MODE_SYS
|
||||
stmfd sp!, {r0, r1} // push r0=spsr_mon, r1=lr_mon.
|
||||
// check point: ns_tread != 0
|
||||
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
||||
bl _dbg_check_lock
|
||||
#endif
|
||||
ldr r0, =_ns_thread
|
||||
mov r1, #SMC_SVC_INTR
|
||||
bl chThdResumeS // resume the ns_thread and serve the IRQ
|
||||
// into non-secure world
|
||||
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE)
|
||||
bl _dbg_check_unlock
|
||||
#endif
|
||||
// The ns_thread reentered smc, that set SRC.NS to 0
|
||||
// re-establish the original conditions
|
||||
ldmfd sp!, {r0, r1} // pop r0=spsr_mon, r1=lr_mon.
|
||||
cps #MODE_MON // switch to monitor mode
|
||||
msr SPSR_fsxc, r0
|
||||
mov lr, r1
|
||||
cps #MODE_SYS
|
||||
ldmfd sp!, {r0-r3, r12, lr}
|
||||
cps #MODE_MON // switch to monitor mode
|
||||
subs pc, lr, #4 // return into secure world
|
||||
|
||||
.global _ns_trampoline
|
||||
_ns_trampoline:
|
||||
mov r1, r0
|
||||
|
||||
ldr r0, =sm_secctx
|
||||
sm_store_ooctx_regs r0
|
||||
cps #MODE_SYS
|
||||
|
||||
ldr r0, =#0
|
||||
/* mov r2, r0 */ // r2 could contain the address of the fdt
|
||||
mov r3, r0
|
||||
mov r4, r0
|
||||
mov r5, r0
|
||||
mov r6, r0
|
||||
mov r7, r0
|
||||
mov r8, r0
|
||||
mov r9, r0
|
||||
mov r10, r0
|
||||
mov r11, r0
|
||||
mov r12, r0
|
||||
mov sp, r0
|
||||
mov lr, r0
|
||||
smc #0
|
||||
|
||||
#endif /* !defined(__DOXYGEN__) */
|
||||
|
||||
/** @} */
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -57,26 +57,17 @@
|
|||
* @param[in] sp the stack pointer being switched-out
|
||||
* @return The stack pointer being switched-in.
|
||||
*/
|
||||
void *port_swap_stacks(void *sp) {
|
||||
thread_t *port_schedule_next(void) {
|
||||
thread_t *ntp;
|
||||
|
||||
#if CH_DBG_ENABLE_STACK_CHECK == TRUE
|
||||
currp->ctx.splim = __get_PSPLIM();
|
||||
#endif
|
||||
|
||||
chSysLock();
|
||||
|
||||
/* TODO statistics, tracing etc */
|
||||
currp->ctx.sp = sp;
|
||||
ntp = chSchRunAhead();
|
||||
|
||||
chSysUnlock();
|
||||
|
||||
#if CH_DBG_ENABLE_STACK_CHECK == TRUE
|
||||
__set_PSPLIM(ntp->ctx.splim);
|
||||
#endif
|
||||
|
||||
return ntp->ctx.sp;
|
||||
return ntp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -255,25 +255,14 @@ struct port_extctx {};
|
|||
* switch.
|
||||
*/
|
||||
struct port_intctx {
|
||||
uint32_t basepri;
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t lr_exc;
|
||||
/* Start of the hardware saved frame.*/
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr_thd;
|
||||
uint32_t pc;
|
||||
uint32_t xpsr;
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
uint32_t r2;
|
||||
uint32_t r3;
|
||||
uint32_t r12;
|
||||
uint32_t lr_thd;
|
||||
uint32_t pc;
|
||||
uint32_t xpsr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -284,9 +273,19 @@ struct port_intctx {
|
|||
*/
|
||||
struct port_context {
|
||||
struct port_intctx *sp;
|
||||
uint32_t basepri;
|
||||
uint32_t r4;
|
||||
uint32_t r5;
|
||||
uint32_t r6;
|
||||
uint32_t r7;
|
||||
uint32_t r8;
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
|
||||
uint32_t splim;
|
||||
#endif
|
||||
uint32_t lr_exc;
|
||||
};
|
||||
|
||||
#endif /* !defined(_FROM_ASM_) */
|
||||
|
@ -364,24 +363,24 @@ struct port_context {
|
|||
*/
|
||||
#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
|
||||
#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) do { \
|
||||
(tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
|
||||
sizeof (struct port_intctx)); \
|
||||
(tp)->ctx.basepri = CORTEX_BASEPRI_KERNEL; \
|
||||
(tp)->ctx.r5 = (uint32_t)(arg); \
|
||||
(tp)->ctx.r4 = (uint32_t)(pf); \
|
||||
(tp)->ctx.splim = (uint32_t)(wbase); \
|
||||
(tp)->ctx.sp = (struct port_intctx *) \
|
||||
((uint8_t *)(wtop) - sizeof (struct port_intctx));\
|
||||
(tp)->ctx.sp->basepri = CORTEX_BASEPRI_KERNEL; \
|
||||
(tp)->ctx.sp->r5 = (uint32_t)(arg); \
|
||||
(tp)->ctx.sp->r4 = (uint32_t)(pf); \
|
||||
(tp)->ctx.sp->lr_exc = (uint32_t)0xFFFFFFFD; \
|
||||
(tp)->ctx.lr_exc = (uint32_t)0xFFFFFFFD; \
|
||||
(tp)->ctx.sp->xpsr = (uint32_t)0x01000000; \
|
||||
(tp)->ctx.sp->pc = (uint32_t)__port_thread_start; \
|
||||
} while (false)
|
||||
#else
|
||||
#define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) do { \
|
||||
(tp)->ctx.sp = (struct port_intctx *) \
|
||||
((uint8_t *)(wtop) - sizeof (struct port_intctx));\
|
||||
(tp)->ctx.sp->basepri = CORTEX_BASEPRI_KERNEL; \
|
||||
(tp)->ctx.sp->r5 = (uint32_t)(arg); \
|
||||
(tp)->ctx.sp->r4 = (uint32_t)(pf); \
|
||||
(tp)->ctx.sp->lr_exc = (uint32_t)0xFFFFFFFD; \
|
||||
(tp)->ctx.sp = (struct port_intctx *)((uint8_t *)(wtop) - \
|
||||
sizeof (struct port_intctx)); \
|
||||
(tp)->ctx.basepri = CORTEX_BASEPRI_KERNEL; \
|
||||
(tp)->ctx.r5 = (uint32_t)(arg); \
|
||||
(tp)->ctx.r4 = (uint32_t)(pf); \
|
||||
(tp)->ctx.lr_exc = (uint32_t)0xFFFFFFFD; \
|
||||
(tp)->ctx.sp->xpsr = (uint32_t)0x01000000; \
|
||||
(tp)->ctx.sp->pc = (uint32_t)__port_thread_start; \
|
||||
} while (false)
|
||||
|
@ -459,7 +458,6 @@ struct port_context {
|
|||
* @param[in] ntp the thread to be switched in
|
||||
* @param[in] otp the thread to be switched out
|
||||
*/
|
||||
#if (CH_DBG_ENABLE_STACK_CHECK == FALSE) || defined(__DOXYGEN__)
|
||||
#define port_switch(ntp, otp) do { \
|
||||
_dbg_leave_lock(); \
|
||||
register thread_t *_ntp asm ("r0") = (ntp); \
|
||||
|
@ -467,19 +465,6 @@ struct port_context {
|
|||
asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory"); \
|
||||
_dbg_enter_lock(); \
|
||||
} while (false)
|
||||
#else
|
||||
#define port_switch(ntp, otp) do { \
|
||||
_dbg_leave_lock(); \
|
||||
register thread_t *_ntp asm ("r0") = (ntp); \
|
||||
register thread_t *_otp asm ("r1") = (otp); \
|
||||
struct port_intctx *r13 = (struct port_intctx *)__get_PSP(); \
|
||||
if ((stkalign_t *)(r13 - 1) < (otp)->wabase) { \
|
||||
chSysHalt("stack overflow"); \
|
||||
} \
|
||||
asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp) : "memory"); \
|
||||
_dbg_enter_lock(); \
|
||||
} while (false)
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
|
|
|
@ -44,9 +44,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
@ -75,20 +84,28 @@
|
|||
.thumb_func
|
||||
.globl SVC_Handler
|
||||
SVC_Handler:
|
||||
mrs r3, BASEPRI
|
||||
/* Saving callee context of thread being swapped out.*/
|
||||
adds r1, #CONTEXT_OFFSET
|
||||
mrs r2, PSP
|
||||
stmdb r2!, {r3-r11,lr}
|
||||
str r2, [r1, #CONTEXT_OFFSET]
|
||||
mrs r3, BASEPRI
|
||||
// movs r3, #(2 << 5)
|
||||
#if CH_DBG_ENABLE_STACK_CHECK
|
||||
mrs r2, PSPLIM
|
||||
str r2, [r1, #CONTEXT_OFFSET + 4]
|
||||
ldr r2, [r0, #CONTEXT_OFFSET + 4]
|
||||
msr PSPLIM, r2
|
||||
mrs r12, PSPLIM
|
||||
stmia r1, {r2-r12,lr}
|
||||
#else
|
||||
stmia r1, {r2-r11,lr}
|
||||
#endif
|
||||
|
||||
/* Restoring calle context of thread being swapped in.*/
|
||||
adds r0, #CONTEXT_OFFSET
|
||||
#if CH_DBG_ENABLE_STACK_CHECK
|
||||
ldmia r0, {r2-r12, lr}
|
||||
msr PSPLIM, r12
|
||||
#else
|
||||
ldmia r0, {r2-r11, lr}
|
||||
#endif
|
||||
ldr r2, [r0, #CONTEXT_OFFSET]
|
||||
ldmia r2!, {r3-r11, lr}
|
||||
msr PSP, r2
|
||||
msr BASEPRI, r3
|
||||
msr PSP, r2
|
||||
bx lr
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
|
@ -97,13 +114,34 @@ SVC_Handler:
|
|||
.thumb_func
|
||||
.globl PendSV_Handler
|
||||
PendSV_Handler:
|
||||
/* Pointer to the current thread.*/
|
||||
ldr r1, =ch
|
||||
ldr r1, [r1, #CURRENT_OFFSET]
|
||||
|
||||
/* Saving callee context of thread being swapped out.*/
|
||||
adds r1, #CONTEXT_OFFSET
|
||||
mrs r2, PSP
|
||||
mrs r3, BASEPRI
|
||||
mrs r0, PSP
|
||||
stmdb r0!, {r3-r11,lr}
|
||||
bl port_swap_stacks
|
||||
ldmia r0!, {r3-r11, lr}
|
||||
msr PSP, r0
|
||||
#if CH_DBG_ENABLE_STACK_CHECK
|
||||
mrs r12, PSPLIM
|
||||
stmia r1, {r2-r12,lr}
|
||||
#else
|
||||
stmia r1, {r2-r11,lr}
|
||||
#endif
|
||||
|
||||
/* Selecting the thread to be swapped in.*/
|
||||
bl port_schedule_next
|
||||
|
||||
/* Restoring calle context of thread being swapped in.*/
|
||||
adds r0, #CONTEXT_OFFSET
|
||||
#if CH_DBG_ENABLE_STACK_CHECK
|
||||
ldmia r0, {r2-r12, lr}
|
||||
msr PSPLIM, r12
|
||||
#else
|
||||
ldmia r0, {r2-r11, lr}
|
||||
#endif
|
||||
msr BASEPRI, r3
|
||||
msr PSP, r2
|
||||
bx lr
|
||||
|
||||
/*--------------------------------------------------------------------------*
|
||||
|
|
|
@ -51,13 +51,19 @@
|
|||
|
||||
#if !defined(__DOXYGEN__)
|
||||
|
||||
/*
|
||||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
@ -80,8 +86,8 @@ _port_switch:
|
|||
se_stw r0, 0(r1)
|
||||
e_stmw r14, 4(r1)
|
||||
|
||||
se_stw r1, 12(r4)
|
||||
se_lwz r1, 12(r3)
|
||||
se_stw r1, CONTEXT_OFFSET(r4)
|
||||
se_lwz r1, CONTEXT_OFFSET(r3)
|
||||
|
||||
e_lmw r14, 4(r1)
|
||||
se_lwz r0, 0(r1)
|
||||
|
|
|
@ -56,9 +56,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -52,9 +52,18 @@
|
|||
* RTOS-specific context offset.
|
||||
*/
|
||||
#if defined(_CHIBIOS_RT_CONF_)
|
||||
#if CH_CFG_USE_REGISTRY
|
||||
#define CURRENT_OFFSET 20 /* ch.rlist.current */
|
||||
#define CONTEXT_OFFSET 20
|
||||
#else
|
||||
#define CURRENT_OFFSET 12 /* nil.current */
|
||||
#define CONTEXT_OFFSET 12
|
||||
#endif
|
||||
|
||||
#elif defined(_CHIBIOS_NIL_CONF_)
|
||||
#define CURRENT_OFFSET 0
|
||||
#define CONTEXT_OFFSET 0
|
||||
|
||||
#else
|
||||
#error "invalid chconf.h"
|
||||
#endif
|
||||
|
|
|
@ -142,12 +142,15 @@ struct ch_threads_queue {
|
|||
struct ch_thread {
|
||||
threads_queue_t queue; /**< @brief Threads queue header. */
|
||||
tprio_t prio; /**< @brief Thread priority. */
|
||||
struct port_context ctx; /**< @brief Processor context. */
|
||||
#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
|
||||
thread_t *newer; /**< @brief Newer registry element. */
|
||||
thread_t *older; /**< @brief Older registry element. */
|
||||
#endif
|
||||
/* End of the fields shared with the ReadyList structure. */
|
||||
/**
|
||||
* @brief Processor context.
|
||||
*/
|
||||
struct port_context ctx;
|
||||
#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Thread name or @p NULL.
|
||||
|
@ -351,8 +354,6 @@ struct ch_ready_list {
|
|||
threads_queue_t queue; /**< @brief Threads queue. */
|
||||
tprio_t prio; /**< @brief This field must be
|
||||
initialized to zero. */
|
||||
struct port_context ctx; /**< @brief Not used, present because
|
||||
offsets. */
|
||||
#if (CH_CFG_USE_REGISTRY == TRUE) || defined(__DOXYGEN__)
|
||||
thread_t *newer; /**< @brief Newer registry element. */
|
||||
thread_t *older; /**< @brief Older registry element. */
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
*****************************************************************************
|
||||
|
||||
*** Next ***
|
||||
- RT: Relocated the "ctx" field in the thread structure in order to save
|
||||
some RAM, it caused unused space in the "ch" variable.
|
||||
- EX: Added support for ADXL355 Low Noise, Low Drift, Low Power, 3-Axis
|
||||
MEMS Accelerometers.
|
||||
- NEW: Safer messages mechanism for sandboxes (to be backported to 20.3.1).
|
||||
|
|
Loading…
Reference in New Issue