git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@13496 27425a3e-05d8-49a3-a47f-9c15f0e5edd8

This commit is contained in:
Giovanni Di Sirio 2020-04-01 17:06:02 +00:00
parent 5395751f6c
commit a0f0a8dc5e
27 changed files with 188 additions and 2221 deletions

View File

@ -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
/**

View File

@ -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;

View File

@ -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}
/*

View File

@ -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. */
/*===========================================================================*/
/** @} */

View File

@ -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 */
/** @} */

View File

@ -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 */
/** @} */

View File

@ -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.*/
}
/** @} */

View File

@ -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 */

View File

@ -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__) */
/** @} */

View File

@ -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 */
/** @} */

View File

@ -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)

View File

@ -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__) */
/** @} */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
/**

View File

@ -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. */

View File

@ -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
/*--------------------------------------------------------------------------*

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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).