diff --git a/portable/ARMv8M/non_secure/port.c b/portable/ARMv8M/non_secure/port.c index e5b90410f..ba5991cb3 100644 --- a/portable/ARMv8M/non_secure/port.c +++ b/portable/ARMv8M/non_secure/port.c @@ -1,1189 +1,1192 @@ -/* - * FreeRTOS Kernel V10.3.1 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - */ - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* MPU wrappers includes. */ -#include "mpu_wrappers.h" - -/* Portasm includes. */ -#include "portasm.h" - -#if ( configENABLE_TRUSTZONE == 1 ) - /* Secure components includes. */ - #include "secure_context.h" - #include "secure_init.h" -#endif /* configENABLE_TRUSTZONE */ - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/** - * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only - * i.e. the processor boots as secure and never jumps to the non-secure side. - * The Trust Zone support in the port must be disabled in order to run FreeRTOS - * on the secure side. The following are the valid configuration seetings: - * - * 1. Run FreeRTOS on the Secure Side: - * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0 - * - * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support: - * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1 - * - * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: - * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0 - */ -#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) - #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. -#endif -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the NVIC. - */ -#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) -#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) -#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) -#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - /* Ensure the SysTick is clocked at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) -#else - -/* The way the SysTick is clocked is not modified in case it is not the - * same a the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 0 ) -#endif -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the SCB. - */ -#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) -#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the FPU. - */ -#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */ -#define portCPACR_CP10_VALUE ( 3UL ) -#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE -#define portCPACR_CP10_POS ( 20UL ) -#define portCPACR_CP11_POS ( 22UL ) - -#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */ -#define portFPCCR_ASPEN_POS ( 31UL ) -#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS ) -#define portFPCCR_LSPEN_POS ( 30UL ) -#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the MPU. - */ -#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) -#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) -#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) ) - -#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) ) -#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) ) - -#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) ) -#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) ) - -#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) ) -#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) ) - -#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) ) -#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) ) - -#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) ) -#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) ) - -#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ -#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ - -#define portMPU_MAIR_ATTR0_POS ( 0UL ) -#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) - -#define portMPU_MAIR_ATTR1_POS ( 8UL ) -#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) - -#define portMPU_MAIR_ATTR2_POS ( 16UL ) -#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) - -#define portMPU_MAIR_ATTR3_POS ( 24UL ) -#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) - -#define portMPU_MAIR_ATTR4_POS ( 0UL ) -#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) - -#define portMPU_MAIR_ATTR5_POS ( 8UL ) -#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) - -#define portMPU_MAIR_ATTR6_POS ( 16UL ) -#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) - -#define portMPU_MAIR_ATTR7_POS ( 24UL ) -#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) - -#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL ) - -#define portMPU_RLAR_REGION_ENABLE ( 1UL ) - -/* Enable privileged access to unmapped region. */ -#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) - -/* Enable MPU. */ -#define portMPU_ENABLE_BIT ( 1UL << 0UL ) - -/* Expected value of the portMPU_TYPE register. */ -#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ -/*-----------------------------------------------------------*/ - -/** - * @brief The maximum 24-bit number. - * - * It is needed because the systick is a 24-bit counter. - */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) - -/** - * @brief A fiddle factor to estimate the number of SysTick counts that would - * have occurred while the SysTick counter is stopped during tickless idle - * calculations. - */ -#define portMISSED_COUNTS_FACTOR ( 45UL ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to set up the initial stack. - */ -#define portINITIAL_XPSR ( 0x01000000 ) - -#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) - -/** - * @brief Initial EXC_RETURN value. - * - * FF FF FF FD - * 1111 1111 1111 1111 1111 1111 1111 1101 - * - * Bit[6] - 1 --> The exception was taken from the Secure state. - * Bit[5] - 1 --> Do not skip stacking of additional state context. - * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. - * Bit[3] - 1 --> Return to the Thread mode. - * Bit[2] - 1 --> Restore registers from the process stack. - * Bit[1] - 0 --> Reserved, 0. - * Bit[0] - 1 --> The exception was taken to the Secure state. - */ - #define portINITIAL_EXC_RETURN ( 0xfffffffd ) -#else - -/** - * @brief Initial EXC_RETURN value. - * - * FF FF FF BC - * 1111 1111 1111 1111 1111 1111 1011 1100 - * - * Bit[6] - 0 --> The exception was taken from the Non-Secure state. - * Bit[5] - 1 --> Do not skip stacking of additional state context. - * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. - * Bit[3] - 1 --> Return to the Thread mode. - * Bit[2] - 1 --> Restore registers from the process stack. - * Bit[1] - 0 --> Reserved, 0. - * Bit[0] - 0 --> The exception was taken to the Non-Secure state. - */ - #define portINITIAL_EXC_RETURN ( 0xffffffbc ) -#endif /* configRUN_FREERTOS_SECURE_ONLY */ - -/** - * @brief CONTROL register privileged bit mask. - * - * Bit[0] in CONTROL register tells the privilege: - * Bit[0] = 0 ==> The task is privileged. - * Bit[0] = 1 ==> The task is not privileged. - */ -#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) - -/** - * @brief Initial CONTROL register values. - */ -#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) -#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) - -/** - * @brief Let the user override the pre-loading of the initial LR with the - * address of prvTaskExitError() in case it messes up unwinding of the stack - * in the debugger. - */ -#ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS -#else - #define portTASK_RETURN_ADDRESS prvTaskExitError -#endif - -/** - * @brief If portPRELOAD_REGISTERS then registers will be given an initial value - * when a task is created. This helps in debugging at the cost of code size. - */ -#define portPRELOAD_REGISTERS 1 - -/** - * @brief A task is created without a secure context, and must call - * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes - * any secure calls. - */ -#define portNO_SECURE_CONTEXT 0 -/*-----------------------------------------------------------*/ - -/** - * @brief Used to catch tasks that attempt to return from their implementing - * function. - */ -static void prvTaskExitError( void ); - -#if ( configENABLE_MPU == 1 ) - -/** - * @brief Setup the Memory Protection Unit (MPU). - */ - static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; -#endif /* configENABLE_MPU */ - -#if ( configENABLE_FPU == 1 ) - -/** - * @brief Setup the Floating Point Unit (FPU). - */ - static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; -#endif /* configENABLE_FPU */ - -/** - * @brief Setup the timer to generate the tick interrupts. - * - * The implementation in this file is weak to allow application writers to - * change the timer used to generate the tick interrupt. - */ -void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Checks whether the current execution context is interrupt. - * - * @return pdTRUE if the current execution context is interrupt, pdFALSE - * otherwise. - */ -BaseType_t xPortIsInsideInterrupt( void ); - -/** - * @brief Yield the processor. - */ -void vPortYield( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Enter critical section. - */ -void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Exit from critical section. - */ -void vPortExitCritical( void ) PRIVILEGED_FUNCTION; - -/** - * @brief SysTick handler. - */ -void SysTick_Handler( void ) PRIVILEGED_FUNCTION; - -/** - * @brief C part of SVC handler. - */ -portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION; -/*-----------------------------------------------------------*/ - -/** - * @brief Each task maintains its own interrupt status in the critical nesting - * variable. - */ -PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; - -#if ( configENABLE_TRUSTZONE == 1 ) - -/** - * @brief Saved as part of the task context to indicate which context the - * task is using on the secure side. - */ - PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; -#endif /* configENABLE_TRUSTZONE */ - -#if ( configUSE_TICKLESS_IDLE == 1 ) - -/** - * @brief The number of SysTick increments that make up one tick period. - */ - PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; - -/** - * @brief The maximum number of tick periods that can be suppressed is - * limited by the 24 bit resolution of the SysTick timer. - */ - PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; - -/** - * @brief Compensate for the CPU cycles that pass while the SysTick is - * stopped (low power functionality only). - */ - PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; -#endif /* configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; - - /* Make sure the SysTick reload value does not overflow the counter. */ - if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) - { - xExpectedIdleTime = xMaximumPossibleSuppressedTicks; - } - - /* Stop the SysTick momentarily. The time the SysTick is stopped for is - * accounted for as best it can be, but using the tickless mode will - * inevitably result in some tiny drift of the time maintained by the - * kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; - - /* Calculate the reload value required to wait xExpectedIdleTime - * tick periods. -1 is used because this code will execute part way - * through one of the tick periods. */ - ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); - - if( ulReloadValue > ulStoppedTimerCompensation ) - { - ulReloadValue -= ulStoppedTimerCompensation; - } - - /* Enter a critical section but don't use the taskENTER_CRITICAL() - * method as that will mask interrupts that should exit sleep mode. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* If a context switch is pending or a task is waiting for the scheduler - * to be un-suspended then abandon the low power entry. */ - if( eTaskConfirmSleepModeStatus() == eAbortSleep ) - { - /* Restart from whatever is left in the count register to complete - * this tick period. */ - portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Reset the reload register to the value required for normal tick - * periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - - /* Re-enable interrupts - see comments above the cpsid instruction() - * above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - - /* Clear the SysTick count flag and set the count value back to - * zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can - * set its parameter to 0 to indicate that its implementation - * contains its own wait for interrupt or wait for event - * instruction, and so wfi should not be executed again. However, - * the original expected idle time variable must remain unmodified, - * so a copy is taken. */ - xModifiableIdleTime = xExpectedIdleTime; - configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); - - if( xModifiableIdleTime > 0 ) - { - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "wfi" ); - __asm volatile ( "isb" ); - } - - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - - /* Re-enable interrupts to allow the interrupt that brought the MCU - * out of sleep mode to execute immediately. See comments above - * the cpsid instruction above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable interrupts again because the clock is about to be stopped - * and interrupts that execute while the clock is stopped will - * increase any slippage between the time maintained by the RTOS and - * calendar time. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. - * Again, the time the SysTick is stopped for is accounted for as - * best it can be, but using the tickless mode will inevitably - * result in some tiny drift of the time maintained by the kernel - * with respect to calendar time*/ - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); - - /* Determine if the SysTick clock has already counted to zero and - * been set back to the current reload value (the reload back being - * correct for the entire expected idle time) or if the SysTick is - * yet to count to zero (in which case an interrupt other than the - * SysTick must have brought the system out of sleep mode). */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - uint32_t ulCalculatedLoadValue; - - /* The tick interrupt is already pending, and the SysTick count - * reloaded with ulReloadValue. Reset the - * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick - * period. */ - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); - - /* Don't allow a tiny value, or values that have somehow - * underflowed because the post sleep hook did something - * that took too long. */ - if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) - { - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); - } - - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - - /* As the pending tick will be processed as soon as this - * function exits, the tick value maintained by the tick is - * stepped forward by one less than the time spent waiting. */ - ulCompleteTickPeriods = xExpectedIdleTime - 1UL; - } - else - { - /* Something other than the tick interrupt ended the sleep. - * Work out how long the sleep lasted rounded to complete tick - * periods (not the ulReload value which accounted for part - * ticks). */ - ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* How many complete tick periods passed while the processor - * was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; - - /* The reload value is set to whatever fraction of a single tick - * period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } - - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG - * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard - * value. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - vTaskStepTick( ulCompleteTickPeriods ); - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - - /* Exit with interrupts enabled. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - } -#endif /* configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - -__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Calculate the constants required to configure the tick interrupt. */ - #if ( configUSE_TICKLESS_IDLE == 1 ) - { - ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); - xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; - ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - } - #endif /* configUSE_TICKLESS_IDLE */ - - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; -} -/*-----------------------------------------------------------*/ - -static void prvTaskExitError( void ) -{ - volatile uint32_t ulDummy = 0UL; - - /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). Artificially force an assert() - * to be triggered if configASSERT() is defined, then stop here so - * application writers can catch the error. */ - configASSERT( ulCriticalNesting == ~0UL ); - portDISABLE_INTERRUPTS(); - - while( ulDummy == 0 ) - { - /* This file calls prvTaskExitError() after the scheduler has been - * started to remove a compiler warning about the function being - * defined but never called. ulDummy is used purely to quieten other - * warnings about code appearing after this function is called - making - * ulDummy volatile makes the compiler think the function could return - * and therefore not output an 'unreachable code' warning for code that - * appears after it. */ - } -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ - { - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_functions_start__; - extern uint32_t * __privileged_functions_end__; - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - extern uint32_t * __unprivileged_flash_start__; - extern uint32_t * __unprivileged_flash_end__; - extern uint32_t * __privileged_sram_start__; - extern uint32_t * __privileged_sram_end__; - #else /* if defined( __ARMCC_VERSION ) */ - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_functions_start__[]; - extern uint32_t __privileged_functions_end__[]; - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - extern uint32_t __unprivileged_flash_start__[]; - extern uint32_t __unprivileged_flash_end__[]; - extern uint32_t __privileged_sram_start__[]; - extern uint32_t __privileged_sram_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - - /* Check that the MPU is present. */ - if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) - { - /* MAIR0 - Index 0. */ - portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); - /* MAIR0 - Index 1. */ - portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); - - /* Setup privileged flash as Read Only so that privileged tasks can - * read it but not modify. */ - portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_PRIVILEGED_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup unprivileged flash as Read Only by both privileged and - * unprivileged tasks. All tasks can read it but no-one can modify. */ - portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup unprivileged syscalls flash as Read Only by both privileged - * and unprivileged tasks. All tasks can read it but no-one can modify. */ - portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup RAM containing kernel data for privileged access only. */ - portMPU_RNR_REG = portPRIVILEGED_RAM_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Enable mem fault. */ - portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; - - /* Enable MPU with privileged background access i.e. unmapped - * regions have privileged access. */ - portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); - } - } -#endif /* configENABLE_MPU */ -/*-----------------------------------------------------------*/ - -#if ( configENABLE_FPU == 1 ) - static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ - { - #if ( configENABLE_TRUSTZONE == 1 ) - { - /* Enable non-secure access to the FPU. */ - SecureInit_EnableNSFPUAccess(); - } - #endif /* configENABLE_TRUSTZONE */ - - /* CP10 = 11 ==> Full access to FPU i.e. both privileged and - * unprivileged code should be able to access FPU. CP11 should be - * programmed to the same value as CP10. */ - *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) | - ( portCPACR_CP11_VALUE << portCPACR_CP11_POS ) - ); - - /* ASPEN = 1 ==> Hardware should automatically preserve floating point - * context on exception entry and restore on exception return. - * LSPEN = 1 ==> Enable lazy context save of FP state. */ - *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK ); - } -#endif /* configENABLE_FPU */ -/*-----------------------------------------------------------*/ - -void vPortYield( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Set a PendSV to request a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - - /* Barriers are normally not required but do ensure the code is - * completely within the specified behaviour for the architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */ -{ - portDISABLE_INTERRUPTS(); - ulCriticalNesting++; - - /* Barriers are normally not required but do ensure the code is - * completely within the specified behaviour for the architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */ -{ - configASSERT( ulCriticalNesting ); - ulCriticalNesting--; - - if( ulCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ -{ - uint32_t ulPreviousMask; - - ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Pend a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); -} -/*-----------------------------------------------------------*/ - -void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ -{ - #if ( configENABLE_MPU == 1 ) - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - #endif /* configENABLE_MPU */ - - uint32_t ulPC; - - #if ( configENABLE_TRUSTZONE == 1 ) - uint32_t ulR0; - #if ( configENABLE_MPU == 1 ) - uint32_t ulControl, ulIsTaskPrivileged; - #endif /* configENABLE_MPU */ - #endif /* configENABLE_TRUSTZONE */ - uint8_t ucSVCNumber; - - /* Register are stored on the stack in the following order - R0, R1, R2, R3, - * R12, LR, PC, xPSR. */ - ulPC = pulCallerStackAddress[ 6 ]; - ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; - - switch( ucSVCNumber ) - { - #if ( configENABLE_TRUSTZONE == 1 ) - case portSVC_ALLOCATE_SECURE_CONTEXT: - - /* R0 contains the stack size passed as parameter to the - * vPortAllocateSecureContext function. */ - ulR0 = pulCallerStackAddress[ 0 ]; - - #if ( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); - } - #else /* if ( configENABLE_MPU == 1 ) */ - { - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0 ); - } - #endif /* configENABLE_MPU */ - - configASSERT( xSecureContext != NULL ); - SecureContext_LoadContext( xSecureContext ); - break; - - case portSVC_FREE_SECURE_CONTEXT: - /* R0 contains the secure context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); - break; - #endif /* configENABLE_TRUSTZONE */ - - case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) - { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); - - /* Initialize the secure context management system. */ - SecureContext_Init(); - } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); - break; - - #if ( configENABLE_MPU == 1 ) - case portSVC_RAISE_PRIVILEGE: - - /* Only raise the privilege, if the svc was raised from any of - * the system calls. */ - if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && - ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) - { - vRaisePrivilege(); - } - break; - #endif /* configENABLE_MPU */ - - default: - /* Incorrect SVC call. */ - configASSERT( pdFALSE ); - } -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - StackType_t * pxEndOfStack, - TaskFunction_t pxCode, - void * pvParameters, - BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ -#else - StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - StackType_t * pxEndOfStack, - TaskFunction_t pxCode, - void * pvParameters ) /* PRIVILEGED_FUNCTION */ -#endif /* configENABLE_MPU */ -{ - /* Simulate the stack frame as it would be created by a context switch - * interrupt. */ - #if ( portPRELOAD_REGISTERS == 0 ) - { - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ - *pxTopOfStack = portINITIAL_EXC_RETURN; - - #if ( configENABLE_MPU == 1 ) - { - pxTopOfStack--; - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - } - #endif /* configENABLE_MPU */ - - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - - #if ( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #else /* portPRELOAD_REGISTERS */ - { - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */ - pxTopOfStack--; - *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ - - #if ( configENABLE_MPU == 1 ) - { - pxTopOfStack--; - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - } - #endif /* configENABLE_MPU */ - - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - - #if ( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #endif /* portPRELOAD_REGISTERS */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ - portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; - portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - - #if ( configENABLE_MPU == 1 ) - { - /* Setup the Memory Protection Unit (MPU). */ - prvSetupMPU(); - } - #endif /* configENABLE_MPU */ - - /* Start the timer that generates the tick ISR. Interrupts are disabled - * here already. */ - vPortSetupTimerInterrupt(); - - /* Initialize the critical nesting count ready for the first task. */ - ulCriticalNesting = 0; - - /* Start the first task. */ - vStartFirstTask(); - - /* Should never get here as the tasks will now be executing. Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. Call - * vTaskSwitchContext() so link time optimization does not remove the - * symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); - - /* Should not get here. */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ - configASSERT( ulCriticalNesting == 1000UL ); -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, - const struct xMEMORY_REGION * const xRegions, - StackType_t * pxBottomOfStack, - uint32_t ulStackDepth ) - { - uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; - int32_t lIndex = 0; - #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_sram_start__; - extern uint32_t * __privileged_sram_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_sram_start__[]; - extern uint32_t __privileged_sram_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - - /* Setup MAIR0. */ - xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); - xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); - - /* This function is called automatically when the task is created - in - * which case the stack region parameters will be valid. At all other - * times the stack parameters will not be valid and it is assumed that - * the stack region has already been configured. */ - if( ulStackDepth > 0 ) - { - ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; - ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; - - /* If the stack is within the privileged SRAM, do not protect it - * using a separate MPU region. This is needed because privileged - * SRAM is already protected using an MPU region and ARMv8-M does - * not allow overlapping MPU regions. */ - if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && - ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) - { - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; - } - else - { - /* Define the region that allows access to the stack. */ - ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); - - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - } - } - - /* User supplied configurable regions. */ - for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ ) - { - /* If xRegions is NULL i.e. the task has not specified any MPU - * region, the else part ensures that all the configurable MPU - * regions are invalidated. */ - if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) ) - { - /* Translate the generic region definition contained in xRegions - * into the ARMv8 specific MPU settings that are then stored in - * xMPUSettings. */ - ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - - /* Start address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ); - - /* RO/RW. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY ); - } - else - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE ); - } - - /* XN. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); - } - - /* End Address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Normal memory/ Device memory. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 ) - { - /* Attr1 in MAIR0 is configured as device memory. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1; - } - else - { - /* Attr1 in MAIR0 is configured as normal memory. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0; - } - } - else - { - /* Invalidate the region. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL; - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL; - } - - lIndex++; - } - } -#endif /* configENABLE_MPU */ -/*-----------------------------------------------------------*/ - -BaseType_t xPortIsInsideInterrupt( void ) -{ - uint32_t ulCurrentInterrupt; - BaseType_t xReturn; - - /* Obtain the number of the currently executing interrupt. Interrupt Program - * Status Register (IPSR) holds the exception number of the currently-executing - * exception or zero for Thread mode.*/ - __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ +/* + * FreeRTOS Kernel V10.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + */ + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* MPU wrappers includes. */ +#include "mpu_wrappers.h" + +/* Portasm includes. */ +#include "portasm.h" + +#if ( configENABLE_TRUSTZONE == 1 ) + /* Secure components includes. */ + #include "secure_context.h" + #include "secure_init.h" +#endif /* configENABLE_TRUSTZONE */ + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/** + * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only + * i.e. the processor boots as secure and never jumps to the non-secure side. + * The Trust Zone support in the port must be disabled in order to run FreeRTOS + * on the secure side. The following are the valid configuration seetings: + * + * 1. Run FreeRTOS on the Secure Side: + * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0 + * + * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support: + * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1 + * + * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: + * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0 + */ +#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) + #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. +#endif +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the NVIC. + */ +#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) +#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + +/* The way the SysTick is clocked is not modified in case it is not the + * same a the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the SCB. + */ +#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) +#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the FPU. + */ +#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */ +#define portCPACR_CP10_VALUE ( 3UL ) +#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE +#define portCPACR_CP10_POS ( 20UL ) +#define portCPACR_CP11_POS ( 22UL ) + +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */ +#define portFPCCR_ASPEN_POS ( 31UL ) +#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS ) +#define portFPCCR_LSPEN_POS ( 30UL ) +#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the MPU. + */ +#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) +#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) +#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) ) + +#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) ) +#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) ) + +#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) ) +#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) ) + +#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) ) +#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) ) + +#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) ) +#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) ) + +#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) ) +#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) ) + +#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ +#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ + +#define portMPU_MAIR_ATTR0_POS ( 0UL ) +#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) + +#define portMPU_MAIR_ATTR1_POS ( 8UL ) +#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) + +#define portMPU_MAIR_ATTR2_POS ( 16UL ) +#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) + +#define portMPU_MAIR_ATTR3_POS ( 24UL ) +#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) + +#define portMPU_MAIR_ATTR4_POS ( 0UL ) +#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) + +#define portMPU_MAIR_ATTR5_POS ( 8UL ) +#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) + +#define portMPU_MAIR_ATTR6_POS ( 16UL ) +#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) + +#define portMPU_MAIR_ATTR7_POS ( 24UL ) +#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) + +#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL ) + +#define portMPU_RLAR_REGION_ENABLE ( 1UL ) + +/* Enable privileged access to unmapped region. */ +#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) + +/* Enable MPU. */ +#define portMPU_ENABLE_BIT ( 1UL << 0UL ) + +/* Expected value of the portMPU_TYPE register. */ +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +/*-----------------------------------------------------------*/ + +/** + * @brief The maximum 24-bit number. + * + * It is needed because the systick is a 24-bit counter. + */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/** + * @brief A fiddle factor to estimate the number of SysTick counts that would + * have occurred while the SysTick counter is stopped during tickless idle + * calculations. + */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to set up the initial stack. + */ +#define portINITIAL_XPSR ( 0x01000000 ) + +#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) + +/** + * @brief Initial EXC_RETURN value. + * + * FF FF FF FD + * 1111 1111 1111 1111 1111 1111 1111 1101 + * + * Bit[6] - 1 --> The exception was taken from the Secure state. + * Bit[5] - 1 --> Do not skip stacking of additional state context. + * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. + * Bit[3] - 1 --> Return to the Thread mode. + * Bit[2] - 1 --> Restore registers from the process stack. + * Bit[1] - 0 --> Reserved, 0. + * Bit[0] - 1 --> The exception was taken to the Secure state. + */ + #define portINITIAL_EXC_RETURN ( 0xfffffffd ) +#else + +/** + * @brief Initial EXC_RETURN value. + * + * FF FF FF BC + * 1111 1111 1111 1111 1111 1111 1011 1100 + * + * Bit[6] - 0 --> The exception was taken from the Non-Secure state. + * Bit[5] - 1 --> Do not skip stacking of additional state context. + * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. + * Bit[3] - 1 --> Return to the Thread mode. + * Bit[2] - 1 --> Restore registers from the process stack. + * Bit[1] - 0 --> Reserved, 0. + * Bit[0] - 0 --> The exception was taken to the Non-Secure state. + */ + #define portINITIAL_EXC_RETURN ( 0xffffffbc ) +#endif /* configRUN_FREERTOS_SECURE_ONLY */ + +/** + * @brief CONTROL register privileged bit mask. + * + * Bit[0] in CONTROL register tells the privilege: + * Bit[0] = 0 ==> The task is privileged. + * Bit[0] = 1 ==> The task is not privileged. + */ +#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) + +/** + * @brief Initial CONTROL register values. + */ +#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) +#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) + +/** + * @brief Let the user override the pre-loading of the initial LR with the + * address of prvTaskExitError() in case it messes up unwinding of the stack + * in the debugger. + */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/** + * @brief If portPRELOAD_REGISTERS then registers will be given an initial value + * when a task is created. This helps in debugging at the cost of code size. + */ +#define portPRELOAD_REGISTERS 1 + +/** + * @brief A task is created without a secure context, and must call + * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes + * any secure calls. + */ +#define portNO_SECURE_CONTEXT 0 +/*-----------------------------------------------------------*/ + +/** + * @brief Used to catch tasks that attempt to return from their implementing + * function. + */ +static void prvTaskExitError( void ); + +#if ( configENABLE_MPU == 1 ) + +/** + * @brief Setup the Memory Protection Unit (MPU). + */ + static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; +#endif /* configENABLE_MPU */ + +#if ( configENABLE_FPU == 1 ) + +/** + * @brief Setup the Floating Point Unit (FPU). + */ + static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; +#endif /* configENABLE_FPU */ + +/** + * @brief Setup the timer to generate the tick interrupts. + * + * The implementation in this file is weak to allow application writers to + * change the timer used to generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Checks whether the current execution context is interrupt. + * + * @return pdTRUE if the current execution context is interrupt, pdFALSE + * otherwise. + */ +BaseType_t xPortIsInsideInterrupt( void ); + +/** + * @brief Yield the processor. + */ +void vPortYield( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Enter critical section. + */ +void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Exit from critical section. + */ +void vPortExitCritical( void ) PRIVILEGED_FUNCTION; + +/** + * @brief SysTick handler. + */ +void SysTick_Handler( void ) PRIVILEGED_FUNCTION; + +/** + * @brief C part of SVC handler. + */ +portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION; +/*-----------------------------------------------------------*/ + +/** + * @brief Each task maintains its own interrupt status in the critical nesting + * variable. + */ +PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; + +#if ( configENABLE_TRUSTZONE == 1 ) + +/** + * @brief Saved as part of the task context to indicate which context the + * task is using on the secure side. + */ + PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; +#endif /* configENABLE_TRUSTZONE */ + +#if ( configUSE_TICKLESS_IDLE == 1 ) + +/** + * @brief The number of SysTick increments that make up one tick period. + */ + PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; + +/** + * @brief The maximum number of tick periods that can be suppressed is + * limited by the 24 bit resolution of the SysTick timer. + */ + PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; + +/** + * @brief Compensate for the CPU cycles that pass while the SysTick is + * stopped (low power functionality only). + */ + PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE == 1 ) + __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for is + * accounted for as best it can be, but using the tickless mode will + * inevitably result in some tiny drift of the time maintained by the + * kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + * tick periods. -1 is used because this code will execute part way + * through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* If a context switch is pending or a task is waiting for the scheduler + * to be un-suspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + * this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + * set its parameter to 0 to indicate that its implementation + * contains its own wait for interrupt or wait for event + * instruction, and so wfi should not be executed again. However, + * the original expected idle time variable must remain unmodified, + * so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "isb" ); + } + + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Re-enable interrupts to allow the interrupt that brought the MCU + * out of sleep mode to execute immediately. See comments above + * the cpsid instruction above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable interrupts again because the clock is about to be stopped + * and interrupts that execute while the clock is stopped will + * increase any slippage between the time maintained by the RTOS and + * calendar time. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable the SysTick clock without reading the + * portNVIC_SYSTICK_CTRL_REG register to ensure the + * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. + * Again, the time the SysTick is stopped for is accounted for as + * best it can be, but using the tickless mode will inevitably + * result in some tiny drift of the time maintained by the kernel + * with respect to calendar time*/ + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); + + /* Determine if the SysTick clock has already counted to zero and + * been set back to the current reload value (the reload back being + * correct for the entire expected idle time) or if the SysTick is + * yet to count to zero (in which case an interrupt other than the + * SysTick must have brought the system out of sleep mode). */ + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt is already pending, and the SysTick count + * reloaded with ulReloadValue. Reset the + * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + * period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + * underflowed because the post sleep hook did something + * that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* As the pending tick will be processed as soon as this + * function exits, the tick value maintained by the tick is + * stepped forward by one less than the time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + * Work out how long the sleep lasted rounded to complete tick + * periods (not the ulReload value which accounted for part + * ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + * was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + * period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + * value. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Exit with interrupts enabled. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if ( configUSE_TICKLESS_IDLE == 1 ) + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Stop and reset the SysTick. */ + portNVIC_SYSTICK_CTRL_REG = 0UL; + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + volatile uint32_t ulDummy = 0UL; + + /* A function that implements a task must not exit or attempt to return to + * its caller as there is nothing to return to. If a task wants to exit it + * should instead call vTaskDelete( NULL ). Artificially force an assert() + * to be triggered if configASSERT() is defined, then stop here so + * application writers can catch the error. */ + configASSERT( ulCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + + while( ulDummy == 0 ) + { + /* This file calls prvTaskExitError() after the scheduler has been + * started to remove a compiler warning about the function being + * defined but never called. ulDummy is used purely to quieten other + * warnings about code appearing after this function is called - making + * ulDummy volatile makes the compiler think the function could return + * and therefore not output an 'unreachable code' warning for code that + * appears after it. */ + } +} +/*-----------------------------------------------------------*/ + +#if ( configENABLE_MPU == 1 ) + static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + extern uint32_t * __unprivileged_flash_start__; + extern uint32_t * __unprivileged_flash_end__; + extern uint32_t * __privileged_sram_start__; + extern uint32_t * __privileged_sram_end__; + #else /* if defined( __ARMCC_VERSION ) */ + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + extern uint32_t __unprivileged_flash_start__[]; + extern uint32_t __unprivileged_flash_end__[]; + extern uint32_t __privileged_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + + /* Check that the MPU is present. */ + if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) + { + /* MAIR0 - Index 0. */ + portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); + /* MAIR0 - Index 1. */ + portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); + + /* Setup privileged flash as Read Only so that privileged tasks can + * read it but not modify. */ + portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_PRIVILEGED_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup unprivileged flash as Read Only by both privileged and + * unprivileged tasks. All tasks can read it but no-one can modify. */ + portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup unprivileged syscalls flash as Read Only by both privileged + * and unprivileged tasks. All tasks can read it but no-one can modify. */ + portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup RAM containing kernel data for privileged access only. */ + portMPU_RNR_REG = portPRIVILEGED_RAM_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Enable mem fault. */ + portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + + /* Enable MPU with privileged background access i.e. unmapped + * regions have privileged access. */ + portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); + } + } +#endif /* configENABLE_MPU */ +/*-----------------------------------------------------------*/ + +#if ( configENABLE_FPU == 1 ) + static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* Enable non-secure access to the FPU. */ + SecureInit_EnableNSFPUAccess(); + } + #endif /* configENABLE_TRUSTZONE */ + + /* CP10 = 11 ==> Full access to FPU i.e. both privileged and + * unprivileged code should be able to access FPU. CP11 should be + * programmed to the same value as CP10. */ + *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) | + ( portCPACR_CP11_VALUE << portCPACR_CP11_POS ) + ); + + /* ASPEN = 1 ==> Hardware should automatically preserve floating point + * context on exception entry and restore on exception return. + * LSPEN = 1 ==> Enable lazy context save of FP state. */ + *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK ); + } +#endif /* configENABLE_FPU */ +/*-----------------------------------------------------------*/ + +void vPortYield( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is + * completely within the specified behaviour for the architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */ +{ + portDISABLE_INTERRUPTS(); + ulCriticalNesting++; + + /* Barriers are normally not required but do ensure the code is + * completely within the specified behaviour for the architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */ +{ + configASSERT( ulCriticalNesting ); + ulCriticalNesting--; + + if( ulCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ +{ + uint32_t ulPreviousMask; + + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ +{ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU */ + + uint32_t ulPC; + + #if ( configENABLE_TRUSTZONE == 1 ) + uint32_t ulR0; + #if ( configENABLE_MPU == 1 ) + uint32_t ulControl, ulIsTaskPrivileged; + #endif /* configENABLE_MPU */ + #endif /* configENABLE_TRUSTZONE */ + uint8_t ucSVCNumber; + + /* Register are stored on the stack in the following order - R0, R1, R2, R3, + * R12, LR, PC, xPSR. */ + ulPC = pulCallerStackAddress[ 6 ]; + ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; + + switch( ucSVCNumber ) + { + #if ( configENABLE_TRUSTZONE == 1 ) + case portSVC_ALLOCATE_SECURE_CONTEXT: + + /* R0 contains the stack size passed as parameter to the + * vPortAllocateSecureContext function. */ + ulR0 = pulCallerStackAddress[ 0 ]; + + #if ( configENABLE_MPU == 1 ) + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } + #endif /* configENABLE_MPU */ + + configASSERT( xSecureContext != NULL ); + SecureContext_LoadContext( xSecureContext ); + break; + + case portSVC_FREE_SECURE_CONTEXT: + /* R0 contains the secure context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); + break; + #endif /* configENABLE_TRUSTZONE */ + + case portSVC_START_SCHEDULER: + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); + + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + break; + + #if ( configENABLE_MPU == 1 ) + case portSVC_RAISE_PRIVILEGE: + + /* Only raise the privilege, if the svc was raised from any of + * the system calls. */ + if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && + ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) + { + vRaisePrivilege(); + } + break; + #endif /* configENABLE_MPU */ + + default: + /* Incorrect SVC call. */ + configASSERT( pdFALSE ); + } +} +/*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ +#if ( configENABLE_MPU == 1 ) + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters, + BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ +#else + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters ) /* PRIVILEGED_FUNCTION */ +#endif /* configENABLE_MPU */ +/* *INDENT-ON* */ +{ + /* Simulate the stack frame as it would be created by a context switch + * interrupt. */ + #if ( portPRELOAD_REGISTERS == 0 ) + { + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ + *pxTopOfStack = portINITIAL_EXC_RETURN; + + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + } + #endif /* configENABLE_MPU */ + + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + + #if ( configENABLE_TRUSTZONE == 1 ) + { + pxTopOfStack--; + *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ + } + #endif /* configENABLE_TRUSTZONE */ + } + #else /* portPRELOAD_REGISTERS */ + { + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ + + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + } + #endif /* configENABLE_MPU */ + + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + + #if ( configENABLE_TRUSTZONE == 1 ) + { + pxTopOfStack--; + *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ + } + #endif /* configENABLE_TRUSTZONE */ + } + #endif /* portPRELOAD_REGISTERS */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; + + #if ( configENABLE_MPU == 1 ) + { + /* Setup the Memory Protection Unit (MPU). */ + prvSetupMPU(); + } + #endif /* configENABLE_MPU */ + + /* Start the timer that generates the tick ISR. Interrupts are disabled + * here already. */ + vPortSetupTimerInterrupt(); + + /* Initialize the critical nesting count ready for the first task. */ + ulCriticalNesting = 0; + + /* Start the first task. */ + vStartFirstTask(); + + /* Should never get here as the tasks will now be executing. Call the task + * exit error function to prevent compiler warnings about a static function + * not being called in the case that the application writer overrides this + * functionality by defining configTASK_RETURN_ADDRESS. Call + * vTaskSwitchContext() so link time optimization does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); + + /* Should not get here. */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( ulCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +#if ( configENABLE_MPU == 1 ) + void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) + { + uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; + int32_t lIndex = 0; + + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_sram_start__; + extern uint32_t * __privileged_sram_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + + /* Setup MAIR0. */ + xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); + xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); + + /* This function is called automatically when the task is created - in + * which case the stack region parameters will be valid. At all other + * times the stack parameters will not be valid and it is assumed that + * the stack region has already been configured. */ + if( ulStackDepth > 0 ) + { + ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; + ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; + + /* If the stack is within the privileged SRAM, do not protect it + * using a separate MPU region. This is needed because privileged + * SRAM is already protected using an MPU region and ARMv8-M does + * not allow overlapping MPU regions. */ + if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) && + ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) ) + { + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; + } + else + { + /* Define the region that allows access to the stack. */ + ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); + + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + } + } + + /* User supplied configurable regions. */ + for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ ) + { + /* If xRegions is NULL i.e. the task has not specified any MPU + * region, the else part ensures that all the configurable MPU + * regions are invalidated. */ + if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) ) + { + /* Translate the generic region definition contained in xRegions + * into the ARMv8 specific MPU settings that are then stored in + * xMPUSettings. */ + ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + + /* Start address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ); + + /* RO/RW. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY ); + } + else + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE ); + } + + /* XN. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); + } + + /* End Address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Normal memory/ Device memory. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 ) + { + /* Attr1 in MAIR0 is configured as device memory. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1; + } + else + { + /* Attr1 in MAIR0 is configured as normal memory. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0; + } + } + else + { + /* Invalidate the region. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL; + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL; + } + + lIndex++; + } + } +#endif /* configENABLE_MPU */ +/*-----------------------------------------------------------*/ + +BaseType_t xPortIsInsideInterrupt( void ) +{ + uint32_t ulCurrentInterrupt; + BaseType_t xReturn; + + /* Obtain the number of the currently executing interrupt. Interrupt Program + * Status Register (IPSR) holds the exception number of the currently-executing + * exception or zero for Thread mode.*/ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/non_secure/port.c b/portable/GCC/ARM_CM23/non_secure/port.c index 8cd327dde..01c4600dc 100644 --- a/portable/GCC/ARM_CM23/non_secure/port.c +++ b/portable/GCC/ARM_CM23/non_secure/port.c @@ -611,7 +611,7 @@ static void prvTaskExitError( void ) extern uint32_t * __unprivileged_flash_end__; extern uint32_t * __privileged_sram_start__; extern uint32_t * __privileged_sram_end__; - #else /* if defined( __ARMCC_VERSION ) */ + #else /* if defined( __ARMCC_VERSION ) */ /* Declaration when these variable are exported from linker scripts. */ extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_end__[]; @@ -801,22 +801,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO ulR0 = pulCallerStackAddress[ 0 ]; #if ( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); - } - #else /* if ( configENABLE_MPU == 1 ) */ - { - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0 ); - } + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } #endif /* configENABLE_MPU */ configASSERT( xSecureContext != NULL ); @@ -834,21 +834,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO case portSVC_START_SCHEDULER: #if ( configENABLE_TRUSTZONE == 1 ) - { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); - } + /* Initialize the secure context management system. */ + SecureContext_Init(); + } #endif /* configENABLE_TRUSTZONE */ #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } #endif /* configENABLE_FPU */ /* Setup the context of the first task so that the first task starts @@ -881,12 +881,12 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO StackType_t * pxEndOfStack, TaskFunction_t pxCode, void * pvParameters, - BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ + BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ #else StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, TaskFunction_t pxCode, - void * pvParameters ) /* PRIVILEGED_FUNCTION */ + void * pvParameters ) /* PRIVILEGED_FUNCTION */ #endif /* configENABLE_MPU */ { /* Simulate the stack frame as it would be created by a context switch @@ -1050,7 +1050,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; int32_t lIndex = 0; + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __privileged_sram_start__; @@ -1078,8 +1080,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ * using a separate MPU region. This is needed because privileged * SRAM is already protected using an MPU region and ARMv8-M does * not allow overlapping MPU regions. */ - if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && - ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) + if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) && + ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) ) { xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; @@ -1088,7 +1090,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ { /* Define the region that allows access to the stack. */ ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | ( portMPU_REGION_NON_SHAREABLE ) | diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c index e5b90410f..d779c6451 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c @@ -1,1189 +1,1193 @@ -/* - * FreeRTOS Kernel V10.3.1 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - */ - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* MPU wrappers includes. */ -#include "mpu_wrappers.h" - -/* Portasm includes. */ -#include "portasm.h" - -#if ( configENABLE_TRUSTZONE == 1 ) - /* Secure components includes. */ - #include "secure_context.h" - #include "secure_init.h" -#endif /* configENABLE_TRUSTZONE */ - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/** - * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only - * i.e. the processor boots as secure and never jumps to the non-secure side. - * The Trust Zone support in the port must be disabled in order to run FreeRTOS - * on the secure side. The following are the valid configuration seetings: - * - * 1. Run FreeRTOS on the Secure Side: - * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0 - * - * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support: - * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1 - * - * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: - * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0 - */ -#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) - #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. -#endif -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the NVIC. - */ -#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) -#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) -#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) -#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - /* Ensure the SysTick is clocked at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) -#else - -/* The way the SysTick is clocked is not modified in case it is not the - * same a the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 0 ) -#endif -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the SCB. - */ -#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) -#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the FPU. - */ -#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */ -#define portCPACR_CP10_VALUE ( 3UL ) -#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE -#define portCPACR_CP10_POS ( 20UL ) -#define portCPACR_CP11_POS ( 22UL ) - -#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */ -#define portFPCCR_ASPEN_POS ( 31UL ) -#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS ) -#define portFPCCR_LSPEN_POS ( 30UL ) -#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the MPU. - */ -#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) -#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) -#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) ) - -#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) ) -#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) ) - -#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) ) -#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) ) - -#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) ) -#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) ) - -#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) ) -#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) ) - -#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) ) -#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) ) - -#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ -#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ - -#define portMPU_MAIR_ATTR0_POS ( 0UL ) -#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) - -#define portMPU_MAIR_ATTR1_POS ( 8UL ) -#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) - -#define portMPU_MAIR_ATTR2_POS ( 16UL ) -#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) - -#define portMPU_MAIR_ATTR3_POS ( 24UL ) -#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) - -#define portMPU_MAIR_ATTR4_POS ( 0UL ) -#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) - -#define portMPU_MAIR_ATTR5_POS ( 8UL ) -#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) - -#define portMPU_MAIR_ATTR6_POS ( 16UL ) -#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) - -#define portMPU_MAIR_ATTR7_POS ( 24UL ) -#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) - -#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL ) - -#define portMPU_RLAR_REGION_ENABLE ( 1UL ) - -/* Enable privileged access to unmapped region. */ -#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) - -/* Enable MPU. */ -#define portMPU_ENABLE_BIT ( 1UL << 0UL ) - -/* Expected value of the portMPU_TYPE register. */ -#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ -/*-----------------------------------------------------------*/ - -/** - * @brief The maximum 24-bit number. - * - * It is needed because the systick is a 24-bit counter. - */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) - -/** - * @brief A fiddle factor to estimate the number of SysTick counts that would - * have occurred while the SysTick counter is stopped during tickless idle - * calculations. - */ -#define portMISSED_COUNTS_FACTOR ( 45UL ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to set up the initial stack. - */ -#define portINITIAL_XPSR ( 0x01000000 ) - -#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) - -/** - * @brief Initial EXC_RETURN value. - * - * FF FF FF FD - * 1111 1111 1111 1111 1111 1111 1111 1101 - * - * Bit[6] - 1 --> The exception was taken from the Secure state. - * Bit[5] - 1 --> Do not skip stacking of additional state context. - * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. - * Bit[3] - 1 --> Return to the Thread mode. - * Bit[2] - 1 --> Restore registers from the process stack. - * Bit[1] - 0 --> Reserved, 0. - * Bit[0] - 1 --> The exception was taken to the Secure state. - */ - #define portINITIAL_EXC_RETURN ( 0xfffffffd ) -#else - -/** - * @brief Initial EXC_RETURN value. - * - * FF FF FF BC - * 1111 1111 1111 1111 1111 1111 1011 1100 - * - * Bit[6] - 0 --> The exception was taken from the Non-Secure state. - * Bit[5] - 1 --> Do not skip stacking of additional state context. - * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. - * Bit[3] - 1 --> Return to the Thread mode. - * Bit[2] - 1 --> Restore registers from the process stack. - * Bit[1] - 0 --> Reserved, 0. - * Bit[0] - 0 --> The exception was taken to the Non-Secure state. - */ - #define portINITIAL_EXC_RETURN ( 0xffffffbc ) -#endif /* configRUN_FREERTOS_SECURE_ONLY */ - -/** - * @brief CONTROL register privileged bit mask. - * - * Bit[0] in CONTROL register tells the privilege: - * Bit[0] = 0 ==> The task is privileged. - * Bit[0] = 1 ==> The task is not privileged. - */ -#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) - -/** - * @brief Initial CONTROL register values. - */ -#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) -#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) - -/** - * @brief Let the user override the pre-loading of the initial LR with the - * address of prvTaskExitError() in case it messes up unwinding of the stack - * in the debugger. - */ -#ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS -#else - #define portTASK_RETURN_ADDRESS prvTaskExitError -#endif - -/** - * @brief If portPRELOAD_REGISTERS then registers will be given an initial value - * when a task is created. This helps in debugging at the cost of code size. - */ -#define portPRELOAD_REGISTERS 1 - -/** - * @brief A task is created without a secure context, and must call - * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes - * any secure calls. - */ -#define portNO_SECURE_CONTEXT 0 -/*-----------------------------------------------------------*/ - -/** - * @brief Used to catch tasks that attempt to return from their implementing - * function. - */ -static void prvTaskExitError( void ); - -#if ( configENABLE_MPU == 1 ) - -/** - * @brief Setup the Memory Protection Unit (MPU). - */ - static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; -#endif /* configENABLE_MPU */ - -#if ( configENABLE_FPU == 1 ) - -/** - * @brief Setup the Floating Point Unit (FPU). - */ - static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; -#endif /* configENABLE_FPU */ - -/** - * @brief Setup the timer to generate the tick interrupts. - * - * The implementation in this file is weak to allow application writers to - * change the timer used to generate the tick interrupt. - */ -void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Checks whether the current execution context is interrupt. - * - * @return pdTRUE if the current execution context is interrupt, pdFALSE - * otherwise. - */ -BaseType_t xPortIsInsideInterrupt( void ); - -/** - * @brief Yield the processor. - */ -void vPortYield( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Enter critical section. - */ -void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Exit from critical section. - */ -void vPortExitCritical( void ) PRIVILEGED_FUNCTION; - -/** - * @brief SysTick handler. - */ -void SysTick_Handler( void ) PRIVILEGED_FUNCTION; - -/** - * @brief C part of SVC handler. - */ -portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION; -/*-----------------------------------------------------------*/ - -/** - * @brief Each task maintains its own interrupt status in the critical nesting - * variable. - */ -PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; - -#if ( configENABLE_TRUSTZONE == 1 ) - -/** - * @brief Saved as part of the task context to indicate which context the - * task is using on the secure side. - */ - PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; -#endif /* configENABLE_TRUSTZONE */ - -#if ( configUSE_TICKLESS_IDLE == 1 ) - -/** - * @brief The number of SysTick increments that make up one tick period. - */ - PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; - -/** - * @brief The maximum number of tick periods that can be suppressed is - * limited by the 24 bit resolution of the SysTick timer. - */ - PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; - -/** - * @brief Compensate for the CPU cycles that pass while the SysTick is - * stopped (low power functionality only). - */ - PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; -#endif /* configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; - - /* Make sure the SysTick reload value does not overflow the counter. */ - if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) - { - xExpectedIdleTime = xMaximumPossibleSuppressedTicks; - } - - /* Stop the SysTick momentarily. The time the SysTick is stopped for is - * accounted for as best it can be, but using the tickless mode will - * inevitably result in some tiny drift of the time maintained by the - * kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; - - /* Calculate the reload value required to wait xExpectedIdleTime - * tick periods. -1 is used because this code will execute part way - * through one of the tick periods. */ - ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); - - if( ulReloadValue > ulStoppedTimerCompensation ) - { - ulReloadValue -= ulStoppedTimerCompensation; - } - - /* Enter a critical section but don't use the taskENTER_CRITICAL() - * method as that will mask interrupts that should exit sleep mode. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* If a context switch is pending or a task is waiting for the scheduler - * to be un-suspended then abandon the low power entry. */ - if( eTaskConfirmSleepModeStatus() == eAbortSleep ) - { - /* Restart from whatever is left in the count register to complete - * this tick period. */ - portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Reset the reload register to the value required for normal tick - * periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - - /* Re-enable interrupts - see comments above the cpsid instruction() - * above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - - /* Clear the SysTick count flag and set the count value back to - * zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can - * set its parameter to 0 to indicate that its implementation - * contains its own wait for interrupt or wait for event - * instruction, and so wfi should not be executed again. However, - * the original expected idle time variable must remain unmodified, - * so a copy is taken. */ - xModifiableIdleTime = xExpectedIdleTime; - configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); - - if( xModifiableIdleTime > 0 ) - { - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "wfi" ); - __asm volatile ( "isb" ); - } - - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - - /* Re-enable interrupts to allow the interrupt that brought the MCU - * out of sleep mode to execute immediately. See comments above - * the cpsid instruction above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable interrupts again because the clock is about to be stopped - * and interrupts that execute while the clock is stopped will - * increase any slippage between the time maintained by the RTOS and - * calendar time. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. - * Again, the time the SysTick is stopped for is accounted for as - * best it can be, but using the tickless mode will inevitably - * result in some tiny drift of the time maintained by the kernel - * with respect to calendar time*/ - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); - - /* Determine if the SysTick clock has already counted to zero and - * been set back to the current reload value (the reload back being - * correct for the entire expected idle time) or if the SysTick is - * yet to count to zero (in which case an interrupt other than the - * SysTick must have brought the system out of sleep mode). */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - uint32_t ulCalculatedLoadValue; - - /* The tick interrupt is already pending, and the SysTick count - * reloaded with ulReloadValue. Reset the - * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick - * period. */ - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); - - /* Don't allow a tiny value, or values that have somehow - * underflowed because the post sleep hook did something - * that took too long. */ - if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) - { - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); - } - - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - - /* As the pending tick will be processed as soon as this - * function exits, the tick value maintained by the tick is - * stepped forward by one less than the time spent waiting. */ - ulCompleteTickPeriods = xExpectedIdleTime - 1UL; - } - else - { - /* Something other than the tick interrupt ended the sleep. - * Work out how long the sleep lasted rounded to complete tick - * periods (not the ulReload value which accounted for part - * ticks). */ - ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* How many complete tick periods passed while the processor - * was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; - - /* The reload value is set to whatever fraction of a single tick - * period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } - - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG - * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard - * value. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - vTaskStepTick( ulCompleteTickPeriods ); - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - - /* Exit with interrupts enabled. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - } -#endif /* configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - -__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Calculate the constants required to configure the tick interrupt. */ - #if ( configUSE_TICKLESS_IDLE == 1 ) - { - ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); - xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; - ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - } - #endif /* configUSE_TICKLESS_IDLE */ - - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; -} -/*-----------------------------------------------------------*/ - -static void prvTaskExitError( void ) -{ - volatile uint32_t ulDummy = 0UL; - - /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). Artificially force an assert() - * to be triggered if configASSERT() is defined, then stop here so - * application writers can catch the error. */ - configASSERT( ulCriticalNesting == ~0UL ); - portDISABLE_INTERRUPTS(); - - while( ulDummy == 0 ) - { - /* This file calls prvTaskExitError() after the scheduler has been - * started to remove a compiler warning about the function being - * defined but never called. ulDummy is used purely to quieten other - * warnings about code appearing after this function is called - making - * ulDummy volatile makes the compiler think the function could return - * and therefore not output an 'unreachable code' warning for code that - * appears after it. */ - } -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ - { - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_functions_start__; - extern uint32_t * __privileged_functions_end__; - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - extern uint32_t * __unprivileged_flash_start__; - extern uint32_t * __unprivileged_flash_end__; - extern uint32_t * __privileged_sram_start__; - extern uint32_t * __privileged_sram_end__; - #else /* if defined( __ARMCC_VERSION ) */ - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_functions_start__[]; - extern uint32_t __privileged_functions_end__[]; - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - extern uint32_t __unprivileged_flash_start__[]; - extern uint32_t __unprivileged_flash_end__[]; - extern uint32_t __privileged_sram_start__[]; - extern uint32_t __privileged_sram_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - - /* Check that the MPU is present. */ - if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) - { - /* MAIR0 - Index 0. */ - portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); - /* MAIR0 - Index 1. */ - portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); - - /* Setup privileged flash as Read Only so that privileged tasks can - * read it but not modify. */ - portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_PRIVILEGED_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup unprivileged flash as Read Only by both privileged and - * unprivileged tasks. All tasks can read it but no-one can modify. */ - portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup unprivileged syscalls flash as Read Only by both privileged - * and unprivileged tasks. All tasks can read it but no-one can modify. */ - portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup RAM containing kernel data for privileged access only. */ - portMPU_RNR_REG = portPRIVILEGED_RAM_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Enable mem fault. */ - portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; - - /* Enable MPU with privileged background access i.e. unmapped - * regions have privileged access. */ - portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); - } - } -#endif /* configENABLE_MPU */ -/*-----------------------------------------------------------*/ - -#if ( configENABLE_FPU == 1 ) - static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ - { - #if ( configENABLE_TRUSTZONE == 1 ) - { - /* Enable non-secure access to the FPU. */ - SecureInit_EnableNSFPUAccess(); - } - #endif /* configENABLE_TRUSTZONE */ - - /* CP10 = 11 ==> Full access to FPU i.e. both privileged and - * unprivileged code should be able to access FPU. CP11 should be - * programmed to the same value as CP10. */ - *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) | - ( portCPACR_CP11_VALUE << portCPACR_CP11_POS ) - ); - - /* ASPEN = 1 ==> Hardware should automatically preserve floating point - * context on exception entry and restore on exception return. - * LSPEN = 1 ==> Enable lazy context save of FP state. */ - *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK ); - } -#endif /* configENABLE_FPU */ -/*-----------------------------------------------------------*/ - -void vPortYield( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Set a PendSV to request a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - - /* Barriers are normally not required but do ensure the code is - * completely within the specified behaviour for the architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */ -{ - portDISABLE_INTERRUPTS(); - ulCriticalNesting++; - - /* Barriers are normally not required but do ensure the code is - * completely within the specified behaviour for the architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */ -{ - configASSERT( ulCriticalNesting ); - ulCriticalNesting--; - - if( ulCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ -{ - uint32_t ulPreviousMask; - - ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Pend a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); -} -/*-----------------------------------------------------------*/ - -void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ -{ - #if ( configENABLE_MPU == 1 ) - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - #endif /* configENABLE_MPU */ - - uint32_t ulPC; - - #if ( configENABLE_TRUSTZONE == 1 ) - uint32_t ulR0; - #if ( configENABLE_MPU == 1 ) - uint32_t ulControl, ulIsTaskPrivileged; - #endif /* configENABLE_MPU */ - #endif /* configENABLE_TRUSTZONE */ - uint8_t ucSVCNumber; - - /* Register are stored on the stack in the following order - R0, R1, R2, R3, - * R12, LR, PC, xPSR. */ - ulPC = pulCallerStackAddress[ 6 ]; - ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; - - switch( ucSVCNumber ) - { - #if ( configENABLE_TRUSTZONE == 1 ) - case portSVC_ALLOCATE_SECURE_CONTEXT: - - /* R0 contains the stack size passed as parameter to the - * vPortAllocateSecureContext function. */ - ulR0 = pulCallerStackAddress[ 0 ]; - - #if ( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); - } - #else /* if ( configENABLE_MPU == 1 ) */ - { - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0 ); - } - #endif /* configENABLE_MPU */ - - configASSERT( xSecureContext != NULL ); - SecureContext_LoadContext( xSecureContext ); - break; - - case portSVC_FREE_SECURE_CONTEXT: - /* R0 contains the secure context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); - break; - #endif /* configENABLE_TRUSTZONE */ - - case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) - { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); - - /* Initialize the secure context management system. */ - SecureContext_Init(); - } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); - break; - - #if ( configENABLE_MPU == 1 ) - case portSVC_RAISE_PRIVILEGE: - - /* Only raise the privilege, if the svc was raised from any of - * the system calls. */ - if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && - ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) - { - vRaisePrivilege(); - } - break; - #endif /* configENABLE_MPU */ - - default: - /* Incorrect SVC call. */ - configASSERT( pdFALSE ); - } -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - StackType_t * pxEndOfStack, - TaskFunction_t pxCode, - void * pvParameters, - BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ -#else - StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - StackType_t * pxEndOfStack, - TaskFunction_t pxCode, - void * pvParameters ) /* PRIVILEGED_FUNCTION */ -#endif /* configENABLE_MPU */ -{ - /* Simulate the stack frame as it would be created by a context switch - * interrupt. */ - #if ( portPRELOAD_REGISTERS == 0 ) - { - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ - *pxTopOfStack = portINITIAL_EXC_RETURN; - - #if ( configENABLE_MPU == 1 ) - { - pxTopOfStack--; - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - } - #endif /* configENABLE_MPU */ - - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - - #if ( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #else /* portPRELOAD_REGISTERS */ - { - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */ - pxTopOfStack--; - *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ - - #if ( configENABLE_MPU == 1 ) - { - pxTopOfStack--; - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - } - #endif /* configENABLE_MPU */ - - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - - #if ( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #endif /* portPRELOAD_REGISTERS */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ - portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; - portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - - #if ( configENABLE_MPU == 1 ) - { - /* Setup the Memory Protection Unit (MPU). */ - prvSetupMPU(); - } - #endif /* configENABLE_MPU */ - - /* Start the timer that generates the tick ISR. Interrupts are disabled - * here already. */ - vPortSetupTimerInterrupt(); - - /* Initialize the critical nesting count ready for the first task. */ - ulCriticalNesting = 0; - - /* Start the first task. */ - vStartFirstTask(); - - /* Should never get here as the tasks will now be executing. Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. Call - * vTaskSwitchContext() so link time optimization does not remove the - * symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); - - /* Should not get here. */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ - configASSERT( ulCriticalNesting == 1000UL ); -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, - const struct xMEMORY_REGION * const xRegions, - StackType_t * pxBottomOfStack, - uint32_t ulStackDepth ) - { - uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; - int32_t lIndex = 0; - #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_sram_start__; - extern uint32_t * __privileged_sram_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_sram_start__[]; - extern uint32_t __privileged_sram_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - - /* Setup MAIR0. */ - xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); - xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); - - /* This function is called automatically when the task is created - in - * which case the stack region parameters will be valid. At all other - * times the stack parameters will not be valid and it is assumed that - * the stack region has already been configured. */ - if( ulStackDepth > 0 ) - { - ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; - ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; - - /* If the stack is within the privileged SRAM, do not protect it - * using a separate MPU region. This is needed because privileged - * SRAM is already protected using an MPU region and ARMv8-M does - * not allow overlapping MPU regions. */ - if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && - ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) - { - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; - } - else - { - /* Define the region that allows access to the stack. */ - ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); - - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - } - } - - /* User supplied configurable regions. */ - for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ ) - { - /* If xRegions is NULL i.e. the task has not specified any MPU - * region, the else part ensures that all the configurable MPU - * regions are invalidated. */ - if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) ) - { - /* Translate the generic region definition contained in xRegions - * into the ARMv8 specific MPU settings that are then stored in - * xMPUSettings. */ - ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - - /* Start address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ); - - /* RO/RW. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY ); - } - else - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE ); - } - - /* XN. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); - } - - /* End Address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Normal memory/ Device memory. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 ) - { - /* Attr1 in MAIR0 is configured as device memory. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1; - } - else - { - /* Attr1 in MAIR0 is configured as normal memory. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0; - } - } - else - { - /* Invalidate the region. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL; - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL; - } - - lIndex++; - } - } -#endif /* configENABLE_MPU */ -/*-----------------------------------------------------------*/ - -BaseType_t xPortIsInsideInterrupt( void ) -{ - uint32_t ulCurrentInterrupt; - BaseType_t xReturn; - - /* Obtain the number of the currently executing interrupt. Interrupt Program - * Status Register (IPSR) holds the exception number of the currently-executing - * exception or zero for Thread mode.*/ - __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ +/* + * FreeRTOS Kernel V10.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + */ + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* MPU wrappers includes. */ +#include "mpu_wrappers.h" + +/* Portasm includes. */ +#include "portasm.h" + +#if ( configENABLE_TRUSTZONE == 1 ) + /* Secure components includes. */ + #include "secure_context.h" + #include "secure_init.h" +#endif /* configENABLE_TRUSTZONE */ + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/** + * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only + * i.e. the processor boots as secure and never jumps to the non-secure side. + * The Trust Zone support in the port must be disabled in order to run FreeRTOS + * on the secure side. The following are the valid configuration seetings: + * + * 1. Run FreeRTOS on the Secure Side: + * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0 + * + * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support: + * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1 + * + * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: + * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0 + */ +#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) + #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. +#endif +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the NVIC. + */ +#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) +#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + +/* The way the SysTick is clocked is not modified in case it is not the + * same a the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the SCB. + */ +#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) +#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the FPU. + */ +#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */ +#define portCPACR_CP10_VALUE ( 3UL ) +#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE +#define portCPACR_CP10_POS ( 20UL ) +#define portCPACR_CP11_POS ( 22UL ) + +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */ +#define portFPCCR_ASPEN_POS ( 31UL ) +#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS ) +#define portFPCCR_LSPEN_POS ( 30UL ) +#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the MPU. + */ +#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) +#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) +#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) ) + +#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) ) +#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) ) + +#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) ) +#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) ) + +#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) ) +#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) ) + +#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) ) +#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) ) + +#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) ) +#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) ) + +#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ +#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ + +#define portMPU_MAIR_ATTR0_POS ( 0UL ) +#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) + +#define portMPU_MAIR_ATTR1_POS ( 8UL ) +#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) + +#define portMPU_MAIR_ATTR2_POS ( 16UL ) +#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) + +#define portMPU_MAIR_ATTR3_POS ( 24UL ) +#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) + +#define portMPU_MAIR_ATTR4_POS ( 0UL ) +#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) + +#define portMPU_MAIR_ATTR5_POS ( 8UL ) +#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) + +#define portMPU_MAIR_ATTR6_POS ( 16UL ) +#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) + +#define portMPU_MAIR_ATTR7_POS ( 24UL ) +#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) + +#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL ) + +#define portMPU_RLAR_REGION_ENABLE ( 1UL ) + +/* Enable privileged access to unmapped region. */ +#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) + +/* Enable MPU. */ +#define portMPU_ENABLE_BIT ( 1UL << 0UL ) + +/* Expected value of the portMPU_TYPE register. */ +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +/*-----------------------------------------------------------*/ + +/** + * @brief The maximum 24-bit number. + * + * It is needed because the systick is a 24-bit counter. + */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/** + * @brief A fiddle factor to estimate the number of SysTick counts that would + * have occurred while the SysTick counter is stopped during tickless idle + * calculations. + */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to set up the initial stack. + */ +#define portINITIAL_XPSR ( 0x01000000 ) + +#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) + +/** + * @brief Initial EXC_RETURN value. + * + * FF FF FF FD + * 1111 1111 1111 1111 1111 1111 1111 1101 + * + * Bit[6] - 1 --> The exception was taken from the Secure state. + * Bit[5] - 1 --> Do not skip stacking of additional state context. + * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. + * Bit[3] - 1 --> Return to the Thread mode. + * Bit[2] - 1 --> Restore registers from the process stack. + * Bit[1] - 0 --> Reserved, 0. + * Bit[0] - 1 --> The exception was taken to the Secure state. + */ + #define portINITIAL_EXC_RETURN ( 0xfffffffd ) +#else + +/** + * @brief Initial EXC_RETURN value. + * + * FF FF FF BC + * 1111 1111 1111 1111 1111 1111 1011 1100 + * + * Bit[6] - 0 --> The exception was taken from the Non-Secure state. + * Bit[5] - 1 --> Do not skip stacking of additional state context. + * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. + * Bit[3] - 1 --> Return to the Thread mode. + * Bit[2] - 1 --> Restore registers from the process stack. + * Bit[1] - 0 --> Reserved, 0. + * Bit[0] - 0 --> The exception was taken to the Non-Secure state. + */ + #define portINITIAL_EXC_RETURN ( 0xffffffbc ) +#endif /* configRUN_FREERTOS_SECURE_ONLY */ + +/** + * @brief CONTROL register privileged bit mask. + * + * Bit[0] in CONTROL register tells the privilege: + * Bit[0] = 0 ==> The task is privileged. + * Bit[0] = 1 ==> The task is not privileged. + */ +#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) + +/** + * @brief Initial CONTROL register values. + */ +#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) +#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) + +/** + * @brief Let the user override the pre-loading of the initial LR with the + * address of prvTaskExitError() in case it messes up unwinding of the stack + * in the debugger. + */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/** + * @brief If portPRELOAD_REGISTERS then registers will be given an initial value + * when a task is created. This helps in debugging at the cost of code size. + */ +#define portPRELOAD_REGISTERS 1 + +/** + * @brief A task is created without a secure context, and must call + * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes + * any secure calls. + */ +#define portNO_SECURE_CONTEXT 0 +/*-----------------------------------------------------------*/ + +/** + * @brief Used to catch tasks that attempt to return from their implementing + * function. + */ +static void prvTaskExitError( void ); + +#if ( configENABLE_MPU == 1 ) + +/** + * @brief Setup the Memory Protection Unit (MPU). + */ + static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; +#endif /* configENABLE_MPU */ + +#if ( configENABLE_FPU == 1 ) + +/** + * @brief Setup the Floating Point Unit (FPU). + */ + static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; +#endif /* configENABLE_FPU */ + +/** + * @brief Setup the timer to generate the tick interrupts. + * + * The implementation in this file is weak to allow application writers to + * change the timer used to generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Checks whether the current execution context is interrupt. + * + * @return pdTRUE if the current execution context is interrupt, pdFALSE + * otherwise. + */ +BaseType_t xPortIsInsideInterrupt( void ); + +/** + * @brief Yield the processor. + */ +void vPortYield( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Enter critical section. + */ +void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Exit from critical section. + */ +void vPortExitCritical( void ) PRIVILEGED_FUNCTION; + +/** + * @brief SysTick handler. + */ +void SysTick_Handler( void ) PRIVILEGED_FUNCTION; + +/** + * @brief C part of SVC handler. + */ +portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION; +/*-----------------------------------------------------------*/ + +/** + * @brief Each task maintains its own interrupt status in the critical nesting + * variable. + */ +PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; + +#if ( configENABLE_TRUSTZONE == 1 ) + +/** + * @brief Saved as part of the task context to indicate which context the + * task is using on the secure side. + */ + PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; +#endif /* configENABLE_TRUSTZONE */ + +#if ( configUSE_TICKLESS_IDLE == 1 ) + +/** + * @brief The number of SysTick increments that make up one tick period. + */ + PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; + +/** + * @brief The maximum number of tick periods that can be suppressed is + * limited by the 24 bit resolution of the SysTick timer. + */ + PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; + +/** + * @brief Compensate for the CPU cycles that pass while the SysTick is + * stopped (low power functionality only). + */ + PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE == 1 ) + __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for is + * accounted for as best it can be, but using the tickless mode will + * inevitably result in some tiny drift of the time maintained by the + * kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + * tick periods. -1 is used because this code will execute part way + * through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* If a context switch is pending or a task is waiting for the scheduler + * to be un-suspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + * this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + * set its parameter to 0 to indicate that its implementation + * contains its own wait for interrupt or wait for event + * instruction, and so wfi should not be executed again. However, + * the original expected idle time variable must remain unmodified, + * so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "isb" ); + } + + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Re-enable interrupts to allow the interrupt that brought the MCU + * out of sleep mode to execute immediately. See comments above + * the cpsid instruction above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable interrupts again because the clock is about to be stopped + * and interrupts that execute while the clock is stopped will + * increase any slippage between the time maintained by the RTOS and + * calendar time. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable the SysTick clock without reading the + * portNVIC_SYSTICK_CTRL_REG register to ensure the + * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. + * Again, the time the SysTick is stopped for is accounted for as + * best it can be, but using the tickless mode will inevitably + * result in some tiny drift of the time maintained by the kernel + * with respect to calendar time*/ + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); + + /* Determine if the SysTick clock has already counted to zero and + * been set back to the current reload value (the reload back being + * correct for the entire expected idle time) or if the SysTick is + * yet to count to zero (in which case an interrupt other than the + * SysTick must have brought the system out of sleep mode). */ + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt is already pending, and the SysTick count + * reloaded with ulReloadValue. Reset the + * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + * period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + * underflowed because the post sleep hook did something + * that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* As the pending tick will be processed as soon as this + * function exits, the tick value maintained by the tick is + * stepped forward by one less than the time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + * Work out how long the sleep lasted rounded to complete tick + * periods (not the ulReload value which accounted for part + * ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + * was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + * period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + * value. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Exit with interrupts enabled. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if ( configUSE_TICKLESS_IDLE == 1 ) + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Stop and reset the SysTick. */ + portNVIC_SYSTICK_CTRL_REG = 0UL; + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + volatile uint32_t ulDummy = 0UL; + + /* A function that implements a task must not exit or attempt to return to + * its caller as there is nothing to return to. If a task wants to exit it + * should instead call vTaskDelete( NULL ). Artificially force an assert() + * to be triggered if configASSERT() is defined, then stop here so + * application writers can catch the error. */ + configASSERT( ulCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + + while( ulDummy == 0 ) + { + /* This file calls prvTaskExitError() after the scheduler has been + * started to remove a compiler warning about the function being + * defined but never called. ulDummy is used purely to quieten other + * warnings about code appearing after this function is called - making + * ulDummy volatile makes the compiler think the function could return + * and therefore not output an 'unreachable code' warning for code that + * appears after it. */ + } +} +/*-----------------------------------------------------------*/ + +#if ( configENABLE_MPU == 1 ) + static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + extern uint32_t * __unprivileged_flash_start__; + extern uint32_t * __unprivileged_flash_end__; + extern uint32_t * __privileged_sram_start__; + extern uint32_t * __privileged_sram_end__; + #else /* if defined( __ARMCC_VERSION ) */ + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + extern uint32_t __unprivileged_flash_start__[]; + extern uint32_t __unprivileged_flash_end__[]; + extern uint32_t __privileged_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + + /* Check that the MPU is present. */ + if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) + { + /* MAIR0 - Index 0. */ + portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); + /* MAIR0 - Index 1. */ + portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); + + /* Setup privileged flash as Read Only so that privileged tasks can + * read it but not modify. */ + portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_PRIVILEGED_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup unprivileged flash as Read Only by both privileged and + * unprivileged tasks. All tasks can read it but no-one can modify. */ + portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup unprivileged syscalls flash as Read Only by both privileged + * and unprivileged tasks. All tasks can read it but no-one can modify. */ + portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup RAM containing kernel data for privileged access only. */ + portMPU_RNR_REG = portPRIVILEGED_RAM_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Enable mem fault. */ + portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + + /* Enable MPU with privileged background access i.e. unmapped + * regions have privileged access. */ + portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); + } + } +#endif /* configENABLE_MPU */ +/*-----------------------------------------------------------*/ + +#if ( configENABLE_FPU == 1 ) + static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* Enable non-secure access to the FPU. */ + SecureInit_EnableNSFPUAccess(); + } + #endif /* configENABLE_TRUSTZONE */ + + /* CP10 = 11 ==> Full access to FPU i.e. both privileged and + * unprivileged code should be able to access FPU. CP11 should be + * programmed to the same value as CP10. */ + *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) | + ( portCPACR_CP11_VALUE << portCPACR_CP11_POS ) + ); + + /* ASPEN = 1 ==> Hardware should automatically preserve floating point + * context on exception entry and restore on exception return. + * LSPEN = 1 ==> Enable lazy context save of FP state. */ + *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK ); + } +#endif /* configENABLE_FPU */ +/*-----------------------------------------------------------*/ + +void vPortYield( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is + * completely within the specified behaviour for the architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */ +{ + portDISABLE_INTERRUPTS(); + ulCriticalNesting++; + + /* Barriers are normally not required but do ensure the code is + * completely within the specified behaviour for the architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */ +{ + configASSERT( ulCriticalNesting ); + ulCriticalNesting--; + + if( ulCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ +{ + uint32_t ulPreviousMask; + + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ +{ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU */ + + uint32_t ulPC; + + #if ( configENABLE_TRUSTZONE == 1 ) + uint32_t ulR0; + #if ( configENABLE_MPU == 1 ) + uint32_t ulControl, ulIsTaskPrivileged; + #endif /* configENABLE_MPU */ + #endif /* configENABLE_TRUSTZONE */ + uint8_t ucSVCNumber; + + /* Register are stored on the stack in the following order - R0, R1, R2, R3, + * R12, LR, PC, xPSR. */ + ulPC = pulCallerStackAddress[ 6 ]; + ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; + + switch( ucSVCNumber ) + { + #if ( configENABLE_TRUSTZONE == 1 ) + case portSVC_ALLOCATE_SECURE_CONTEXT: + + /* R0 contains the stack size passed as parameter to the + * vPortAllocateSecureContext function. */ + ulR0 = pulCallerStackAddress[ 0 ]; + + #if ( configENABLE_MPU == 1 ) + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } + #endif /* configENABLE_MPU */ + + configASSERT( xSecureContext != NULL ); + SecureContext_LoadContext( xSecureContext ); + break; + + case portSVC_FREE_SECURE_CONTEXT: + /* R0 contains the secure context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); + break; + #endif /* configENABLE_TRUSTZONE */ + + case portSVC_START_SCHEDULER: + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); + + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + break; + + #if ( configENABLE_MPU == 1 ) + case portSVC_RAISE_PRIVILEGE: + + /* Only raise the privilege, if the svc was raised from any of + * the system calls. */ + if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && + ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) + { + vRaisePrivilege(); + } + break; + #endif /* configENABLE_MPU */ + + default: + /* Incorrect SVC call. */ + configASSERT( pdFALSE ); + } +} +/*-----------------------------------------------------------*/ + +/* *INDENT-OFF* */ +#if ( configENABLE_MPU == 1 ) + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters, + BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ +#else + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters ) /* PRIVILEGED_FUNCTION */ +#endif /* configENABLE_MPU */ +/* *INDENT-ON* */ +{ + /* Simulate the stack frame as it would be created by a context switch + * interrupt. */ + #if ( portPRELOAD_REGISTERS == 0 ) + { + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ + *pxTopOfStack = portINITIAL_EXC_RETURN; + + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + } + #endif /* configENABLE_MPU */ + + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + + #if ( configENABLE_TRUSTZONE == 1 ) + { + pxTopOfStack--; + *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ + } + #endif /* configENABLE_TRUSTZONE */ + } + #else /* portPRELOAD_REGISTERS */ + { + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ + + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + } + #endif /* configENABLE_MPU */ + + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + + #if ( configENABLE_TRUSTZONE == 1 ) + { + pxTopOfStack--; + *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ + } + #endif /* configENABLE_TRUSTZONE */ + } + #endif /* portPRELOAD_REGISTERS */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; + + #if ( configENABLE_MPU == 1 ) + { + /* Setup the Memory Protection Unit (MPU). */ + prvSetupMPU(); + } + #endif /* configENABLE_MPU */ + + /* Start the timer that generates the tick ISR. Interrupts are disabled + * here already. */ + vPortSetupTimerInterrupt(); + + /* Initialize the critical nesting count ready for the first task. */ + ulCriticalNesting = 0; + + /* Start the first task. */ + vStartFirstTask(); + + /* Should never get here as the tasks will now be executing. Call the task + * exit error function to prevent compiler warnings about a static function + * not being called in the case that the application writer overrides this + * functionality by defining configTASK_RETURN_ADDRESS. Call + * vTaskSwitchContext() so link time optimization does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); + + /* Should not get here. */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( ulCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +#if ( configENABLE_MPU == 1 ) + void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) + { + uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; + int32_t lIndex = 0; + + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_sram_start__; + extern uint32_t * __privileged_sram_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + + /* Setup MAIR0. */ + xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); + xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); + + /* This function is called automatically when the task is created - in + * which case the stack region parameters will be valid. At all other + * times the stack parameters will not be valid and it is assumed that + * the stack region has already been configured. */ + if( ulStackDepth > 0 ) + { + ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; + ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; + + /* If the stack is within the privileged SRAM, do not protect it + * using a separate MPU region. This is needed because privileged + * SRAM is already protected using an MPU region and ARMv8-M does + * not allow overlapping MPU regions. */ + if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) && + ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) ) + { + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; + } + else + { + /* Define the region that allows access to the stack. */ + ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); + + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + } + } + + /* User supplied configurable regions. */ + for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ ) + { + /* If xRegions is NULL i.e. the task has not specified any MPU + * region, the else part ensures that all the configurable MPU + * regions are invalidated. */ + if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) ) + { + /* Translate the generic region definition contained in xRegions + * into the ARMv8 specific MPU settings that are then stored in + * xMPUSettings. */ + ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + + /* Start address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ); + + /* RO/RW. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY ); + } + else + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE ); + } + + /* XN. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); + } + + /* End Address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Normal memory/ Device memory. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 ) + { + /* Attr1 in MAIR0 is configured as device memory. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1; + } + else + { + /* Attr1 in MAIR0 is configured as normal memory. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0; + } + } + else + { + /* Invalidate the region. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL; + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL; + } + + lIndex++; + } + } +#endif /* configENABLE_MPU */ +/*-----------------------------------------------------------*/ + +BaseType_t xPortIsInsideInterrupt( void ) +{ + uint32_t ulCurrentInterrupt; + BaseType_t xReturn; + + /* Obtain the number of the currently executing interrupt. Interrupt Program + * Status Register (IPSR) holds the exception number of the currently-executing + * exception or zero for Thread mode.*/ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c index e5b90410f..8cccf3f5f 100644 --- a/portable/GCC/ARM_CM33/non_secure/port.c +++ b/portable/GCC/ARM_CM33/non_secure/port.c @@ -1,1189 +1,1193 @@ -/* - * FreeRTOS Kernel V10.3.1 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - */ - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/* Scheduler includes. */ -#include "FreeRTOS.h" -#include "task.h" - -/* MPU wrappers includes. */ -#include "mpu_wrappers.h" - -/* Portasm includes. */ -#include "portasm.h" - -#if ( configENABLE_TRUSTZONE == 1 ) - /* Secure components includes. */ - #include "secure_context.h" - #include "secure_init.h" -#endif /* configENABLE_TRUSTZONE */ - -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -/** - * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only - * i.e. the processor boots as secure and never jumps to the non-secure side. - * The Trust Zone support in the port must be disabled in order to run FreeRTOS - * on the secure side. The following are the valid configuration seetings: - * - * 1. Run FreeRTOS on the Secure Side: - * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0 - * - * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support: - * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1 - * - * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: - * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0 - */ -#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) - #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. -#endif -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the NVIC. - */ -#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) -#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) -#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) -#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - /* Ensure the SysTick is clocked at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) -#else - -/* The way the SysTick is clocked is not modified in case it is not the - * same a the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 0 ) -#endif -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the SCB. - */ -#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) -#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the FPU. - */ -#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */ -#define portCPACR_CP10_VALUE ( 3UL ) -#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE -#define portCPACR_CP10_POS ( 20UL ) -#define portCPACR_CP11_POS ( 22UL ) - -#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */ -#define portFPCCR_ASPEN_POS ( 31UL ) -#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS ) -#define portFPCCR_LSPEN_POS ( 30UL ) -#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to manipulate the MPU. - */ -#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) -#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) -#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) ) - -#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) ) -#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) ) - -#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) ) -#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) ) - -#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) ) -#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) ) - -#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) ) -#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) ) - -#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) ) -#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) ) - -#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ -#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ - -#define portMPU_MAIR_ATTR0_POS ( 0UL ) -#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) - -#define portMPU_MAIR_ATTR1_POS ( 8UL ) -#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) - -#define portMPU_MAIR_ATTR2_POS ( 16UL ) -#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) - -#define portMPU_MAIR_ATTR3_POS ( 24UL ) -#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) - -#define portMPU_MAIR_ATTR4_POS ( 0UL ) -#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) - -#define portMPU_MAIR_ATTR5_POS ( 8UL ) -#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) - -#define portMPU_MAIR_ATTR6_POS ( 16UL ) -#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) - -#define portMPU_MAIR_ATTR7_POS ( 24UL ) -#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) - -#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL ) -#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL ) - -#define portMPU_RLAR_REGION_ENABLE ( 1UL ) - -/* Enable privileged access to unmapped region. */ -#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) - -/* Enable MPU. */ -#define portMPU_ENABLE_BIT ( 1UL << 0UL ) - -/* Expected value of the portMPU_TYPE register. */ -#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ -/*-----------------------------------------------------------*/ - -/** - * @brief The maximum 24-bit number. - * - * It is needed because the systick is a 24-bit counter. - */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) - -/** - * @brief A fiddle factor to estimate the number of SysTick counts that would - * have occurred while the SysTick counter is stopped during tickless idle - * calculations. - */ -#define portMISSED_COUNTS_FACTOR ( 45UL ) -/*-----------------------------------------------------------*/ - -/** - * @brief Constants required to set up the initial stack. - */ -#define portINITIAL_XPSR ( 0x01000000 ) - -#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) - -/** - * @brief Initial EXC_RETURN value. - * - * FF FF FF FD - * 1111 1111 1111 1111 1111 1111 1111 1101 - * - * Bit[6] - 1 --> The exception was taken from the Secure state. - * Bit[5] - 1 --> Do not skip stacking of additional state context. - * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. - * Bit[3] - 1 --> Return to the Thread mode. - * Bit[2] - 1 --> Restore registers from the process stack. - * Bit[1] - 0 --> Reserved, 0. - * Bit[0] - 1 --> The exception was taken to the Secure state. - */ - #define portINITIAL_EXC_RETURN ( 0xfffffffd ) -#else - -/** - * @brief Initial EXC_RETURN value. - * - * FF FF FF BC - * 1111 1111 1111 1111 1111 1111 1011 1100 - * - * Bit[6] - 0 --> The exception was taken from the Non-Secure state. - * Bit[5] - 1 --> Do not skip stacking of additional state context. - * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. - * Bit[3] - 1 --> Return to the Thread mode. - * Bit[2] - 1 --> Restore registers from the process stack. - * Bit[1] - 0 --> Reserved, 0. - * Bit[0] - 0 --> The exception was taken to the Non-Secure state. - */ - #define portINITIAL_EXC_RETURN ( 0xffffffbc ) -#endif /* configRUN_FREERTOS_SECURE_ONLY */ - -/** - * @brief CONTROL register privileged bit mask. - * - * Bit[0] in CONTROL register tells the privilege: - * Bit[0] = 0 ==> The task is privileged. - * Bit[0] = 1 ==> The task is not privileged. - */ -#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) - -/** - * @brief Initial CONTROL register values. - */ -#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) -#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) - -/** - * @brief Let the user override the pre-loading of the initial LR with the - * address of prvTaskExitError() in case it messes up unwinding of the stack - * in the debugger. - */ -#ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS -#else - #define portTASK_RETURN_ADDRESS prvTaskExitError -#endif - -/** - * @brief If portPRELOAD_REGISTERS then registers will be given an initial value - * when a task is created. This helps in debugging at the cost of code size. - */ -#define portPRELOAD_REGISTERS 1 - -/** - * @brief A task is created without a secure context, and must call - * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes - * any secure calls. - */ -#define portNO_SECURE_CONTEXT 0 -/*-----------------------------------------------------------*/ - -/** - * @brief Used to catch tasks that attempt to return from their implementing - * function. - */ -static void prvTaskExitError( void ); - -#if ( configENABLE_MPU == 1 ) - -/** - * @brief Setup the Memory Protection Unit (MPU). - */ - static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; -#endif /* configENABLE_MPU */ - -#if ( configENABLE_FPU == 1 ) - -/** - * @brief Setup the Floating Point Unit (FPU). - */ - static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; -#endif /* configENABLE_FPU */ - -/** - * @brief Setup the timer to generate the tick interrupts. - * - * The implementation in this file is weak to allow application writers to - * change the timer used to generate the tick interrupt. - */ -void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Checks whether the current execution context is interrupt. - * - * @return pdTRUE if the current execution context is interrupt, pdFALSE - * otherwise. - */ -BaseType_t xPortIsInsideInterrupt( void ); - -/** - * @brief Yield the processor. - */ -void vPortYield( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Enter critical section. - */ -void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; - -/** - * @brief Exit from critical section. - */ -void vPortExitCritical( void ) PRIVILEGED_FUNCTION; - -/** - * @brief SysTick handler. - */ -void SysTick_Handler( void ) PRIVILEGED_FUNCTION; - -/** - * @brief C part of SVC handler. - */ -portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION; -/*-----------------------------------------------------------*/ - -/** - * @brief Each task maintains its own interrupt status in the critical nesting - * variable. - */ -PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; - -#if ( configENABLE_TRUSTZONE == 1 ) - -/** - * @brief Saved as part of the task context to indicate which context the - * task is using on the secure side. - */ - PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; -#endif /* configENABLE_TRUSTZONE */ - -#if ( configUSE_TICKLESS_IDLE == 1 ) - -/** - * @brief The number of SysTick increments that make up one tick period. - */ - PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; - -/** - * @brief The maximum number of tick periods that can be suppressed is - * limited by the 24 bit resolution of the SysTick timer. - */ - PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; - -/** - * @brief Compensate for the CPU cycles that pass while the SysTick is - * stopped (low power functionality only). - */ - PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; -#endif /* configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; - - /* Make sure the SysTick reload value does not overflow the counter. */ - if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) - { - xExpectedIdleTime = xMaximumPossibleSuppressedTicks; - } - - /* Stop the SysTick momentarily. The time the SysTick is stopped for is - * accounted for as best it can be, but using the tickless mode will - * inevitably result in some tiny drift of the time maintained by the - * kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; - - /* Calculate the reload value required to wait xExpectedIdleTime - * tick periods. -1 is used because this code will execute part way - * through one of the tick periods. */ - ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); - - if( ulReloadValue > ulStoppedTimerCompensation ) - { - ulReloadValue -= ulStoppedTimerCompensation; - } - - /* Enter a critical section but don't use the taskENTER_CRITICAL() - * method as that will mask interrupts that should exit sleep mode. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* If a context switch is pending or a task is waiting for the scheduler - * to be un-suspended then abandon the low power entry. */ - if( eTaskConfirmSleepModeStatus() == eAbortSleep ) - { - /* Restart from whatever is left in the count register to complete - * this tick period. */ - portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Reset the reload register to the value required for normal tick - * periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - - /* Re-enable interrupts - see comments above the cpsid instruction() - * above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - - /* Clear the SysTick count flag and set the count value back to - * zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can - * set its parameter to 0 to indicate that its implementation - * contains its own wait for interrupt or wait for event - * instruction, and so wfi should not be executed again. However, - * the original expected idle time variable must remain unmodified, - * so a copy is taken. */ - xModifiableIdleTime = xExpectedIdleTime; - configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); - - if( xModifiableIdleTime > 0 ) - { - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "wfi" ); - __asm volatile ( "isb" ); - } - - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - - /* Re-enable interrupts to allow the interrupt that brought the MCU - * out of sleep mode to execute immediately. See comments above - * the cpsid instruction above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable interrupts again because the clock is about to be stopped - * and interrupts that execute while the clock is stopped will - * increase any slippage between the time maintained by the RTOS and - * calendar time. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. - * Again, the time the SysTick is stopped for is accounted for as - * best it can be, but using the tickless mode will inevitably - * result in some tiny drift of the time maintained by the kernel - * with respect to calendar time*/ - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); - - /* Determine if the SysTick clock has already counted to zero and - * been set back to the current reload value (the reload back being - * correct for the entire expected idle time) or if the SysTick is - * yet to count to zero (in which case an interrupt other than the - * SysTick must have brought the system out of sleep mode). */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - uint32_t ulCalculatedLoadValue; - - /* The tick interrupt is already pending, and the SysTick count - * reloaded with ulReloadValue. Reset the - * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick - * period. */ - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); - - /* Don't allow a tiny value, or values that have somehow - * underflowed because the post sleep hook did something - * that took too long. */ - if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) - { - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); - } - - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - - /* As the pending tick will be processed as soon as this - * function exits, the tick value maintained by the tick is - * stepped forward by one less than the time spent waiting. */ - ulCompleteTickPeriods = xExpectedIdleTime - 1UL; - } - else - { - /* Something other than the tick interrupt ended the sleep. - * Work out how long the sleep lasted rounded to complete tick - * periods (not the ulReload value which accounted for part - * ticks). */ - ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; - - /* How many complete tick periods passed while the processor - * was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; - - /* The reload value is set to whatever fraction of a single tick - * period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } - - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG - * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard - * value. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - vTaskStepTick( ulCompleteTickPeriods ); - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - - /* Exit with interrupts enabled. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - } -#endif /* configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - -__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Calculate the constants required to configure the tick interrupt. */ - #if ( configUSE_TICKLESS_IDLE == 1 ) - { - ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); - xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; - ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - } - #endif /* configUSE_TICKLESS_IDLE */ - - /* Stop and reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Configure SysTick to interrupt at the requested rate. */ - portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; -} -/*-----------------------------------------------------------*/ - -static void prvTaskExitError( void ) -{ - volatile uint32_t ulDummy = 0UL; - - /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). Artificially force an assert() - * to be triggered if configASSERT() is defined, then stop here so - * application writers can catch the error. */ - configASSERT( ulCriticalNesting == ~0UL ); - portDISABLE_INTERRUPTS(); - - while( ulDummy == 0 ) - { - /* This file calls prvTaskExitError() after the scheduler has been - * started to remove a compiler warning about the function being - * defined but never called. ulDummy is used purely to quieten other - * warnings about code appearing after this function is called - making - * ulDummy volatile makes the compiler think the function could return - * and therefore not output an 'unreachable code' warning for code that - * appears after it. */ - } -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ - { - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_functions_start__; - extern uint32_t * __privileged_functions_end__; - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - extern uint32_t * __unprivileged_flash_start__; - extern uint32_t * __unprivileged_flash_end__; - extern uint32_t * __privileged_sram_start__; - extern uint32_t * __privileged_sram_end__; - #else /* if defined( __ARMCC_VERSION ) */ - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_functions_start__[]; - extern uint32_t __privileged_functions_end__[]; - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - extern uint32_t __unprivileged_flash_start__[]; - extern uint32_t __unprivileged_flash_end__[]; - extern uint32_t __privileged_sram_start__[]; - extern uint32_t __privileged_sram_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - - /* Check that the MPU is present. */ - if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) - { - /* MAIR0 - Index 0. */ - portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); - /* MAIR0 - Index 1. */ - portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); - - /* Setup privileged flash as Read Only so that privileged tasks can - * read it but not modify. */ - portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_PRIVILEGED_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup unprivileged flash as Read Only by both privileged and - * unprivileged tasks. All tasks can read it but no-one can modify. */ - portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup unprivileged syscalls flash as Read Only by both privileged - * and unprivileged tasks. All tasks can read it but no-one can modify. */ - portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_ONLY ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Setup RAM containing kernel data for privileged access only. */ - portMPU_RNR_REG = portPRIVILEGED_RAM_REGION; - portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); - portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Enable mem fault. */ - portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; - - /* Enable MPU with privileged background access i.e. unmapped - * regions have privileged access. */ - portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); - } - } -#endif /* configENABLE_MPU */ -/*-----------------------------------------------------------*/ - -#if ( configENABLE_FPU == 1 ) - static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ - { - #if ( configENABLE_TRUSTZONE == 1 ) - { - /* Enable non-secure access to the FPU. */ - SecureInit_EnableNSFPUAccess(); - } - #endif /* configENABLE_TRUSTZONE */ - - /* CP10 = 11 ==> Full access to FPU i.e. both privileged and - * unprivileged code should be able to access FPU. CP11 should be - * programmed to the same value as CP10. */ - *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) | - ( portCPACR_CP11_VALUE << portCPACR_CP11_POS ) - ); - - /* ASPEN = 1 ==> Hardware should automatically preserve floating point - * context on exception entry and restore on exception return. - * LSPEN = 1 ==> Enable lazy context save of FP state. */ - *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK ); - } -#endif /* configENABLE_FPU */ -/*-----------------------------------------------------------*/ - -void vPortYield( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Set a PendSV to request a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - - /* Barriers are normally not required but do ensure the code is - * completely within the specified behaviour for the architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); -} -/*-----------------------------------------------------------*/ - -void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */ -{ - portDISABLE_INTERRUPTS(); - ulCriticalNesting++; - - /* Barriers are normally not required but do ensure the code is - * completely within the specified behaviour for the architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); -} -/*-----------------------------------------------------------*/ - -void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */ -{ - configASSERT( ulCriticalNesting ); - ulCriticalNesting--; - - if( ulCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -} -/*-----------------------------------------------------------*/ - -void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ -{ - uint32_t ulPreviousMask; - - ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Pend a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); -} -/*-----------------------------------------------------------*/ - -void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ -{ - #if ( configENABLE_MPU == 1 ) - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - #endif /* configENABLE_MPU */ - - uint32_t ulPC; - - #if ( configENABLE_TRUSTZONE == 1 ) - uint32_t ulR0; - #if ( configENABLE_MPU == 1 ) - uint32_t ulControl, ulIsTaskPrivileged; - #endif /* configENABLE_MPU */ - #endif /* configENABLE_TRUSTZONE */ - uint8_t ucSVCNumber; - - /* Register are stored on the stack in the following order - R0, R1, R2, R3, - * R12, LR, PC, xPSR. */ - ulPC = pulCallerStackAddress[ 6 ]; - ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; - - switch( ucSVCNumber ) - { - #if ( configENABLE_TRUSTZONE == 1 ) - case portSVC_ALLOCATE_SECURE_CONTEXT: - - /* R0 contains the stack size passed as parameter to the - * vPortAllocateSecureContext function. */ - ulR0 = pulCallerStackAddress[ 0 ]; - - #if ( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); - } - #else /* if ( configENABLE_MPU == 1 ) */ - { - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0 ); - } - #endif /* configENABLE_MPU */ - - configASSERT( xSecureContext != NULL ); - SecureContext_LoadContext( xSecureContext ); - break; - - case portSVC_FREE_SECURE_CONTEXT: - /* R0 contains the secure context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; - - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); - break; - #endif /* configENABLE_TRUSTZONE */ - - case portSVC_START_SCHEDULER: - #if ( configENABLE_TRUSTZONE == 1 ) - { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); - - /* Initialize the secure context management system. */ - SecureContext_Init(); - } - #endif /* configENABLE_TRUSTZONE */ - - #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ - - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); - break; - - #if ( configENABLE_MPU == 1 ) - case portSVC_RAISE_PRIVILEGE: - - /* Only raise the privilege, if the svc was raised from any of - * the system calls. */ - if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && - ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) - { - vRaisePrivilege(); - } - break; - #endif /* configENABLE_MPU */ - - default: - /* Incorrect SVC call. */ - configASSERT( pdFALSE ); - } -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - StackType_t * pxEndOfStack, - TaskFunction_t pxCode, - void * pvParameters, - BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ -#else - StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - StackType_t * pxEndOfStack, - TaskFunction_t pxCode, - void * pvParameters ) /* PRIVILEGED_FUNCTION */ -#endif /* configENABLE_MPU */ -{ - /* Simulate the stack frame as it would be created by a context switch - * interrupt. */ - #if ( portPRELOAD_REGISTERS == 0 ) - { - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ - *pxTopOfStack = portINITIAL_EXC_RETURN; - - #if ( configENABLE_MPU == 1 ) - { - pxTopOfStack--; - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - } - #endif /* configENABLE_MPU */ - - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - - #if ( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #else /* portPRELOAD_REGISTERS */ - { - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ - *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */ - pxTopOfStack--; - *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ - - #if ( configENABLE_MPU == 1 ) - { - pxTopOfStack--; - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ - } - } - #endif /* configENABLE_MPU */ - - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - - #if ( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #endif /* portPRELOAD_REGISTERS */ - - return pxTopOfStack; -} -/*-----------------------------------------------------------*/ - -BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ - portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; - portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - - #if ( configENABLE_MPU == 1 ) - { - /* Setup the Memory Protection Unit (MPU). */ - prvSetupMPU(); - } - #endif /* configENABLE_MPU */ - - /* Start the timer that generates the tick ISR. Interrupts are disabled - * here already. */ - vPortSetupTimerInterrupt(); - - /* Initialize the critical nesting count ready for the first task. */ - ulCriticalNesting = 0; - - /* Start the first task. */ - vStartFirstTask(); - - /* Should never get here as the tasks will now be executing. Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. Call - * vTaskSwitchContext() so link time optimization does not remove the - * symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); - - /* Should not get here. */ - return 0; -} -/*-----------------------------------------------------------*/ - -void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ -{ - /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ - configASSERT( ulCriticalNesting == 1000UL ); -} -/*-----------------------------------------------------------*/ - -#if ( configENABLE_MPU == 1 ) - void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, - const struct xMEMORY_REGION * const xRegions, - StackType_t * pxBottomOfStack, - uint32_t ulStackDepth ) - { - uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; - int32_t lIndex = 0; - #if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_sram_start__; - extern uint32_t * __privileged_sram_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_sram_start__[]; - extern uint32_t __privileged_sram_end__[]; - #endif /* defined( __ARMCC_VERSION ) */ - - /* Setup MAIR0. */ - xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); - xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); - - /* This function is called automatically when the task is created - in - * which case the stack region parameters will be valid. At all other - * times the stack parameters will not be valid and it is assumed that - * the stack region has already been configured. */ - if( ulStackDepth > 0 ) - { - ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; - ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; - - /* If the stack is within the privileged SRAM, do not protect it - * using a separate MPU region. This is needed because privileged - * SRAM is already protected using an MPU region and ARMv8-M does - * not allow overlapping MPU regions. */ - if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && - ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) - { - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; - } - else - { - /* Define the region that allows access to the stack. */ - ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); - - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - } - } - - /* User supplied configurable regions. */ - for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ ) - { - /* If xRegions is NULL i.e. the task has not specified any MPU - * region, the else part ensures that all the configurable MPU - * regions are invalidated. */ - if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) ) - { - /* Translate the generic region definition contained in xRegions - * into the ARMv8 specific MPU settings that are then stored in - * xMPUSettings. */ - ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - - /* Start address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ); - - /* RO/RW. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY ); - } - else - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE ); - } - - /* XN. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); - } - - /* End Address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_REGION_ENABLE ); - - /* Normal memory/ Device memory. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 ) - { - /* Attr1 in MAIR0 is configured as device memory. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1; - } - else - { - /* Attr1 in MAIR0 is configured as normal memory. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0; - } - } - else - { - /* Invalidate the region. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL; - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL; - } - - lIndex++; - } - } -#endif /* configENABLE_MPU */ -/*-----------------------------------------------------------*/ - -BaseType_t xPortIsInsideInterrupt( void ) -{ - uint32_t ulCurrentInterrupt; - BaseType_t xReturn; - - /* Obtain the number of the currently executing interrupt. Interrupt Program - * Status Register (IPSR) holds the exception number of the currently-executing - * exception or zero for Thread mode.*/ - __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ +/* + * FreeRTOS Kernel V10.3.1 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + */ + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* MPU wrappers includes. */ +#include "mpu_wrappers.h" + +/* Portasm includes. */ +#include "portasm.h" + +#if ( configENABLE_TRUSTZONE == 1 ) + /* Secure components includes. */ + #include "secure_context.h" + #include "secure_init.h" +#endif /* configENABLE_TRUSTZONE */ + +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/** + * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only + * i.e. the processor boots as secure and never jumps to the non-secure side. + * The Trust Zone support in the port must be disabled in order to run FreeRTOS + * on the secure side. The following are the valid configuration seetings: + * + * 1. Run FreeRTOS on the Secure Side: + * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0 + * + * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support: + * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1 + * + * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support: + * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0 + */ +#if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) ) + #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side. +#endif +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the NVIC. + */ +#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) +#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#else + +/* The way the SysTick is clocked is not modified in case it is not the + * same a the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) +#endif +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the SCB. + */ +#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) +#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the FPU. + */ +#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */ +#define portCPACR_CP10_VALUE ( 3UL ) +#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE +#define portCPACR_CP10_POS ( 20UL ) +#define portCPACR_CP11_POS ( 22UL ) + +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */ +#define portFPCCR_ASPEN_POS ( 31UL ) +#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS ) +#define portFPCCR_LSPEN_POS ( 30UL ) +#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to manipulate the MPU. + */ +#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) +#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) +#define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) ) + +#define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) ) +#define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) ) + +#define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) ) +#define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) ) + +#define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) ) +#define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) ) + +#define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) ) +#define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) ) + +#define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) ) +#define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) ) + +#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ +#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */ + +#define portMPU_MAIR_ATTR0_POS ( 0UL ) +#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) + +#define portMPU_MAIR_ATTR1_POS ( 8UL ) +#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) + +#define portMPU_MAIR_ATTR2_POS ( 16UL ) +#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) + +#define portMPU_MAIR_ATTR3_POS ( 24UL ) +#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) + +#define portMPU_MAIR_ATTR4_POS ( 0UL ) +#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) + +#define portMPU_MAIR_ATTR5_POS ( 8UL ) +#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) + +#define portMPU_MAIR_ATTR6_POS ( 16UL ) +#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) + +#define portMPU_MAIR_ATTR7_POS ( 24UL ) +#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) + +#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL ) +#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL ) + +#define portMPU_RLAR_REGION_ENABLE ( 1UL ) + +/* Enable privileged access to unmapped region. */ +#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) + +/* Enable MPU. */ +#define portMPU_ENABLE_BIT ( 1UL << 0UL ) + +/* Expected value of the portMPU_TYPE register. */ +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +/*-----------------------------------------------------------*/ + +/** + * @brief The maximum 24-bit number. + * + * It is needed because the systick is a 24-bit counter. + */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) + +/** + * @brief A fiddle factor to estimate the number of SysTick counts that would + * have occurred while the SysTick counter is stopped during tickless idle + * calculations. + */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) +/*-----------------------------------------------------------*/ + +/** + * @brief Constants required to set up the initial stack. + */ +#define portINITIAL_XPSR ( 0x01000000 ) + +#if ( configRUN_FREERTOS_SECURE_ONLY == 1 ) + +/** + * @brief Initial EXC_RETURN value. + * + * FF FF FF FD + * 1111 1111 1111 1111 1111 1111 1111 1101 + * + * Bit[6] - 1 --> The exception was taken from the Secure state. + * Bit[5] - 1 --> Do not skip stacking of additional state context. + * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. + * Bit[3] - 1 --> Return to the Thread mode. + * Bit[2] - 1 --> Restore registers from the process stack. + * Bit[1] - 0 --> Reserved, 0. + * Bit[0] - 1 --> The exception was taken to the Secure state. + */ + #define portINITIAL_EXC_RETURN ( 0xfffffffd ) +#else + +/** + * @brief Initial EXC_RETURN value. + * + * FF FF FF BC + * 1111 1111 1111 1111 1111 1111 1011 1100 + * + * Bit[6] - 0 --> The exception was taken from the Non-Secure state. + * Bit[5] - 1 --> Do not skip stacking of additional state context. + * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context. + * Bit[3] - 1 --> Return to the Thread mode. + * Bit[2] - 1 --> Restore registers from the process stack. + * Bit[1] - 0 --> Reserved, 0. + * Bit[0] - 0 --> The exception was taken to the Non-Secure state. + */ + #define portINITIAL_EXC_RETURN ( 0xffffffbc ) +#endif /* configRUN_FREERTOS_SECURE_ONLY */ + +/** + * @brief CONTROL register privileged bit mask. + * + * Bit[0] in CONTROL register tells the privilege: + * Bit[0] = 0 ==> The task is privileged. + * Bit[0] = 1 ==> The task is not privileged. + */ +#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) + +/** + * @brief Initial CONTROL register values. + */ +#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) +#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) + +/** + * @brief Let the user override the pre-loading of the initial LR with the + * address of prvTaskExitError() in case it messes up unwinding of the stack + * in the debugger. + */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/** + * @brief If portPRELOAD_REGISTERS then registers will be given an initial value + * when a task is created. This helps in debugging at the cost of code size. + */ +#define portPRELOAD_REGISTERS 1 + +/** + * @brief A task is created without a secure context, and must call + * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes + * any secure calls. + */ +#define portNO_SECURE_CONTEXT 0 +/*-----------------------------------------------------------*/ + +/** + * @brief Used to catch tasks that attempt to return from their implementing + * function. + */ +static void prvTaskExitError( void ); + +#if ( configENABLE_MPU == 1 ) + +/** + * @brief Setup the Memory Protection Unit (MPU). + */ + static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; +#endif /* configENABLE_MPU */ + +#if ( configENABLE_FPU == 1 ) + +/** + * @brief Setup the Floating Point Unit (FPU). + */ + static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; +#endif /* configENABLE_FPU */ + +/** + * @brief Setup the timer to generate the tick interrupts. + * + * The implementation in this file is weak to allow application writers to + * change the timer used to generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Checks whether the current execution context is interrupt. + * + * @return pdTRUE if the current execution context is interrupt, pdFALSE + * otherwise. + */ +BaseType_t xPortIsInsideInterrupt( void ); + +/** + * @brief Yield the processor. + */ +void vPortYield( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Enter critical section. + */ +void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; + +/** + * @brief Exit from critical section. + */ +void vPortExitCritical( void ) PRIVILEGED_FUNCTION; + +/** + * @brief SysTick handler. + */ +void SysTick_Handler( void ) PRIVILEGED_FUNCTION; + +/** + * @brief C part of SVC handler. + */ +portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION; +/*-----------------------------------------------------------*/ + +/** + * @brief Each task maintains its own interrupt status in the critical nesting + * variable. + */ +PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; + +#if ( configENABLE_TRUSTZONE == 1 ) + +/** + * @brief Saved as part of the task context to indicate which context the + * task is using on the secure side. + */ + PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; +#endif /* configENABLE_TRUSTZONE */ + +#if ( configUSE_TICKLESS_IDLE == 1 ) + +/** + * @brief The number of SysTick increments that make up one tick period. + */ + PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; + +/** + * @brief The maximum number of tick periods that can be suppressed is + * limited by the 24 bit resolution of the SysTick timer. + */ + PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; + +/** + * @brief Compensate for the CPU cycles that pass while the SysTick is + * stopped (low power functionality only). + */ + PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TICKLESS_IDLE == 1 ) + __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Stop the SysTick momentarily. The time the SysTick is stopped for is + * accounted for as best it can be, but using the tickless mode will + * inevitably result in some tiny drift of the time maintained by the + * kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT; + + /* Calculate the reload value required to wait xExpectedIdleTime + * tick periods. -1 is used because this code will execute part way + * through one of the tick periods. */ + ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* If a context switch is pending or a task is waiting for the scheduler + * to be un-suspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Restart from whatever is left in the count register to complete + * this tick period. */ + portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + * set its parameter to 0 to indicate that its implementation + * contains its own wait for interrupt or wait for event + * instruction, and so wfi should not be executed again. However, + * the original expected idle time variable must remain unmodified, + * so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "isb" ); + } + + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Re-enable interrupts to allow the interrupt that brought the MCU + * out of sleep mode to execute immediately. See comments above + * the cpsid instruction above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable interrupts again because the clock is about to be stopped + * and interrupts that execute while the clock is stopped will + * increase any slippage between the time maintained by the RTOS and + * calendar time. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable the SysTick clock without reading the + * portNVIC_SYSTICK_CTRL_REG register to ensure the + * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. + * Again, the time the SysTick is stopped for is accounted for as + * best it can be, but using the tickless mode will inevitably + * result in some tiny drift of the time maintained by the kernel + * with respect to calendar time*/ + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT ); + + /* Determine if the SysTick clock has already counted to zero and + * been set back to the current reload value (the reload back being + * correct for the entire expected idle time) or if the SysTick is + * yet to count to zero (in which case an interrupt other than the + * SysTick must have brought the system out of sleep mode). */ + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt is already pending, and the SysTick count + * reloaded with ulReloadValue. Reset the + * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick + * period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + * underflowed because the post sleep hook did something + * that took too long. */ + if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* As the pending tick will be processed as soon as this + * function exits, the tick value maintained by the tick is + * stepped forward by one less than the time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. + * Work out how long the sleep lasted rounded to complete tick + * periods (not the ulReload value which accounted for part + * ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG; + + /* How many complete tick periods passed while the processor + * was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + * period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG + * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard + * value. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + vTaskStepTick( ulCompleteTickPeriods ); + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + + /* Exit with interrupts enabled. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } +#endif /* configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Calculate the constants required to configure the tick interrupt. */ + #if ( configUSE_TICKLESS_IDLE == 1 ) + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + + /* Stop and reset the SysTick. */ + portNVIC_SYSTICK_CTRL_REG = 0UL; + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Configure SysTick to interrupt at the requested rate. */ + portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; +} +/*-----------------------------------------------------------*/ + +static void prvTaskExitError( void ) +{ + volatile uint32_t ulDummy = 0UL; + + /* A function that implements a task must not exit or attempt to return to + * its caller as there is nothing to return to. If a task wants to exit it + * should instead call vTaskDelete( NULL ). Artificially force an assert() + * to be triggered if configASSERT() is defined, then stop here so + * application writers can catch the error. */ + configASSERT( ulCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + + while( ulDummy == 0 ) + { + /* This file calls prvTaskExitError() after the scheduler has been + * started to remove a compiler warning about the function being + * defined but never called. ulDummy is used purely to quieten other + * warnings about code appearing after this function is called - making + * ulDummy volatile makes the compiler think the function could return + * and therefore not output an 'unreachable code' warning for code that + * appears after it. */ + } +} +/*-----------------------------------------------------------*/ + +#if ( configENABLE_MPU == 1 ) + static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + extern uint32_t * __unprivileged_flash_start__; + extern uint32_t * __unprivileged_flash_end__; + extern uint32_t * __privileged_sram_start__; + extern uint32_t * __privileged_sram_end__; + #else /* if defined( __ARMCC_VERSION ) */ + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + extern uint32_t __unprivileged_flash_start__[]; + extern uint32_t __unprivileged_flash_end__[]; + extern uint32_t __privileged_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + + /* Check that the MPU is present. */ + if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) + { + /* MAIR0 - Index 0. */ + portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); + /* MAIR0 - Index 1. */ + portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); + + /* Setup privileged flash as Read Only so that privileged tasks can + * read it but not modify. */ + portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_PRIVILEGED_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup unprivileged flash as Read Only by both privileged and + * unprivileged tasks. All tasks can read it but no-one can modify. */ + portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup unprivileged syscalls flash as Read Only by both privileged + * and unprivileged tasks. All tasks can read it but no-one can modify. */ + portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_ONLY ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Setup RAM containing kernel data for privileged access only. */ + portMPU_RNR_REG = portPRIVILEGED_RAM_REGION; + portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); + portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Enable mem fault. */ + portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + + /* Enable MPU with privileged background access i.e. unmapped + * regions have privileged access. */ + portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); + } + } +#endif /* configENABLE_MPU */ +/*-----------------------------------------------------------*/ + +#if ( configENABLE_FPU == 1 ) + static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* Enable non-secure access to the FPU. */ + SecureInit_EnableNSFPUAccess(); + } + #endif /* configENABLE_TRUSTZONE */ + + /* CP10 = 11 ==> Full access to FPU i.e. both privileged and + * unprivileged code should be able to access FPU. CP11 should be + * programmed to the same value as CP10. */ + *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) | + ( portCPACR_CP11_VALUE << portCPACR_CP11_POS ) + ); + + /* ASPEN = 1 ==> Hardware should automatically preserve floating point + * context on exception entry and restore on exception return. + * LSPEN = 1 ==> Enable lazy context save of FP state. */ + *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK ); + } +#endif /* configENABLE_FPU */ +/*-----------------------------------------------------------*/ + +void vPortYield( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Set a PendSV to request a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required but do ensure the code is + * completely within the specified behaviour for the architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */ +{ + portDISABLE_INTERRUPTS(); + ulCriticalNesting++; + + /* Barriers are normally not required but do ensure the code is + * completely within the specified behaviour for the architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); +} +/*-----------------------------------------------------------*/ + +void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */ +{ + configASSERT( ulCriticalNesting ); + ulCriticalNesting--; + + if( ulCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +} +/*-----------------------------------------------------------*/ + +void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ +{ + uint32_t ulPreviousMask; + + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); +} +/*-----------------------------------------------------------*/ + +void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ +{ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + #endif /* configENABLE_MPU */ + + uint32_t ulPC; + + #if ( configENABLE_TRUSTZONE == 1 ) + uint32_t ulR0; + #if ( configENABLE_MPU == 1 ) + uint32_t ulControl, ulIsTaskPrivileged; + #endif /* configENABLE_MPU */ + #endif /* configENABLE_TRUSTZONE */ + uint8_t ucSVCNumber; + + /* Register are stored on the stack in the following order - R0, R1, R2, R3, + * R12, LR, PC, xPSR. */ + ulPC = pulCallerStackAddress[ 6 ]; + ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; + + switch( ucSVCNumber ) + { + #if ( configENABLE_TRUSTZONE == 1 ) + case portSVC_ALLOCATE_SECURE_CONTEXT: + + /* R0 contains the stack size passed as parameter to the + * vPortAllocateSecureContext function. */ + ulR0 = pulCallerStackAddress[ 0 ]; + + #if ( configENABLE_MPU == 1 ) + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } + #endif /* configENABLE_MPU */ + + configASSERT( xSecureContext != NULL ); + SecureContext_LoadContext( xSecureContext ); + break; + + case portSVC_FREE_SECURE_CONTEXT: + /* R0 contains the secure context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; + + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); + break; + #endif /* configENABLE_TRUSTZONE */ + + case portSVC_START_SCHEDULER: + #if ( configENABLE_TRUSTZONE == 1 ) + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); + + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ + + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ + + /* Setup the context of the first task so that the first task starts + * executing. */ + vRestoreContextOfFirstTask(); + break; + + #if ( configENABLE_MPU == 1 ) + case portSVC_RAISE_PRIVILEGE: + + /* Only raise the privilege, if the svc was raised from any of + * the system calls. */ + if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && + ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) + { + vRaisePrivilege(); + } + break; + #endif /* configENABLE_MPU */ + + default: + /* Incorrect SVC call. */ + configASSERT( pdFALSE ); + } +} +/*-----------------------------------------------------------*/ + +/* *INDENT-OFF* */ +#if ( configENABLE_MPU == 1 ) + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters, + BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ +#else + StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + StackType_t * pxEndOfStack, + TaskFunction_t pxCode, + void * pvParameters ) /* PRIVILEGED_FUNCTION */ +#endif /* configENABLE_MPU */ +/* *INDENT-ON* */ +{ + /* Simulate the stack frame as it would be created by a context switch + * interrupt. */ + #if ( portPRELOAD_REGISTERS == 0 ) + { + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */ + *pxTopOfStack = portINITIAL_EXC_RETURN; + + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + } + #endif /* configENABLE_MPU */ + + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + + #if ( configENABLE_TRUSTZONE == 1 ) + { + pxTopOfStack--; + *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ + } + #endif /* configENABLE_TRUSTZONE */ + } + #else /* portPRELOAD_REGISTERS */ + { + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxCode; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */ + + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */ + } + } + #endif /* configENABLE_MPU */ + + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + + #if ( configENABLE_TRUSTZONE == 1 ) + { + pxTopOfStack--; + *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ + } + #endif /* configENABLE_TRUSTZONE */ + } + #endif /* portPRELOAD_REGISTERS */ + + return pxTopOfStack; +} +/*-----------------------------------------------------------*/ + +BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; + + #if ( configENABLE_MPU == 1 ) + { + /* Setup the Memory Protection Unit (MPU). */ + prvSetupMPU(); + } + #endif /* configENABLE_MPU */ + + /* Start the timer that generates the tick ISR. Interrupts are disabled + * here already. */ + vPortSetupTimerInterrupt(); + + /* Initialize the critical nesting count ready for the first task. */ + ulCriticalNesting = 0; + + /* Start the first task. */ + vStartFirstTask(); + + /* Should never get here as the tasks will now be executing. Call the task + * exit error function to prevent compiler warnings about a static function + * not being called in the case that the application writer overrides this + * functionality by defining configTASK_RETURN_ADDRESS. Call + * vTaskSwitchContext() so link time optimization does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); + + /* Should not get here. */ + return 0; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ +{ + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( ulCriticalNesting == 1000UL ); +} +/*-----------------------------------------------------------*/ + +#if ( configENABLE_MPU == 1 ) + void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) + { + uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; + int32_t lIndex = 0; + + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_sram_start__; + extern uint32_t * __privileged_sram_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ + + /* Setup MAIR0. */ + xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK ); + xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK ); + + /* This function is called automatically when the task is created - in + * which case the stack region parameters will be valid. At all other + * times the stack parameters will not be valid and it is assumed that + * the stack region has already been configured. */ + if( ulStackDepth > 0 ) + { + ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; + ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; + + /* If the stack is within the privileged SRAM, do not protect it + * using a separate MPU region. This is needed because privileged + * SRAM is already protected using an MPU region and ARMv8-M does + * not allow overlapping MPU regions. */ + if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) && + ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) ) + { + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; + } + else + { + /* Define the region that allows access to the stack. */ + ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); + + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + } + } + + /* User supplied configurable regions. */ + for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ ) + { + /* If xRegions is NULL i.e. the task has not specified any MPU + * region, the else part ensures that all the configurable MPU + * regions are invalidated. */ + if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) ) + { + /* Translate the generic region definition contained in xRegions + * into the ARMv8 specific MPU settings that are then stored in + * xMPUSettings. */ + ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + + /* Start address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ); + + /* RO/RW. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY ); + } + else + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE ); + } + + /* XN. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); + } + + /* End Address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_REGION_ENABLE ); + + /* Normal memory/ Device memory. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 ) + { + /* Attr1 in MAIR0 is configured as device memory. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1; + } + else + { + /* Attr1 in MAIR0 is configured as normal memory. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0; + } + } + else + { + /* Invalidate the region. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL; + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL; + } + + lIndex++; + } + } +#endif /* configENABLE_MPU */ +/*-----------------------------------------------------------*/ + +BaseType_t xPortIsInsideInterrupt( void ) +{ + uint32_t ulCurrentInterrupt; + BaseType_t xReturn; + + /* Obtain the number of the currently executing interrupt. Interrupt Program + * Status Register (IPSR) holds the exception number of the currently-executing + * exception or zero for Thread mode.*/ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c index e5b90410f..aabe5c2ff 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c @@ -611,7 +611,7 @@ static void prvTaskExitError( void ) extern uint32_t * __unprivileged_flash_end__; extern uint32_t * __privileged_sram_start__; extern uint32_t * __privileged_sram_end__; - #else /* if defined( __ARMCC_VERSION ) */ + #else /* if defined( __ARMCC_VERSION ) */ /* Declaration when these variable are exported from linker scripts. */ extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_end__[]; @@ -801,22 +801,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO ulR0 = pulCallerStackAddress[ 0 ]; #if ( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); - } - #else /* if ( configENABLE_MPU == 1 ) */ - { - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0 ); - } + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } #endif /* configENABLE_MPU */ configASSERT( xSecureContext != NULL ); @@ -834,21 +834,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO case portSVC_START_SCHEDULER: #if ( configENABLE_TRUSTZONE == 1 ) - { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); - } + /* Initialize the secure context management system. */ + SecureContext_Init(); + } #endif /* configENABLE_TRUSTZONE */ #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } #endif /* configENABLE_FPU */ /* Setup the context of the first task so that the first task starts @@ -876,6 +876,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, @@ -888,6 +889,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO TaskFunction_t pxCode, void * pvParameters ) /* PRIVILEGED_FUNCTION */ #endif /* configENABLE_MPU */ +/* *INDENT-ON* */ { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ @@ -1050,7 +1052,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; int32_t lIndex = 0; + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __privileged_sram_start__; @@ -1078,8 +1082,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ * using a separate MPU region. This is needed because privileged * SRAM is already protected using an MPU region and ARMv8-M does * not allow overlapping MPU regions. */ - if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && - ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) + if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) && + ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) ) { xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; @@ -1088,7 +1092,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ { /* Define the region that allows access to the stack. */ ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | ( portMPU_REGION_NON_SHAREABLE ) | diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index 362d5a5a4..61d005e91 100644 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -359,14 +359,14 @@ static void prvRestoreContextOfFirstTask( void ) " str r3, [r2] \n"/* Disable MPU. */ " \n" " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ - " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ " \n" #if ( portTOTAL_NUM_REGIONS == 16 ) - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ - " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ - " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ #endif /* portTOTAL_NUM_REGIONS == 16. */ " \n" " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ @@ -583,14 +583,14 @@ void xPortPendSVHandler( void ) " str r3, [r2] \n"/* Disable MPU. */ " \n" " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ - " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ " \n" #if ( portTOTAL_NUM_REGIONS == 16 ) - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ - " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ - " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ #endif /* portTOTAL_NUM_REGIONS == 16. */ " \n" " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ diff --git a/portable/GCC/ARM_CR5/port.c b/portable/GCC/ARM_CR5/port.c index 626fd0d14..8b162b19b 100644 --- a/portable/GCC/ARM_CR5/port.c +++ b/portable/GCC/ARM_CR5/port.c @@ -148,17 +148,18 @@ /* Adding the necessary stuff in order to be able to determine from C code wheter or not the IRQs are enabled at the processor level (not interrupt controller level) */ -#define GET_CPSR() ({u32 rval = 0U; \ - __asm__ __volatile__(\ - "mrs %0, cpsr\n"\ - : "=r" (rval)\ - );\ - rval;\ - }) +#define GET_CPSR() \ + ( { u32 rval = 0U; \ + __asm__ __volatile__ ( \ + "mrs %0, cpsr\n"\ + : "=r" ( rval ) \ + ); \ + rval; \ + } ) -#define CPSR_IRQ_ENABLE_MASK 0x80U +#define CPSR_IRQ_ENABLE_MASK 0x80U -#define IS_IRQ_DISABLED() ({unsigned int val = 0; val = (GET_CPSR() & CPSR_IRQ_ENABLE_MASK) ? 1 : 0; val;}) +#define IS_IRQ_DISABLED() ( { unsigned int val = 0; val = ( GET_CPSR() & CPSR_IRQ_ENABLE_MASK ) ? 1 : 0; val; } ) /*-----------------------------------------------------------*/ /* @@ -504,18 +505,20 @@ uint32_t ulPortSetInterruptMask( void ) "isb \n"::: "memory" ); } - /* Just like this function returns a value of wether or not the interrupts where masked in the interrupt controller in order to avoid race condition when + /* Just like this function returns a value of wether or not the interrupts where masked in the interrupt controller in order to avoid race condition when * calling its matching vPortClearInterruptMask function, we needed a 'wasIRQDisabled' variable holding the state of the IRQ Enable bit in the CPSR in order - * to leave that bit in it's original state. Like mentioned above, hardware automatically clear the IRQEnable bit upon trapping into IRQ Mode, so the programmer + * to leave that bit in it's original state. Like mentioned above, hardware automatically clear the IRQEnable bit upon trapping into IRQ Mode, so the programmer * cannot make assumption about it's state. Very rare, but very important race condition is avoided with this when this function is called in an ISR. The race * condition in question was discovered when integrating tracealyzer code. Inside the function 'void vTaskSwitchContext( void )' in tasks.c, there is a macro 'traceTASK_SWITCHED_IN();' - * which gets replaced by something when using the tracing capabilities. That macro protects some critical section with matching calls to 'ulPortSetInterruptMask' + * which gets replaced by something when using the tracing capabilities. That macro protects some critical section with matching calls to 'ulPortSetInterruptMask' * and 'vPortClearInterruptMask'. At the time of calling those functions, the interrupt mask is not set in the interrupt controller, thus the only protecting barrier - * against the CPU traping into recursive interrupt was the IRQ Enable bit in the CPSR. By not taking it into acount, the very code that protects the CPU against - * critical section violation just enabled it to happen : A SysTick was waiting to happen, and calling 'portCPU_IRQ_ENABLE' would enable it to occur... Thus triggering a + * against the CPU traping into recursive interrupt was the IRQ Enable bit in the CPSR. By not taking it into acount, the very code that protects the CPU against + * critical section violation just enabled it to happen : A SysTick was waiting to happen, and calling 'portCPU_IRQ_ENABLE' would enable it to occur... Thus triggering a * switch of context while already performing a switch context. */ - if(!wasIRQDisabled) - portCPU_IRQ_ENABLE(); + if( !wasIRQDisabled ) + { + portCPU_IRQ_ENABLE(); + } return ulReturn; } diff --git a/portable/GCC/AVR_AVRDx/port.c b/portable/GCC/AVR_AVRDx/port.c index f452db05f..a9727dd52 100644 --- a/portable/GCC/AVR_AVRDx/port.c +++ b/portable/GCC/AVR_AVRDx/port.c @@ -33,18 +33,18 @@ #include "task.h" /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the AVR port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the AVR port. +*----------------------------------------------------------*/ /* Start tasks with interrupts enables. */ -#define portFLAGS_INT_ENABLED ((StackType_t) 0x80) +#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 ) /*-----------------------------------------------------------*/ /* We require the address of the pxCurrentTCB variable, but don't want to know -any details of its type. */ + * any details of its type. */ typedef void RTOS_TCB_t; -extern volatile RTOS_TCB_t *volatile pxCurrentTCB; +extern volatile RTOS_TCB_t * volatile pxCurrentTCB; /*-----------------------------------------------------------*/ @@ -64,161 +64,163 @@ extern volatile RTOS_TCB_t *volatile pxCurrentTCB; * so we need not worry about reading/writing to the stack pointer. */ -#define portSAVE_CONTEXT() \ - asm volatile("push r0 \n\t" \ - "in r0, __SREG__ \n\t" \ - "cli \n\t" \ - "push r0 \n\t" \ - "in r0, __RAMPZ__ \n\t" \ - "push r0 \n\t" \ - "push r1 \n\t" \ - "clr r1 \n\t" \ - "push r2 \n\t" \ - "push r3 \n\t" \ - "push r4 \n\t" \ - "push r5 \n\t" \ - "push r6 \n\t" \ - "push r7 \n\t" \ - "push r8 \n\t" \ - "push r9 \n\t" \ - "push r10 \n\t" \ - "push r11 \n\t" \ - "push r12 \n\t" \ - "push r13 \n\t" \ - "push r14 \n\t" \ - "push r15 \n\t" \ - "push r16 \n\t" \ - "push r17 \n\t" \ - "push r18 \n\t" \ - "push r19 \n\t" \ - "push r20 \n\t" \ - "push r21 \n\t" \ - "push r22 \n\t" \ - "push r23 \n\t" \ - "push r24 \n\t" \ - "push r25 \n\t" \ - "push r26 \n\t" \ - "push r27 \n\t" \ - "push r28 \n\t" \ - "push r29 \n\t" \ - "push r30 \n\t" \ - "push r31 \n\t" \ - "lds r26, pxCurrentTCB \n\t" \ - "lds r27, pxCurrentTCB + 1 \n\t" \ - "in r0, __SP_L__ \n\t" \ - "st x+, r0 \n\t" \ - "in r0, __SP_H__ \n\t" \ - "st x+, r0 \n\t"); +#define portSAVE_CONTEXT() \ + asm volatile ( "push r0 \n\t" \ + "in r0, __SREG__ \n\t" \ + "cli \n\t" \ + "push r0 \n\t" \ + "in r0, __RAMPZ__ \n\t" \ + "push r0 \n\t" \ + "push r1 \n\t" \ + "clr r1 \n\t" \ + "push r2 \n\t" \ + "push r3 \n\t" \ + "push r4 \n\t" \ + "push r5 \n\t" \ + "push r6 \n\t" \ + "push r7 \n\t" \ + "push r8 \n\t" \ + "push r9 \n\t" \ + "push r10 \n\t" \ + "push r11 \n\t" \ + "push r12 \n\t" \ + "push r13 \n\t" \ + "push r14 \n\t" \ + "push r15 \n\t" \ + "push r16 \n\t" \ + "push r17 \n\t" \ + "push r18 \n\t" \ + "push r19 \n\t" \ + "push r20 \n\t" \ + "push r21 \n\t" \ + "push r22 \n\t" \ + "push r23 \n\t" \ + "push r24 \n\t" \ + "push r25 \n\t" \ + "push r26 \n\t" \ + "push r27 \n\t" \ + "push r28 \n\t" \ + "push r29 \n\t" \ + "push r30 \n\t" \ + "push r31 \n\t" \ + "lds r26, pxCurrentTCB \n\t" \ + "lds r27, pxCurrentTCB + 1 \n\t" \ + "in r0, __SP_L__ \n\t" \ + "st x+, r0 \n\t" \ + "in r0, __SP_H__ \n\t" \ + "st x+, r0 \n\t" ); /* * Opposite to portSAVE_CONTEXT(). Interrupts will have been disabled during * the context save so we can write to the stack pointer. */ -#define portRESTORE_CONTEXT() \ - asm volatile("lds r26, pxCurrentTCB \n\t" \ - "lds r27, pxCurrentTCB + 1 \n\t" \ - "ld r28, x+ \n\t" \ - "out __SP_L__, r28 \n\t" \ - "ld r29, x+ \n\t" \ - "out __SP_H__, r29 \n\t" \ - "pop r31 \n\t" \ - "pop r30 \n\t" \ - "pop r29 \n\t" \ - "pop r28 \n\t" \ - "pop r27 \n\t" \ - "pop r26 \n\t" \ - "pop r25 \n\t" \ - "pop r24 \n\t" \ - "pop r23 \n\t" \ - "pop r22 \n\t" \ - "pop r21 \n\t" \ - "pop r20 \n\t" \ - "pop r19 \n\t" \ - "pop r18 \n\t" \ - "pop r17 \n\t" \ - "pop r16 \n\t" \ - "pop r15 \n\t" \ - "pop r14 \n\t" \ - "pop r13 \n\t" \ - "pop r12 \n\t" \ - "pop r11 \n\t" \ - "pop r10 \n\t" \ - "pop r9 \n\t" \ - "pop r8 \n\t" \ - "pop r7 \n\t" \ - "pop r6 \n\t" \ - "pop r5 \n\t" \ - "pop r4 \n\t" \ - "pop r3 \n\t" \ - "pop r2 \n\t" \ - "pop r1 \n\t" \ - "pop r0 \n\t" \ - "out __RAMPZ__, r0 \n\t" \ - "pop r0 \n\t" \ - "out __SREG__, r0 \n\t" \ - "pop r0 \n\t"); +#define portRESTORE_CONTEXT() \ + asm volatile ( "lds r26, pxCurrentTCB \n\t" \ + "lds r27, pxCurrentTCB + 1 \n\t" \ + "ld r28, x+ \n\t" \ + "out __SP_L__, r28 \n\t" \ + "ld r29, x+ \n\t" \ + "out __SP_H__, r29 \n\t" \ + "pop r31 \n\t" \ + "pop r30 \n\t" \ + "pop r29 \n\t" \ + "pop r28 \n\t" \ + "pop r27 \n\t" \ + "pop r26 \n\t" \ + "pop r25 \n\t" \ + "pop r24 \n\t" \ + "pop r23 \n\t" \ + "pop r22 \n\t" \ + "pop r21 \n\t" \ + "pop r20 \n\t" \ + "pop r19 \n\t" \ + "pop r18 \n\t" \ + "pop r17 \n\t" \ + "pop r16 \n\t" \ + "pop r15 \n\t" \ + "pop r14 \n\t" \ + "pop r13 \n\t" \ + "pop r12 \n\t" \ + "pop r11 \n\t" \ + "pop r10 \n\t" \ + "pop r9 \n\t" \ + "pop r8 \n\t" \ + "pop r7 \n\t" \ + "pop r6 \n\t" \ + "pop r5 \n\t" \ + "pop r4 \n\t" \ + "pop r3 \n\t" \ + "pop r2 \n\t" \ + "pop r1 \n\t" \ + "pop r0 \n\t" \ + "out __RAMPZ__, r0 \n\t" \ + "pop r0 \n\t" \ + "out __SREG__, r0 \n\t" \ + "pop r0 \n\t" ); /*-----------------------------------------------------------*/ /* * Perform hardware setup to enable ticks from timer. */ -static void prvSetupTimerInterrupt(void); +static void prvSetupTimerInterrupt( void ); /*-----------------------------------------------------------*/ /* * See header file for description. */ -StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) { uint16_t usAddress; /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ /* Place a few bytes of known values on the bottom of the stack. - This is just useful for debugging. Uncomment if needed. */ - // *pxTopOfStack = 0x11; - // pxTopOfStack--; - // *pxTopOfStack = 0x22; - // pxTopOfStack--; - // *pxTopOfStack = 0x33; - // pxTopOfStack--; + * This is just useful for debugging. Uncomment if needed. */ + /* *pxTopOfStack = 0x11; */ + /* pxTopOfStack--; */ + /* *pxTopOfStack = 0x22; */ + /* pxTopOfStack--; */ + /* *pxTopOfStack = 0x33; */ + /* pxTopOfStack--; */ /* The start of the task code will be popped off the stack last, so place - it on first. */ - usAddress = (uint16_t)pxCode; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + * it on first. */ + usAddress = ( uint16_t ) pxCode; + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfStack--; usAddress >>= 8; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfStack--; /* Next simulate the stack as if after a call to portSAVE_CONTEXT(). - portSAVE_CONTEXT places the flags on the stack immediately after r0 - to ensure the interrupts get disabled as soon as possible, and so ensuring - the stack use is minimal should a context switch interrupt occur. */ - *pxTopOfStack = (StackType_t)0x00; /* R0 */ + * portSAVE_CONTEXT places the flags on the stack immediately after r0 + * to ensure the interrupts get disabled as soon as possible, and so ensuring + * the stack use is minimal should a context switch interrupt occur. */ + *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */ pxTopOfStack--; *pxTopOfStack = portFLAGS_INT_ENABLED; pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */ + *pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */ pxTopOfStack--; /* Now the remaining registers. The compiler expects R1 to be 0. */ - *pxTopOfStack = (StackType_t)0x00; /* R1 */ + *pxTopOfStack = ( StackType_t ) 0x00; /* R1 */ /* Leave R2 - R23 untouched */ pxTopOfStack -= 23; /* Place the parameter on the stack in the expected location. */ - usAddress = (uint16_t)pvParameters; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + usAddress = ( uint16_t ) pvParameters; + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfStack--; usAddress >>= 8; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); /* Leave register R26 - R31 untouched */ pxTopOfStack -= 7; @@ -229,7 +231,7 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC } /*-----------------------------------------------------------*/ -BaseType_t xPortStartScheduler(void) +BaseType_t xPortStartScheduler( void ) { /* Setup the hardware to generate the tick. */ prvSetupTimerInterrupt(); @@ -238,15 +240,15 @@ BaseType_t xPortStartScheduler(void) portRESTORE_CONTEXT(); /* Simulate a function call end as generated by the compiler. We will now - jump to the start of the task the context of which we have just restored. */ - asm volatile("ret"); + * jump to the start of the task the context of which we have just restored. */ + asm volatile ( "ret" ); /* Should not get here. */ return pdTRUE; } /*-----------------------------------------------------------*/ -void vPortEndScheduler(void) +void vPortEndScheduler( void ) { /* vPortEndScheduler is not implemented in this port. */ } @@ -256,13 +258,13 @@ void vPortEndScheduler(void) * Manual context switch. The first thing we do is save the registers so we * can use a naked attribute. */ -void vPortYield(void) __attribute__((naked)); -void vPortYield(void) +void vPortYield( void ) __attribute__( ( naked ) ); +void vPortYield( void ) { portSAVE_CONTEXT(); vTaskSwitchContext(); portRESTORE_CONTEXT(); - asm volatile("ret"); + asm volatile ( "ret" ); } /*-----------------------------------------------------------*/ @@ -270,13 +272,13 @@ void vPortYield(void) * Manual context switch callable from ISRs. The first thing * we do is save the registers so we can use a naked attribute. */ -void vPortYieldFromISR(void) __attribute__((naked)); -void vPortYieldFromISR(void) +void vPortYieldFromISR( void ) __attribute__( ( naked ) ); +void vPortYieldFromISR( void ) { portSAVE_CONTEXT(); vTaskSwitchContext(); portRESTORE_CONTEXT(); - asm volatile("reti"); + asm volatile ( "reti" ); } /*-----------------------------------------------------------*/ @@ -286,24 +288,26 @@ void vPortYieldFromISR(void) * difference from vPortYield() is the tick count is incremented as the * call comes from the tick ISR. */ -void vPortYieldFromTick(void) __attribute__((naked)); -void vPortYieldFromTick(void) +void vPortYieldFromTick( void ) __attribute__( ( naked ) ); +void vPortYieldFromTick( void ) { portSAVE_CONTEXT(); - if (xTaskIncrementTick() != pdFALSE) { + + if( xTaskIncrementTick() != pdFALSE ) + { vTaskSwitchContext(); } portRESTORE_CONTEXT(); - asm volatile("reti"); + asm volatile ( "reti" ); } /*-----------------------------------------------------------*/ /* * Setup timer to generate a tick interrupt. */ -static void prvSetupTimerInterrupt(void) +static void prvSetupTimerInterrupt( void ) { TICK_init(); } @@ -316,26 +320,26 @@ static void prvSetupTimerInterrupt(void) * the context is saved at the start of vPortYieldFromTick(). The tick * count is incremented after the context is saved. */ -ISR(TICK_INT_vect, ISR_NAKED) -{ - /* Clear tick interrupt flag. */ - CLR_INT(INT_FLAGS, INT_MASK); + ISR( TICK_INT_vect, ISR_NAKED ) + { + /* Clear tick interrupt flag. */ + CLR_INT( INT_FLAGS, INT_MASK ); - vPortYieldFromTick(); + vPortYieldFromTick(); - asm volatile("reti"); -} -#else + asm volatile ( "reti" ); + } +#else /* if configUSE_PREEMPTION == 1 */ /* * Tick ISR for the cooperative scheduler. All this does is increment the * tick count. We don't need to switch context, this can only be done by * manual calls to taskYIELD(); */ -ISR(TICK_INT_vect) -{ - /* Clear tick interrupt flag. */ - INT_FLAGS = INT_MASK; - xTaskIncrementTick(); -} -#endif + ISR( TICK_INT_vect ) + { + /* Clear tick interrupt flag. */ + INT_FLAGS = INT_MASK; + xTaskIncrementTick(); + } +#endif /* if configUSE_PREEMPTION == 1 */ diff --git a/portable/GCC/AVR_AVRDx/porthardware.h b/portable/GCC/AVR_AVRDx/porthardware.h index cf2377844..7e670d933 100644 --- a/portable/GCC/AVR_AVRDx/porthardware.h +++ b/portable/GCC/AVR_AVRDx/porthardware.h @@ -5,98 +5,104 @@ /*-----------------------------------------------------------*/ -#define CLR_INT(FLAG_REG, FLAG_MASK) \ - asm volatile( \ - "push r16\n\t" \ - "ldi r16, %1\n\t" \ - "sts %0, r16\n\t" \ - "pop r16\n\t" \ - : \ - : "i"(_SFR_MEM_ADDR(FLAG_REG)),"i"((uint8_t)(FLAG_MASK)) \ +#define CLR_INT( FLAG_REG, FLAG_MASK ) \ + asm volatile ( \ + "push r16\n\t" \ + "ldi r16, %1\n\t" \ + "sts %0, r16\n\t" \ + "pop r16\n\t" \ + : \ + : "i" ( _SFR_MEM_ADDR( FLAG_REG ) ), "i" ( ( uint8_t ) ( FLAG_MASK ) ) \ ); #if ( configUSE_TIMER_INSTANCE == 0 ) - #define TICK_INT_vect TCB0_INT_vect - #define INT_FLAGS TCB0_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB0_INT_vect + #define INT_FLAGS TCB0_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB0.INTCTRL = TCB_CAPT_bm; \ - TCB0.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB0.INTCTRL = TCB_CAPT_bm; \ + TCB0.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 1 ) - #define TICK_INT_vect TCB1_INT_vect - #define INT_FLAGS TCB1_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB1_INT_vect + #define INT_FLAGS TCB1_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB1.INTCTRL = TCB_CAPT_bm; \ + TCB1.CTRLA = TCB_ENABLE_bm; \ + } - #define TICK_init() { \ - TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB1.INTCTRL = TCB_CAPT_bm; \ - TCB1.CTRLA = TCB_ENABLE_bm; \ - } - #elif ( configUSE_TIMER_INSTANCE == 2 ) - #define TICK_INT_vect TCB2_INT_vect - #define INT_FLAGS TCB2_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB2_INT_vect + #define INT_FLAGS TCB2_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB2.INTCTRL = TCB_CAPT_bm; \ + TCB2.CTRLA = TCB_ENABLE_bm; \ + } - #define TICK_init() { \ - TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB2.INTCTRL = TCB_CAPT_bm; \ - TCB2.CTRLA = TCB_ENABLE_bm; \ - } - #elif ( configUSE_TIMER_INSTANCE == 3 ) - #define TICK_INT_vect TCB3_INT_vect - #define INT_FLAGS TCB3_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB3_INT_vect + #define INT_FLAGS TCB3_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB3.INTCTRL = TCB_CAPT_bm; \ + TCB3.CTRLA = TCB_ENABLE_bm; \ + } - #define TICK_init() { \ - TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB3.INTCTRL = TCB_CAPT_bm; \ - TCB3.CTRLA = TCB_ENABLE_bm; \ - } - #elif ( configUSE_TIMER_INSTANCE == 4 ) - #define TICK_INT_vect TCB4_INT_vect - #define INT_FLAGS TCB4_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB4_INT_vect + #define INT_FLAGS TCB4_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB4.INTCTRL = TCB_CAPT_bm; \ - TCB4.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB4.INTCTRL = TCB_CAPT_bm; \ + TCB4.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 5 ) - #define TICK_INT_vect RTC_CNT_vect - #define INT_FLAGS RTC_INTFLAGS - #define INT_MASK RTC_OVF_bm + #define TICK_INT_vect RTC_CNT_vect + #define INT_FLAGS RTC_INTFLAGS + #define INT_MASK RTC_OVF_bm - /* Hertz to period for RTC setup */ - #define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) ) - #define TICK_init() { \ - while (RTC.STATUS > 0); \ - RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ - RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \ - RTC.INTCTRL |= 1 << RTC_OVF_bp; \ - } +/* Hertz to period for RTC setup */ + #define RTC_PERIOD_HZ( x ) ( 32768 * ( ( 1.0 / x ) ) ) + #define TICK_init() \ + { \ + while( RTC.STATUS > 0 ) {; } \ + RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ + RTC.PER = RTC_PERIOD_HZ( configTICK_RATE_HZ ); \ + RTC.INTCTRL |= 1 << RTC_OVF_bp; \ + } -#else +#else /* if ( configUSE_TIMER_INSTANCE == 0 ) */ #undef TICK_INT_vect #undef INT_FLAGS #undef INT_MASK #undef TICK_init() #error Invalid timer setting. -#endif +#endif /* if ( configUSE_TIMER_INSTANCE == 0 ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/AVR_Mega0/port.c b/portable/GCC/AVR_Mega0/port.c index 6b8ec3562..98bf30252 100644 --- a/portable/GCC/AVR_Mega0/port.c +++ b/portable/GCC/AVR_Mega0/port.c @@ -33,18 +33,18 @@ #include "task.h" /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the AVR port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the AVR port. +*----------------------------------------------------------*/ /* Start tasks with interrupts enables. */ -#define portFLAGS_INT_ENABLED ((StackType_t) 0x80) +#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 ) /*-----------------------------------------------------------*/ /* We require the address of the pxCurrentTCB variable, but don't want to know -any details of its type. */ + * any details of its type. */ typedef void RTOS_TCB_t; -extern volatile RTOS_TCB_t *volatile pxCurrentTCB; +extern volatile RTOS_TCB_t * volatile pxCurrentTCB; /*-----------------------------------------------------------*/ @@ -64,155 +64,157 @@ extern volatile RTOS_TCB_t *volatile pxCurrentTCB; * so we need not worry about reading/writing to the stack pointer. */ -#define portSAVE_CONTEXT() \ - asm volatile("push r0 \n\t" \ - "in r0, __SREG__ \n\t" \ - "cli \n\t" \ - "push r0 \n\t" \ - "push r1 \n\t" \ - "clr r1 \n\t" \ - "push r2 \n\t" \ - "push r3 \n\t" \ - "push r4 \n\t" \ - "push r5 \n\t" \ - "push r6 \n\t" \ - "push r7 \n\t" \ - "push r8 \n\t" \ - "push r9 \n\t" \ - "push r10 \n\t" \ - "push r11 \n\t" \ - "push r12 \n\t" \ - "push r13 \n\t" \ - "push r14 \n\t" \ - "push r15 \n\t" \ - "push r16 \n\t" \ - "push r17 \n\t" \ - "push r18 \n\t" \ - "push r19 \n\t" \ - "push r20 \n\t" \ - "push r21 \n\t" \ - "push r22 \n\t" \ - "push r23 \n\t" \ - "push r24 \n\t" \ - "push r25 \n\t" \ - "push r26 \n\t" \ - "push r27 \n\t" \ - "push r28 \n\t" \ - "push r29 \n\t" \ - "push r30 \n\t" \ - "push r31 \n\t" \ - "lds r26, pxCurrentTCB \n\t" \ - "lds r27, pxCurrentTCB + 1 \n\t" \ - "in r0, __SP_L__ \n\t" \ - "st x+, r0 \n\t" \ - "in r0, __SP_H__ \n\t" \ - "st x+, r0 \n\t"); +#define portSAVE_CONTEXT() \ + asm volatile ( "push r0 \n\t" \ + "in r0, __SREG__ \n\t" \ + "cli \n\t" \ + "push r0 \n\t" \ + "push r1 \n\t" \ + "clr r1 \n\t" \ + "push r2 \n\t" \ + "push r3 \n\t" \ + "push r4 \n\t" \ + "push r5 \n\t" \ + "push r6 \n\t" \ + "push r7 \n\t" \ + "push r8 \n\t" \ + "push r9 \n\t" \ + "push r10 \n\t" \ + "push r11 \n\t" \ + "push r12 \n\t" \ + "push r13 \n\t" \ + "push r14 \n\t" \ + "push r15 \n\t" \ + "push r16 \n\t" \ + "push r17 \n\t" \ + "push r18 \n\t" \ + "push r19 \n\t" \ + "push r20 \n\t" \ + "push r21 \n\t" \ + "push r22 \n\t" \ + "push r23 \n\t" \ + "push r24 \n\t" \ + "push r25 \n\t" \ + "push r26 \n\t" \ + "push r27 \n\t" \ + "push r28 \n\t" \ + "push r29 \n\t" \ + "push r30 \n\t" \ + "push r31 \n\t" \ + "lds r26, pxCurrentTCB \n\t" \ + "lds r27, pxCurrentTCB + 1 \n\t" \ + "in r0, __SP_L__ \n\t" \ + "st x+, r0 \n\t" \ + "in r0, __SP_H__ \n\t" \ + "st x+, r0 \n\t" ); /* * Opposite to portSAVE_CONTEXT(). Interrupts will have been disabled during * the context save so we can write to the stack pointer. */ -#define portRESTORE_CONTEXT() \ - asm volatile("lds r26, pxCurrentTCB \n\t" \ - "lds r27, pxCurrentTCB + 1 \n\t" \ - "ld r28, x+ \n\t" \ - "out __SP_L__, r28 \n\t" \ - "ld r29, x+ \n\t" \ - "out __SP_H__, r29 \n\t" \ - "pop r31 \n\t" \ - "pop r30 \n\t" \ - "pop r29 \n\t" \ - "pop r28 \n\t" \ - "pop r27 \n\t" \ - "pop r26 \n\t" \ - "pop r25 \n\t" \ - "pop r24 \n\t" \ - "pop r23 \n\t" \ - "pop r22 \n\t" \ - "pop r21 \n\t" \ - "pop r20 \n\t" \ - "pop r19 \n\t" \ - "pop r18 \n\t" \ - "pop r17 \n\t" \ - "pop r16 \n\t" \ - "pop r15 \n\t" \ - "pop r14 \n\t" \ - "pop r13 \n\t" \ - "pop r12 \n\t" \ - "pop r11 \n\t" \ - "pop r10 \n\t" \ - "pop r9 \n\t" \ - "pop r8 \n\t" \ - "pop r7 \n\t" \ - "pop r6 \n\t" \ - "pop r5 \n\t" \ - "pop r4 \n\t" \ - "pop r3 \n\t" \ - "pop r2 \n\t" \ - "pop r1 \n\t" \ - "pop r0 \n\t" \ - "out __SREG__, r0 \n\t" \ - "pop r0 \n\t"); +#define portRESTORE_CONTEXT() \ + asm volatile ( "lds r26, pxCurrentTCB \n\t" \ + "lds r27, pxCurrentTCB + 1 \n\t" \ + "ld r28, x+ \n\t" \ + "out __SP_L__, r28 \n\t" \ + "ld r29, x+ \n\t" \ + "out __SP_H__, r29 \n\t" \ + "pop r31 \n\t" \ + "pop r30 \n\t" \ + "pop r29 \n\t" \ + "pop r28 \n\t" \ + "pop r27 \n\t" \ + "pop r26 \n\t" \ + "pop r25 \n\t" \ + "pop r24 \n\t" \ + "pop r23 \n\t" \ + "pop r22 \n\t" \ + "pop r21 \n\t" \ + "pop r20 \n\t" \ + "pop r19 \n\t" \ + "pop r18 \n\t" \ + "pop r17 \n\t" \ + "pop r16 \n\t" \ + "pop r15 \n\t" \ + "pop r14 \n\t" \ + "pop r13 \n\t" \ + "pop r12 \n\t" \ + "pop r11 \n\t" \ + "pop r10 \n\t" \ + "pop r9 \n\t" \ + "pop r8 \n\t" \ + "pop r7 \n\t" \ + "pop r6 \n\t" \ + "pop r5 \n\t" \ + "pop r4 \n\t" \ + "pop r3 \n\t" \ + "pop r2 \n\t" \ + "pop r1 \n\t" \ + "pop r0 \n\t" \ + "out __SREG__, r0 \n\t" \ + "pop r0 \n\t" ); /*-----------------------------------------------------------*/ /* * Perform hardware setup to enable ticks from timer. */ -static void prvSetupTimerInterrupt(void); +static void prvSetupTimerInterrupt( void ); /*-----------------------------------------------------------*/ /* * See header file for description. */ -StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) +StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, + TaskFunction_t pxCode, + void * pvParameters ) { uint16_t usAddress; /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ /* Place a few bytes of known values on the bottom of the stack. - This is just useful for debugging. Uncomment if needed. */ - // *pxTopOfStack = 0x11; - // pxTopOfStack--; - // *pxTopOfStack = 0x22; - // pxTopOfStack--; - // *pxTopOfStack = 0x33; - // pxTopOfStack--; + * This is just useful for debugging. Uncomment if needed. */ + /* *pxTopOfStack = 0x11; */ + /* pxTopOfStack--; */ + /* *pxTopOfStack = 0x22; */ + /* pxTopOfStack--; */ + /* *pxTopOfStack = 0x33; */ + /* pxTopOfStack--; */ /* The start of the task code will be popped off the stack last, so place - it on first. */ - usAddress = (uint16_t)pxCode; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + * it on first. */ + usAddress = ( uint16_t ) pxCode; + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfStack--; usAddress >>= 8; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfStack--; /* Next simulate the stack as if after a call to portSAVE_CONTEXT(). - portSAVE_CONTEXT places the flags on the stack immediately after r0 - to ensure the interrupts get disabled as soon as possible, and so ensuring - the stack use is minimal should a context switch interrupt occur. */ - *pxTopOfStack = (StackType_t)0x00; /* R0 */ + * portSAVE_CONTEXT places the flags on the stack immediately after r0 + * to ensure the interrupts get disabled as soon as possible, and so ensuring + * the stack use is minimal should a context switch interrupt occur. */ + *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */ pxTopOfStack--; *pxTopOfStack = portFLAGS_INT_ENABLED; pxTopOfStack--; /* Now the remaining registers. The compiler expects R1 to be 0. */ - *pxTopOfStack = (StackType_t)0x00; /* R1 */ + *pxTopOfStack = ( StackType_t ) 0x00; /* R1 */ /* Leave R2 - R23 untouched */ pxTopOfStack -= 23; /* Place the parameter on the stack in the expected location. */ - usAddress = (uint16_t)pvParameters; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + usAddress = ( uint16_t ) pvParameters; + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfStack--; usAddress >>= 8; - *pxTopOfStack = (StackType_t)(usAddress & (uint16_t)0x00ff); + *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); /* Leave register R26 - R31 untouched */ pxTopOfStack -= 7; @@ -223,7 +225,7 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC } /*-----------------------------------------------------------*/ -BaseType_t xPortStartScheduler(void) +BaseType_t xPortStartScheduler( void ) { /* Setup the hardware to generate the tick. */ prvSetupTimerInterrupt(); @@ -232,15 +234,15 @@ BaseType_t xPortStartScheduler(void) portRESTORE_CONTEXT(); /* Simulate a function call end as generated by the compiler. We will now - jump to the start of the task the context of which we have just restored. */ - asm volatile("ret"); + * jump to the start of the task the context of which we have just restored. */ + asm volatile ( "ret" ); /* Should not get here. */ return pdTRUE; } /*-----------------------------------------------------------*/ -void vPortEndScheduler(void) +void vPortEndScheduler( void ) { /* vPortEndScheduler is not implemented in this port. */ } @@ -250,13 +252,13 @@ void vPortEndScheduler(void) * Manual context switch. The first thing we do is save the registers so we * can use a naked attribute. */ -void vPortYield(void) __attribute__((naked)); -void vPortYield(void) +void vPortYield( void ) __attribute__( ( naked ) ); +void vPortYield( void ) { portSAVE_CONTEXT(); vTaskSwitchContext(); portRESTORE_CONTEXT(); - asm volatile("ret"); + asm volatile ( "ret" ); } /*-----------------------------------------------------------*/ @@ -264,13 +266,13 @@ void vPortYield(void) * Manual context switch callable from ISRs. The first thing * we do is save the registers so we can use a naked attribute. */ -void vPortYieldFromISR(void) __attribute__((naked)); -void vPortYieldFromISR(void) +void vPortYieldFromISR( void ) __attribute__( ( naked ) ); +void vPortYieldFromISR( void ) { portSAVE_CONTEXT(); vTaskSwitchContext(); portRESTORE_CONTEXT(); - asm volatile("reti"); + asm volatile ( "reti" ); } /*-----------------------------------------------------------*/ @@ -280,24 +282,26 @@ void vPortYieldFromISR(void) * difference from vPortYield() is the tick count is incremented as the * call comes from the tick ISR. */ -void vPortYieldFromTick(void) __attribute__((naked)); -void vPortYieldFromTick(void) +void vPortYieldFromTick( void ) __attribute__( ( naked ) ); +void vPortYieldFromTick( void ) { portSAVE_CONTEXT(); - if (xTaskIncrementTick() != pdFALSE) { + + if( xTaskIncrementTick() != pdFALSE ) + { vTaskSwitchContext(); } portRESTORE_CONTEXT(); - asm volatile("reti"); + asm volatile ( "reti" ); } /*-----------------------------------------------------------*/ /* * Setup timer to generate a tick interrupt. */ -static void prvSetupTimerInterrupt(void) +static void prvSetupTimerInterrupt( void ) { TICK_init(); } @@ -310,26 +314,26 @@ static void prvSetupTimerInterrupt(void) * the context is saved at the start of vPortYieldFromTick(). The tick * count is incremented after the context is saved. */ -ISR(TICK_INT_vect, ISR_NAKED) -{ - /* Clear tick interrupt flag. */ - CLR_INT(INT_FLAGS, INT_MASK); + ISR( TICK_INT_vect, ISR_NAKED ) + { + /* Clear tick interrupt flag. */ + CLR_INT( INT_FLAGS, INT_MASK ); - vPortYieldFromTick(); + vPortYieldFromTick(); - asm volatile("reti"); -} -#else + asm volatile ( "reti" ); + } +#else /* if configUSE_PREEMPTION == 1 */ /* * Tick ISR for the cooperative scheduler. All this does is increment the * tick count. We don't need to switch context, this can only be done by * manual calls to taskYIELD(); */ -ISR(TICK_INT_vect) -{ - /* Clear tick interrupt flag. */ - INT_FLAGS = INT_MASK; - xTaskIncrementTick(); -} -#endif + ISR( TICK_INT_vect ) + { + /* Clear tick interrupt flag. */ + INT_FLAGS = INT_MASK; + xTaskIncrementTick(); + } +#endif /* if configUSE_PREEMPTION == 1 */ diff --git a/portable/GCC/AVR_Mega0/porthardware.h b/portable/GCC/AVR_Mega0/porthardware.h index aeeccf534..8d4f1bcc3 100644 --- a/portable/GCC/AVR_Mega0/porthardware.h +++ b/portable/GCC/AVR_Mega0/porthardware.h @@ -5,86 +5,91 @@ /*-----------------------------------------------------------*/ -#define CLR_INT(FLAG_REG, FLAG_MASK) \ - asm volatile( \ - "push r16\n\t" \ - "ldi r16, %1\n\t" \ - "sts %0, r16\n\t" \ - "pop r16\n\t" \ - : \ - : "i"(_SFR_MEM_ADDR(FLAG_REG)),"i"((uint8_t)(FLAG_MASK)) \ +#define CLR_INT( FLAG_REG, FLAG_MASK ) \ + asm volatile ( \ + "push r16\n\t" \ + "ldi r16, %1\n\t" \ + "sts %0, r16\n\t" \ + "pop r16\n\t" \ + : \ + : "i" ( _SFR_MEM_ADDR( FLAG_REG ) ), "i" ( ( uint8_t ) ( FLAG_MASK ) ) \ ); #if ( configUSE_TIMER_INSTANCE == 0 ) - #define TICK_INT_vect TCB0_INT_vect - #define INT_FLAGS TCB0_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB0_INT_vect + #define INT_FLAGS TCB0_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB0.INTCTRL = TCB_CAPT_bm; \ - TCB0.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB0.INTCTRL = TCB_CAPT_bm; \ + TCB0.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 1 ) - #define TICK_INT_vect TCB1_INT_vect - #define INT_FLAGS TCB1_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB1_INT_vect + #define INT_FLAGS TCB1_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB1.INTCTRL = TCB_CAPT_bm; \ - TCB1.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB1.INTCTRL = TCB_CAPT_bm; \ + TCB1.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 2 ) - #define TICK_INT_vect TCB2_INT_vect - #define INT_FLAGS TCB2_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB2_INT_vect + #define INT_FLAGS TCB2_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB2.INTCTRL = TCB_CAPT_bm; \ - TCB2.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB2.INTCTRL = TCB_CAPT_bm; \ + TCB2.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 3 ) - #define TICK_INT_vect TCB3_INT_vect - #define INT_FLAGS TCB3_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB3_INT_vect + #define INT_FLAGS TCB3_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB3.INTCTRL = TCB_CAPT_bm; \ - TCB3.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB3.INTCTRL = TCB_CAPT_bm; \ + TCB3.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 4 ) - #define TICK_INT_vect RTC_CNT_vect - #define INT_FLAGS RTC_INTFLAGS - #define INT_MASK RTC_OVF_bm + #define TICK_INT_vect RTC_CNT_vect + #define INT_FLAGS RTC_INTFLAGS + #define INT_MASK RTC_OVF_bm - /* Hertz to period for RTC setup */ - #define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) ) - #define TICK_init() { \ - while (RTC.STATUS > 0); \ - RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ - RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \ - RTC.INTCTRL |= 1 << RTC_OVF_bp; \ - } +/* Hertz to period for RTC setup */ + #define RTC_PERIOD_HZ( x ) ( 32768 * ( ( 1.0 / x ) ) ) + #define TICK_init() \ + { \ + while( RTC.STATUS > 0 ) {; } \ + RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ + RTC.PER = RTC_PERIOD_HZ( configTICK_RATE_HZ ); \ + RTC.INTCTRL |= 1 << RTC_OVF_bp; \ + } -#else +#else /* if ( configUSE_TIMER_INSTANCE == 0 ) */ #undef TICK_INT_vect #undef INT_FLAGS #undef INT_MASK #undef TICK_init() #error Invalid timer setting. -#endif +#endif /* if ( configUSE_TIMER_INSTANCE == 0 ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23/non_secure/port.c b/portable/IAR/ARM_CM23/non_secure/port.c index 8cd327dde..8c91b55a6 100644 --- a/portable/IAR/ARM_CM23/non_secure/port.c +++ b/portable/IAR/ARM_CM23/non_secure/port.c @@ -611,7 +611,7 @@ static void prvTaskExitError( void ) extern uint32_t * __unprivileged_flash_end__; extern uint32_t * __privileged_sram_start__; extern uint32_t * __privileged_sram_end__; - #else /* if defined( __ARMCC_VERSION ) */ + #else /* if defined( __ARMCC_VERSION ) */ /* Declaration when these variable are exported from linker scripts. */ extern uint32_t __privileged_functions_start__[]; extern uint32_t __privileged_functions_end__[]; @@ -801,22 +801,22 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO ulR0 = pulCallerStackAddress[ 0 ]; #if ( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); - } - #else /* if ( configENABLE_MPU == 1 ) */ - { - /* Allocate and load a context for the secure task. */ - xSecureContext = SecureContext_AllocateContext( ulR0 ); - } + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } #endif /* configENABLE_MPU */ configASSERT( xSecureContext != NULL ); @@ -834,21 +834,21 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO case portSVC_START_SCHEDULER: #if ( configENABLE_TRUSTZONE == 1 ) - { - /* De-prioritize the non-secure exceptions so that the - * non-secure pendSV runs at the lowest priority. */ - SecureInit_DePrioritizeNSExceptions(); + { + /* De-prioritize the non-secure exceptions so that the + * non-secure pendSV runs at the lowest priority. */ + SecureInit_DePrioritizeNSExceptions(); - /* Initialize the secure context management system. */ - SecureContext_Init(); - } + /* Initialize the secure context management system. */ + SecureContext_Init(); + } #endif /* configENABLE_TRUSTZONE */ #if ( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } #endif /* configENABLE_FPU */ /* Setup the context of the first task so that the first task starts @@ -876,18 +876,20 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, TaskFunction_t pxCode, void * pvParameters, - BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ + BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */ #else StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, TaskFunction_t pxCode, - void * pvParameters ) /* PRIVILEGED_FUNCTION */ + void * pvParameters ) /* PRIVILEGED_FUNCTION */ #endif /* configENABLE_MPU */ +/* *INDENT-ON* */ { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ @@ -1050,7 +1052,9 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber; int32_t lIndex = 0; + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being * exported from linker scripts. */ extern uint32_t * __privileged_sram_start__; @@ -1078,8 +1082,8 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ * using a separate MPU region. This is needed because privileged * SRAM is already protected using an MPU region and ARMv8-M does * not allow overlapping MPU regions. */ - if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && - ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) + if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) && + ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) ) { xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; @@ -1088,7 +1092,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */ { /* Define the region that allows access to the stack. */ ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; - ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | ( portMPU_REGION_NON_SHAREABLE ) | diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c index 01c4600dc..8c91b55a6 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c @@ -876,6 +876,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, @@ -888,6 +889,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO TaskFunction_t pxCode, void * pvParameters ) /* PRIVILEGED_FUNCTION */ #endif /* configENABLE_MPU */ +/* *INDENT-ON* */ { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ diff --git a/portable/IAR/ARM_CM33/non_secure/port.c b/portable/IAR/ARM_CM33/non_secure/port.c index 01c4600dc..8c91b55a6 100644 --- a/portable/IAR/ARM_CM33/non_secure/port.c +++ b/portable/IAR/ARM_CM33/non_secure/port.c @@ -876,6 +876,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, @@ -888,6 +889,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO TaskFunction_t pxCode, void * pvParameters ) /* PRIVILEGED_FUNCTION */ #endif /* configENABLE_MPU */ +/* *INDENT-ON* */ { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c index 01c4600dc..8c91b55a6 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c @@ -876,6 +876,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t * pxEndOfStack, @@ -888,6 +889,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO TaskFunction_t pxCode, void * pvParameters ) /* PRIVILEGED_FUNCTION */ #endif /* configENABLE_MPU */ +/* *INDENT-ON* */ { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ diff --git a/portable/IAR/AVR_AVRDx/port.c b/portable/IAR/AVR_AVRDx/port.c index 36475d7af..9f7554c56 100644 --- a/portable/IAR/AVR_AVRDx/port.c +++ b/portable/IAR/AVR_AVRDx/port.c @@ -114,9 +114,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, pxTopOfStack -= ( configCALL_STACK_SIZE - 2 ); /* Next simulate the stack as if after a call to portSAVE_CONTEXT(). - * portSAVE_CONTEXT places the flags on the stack immediately after r0 - * to ensure the interrupts get disabled as soon as possible, and so ensuring - * the stack use is minimal should a context switch interrupt occur. */ + * portSAVE_CONTEXT places the flags on the stack immediately after r0 + * to ensure the interrupts get disabled as soon as possible, and so ensuring + * the stack use is minimal should a context switch interrupt occur. */ + *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */ pxTopOfStack--; *pxTopOfStack = portFLAGS_INT_ENABLED; diff --git a/portable/IAR/AVR_AVRDx/porthardware.h b/portable/IAR/AVR_AVRDx/porthardware.h index 195d881aa..2d17b4202 100644 --- a/portable/IAR/AVR_AVRDx/porthardware.h +++ b/portable/IAR/AVR_AVRDx/porthardware.h @@ -8,86 +8,92 @@ #if ( configUSE_TIMER_INSTANCE == 0 ) - #define TICK_INT_vect TCB0_INT_vect - #define INT_FLAGS TCB0_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB0.INTCTRL = TCB_CAPT_bm; \ - TCB0.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_INT_vect TCB0_INT_vect + #define INT_FLAGS TCB0_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB0.INTCTRL = TCB_CAPT_bm; \ + TCB0.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 1 ) - #define TICK_INT_vect TCB1_INT_vect - #define INT_FLAGS TCB1_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB1.INTCTRL = TCB_CAPT_bm; \ - TCB1.CTRLA = TCB_ENABLE_bm; \ - } - + #define TICK_INT_vect TCB1_INT_vect + #define INT_FLAGS TCB1_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB1.INTCTRL = TCB_CAPT_bm; \ + TCB1.CTRLA = TCB_ENABLE_bm; \ + } + #elif ( configUSE_TIMER_INSTANCE == 2 ) - #define TICK_INT_vect TCB2_INT_vect - #define INT_FLAGS TCB2_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB2_INT_vect + #define INT_FLAGS TCB2_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB2.INTCTRL = TCB_CAPT_bm; \ + TCB2.CTRLA = TCB_ENABLE_bm; \ + } - #define TICK_init() { \ - TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB2.INTCTRL = TCB_CAPT_bm; \ - TCB2.CTRLA = TCB_ENABLE_bm; \ - } - #elif ( configUSE_TIMER_INSTANCE == 3 ) - #define TICK_INT_vect TCB3_INT_vect - #define INT_FLAGS TCB3_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB3.INTCTRL = TCB_CAPT_bm; \ - TCB3.CTRLA = TCB_ENABLE_bm; \ - } - + #define TICK_INT_vect TCB3_INT_vect + #define INT_FLAGS TCB3_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB3.INTCTRL = TCB_CAPT_bm; \ + TCB3.CTRLA = TCB_ENABLE_bm; \ + } + #elif ( configUSE_TIMER_INSTANCE == 4 ) - #define TICK_INT_vect TCB4_INT_vect - #define INT_FLAGS TCB4_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB4.INTCTRL = TCB_CAPT_bm; \ - TCB4.CTRLA = TCB_ENABLE_bm; \ - } - -#elif ( configUSE_TIMER_INSTANCE == 5 ) - - #define TICK_INT_vect RTC_CNT_vect - #define INT_FLAGS RTC_INTFLAGS - #define INT_MASK RTC_OVF_bm - - /* Hertz to period for RTC setup */ - #define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) ) - #define TICK_init() { \ - while (RTC.STATUS > 0); \ - RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ - RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \ - RTC.INTCTRL |= 1 << RTC_OVF_bp; \ - } + #define TICK_INT_vect TCB4_INT_vect + #define INT_FLAGS TCB4_INTFLAGS + #define INT_MASK TCB_CAPT_bm -#else + #define TICK_init() \ + { \ + TCB4.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB4.INTCTRL = TCB_CAPT_bm; \ + TCB4.CTRLA = TCB_ENABLE_bm; \ + } + +#elif ( configUSE_TIMER_INSTANCE == 5 ) + + #define TICK_INT_vect RTC_CNT_vect + #define INT_FLAGS RTC_INTFLAGS + #define INT_MASK RTC_OVF_bm + +/* Hertz to period for RTC setup */ + #define RTC_PERIOD_HZ( x ) ( 32768 * ( ( 1.0 / x ) ) ) + #define TICK_init() \ + { \ + while( RTC.STATUS > 0 ) {; } \ + RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ + RTC.PER = RTC_PERIOD_HZ( configTICK_RATE_HZ ); \ + RTC.INTCTRL |= 1 << RTC_OVF_bp; \ + } + +#else /* if ( configUSE_TIMER_INSTANCE == 0 ) */ #undef TICK_INT_vect #undef INT_FLAGS #undef INT_MASK #undef TICK_init() #error Invalid timer setting. -#endif +#endif /* if ( configUSE_TIMER_INSTANCE == 0 ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/AVR_Mega0/port.c b/portable/IAR/AVR_Mega0/port.c index d0f220569..f6e8504d1 100644 --- a/portable/IAR/AVR_Mega0/port.c +++ b/portable/IAR/AVR_Mega0/port.c @@ -114,9 +114,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, pxTopOfStack -= ( configCALL_STACK_SIZE - 2 ); /* Next simulate the stack as if after a call to portSAVE_CONTEXT(). - * portSAVE_CONTEXT places the flags on the stack immediately after r0 - * to ensure the interrupts get disabled as soon as possible, and so ensuring - * the stack use is minimal should a context switch interrupt occur. */ + * portSAVE_CONTEXT places the flags on the stack immediately after r0 + * to ensure the interrupts get disabled as soon as possible, and so ensuring + * the stack use is minimal should a context switch interrupt occur. */ + *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */ pxTopOfStack--; *pxTopOfStack = portFLAGS_INT_ENABLED; diff --git a/portable/IAR/AVR_Mega0/porthardware.h b/portable/IAR/AVR_Mega0/porthardware.h index 5468bdabe..4188ae274 100644 --- a/portable/IAR/AVR_Mega0/porthardware.h +++ b/portable/IAR/AVR_Mega0/porthardware.h @@ -8,74 +8,79 @@ #if ( configUSE_TIMER_INSTANCE == 0 ) - #define TICK_INT_vect TCB0_INT_vect - #define INT_FLAGS TCB0_INTFLAGS - #define INT_MASK TCB_CAPT_bm + #define TICK_INT_vect TCB0_INT_vect + #define INT_FLAGS TCB0_INTFLAGS + #define INT_MASK TCB_CAPT_bm - #define TICK_init() { \ - TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB0.INTCTRL = TCB_CAPT_bm; \ - TCB0.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_init() \ + { \ + TCB0.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB0.INTCTRL = TCB_CAPT_bm; \ + TCB0.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 1 ) - #define TICK_INT_vect TCB1_INT_vect - #define INT_FLAGS TCB1_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB1.INTCTRL = TCB_CAPT_bm; \ - TCB1.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_INT_vect TCB1_INT_vect + #define INT_FLAGS TCB1_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB1.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB1.INTCTRL = TCB_CAPT_bm; \ + TCB1.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 2 ) - #define TICK_INT_vect TCB2_INT_vect - #define INT_FLAGS TCB2_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB2.INTCTRL = TCB_CAPT_bm; \ - TCB2.CTRLA = TCB_ENABLE_bm; \ - } - + #define TICK_INT_vect TCB2_INT_vect + #define INT_FLAGS TCB2_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB2.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB2.INTCTRL = TCB_CAPT_bm; \ + TCB2.CTRLA = TCB_ENABLE_bm; \ + } + #elif ( configUSE_TIMER_INSTANCE == 3 ) - #define TICK_INT_vect TCB3_INT_vect - #define INT_FLAGS TCB3_INTFLAGS - #define INT_MASK TCB_CAPT_bm - - #define TICK_init() { \ - TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ - TCB3.INTCTRL = TCB_CAPT_bm; \ - TCB3.CTRLA = TCB_ENABLE_bm; \ - } + #define TICK_INT_vect TCB3_INT_vect + #define INT_FLAGS TCB3_INTFLAGS + #define INT_MASK TCB_CAPT_bm + + #define TICK_init() \ + { \ + TCB3.CCMP = configCPU_CLOCK_HZ / configTICK_RATE_HZ; \ + TCB3.INTCTRL = TCB_CAPT_bm; \ + TCB3.CTRLA = TCB_ENABLE_bm; \ + } #elif ( configUSE_TIMER_INSTANCE == 4 ) - #define TICK_INT_vect RTC_CNT_vect - #define INT_FLAGS RTC_INTFLAGS - #define INT_MASK RTC_OVF_bm - - /* Hertz to period for RTC setup */ - #define RTC_PERIOD_HZ(x) ( 32768 * ( ( 1.0 / x ) ) ) - #define TICK_init() { \ - while (RTC.STATUS > 0); \ - RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ - RTC.PER = RTC_PERIOD_HZ(configTICK_RATE_HZ); \ - RTC.INTCTRL |= 1 << RTC_OVF_bp; \ - } + #define TICK_INT_vect RTC_CNT_vect + #define INT_FLAGS RTC_INTFLAGS + #define INT_MASK RTC_OVF_bm -#else +/* Hertz to period for RTC setup */ + #define RTC_PERIOD_HZ( x ) ( 32768 * ( ( 1.0 / x ) ) ) + #define TICK_init() \ + { \ + while( RTC.STATUS > 0 ) {; } \ + RTC.CTRLA = RTC_PRESCALER_DIV1_gc | 1 << RTC_RTCEN_bp; \ + RTC.PER = RTC_PERIOD_HZ( configTICK_RATE_HZ ); \ + RTC.INTCTRL |= 1 << RTC_OVF_bp; \ + } + +#else /* if ( configUSE_TIMER_INSTANCE == 0 ) */ #undef TICK_INT_vect #undef INT_FLAGS #undef INT_MASK #undef TICK_init() #error Invalid timer setting. -#endif +#endif /* if ( configUSE_TIMER_INSTANCE == 0 ) */ /*-----------------------------------------------------------*/ diff --git a/portable/ThirdParty/GCC/ARC_EM_HS/port.c b/portable/ThirdParty/GCC/ARC_EM_HS/port.c index d0ba4061e..a2605b00c 100644 --- a/portable/ThirdParty/GCC/ARC_EM_HS/port.c +++ b/portable/ThirdParty/GCC/ARC_EM_HS/port.c @@ -40,6 +40,7 @@ volatile unsigned int ulCriticalNesting = 999UL; volatile unsigned int context_switch_reqflg; /* task context switch request flag in exceptions and interrupts handling */ + /** * \var exc_nest_count * \brief the counter for exc/int processing, =0 no int/exc diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/port.c b/portable/ThirdParty/GCC/Xtensa_ESP32/port.c index 8b852cfee..822aad721 100644 --- a/portable/ThirdParty/GCC/Xtensa_ESP32/port.c +++ b/portable/ThirdParty/GCC/Xtensa_ESP32/port.c @@ -153,6 +153,7 @@ void _xt_user_exit( void ); /* * Stack initialization */ +/* *INDENT-OFF* */ #if portUSING_MPU_WRAPPERS StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, @@ -163,6 +164,7 @@ void _xt_user_exit( void ); TaskFunction_t pxCode, void * pvParameters ) #endif +/* *INDENT-ON* */ { StackType_t * sp, * tp; XtExcFrame * frame; @@ -408,7 +410,7 @@ void vPortCPUInitializeMutex( portMUX_TYPE * mux ) return result; } -#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */ +#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */ void vPortCPUAcquireMutex( portMUX_TYPE * mux ) { unsigned int irqStatus = portENTER_CRITICAL_NESTED(); diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c index 2bf1da7ef..63789951d 100644 --- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c +++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c @@ -35,9 +35,9 @@ #include "xtensa_rtos.h" #if CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/clk.h" + #include "esp32s2/clk.h" #elif CONFIG_IDF_TARGET_ESP32 -#include "esp32/clk.h" + #include "esp32/clk.h" #endif #ifdef XT_RTOS_TIMER_INT diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c index 93e416068..8e1465df5 100644 --- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c +++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c @@ -35,9 +35,9 @@ #include "freertos/portable.h" #if CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/ets_sys.h" + #include "esp32s2/rom/ets_sys.h" #elif CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/ets_sys.h" + #include "esp32/rom/ets_sys.h" #endif #if XCHAL_HAVE_EXCEPTIONS