diff --git a/demos/STM32/RT-STM32L476-DISCOVERY-SB_HOST/cfg/chconf.h b/demos/STM32/RT-STM32L476-DISCOVERY-SB_HOST/cfg/chconf.h index 000c38f96..0618230a2 100644 --- a/demos/STM32/RT-STM32L476-DISCOVERY-SB_HOST/cfg/chconf.h +++ b/demos/STM32/RT-STM32L476-DISCOVERY-SB_HOST/cfg/chconf.h @@ -756,6 +756,9 @@ /* Port-specific settings (override port settings defaulted in chcore.h). */ /*===========================================================================*/ +#define PORT_USE_SYSCALL TRUE +#define PORT_SWITCHED_REGIONS_NUMBER 0 + #endif /* CHCONF_H */ /** @} */ diff --git a/os/common/ports/ARMCMx/chcore_v7m.c b/os/common/ports/ARMCMx/chcore_v7m.c index d00134602..9d43b1cf2 100644 --- a/os/common/ports/ARMCMx/chcore_v7m.c +++ b/os/common/ports/ARMCMx/chcore_v7m.c @@ -122,13 +122,13 @@ void port_unprivileged_jump(regarm_t pc, regarm_t psp) { /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ void SVC_Handler(void) { /*lint -restore*/ - uint32_t control; uint32_t psp = __get_PSP(); chDbgAssert(((uint32_t)__builtin_return_address(0) & 4U) == 0U, "not process"); #if PORT_USE_SYSCALL == TRUE + uint32_t control; /* Caller context.*/ struct port_extctx *ectxp = (struct port_extctx *)psp; diff --git a/os/common/ports/ARMCMx/chcore_v7m.h b/os/common/ports/ARMCMx/chcore_v7m.h index d1122cc7c..295e99069 100644 --- a/os/common/ports/ARMCMx/chcore_v7m.h +++ b/os/common/ports/ARMCMx/chcore_v7m.h @@ -74,7 +74,18 @@ * @brief Implements a syscall interface on SVC. */ #if !defined(PORT_USE_SYSCALL) || defined(__DOXYGEN__) -#define PORT_USE_SYSCALL TRUE +#define PORT_USE_SYSCALL FALSE +#endif + +/** + * @brief Number of MPU regions to be saved/restored during context switch. + * @note The first region is always region zero. + * @note The use of this option has an overhead of 8 bytes for each + * region for each thread. + * @note Allowed values are 0..4, zero means none. + */ +#if !defined(PORT_SWITCHED_REGIONS_NUMBER) || defined(__DOXYGEN__) +#define PORT_SWITCHED_REGIONS_NUMBER 0 #endif /** @@ -90,9 +101,11 @@ /** * @brief MPU region to be used to stack guards. + * @note Make sure this region is not included in the + * @p PORT_SWITCHED_REGIONS_NUMBER regions range. */ -#if !defined(PORT_USE_MPU_REGION) || defined(__DOXYGEN__) -#define PORT_USE_MPU_REGION MPU_REGION_7 +#if !defined(PORT_USE_GUARD_MPU_REGION) || defined(__DOXYGEN__) +#define PORT_USE_GUARD_MPU_REGION MPU_REGION_7 #endif /** @@ -177,6 +190,10 @@ /* Derived constants and error checks. */ /*===========================================================================*/ +#if (PORT_SWITCHED_REGIONS_NUMBER < 0) || (PORT_SWITCHED_REGIONS_NUMBER > 4) +#error "invalid PORT_SWITCHED_REGIONS_NUMBER value" +#endif + #if !defined(_FROM_ASM_) /** * @brief MPU guard page size. @@ -370,6 +387,12 @@ struct port_linkctx { #endif struct port_intctx { +#if (PORT_SWITCHED_REGIONS_NUMBER > 0) || defined(__DOXYGEN__) + struct { + uint32_t rbar; + uint32_t rasr; + } regions[PORT_SWITCHED_REGIONS_NUMBER]; +#endif #if CORTEX_USE_FPU regarm_t s16; regarm_t s17; @@ -404,7 +427,7 @@ struct port_context { #if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) struct { regarm_t psp; - const void *regions; + const void *p; } syscall; #endif }; @@ -414,14 +437,49 @@ struct port_context { /* Module macros. */ /*===========================================================================*/ +/* By default threads have no syscall context information.*/ #if (PORT_USE_SYSCALL == TRUE) || defined(__DOXYGEN__) #define __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop) \ (tp)->ctx.syscall.psp = (regarm_t)(wtop); \ - (tp)->ctx.syscall.regions = NULL; + (tp)->ctx.syscall.p = NULL; #else #define __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop) #endif +/* By default threads have all regions disabled.*/ +#if (PORT_SWITCHED_REGIONS_NUMBER == 0) || defined(__DOXYGEN__) +#define __PORT_SETUP_CONTEXT_MPU(tp) +#elif (PORT_SWITCHED_REGIONS_NUMBER == 1) || defined(__DOXYGEN__) +#define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.sp->regions[0].rbar = 0U; \ + (tp)->ctx.sp->regions[0].rasr = 0U +#elif (PORT_SWITCHED_REGIONS_NUMBER == 2) || defined(__DOXYGEN__) +#define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.sp->regions[0].rbar = 0U; \ + (tp)->ctx.sp->regions[0].rasr = 0U; \ + (tp)->ctx.sp->regions[1].rbar = 0U; \ + (tp)->ctx.sp->regions[1].rasr = 0U +#elif (PORT_SWITCHED_REGIONS_NUMBER == 3) || defined(__DOXYGEN__) +#define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.sp->regions[0].rbar = 0U; \ + (tp)->ctx.sp->regions[0].rasr = 0U; \ + (tp)->ctx.sp->regions[1].rbar = 0U; \ + (tp)->ctx.sp->regions[1].rasr = 0U; \ + (tp)->ctx.sp->regions[2].rbar = 0U; \ + (tp)->ctx.sp->regions[2].rasr = 0U +#elif (PORT_SWITCHED_REGIONS_NUMBER == 4) || defined(__DOXYGEN__) +#define __PORT_SETUP_CONTEXT_MPU(tp) \ + (tp)->ctx.sp->regions[0].rbar = 0U; \ + (tp)->ctx.sp->regions[0].rasr = 0U; \ + (tp)->ctx.sp->regions[1].rbar = 0U; \ + (tp)->ctx.sp->regions[1].rasr = 0U; \ + (tp)->ctx.sp->regions[2].rbar = 0U; \ + (tp)->ctx.sp->regions[2].rasr = 0U; \ + (tp)->ctx.sp->regions[3].rbar = 0U; \ + (tp)->ctx.sp->regions[3].rasr = 0U +#else +#endif + /** * @brief Platform dependent part of the @p chThdCreateI() API. * @details This code usually setup the context switching frame represented @@ -433,9 +491,12 @@ struct port_context { (tp)->ctx.sp->r4 = (regarm_t)(pf); \ (tp)->ctx.sp->r5 = (regarm_t)(arg); \ (tp)->ctx.sp->lr = (regarm_t)_port_thread_start; \ - __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop) \ + __PORT_SETUP_CONTEXT_MPU(tp); \ + __PORT_SETUP_CONTEXT_SYSCALL(tp, wtop); \ } +// __PORT_SETUP_CONTEXT_MPU(tp) + /** * @brief Computes the thread working area global size. * @note There is no need to perform alignments in this macro. @@ -524,8 +585,8 @@ struct port_context { _port_switch(ntp, otp); \ \ /* Setting up the guard page for the switched-in thread.*/ \ - mpuSetRegionAddress(PORT_USE_MPU_REGION, \ - chThdGetSelfX()->wabase); \ + mpuSetRegionAddress(PORT_USE_GUARD_MPU_REGION, \ + chThdGetSelfX()->wabase); \ } #endif #endif @@ -559,7 +620,7 @@ extern "C" { * * @return The interrupts status. */ -static inline syssts_t port_get_irq_status(void) { +__STATIC_FORCEINLINE syssts_t port_get_irq_status(void) { syssts_t sts; #if CORTEX_SIMPLIFIED_PRIORITY == FALSE @@ -579,7 +640,7 @@ static inline syssts_t port_get_irq_status(void) { * @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) { +__STATIC_FORCEINLINE bool port_irq_enabled(syssts_t sts) { #if CORTEX_SIMPLIFIED_PRIORITY == FALSE return sts == (syssts_t)CORTEX_BASEPRI_DISABLED; @@ -595,7 +656,7 @@ static inline bool port_irq_enabled(syssts_t sts) { * @retval false not running in ISR mode. * @retval true running in ISR mode. */ -static inline bool port_is_isr_context(void) { +__STATIC_FORCEINLINE bool port_is_isr_context(void) { return (bool)((__get_IPSR() & 0x1FFU) != 0U); } @@ -605,7 +666,7 @@ static inline bool port_is_isr_context(void) { * @details In this port this function raises the base priority to kernel * level. */ -static inline void port_lock(void) { +__STATIC_FORCEINLINE void port_lock(void) { #if CORTEX_SIMPLIFIED_PRIORITY == FALSE #if defined(__CM7_REV) @@ -629,7 +690,7 @@ static inline void port_lock(void) { * @details In this port this function lowers the base priority to user * level. */ -static inline void port_unlock(void) { +__STATIC_FORCEINLINE void port_unlock(void) { #if CORTEX_SIMPLIFIED_PRIORITY == FALSE __set_BASEPRI(CORTEX_BASEPRI_DISABLED); @@ -644,7 +705,7 @@ static inline void port_unlock(void) { * level. * @note Same as @p port_lock() in this port. */ -static inline void port_lock_from_isr(void) { +__STATIC_FORCEINLINE void port_lock_from_isr(void) { port_lock(); } @@ -655,7 +716,7 @@ static inline void port_lock_from_isr(void) { * level. * @note Same as @p port_unlock() in this port. */ -static inline void port_unlock_from_isr(void) { +__STATIC_FORCEINLINE void port_unlock_from_isr(void) { port_unlock(); } @@ -665,7 +726,7 @@ static inline void port_unlock_from_isr(void) { * @note In this port it disables all the interrupt sources by raising * the priority mask to level 0. */ -static inline void port_disable(void) { +__STATIC_FORCEINLINE void port_disable(void) { __disable_irq(); } @@ -675,7 +736,7 @@ static inline void port_disable(void) { * @note Interrupt sources above kernel level remains enabled. * @note In this port it raises/lowers the base priority to kernel level. */ -static inline void port_suspend(void) { +__STATIC_FORCEINLINE void port_suspend(void) { #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) __set_BASEPRI(CORTEX_BASEPRI_KERNEL); @@ -689,7 +750,7 @@ static inline void port_suspend(void) { * @brief Enables all the interrupt sources. * @note In this port it lowers the base priority to user level. */ -static inline void port_enable(void) { +__STATIC_FORCEINLINE void port_enable(void) { #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) || defined(__DOXYGEN__) __set_BASEPRI(CORTEX_BASEPRI_DISABLED); @@ -705,7 +766,7 @@ static inline void port_enable(void) { * modes. * @note Implemented as an inlined @p WFI instruction. */ -static inline void port_wait_for_interrupt(void) { +__STATIC_FORCEINLINE void port_wait_for_interrupt(void) { #if CORTEX_ENABLE_WFI_IDLE == TRUE __WFI(); @@ -717,7 +778,7 @@ static inline void port_wait_for_interrupt(void) { * * @return The realtime counter value. */ -static inline rtcnt_t port_rt_get_counter_value(void) { +__STATIC_FORCEINLINE rtcnt_t port_rt_get_counter_value(void) { return DWT->CYCCNT; } diff --git a/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S b/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S index 8e984c6e8..044e97696 100644 --- a/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S +++ b/os/common/ports/ARMCMx/compilers/GCC/chcoreasm_v7m.S @@ -51,8 +51,12 @@ #error "invalid chconf.h" #endif - .set SCB_ICSR, 0xE000ED04 - .set ICSR_PENDSVSET, 0x10000000 +/* MPU-related constants.*/ +#define MPU_RBAR 0xE000ED9C + +/* Other constants.*/ +#define SCB_ICSR 0xE000ED04 +#define ICSR_PENDSVSET 0x10000000 .syntax unified .cpu cortex-m4 @@ -73,9 +77,47 @@ _port_switch: push {r4, r5, r6, r7, r8, r9, r10, r11, lr} #if CORTEX_USE_FPU + /* Saving FPU context.*/ vpush {s16-s31} #endif +#if PORT_SWITCHED_REGIONS_NUMBER > 0 + /* Saving MPU context.*/ + ldr r2, =MPU_RBAR +#if PORT_SWITCHED_REGIONS_NUMBER >= 1 + mov r3, #0 + str r3, [r2, #-4] /* RNR */ + ldm r2, {r4, r5} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 2 + add r3, #1 + str r4, [r2, #-4] /* RNR */ + ldm r2, {r6, r7} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 3 + add r3, #1 + str r4, [r2, #-4] /* RNR */ + ldm r2, {r8, r9} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 4 + add r3, #1 + str r4, [r2, #-4] /* RNR */ + ldm r2, {r10, r11} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 1 + push {r4, r5} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 2 + push {r4, r5, r6, r7} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 3 + push {r4, r5, r6, r7, r8, r9} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 4 + push {r4, r5, r6, r7, r8, r9, r10, r11} +#endif +#endif + str sp, [r1, #CONTEXT_OFFSET] #if (CORTEX_SIMPLIFIED_PRIORITY == FALSE) && \ ((CORTEX_MODEL == 3) || (CORTEX_MODEL == 4)) @@ -87,7 +129,44 @@ _port_switch: ldr sp, [r0, #CONTEXT_OFFSET] #endif +#if PORT_SWITCHED_REGIONS_NUMBER > 0 + /* Restoring MPU context.*/ +#if PORT_SWITCHED_REGIONS_NUMBER == 1 + pop {r4, r5} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 2 + pop {r4, r5, r6, r7} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 3 + pop {r4, r5, r6, r7, r8, r9} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER == 4 + pop {r4, r5, r6, r7, r8, r9, r10, r11} +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 1 + mov r3, #0 + str r3, [r2, #-4] /* RNR */ + stm r2, {r4, r5} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 2 + add r3, #1 + str r3, [r2, #-4] /* RNR */ + stm r2, {r6, r7} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 3 + add r3, #1 + str r3, [r2, #-4] /* RNR */ + stm r2, {r8, r9} /* RBAR, RASR */ +#endif +#if PORT_SWITCHED_REGIONS_NUMBER >= 4 + add r3, #1 + str r3, [r2, #-4] /* RNR */ + stm r2, {r10, r11} /* RBAR, RASR */ +#endif +#endif + #if CORTEX_USE_FPU + /* Restoring FPU context.*/ vpop {s16-s31} #endif pop {r4, r5, r6, r7, r8, r9, r10, r11, pc}