mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-04 11:09:01 +01:00 
			
		
		
		
	* Fix spelling --------- Co-authored-by: Rahul Kar <118818625+kar-rahul-aws@users.noreply.github.com>
		
			
				
	
	
		
			846 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			846 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
 | 
						|
 * Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: MIT
 | 
						|
 *
 | 
						|
 * 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.
 | 
						|
 *
 | 
						|
 * https://www.FreeRTOS.org
 | 
						|
 * https://github.com/FreeRTOS
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/* Standard includes. */
 | 
						|
#include <stdint.h>
 | 
						|
 | 
						|
/* 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. */
 | 
						|
#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
						|
    #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
						|
#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */
 | 
						|
 | 
						|
/* Scheduler includes. */
 | 
						|
#include "FreeRTOS.h"
 | 
						|
#include "portmacro.h"
 | 
						|
#include "task.h"
 | 
						|
#include "mpu_syscall_numbers.h"
 | 
						|
 | 
						|
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
 | 
						|
 | 
						|
/* Max value that fits in a uint32_t type. */
 | 
						|
#define portUINT32_MAX    ( ~( ( uint32_t ) 0 ) )
 | 
						|
 | 
						|
/* Check if adding a and b will result in overflow. */
 | 
						|
#define portADD_UINT32_WILL_OVERFLOW( a, b )    ( ( a ) > ( portUINT32_MAX - ( b ) ) )
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Variable used to keep track of critical section nesting.
 | 
						|
 *
 | 
						|
 * @ingroup Critical Sections
 | 
						|
 *
 | 
						|
 * This variable is stored as part of the task context and must be initialised
 | 
						|
 * to a non zero value to ensure interrupts don't inadvertently become unmasked
 | 
						|
 * before the scheduler starts. As it is stored as part of the task context, it
 | 
						|
 * will be set to 0 when the first task is started.
 | 
						|
 */
 | 
						|
PRIVILEGED_DATA volatile UBaseType_t ulCriticalNesting = 0xFFFF;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Set to 1 to pend a context switch from an ISR.
 | 
						|
 *
 | 
						|
 * @ingroup Interrupt Management
 | 
						|
 */
 | 
						|
PRIVILEGED_DATA volatile UBaseType_t ulPortYieldRequired = pdFALSE;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Interrupt nesting depth, used to count the number of interrupts to unwind.
 | 
						|
 *
 | 
						|
 * @ingroup Interrupt Management
 | 
						|
 */
 | 
						|
PRIVILEGED_DATA volatile UBaseType_t ulPortInterruptNesting = 0UL;
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Variable to track whether or not the scheduler has been started.
 | 
						|
 *
 | 
						|
 * @ingroup Scheduler
 | 
						|
 *
 | 
						|
 * This is the port specific version of the xSchedulerRunning in tasks.c.
 | 
						|
 */
 | 
						|
PRIVILEGED_DATA static BaseType_t prvPortSchedulerRunning = pdFALSE;
 | 
						|
 | 
						|
/* -------------------------- Private Function Declarations -------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Determine if the given MPU region settings authorizes the requested
 | 
						|
 * access to the given buffer.
 | 
						|
 *
 | 
						|
 * @ingroup Task Context
 | 
						|
 * @ingroup MPU Control
 | 
						|
 *
 | 
						|
 * @param xTaskMPURegion MPU region settings.
 | 
						|
 * @param ulBufferStart Start address of the given buffer.
 | 
						|
 * @param ulBufferLength Length of the given buffer.
 | 
						|
 * @param ulAccessRequested Access requested.
 | 
						|
 *
 | 
						|
 * @return pdTRUE if MPU region settings authorizes the requested access to the
 | 
						|
 * given buffer, pdFALSE otherwise.
 | 
						|
 */
 | 
						|
PRIVILEGED_FUNCTION static BaseType_t prvMPURegionAuthorizesBuffer( const xMPU_REGION_REGISTERS * xTaskMPURegion,
 | 
						|
                                                                    const uint32_t ulBufferStart,
 | 
						|
                                                                    const uint32_t ulBufferLength,
 | 
						|
                                                                    const uint32_t ulAccessRequested );
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Determine the smallest MPU Region Size Encoding for the given MPU
 | 
						|
 * region size.
 | 
						|
 *
 | 
						|
 * @ingroup MPU Control
 | 
						|
 *
 | 
						|
 * @param ulActualMPURegionSize MPU region size in bytes.
 | 
						|
 *
 | 
						|
 * @return The smallest MPU Region Size Encoding for the given MPU region size.
 | 
						|
 */
 | 
						|
PRIVILEGED_FUNCTION static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize );
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Set up MPU.
 | 
						|
 *
 | 
						|
 * @ingroup MPU Control
 | 
						|
 */
 | 
						|
PRIVILEGED_FUNCTION static void prvSetupMPU( void );
 | 
						|
 | 
						|
/* -------------------------- Exported Function Declarations -------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Enter critical section.
 | 
						|
 *
 | 
						|
 * @ingroup Critical Section
 | 
						|
 */
 | 
						|
PRIVILEGED_FUNCTION void vPortEnterCritical( void );
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Exit critical section.
 | 
						|
 *
 | 
						|
 * @ingroup Critical Section
 | 
						|
 */
 | 
						|
PRIVILEGED_FUNCTION void vPortExitCritical( void );
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Setup a FreeRTOS task's initial context.
 | 
						|
 *
 | 
						|
 * @ingroup Task Context
 | 
						|
 *
 | 
						|
 * @param pxTopOfStack Top of stack.
 | 
						|
 * @param pxCode The task function.
 | 
						|
 * @param pvParameters Argument passed to the task function.
 | 
						|
 * @param xRunPrivileged Marks if the task is privileged.
 | 
						|
 * @param xMPUSettings MPU settings of the task.
 | 
						|
 *
 | 
						|
 * @return Location where to restore the task's context from.
 | 
						|
 */
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
 | 
						|
                                     TaskFunction_t pxCode,
 | 
						|
                                     void * pvParameters,
 | 
						|
                                     BaseType_t xRunPrivileged,
 | 
						|
                                     xMPU_SETTINGS * xMPUSettings )
 | 
						|
{
 | 
						|
    /* Setup the initial context of the task. The context is set exactly as
 | 
						|
     * expected by the portRESTORE_CONTEXT() macro. */
 | 
						|
    UBaseType_t ulIndex = CONTEXT_SIZE - 1U;
 | 
						|
 | 
						|
    xSYSTEM_CALL_STACK_INFO * xSysCallInfo = NULL;
 | 
						|
 | 
						|
    if( xRunPrivileged == pdTRUE )
 | 
						|
    {
 | 
						|
        xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
 | 
						|
        /* Current Program Status Register (CPSR). */
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = SYS_MODE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
 | 
						|
        /* Current Program Status Register (CPSR). */
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = USER_MODE;
 | 
						|
    }
 | 
						|
 | 
						|
    if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x0UL )
 | 
						|
    {
 | 
						|
        /* The task will cause the processor to start in THUMB state, set the
 | 
						|
         * Thumb state bit in the CPSR. */
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] |= portTHUMB_MODE_BIT;
 | 
						|
    }
 | 
						|
 | 
						|
    ulIndex--;
 | 
						|
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxCode; /* PC. */
 | 
						|
    ulIndex--;
 | 
						|
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
 | 
						|
    ulIndex--;
 | 
						|
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pxTopOfStack; /* SP. */
 | 
						|
    ulIndex--;
 | 
						|
 | 
						|
    /* General Purpose Registers. */
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x12121212; /* R12. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x11111111; /* R11. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x10101010; /* R10. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x09090909; /* R9. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x08080808; /* R8. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x07070707; /* R7. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x06060606; /* R6. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x05050505; /* R5. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x04040404; /* R4. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x03030303; /* R3. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x02020202; /* R2. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x01010101; /* R1. */
 | 
						|
    ulIndex--;
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) pvParameters; /* R0. */
 | 
						|
    ulIndex--;
 | 
						|
 | 
						|
    #if( portENABLE_FPU == 1 )
 | 
						|
    {
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000015; /* S31. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1500000; /* S30. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000014; /* S29. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1400000; /* S28. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000013; /* S27. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1300000; /* S26. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000012; /* S25. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1200000; /* S24. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000011; /* S23. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1100000; /* S22. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000010; /* S21. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S20. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000009; /* S19. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD9000000; /* S18. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000008; /* S17. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD8000000; /* S16. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000007; /* S15. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD7000000; /* S14. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000006; /* S13. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD6000000; /* S12. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000005; /* S11. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD5000000; /* S10. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000004; /* S9. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD4000000; /* S8. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000003; /* S7. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD3000000; /* S6. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000002; /* S5. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD2000000; /* S4. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000001; /* S3. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD1000000; /* S2. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S1. */
 | 
						|
        ulIndex--;
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0xD0000000; /* S0. */
 | 
						|
        ulIndex--;
 | 
						|
 | 
						|
        xMPUSettings->ulContext[ ulIndex ] = ( StackType_t ) 0x00000000; /* FPSR. */
 | 
						|
        ulIndex--;
 | 
						|
    }
 | 
						|
    #endif /* portENABLE_FPU */
 | 
						|
 | 
						|
    /* The task will start with a critical nesting count of 0. */
 | 
						|
    xMPUSettings->ulContext[ ulIndex ] = portNO_CRITICAL_NESTING;
 | 
						|
 | 
						|
    /* Ensure that the system call stack is double word aligned. */
 | 
						|
    xSysCallInfo = &( xMPUSettings->xSystemCallStackInfo );
 | 
						|
    xSysCallInfo->pulSystemCallStackPointer = &( xSysCallInfo->ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1U ] );
 | 
						|
    xSysCallInfo->pulSystemCallStackPointer = ( uint32_t * ) ( ( ( uint32_t ) ( xSysCallInfo->pulSystemCallStackPointer ) ) &
 | 
						|
                                                               ( ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) ) );
 | 
						|
 | 
						|
    /* This is not NULL only for the duration of a system call. */
 | 
						|
    xSysCallInfo->pulTaskStackPointer = NULL;
 | 
						|
 | 
						|
    /* Set the System Call to return to vPortSystemCallExit. */
 | 
						|
    xSysCallInfo->pulSystemCallExitAddress = ( uint32_t * ) ( &vPortSystemCallExit );
 | 
						|
 | 
						|
    /* Return the address where this task's context should be restored from. */
 | 
						|
    return &( xMPUSettings->ulContext[ ulIndex ] );
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/**
 | 
						|
 * @brief Store a FreeRTOS task's MPU settings in its TCB.
 | 
						|
 *
 | 
						|
 * @ingroup Task Context
 | 
						|
 * @ingroup MPU Control
 | 
						|
 *
 | 
						|
 * @param xMPUSettings The MPU settings in TCB.
 | 
						|
 * @param xRegions The updated MPU settings requested by the task.
 | 
						|
 * @param pxBottomOfStack The base address of the task's Stack.
 | 
						|
 * @param ulStackDepth The length of the task's stack.
 | 
						|
 */
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
 | 
						|
                                const struct xMEMORY_REGION * const xRegions,
 | 
						|
                                StackType_t * pxBottomOfStack,
 | 
						|
                                uint32_t ulStackDepth )
 | 
						|
{
 | 
						|
    #if defined( __ARMCC_VERSION )
 | 
						|
        /* Declaration when these variable are defined in code instead of being
 | 
						|
         * exported from linker scripts. */
 | 
						|
        extern uint32_t * __SRAM_segment_start__;
 | 
						|
        extern uint32_t * __SRAM_segment_end__;
 | 
						|
    #else
 | 
						|
        /* Declaration when these variable are exported from linker scripts. */
 | 
						|
        extern uint32_t __SRAM_segment_start__[];
 | 
						|
        extern uint32_t __SRAM_segment_end__[];
 | 
						|
    #endif /* if defined( __ARMCC_VERSION ) */
 | 
						|
 | 
						|
    uint32_t ulIndex = 0x0;
 | 
						|
    uint32_t ulRegionLength;
 | 
						|
    uint32_t ulRegionLengthEncoded;
 | 
						|
    uint32_t ulRegionLengthDecoded;
 | 
						|
 | 
						|
    if( xRegions == NULL )
 | 
						|
    {
 | 
						|
        /* No MPU regions are specified so allow access to all of the RAM. */
 | 
						|
        ulRegionLength = ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__;
 | 
						|
        ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
 | 
						|
        ulRegionLength |= portMPU_REGION_ENABLE;
 | 
						|
 | 
						|
        /* MPU Settings is zero'd out in the TCB before this function is called.
 | 
						|
         * We, therefore, do not need to explicitly zero out unused MPU regions
 | 
						|
         * in xMPUSettings. */
 | 
						|
        ulIndex = portSTACK_REGION;
 | 
						|
 | 
						|
        xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) __SRAM_segment_start__;
 | 
						|
        xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded |
 | 
						|
                                                          portMPU_REGION_ENABLE );
 | 
						|
        xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ( portMPU_REGION_PRIV_RW_USER_RW_NOEXEC |
 | 
						|
                                                               portMPU_REGION_NORMAL_OIWTNOWA_SHARED );
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        for( ulIndex = 0UL; ulIndex < portNUM_CONFIGURABLE_REGIONS; ulIndex++ )
 | 
						|
        {
 | 
						|
            /* If a length has been provided, the region is in use. */
 | 
						|
            if( ( xRegions[ ulIndex ] ).ulLengthInBytes > 0UL )
 | 
						|
            {
 | 
						|
                ulRegionLength = xRegions[ ulIndex ].ulLengthInBytes;
 | 
						|
                ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
 | 
						|
 | 
						|
                /* MPU region base address must be aligned to the region size
 | 
						|
                 * boundary. */
 | 
						|
                ulRegionLengthDecoded = 2UL << ( ulRegionLengthEncoded >> 1UL );
 | 
						|
                configASSERT( ( ( ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress ) % ( ulRegionLengthDecoded ) ) == 0UL );
 | 
						|
 | 
						|
                xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) xRegions[ ulIndex ].pvBaseAddress;
 | 
						|
                xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded |
 | 
						|
                                                                  portMPU_REGION_ENABLE );
 | 
						|
                xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = xRegions[ ulIndex ].ulParameters;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = 0x0UL;
 | 
						|
                xMPUSettings->xRegion[ ulIndex ].ulRegionSize = 0x0UL;
 | 
						|
                xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = 0x0UL;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        /* 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 != 0x0UL )
 | 
						|
        {
 | 
						|
            ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) );
 | 
						|
 | 
						|
            /* MPU region base address must be aligned to the region size
 | 
						|
             * boundary. */
 | 
						|
            ulRegionLengthDecoded = 2UL << ( ulRegionLengthEncoded >> 1UL );
 | 
						|
            configASSERT( ( ( uint32_t ) pxBottomOfStack % ( ulRegionLengthDecoded ) ) == 0U );
 | 
						|
 | 
						|
            ulIndex = portSTACK_REGION;
 | 
						|
            xMPUSettings->xRegion[ ulIndex ].ulRegionBaseAddress = ( uint32_t ) pxBottomOfStack;
 | 
						|
            xMPUSettings->xRegion[ ulIndex ].ulRegionSize = ( ulRegionLengthEncoded |
 | 
						|
                                                              portMPU_REGION_ENABLE );;
 | 
						|
            xMPUSettings->xRegion[ ulIndex ].ulRegionAttribute = ( portMPU_REGION_PRIV_RW_USER_RW_NOEXEC |
 | 
						|
                                                                   portMPU_REGION_NORMAL_OIWTNOWA_SHARED );
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
BaseType_t xPortIsTaskPrivileged( void )
 | 
						|
{
 | 
						|
    BaseType_t xTaskIsPrivileged = pdFALSE;
 | 
						|
 | 
						|
    /* Calling task's MPU settings. */
 | 
						|
    const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL );
 | 
						|
 | 
						|
    if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
 | 
						|
    {
 | 
						|
        xTaskIsPrivileged = pdTRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    return xTaskIsPrivileged;
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
BaseType_t xPortStartScheduler( void )
 | 
						|
{
 | 
						|
    /* Start the timer that generates the tick ISR. */
 | 
						|
    configSETUP_TICK_INTERRUPT();
 | 
						|
 | 
						|
    /* Configure MPU regions that are common to all tasks. */
 | 
						|
    prvSetupMPU();
 | 
						|
 | 
						|
    prvPortSchedulerRunning = pdTRUE;
 | 
						|
 | 
						|
    /* Load the context of the first task. */
 | 
						|
    vPortStartFirstTask();
 | 
						|
 | 
						|
    /* Will only get here if vTaskStartScheduler() was called with the CPU in
 | 
						|
     * a non-privileged mode or the binary point register was not set to its lowest
 | 
						|
     * possible value. prvTaskExitError() is referenced to prevent a compiler
 | 
						|
     * warning about it being defined but not referenced in the case that the user
 | 
						|
     * defines their own exit address. */
 | 
						|
    ( void ) prvTaskExitError();
 | 
						|
    return pdFALSE;
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
static uint32_t prvGetMPURegionSizeEncoding( uint32_t ulActualMPURegionSize )
 | 
						|
{
 | 
						|
    uint32_t ulRegionSize, ulReturnValue = 4U;
 | 
						|
 | 
						|
    /* 32 bytes is the smallest valid region for Cortex R4 and R5 CPUs. */
 | 
						|
    for( ulRegionSize = 0x20UL; ulReturnValue < 0x1FUL; ( ulRegionSize <<= 1UL ) )
 | 
						|
    {
 | 
						|
        if( ulActualMPURegionSize <= ulRegionSize )
 | 
						|
        {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            ulReturnValue++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    /* Shift the code by one before returning so it can be written directly
 | 
						|
     * into the the correct bit position of the attribute register. */
 | 
						|
    return ulReturnValue << 1UL;
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
static void prvSetupMPU( void )
 | 
						|
{
 | 
						|
#if defined( __ARMCC_VERSION )
 | 
						|
    /* Declaration when these variable are defined in code. */
 | 
						|
    /* Sections used for FLASH. */
 | 
						|
    extern uint32_t * __FLASH_segment_start__;
 | 
						|
    extern uint32_t * __FLASH_segment_end__;
 | 
						|
    extern uint32_t * __privileged_functions_start__;
 | 
						|
    extern uint32_t * __privileged_functions_end__;
 | 
						|
 | 
						|
    /* Sections used for RAM. */
 | 
						|
    extern uint32_t * __SRAM_segment_start__;
 | 
						|
    extern uint32_t * __SRAM_segment_end__;
 | 
						|
    extern uint32_t * __privileged_data_start__;
 | 
						|
    extern uint32_t * __privileged_data_end__;
 | 
						|
#else
 | 
						|
    /* Declaration when these variable are exported from linker scripts. */
 | 
						|
    /* Sections used for FLASH. */
 | 
						|
    extern uint32_t __FLASH_segment_start__[];
 | 
						|
    extern uint32_t __FLASH_segment_end__[];
 | 
						|
    extern uint32_t __privileged_functions_start__[];
 | 
						|
    extern uint32_t __privileged_functions_end__[];
 | 
						|
 | 
						|
    /* Sections used for RAM. */
 | 
						|
    extern uint32_t __SRAM_segment_start__[];
 | 
						|
    extern uint32_t __SRAM_segment_end__[];
 | 
						|
    extern uint32_t __privileged_data_start__[];
 | 
						|
    extern uint32_t __privileged_data_end__[];
 | 
						|
#endif /* if defined( __ARMCC_VERSION ) */
 | 
						|
 | 
						|
    uint32_t ulRegionLength;
 | 
						|
    uint32_t ulRegionLengthEncoded;
 | 
						|
 | 
						|
    /* Disable the MPU before programming it. */
 | 
						|
    vMPUDisable();
 | 
						|
 | 
						|
    /* Priv: RX, Unpriv: RX for entire Flash. */
 | 
						|
    ulRegionLength = ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__;
 | 
						|
    ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
 | 
						|
    vMPUSetRegion( portUNPRIVILEGED_FLASH_REGION,
 | 
						|
                   ( uint32_t ) __FLASH_segment_start__,
 | 
						|
                   ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
 | 
						|
                   ( portMPU_REGION_PRIV_RO_USER_RO_EXEC |
 | 
						|
                     portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) );
 | 
						|
 | 
						|
    /* Priv: RX, Unpriv: No access for privileged functions. */
 | 
						|
    ulRegionLength = ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__;
 | 
						|
    ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
 | 
						|
    vMPUSetRegion( portPRIVILEGED_FLASH_REGION,
 | 
						|
                   ( uint32_t ) __privileged_functions_start__,
 | 
						|
                   ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
 | 
						|
                   ( portMPU_REGION_PRIV_RO_USER_NA_EXEC |
 | 
						|
                     portMPU_REGION_NORMAL_OIWTNOWA_SHARED ) );
 | 
						|
 | 
						|
    /* Priv: RW, Unpriv: No Access for privileged data. */
 | 
						|
    ulRegionLength = ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__;
 | 
						|
    ulRegionLengthEncoded = prvGetMPURegionSizeEncoding( ulRegionLength );
 | 
						|
    vMPUSetRegion( portPRIVILEGED_RAM_REGION,
 | 
						|
                   ( uint32_t ) __privileged_data_start__,
 | 
						|
                   ( ulRegionLengthEncoded | portMPU_REGION_ENABLE ),
 | 
						|
                   ( portMPU_REGION_PRIV_RW_USER_NA_NOEXEC |
 | 
						|
                     portMPU_REGION_PRIV_RW_USER_NA_NOEXEC ) );
 | 
						|
 | 
						|
    /* Enable the MPU background region - it allows privileged operating modes
 | 
						|
     * access to unmapped regions of memory without generating a fault. */
 | 
						|
    vMPUEnableBackgroundRegion();
 | 
						|
 | 
						|
    /* After setting default regions, enable the MPU. */
 | 
						|
    vMPUEnable();
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
static BaseType_t prvMPURegionAuthorizesBuffer( const xMPU_REGION_REGISTERS * xTaskMPURegion,
 | 
						|
                                                const uint32_t ulBufferStart,
 | 
						|
                                                const uint32_t ulBufferLength,
 | 
						|
                                                const uint32_t ulAccessRequested )
 | 
						|
{
 | 
						|
    BaseType_t xAccessGranted = pdFALSE;
 | 
						|
    uint32_t ulBufferEnd;
 | 
						|
    uint32_t ulMPURegionLength;
 | 
						|
    uint32_t ulMPURegionStart;
 | 
						|
    uint32_t ulMPURegionEnd;
 | 
						|
    uint32_t ulMPURegionAccessPermissions;
 | 
						|
 | 
						|
    if( portADD_UINT32_WILL_OVERFLOW( ulBufferStart, ( ulBufferLength - 1UL ) ) == pdFALSE )
 | 
						|
    {
 | 
						|
        ulBufferEnd = ulBufferStart + ulBufferLength - 1UL;
 | 
						|
        ulMPURegionLength = 2UL << ( xTaskMPURegion->ulRegionSize >> 1UL );
 | 
						|
        ulMPURegionStart = xTaskMPURegion->ulRegionBaseAddress;
 | 
						|
        ulMPURegionEnd = xTaskMPURegion->ulRegionBaseAddress + ulMPURegionLength - 1UL;
 | 
						|
 | 
						|
        if( ( ulBufferStart >= ulMPURegionStart ) &&
 | 
						|
            ( ulBufferEnd <= ulMPURegionEnd ) &&
 | 
						|
            ( ulBufferStart <= ulBufferEnd ) )
 | 
						|
        {
 | 
						|
            ulMPURegionAccessPermissions = xTaskMPURegion->ulRegionAttribute & portMPU_REGION_AP_BITMASK;
 | 
						|
 | 
						|
            if( ulAccessRequested == tskMPU_READ_PERMISSION ) /* RO. */
 | 
						|
            {
 | 
						|
                if( ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RO ) ||
 | 
						|
                    ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RO_USER_RO ) ||
 | 
						|
                    ( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RW ) )
 | 
						|
 | 
						|
                {
 | 
						|
                    xAccessGranted = pdTRUE;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else if( ( ulAccessRequested & tskMPU_WRITE_PERMISSION ) != 0UL ) /* W or RW. */
 | 
						|
            {
 | 
						|
                if( ulMPURegionAccessPermissions == portMPU_REGION_PRIV_RW_USER_RW )
 | 
						|
                {
 | 
						|
                    xAccessGranted = pdTRUE;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return xAccessGranted;
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
 | 
						|
                                            uint32_t ulBufferLength,
 | 
						|
                                            uint32_t ulAccessRequested )
 | 
						|
{
 | 
						|
    BaseType_t xAccessGranted = pdFALSE;
 | 
						|
    uint32_t ulRegionIndex;
 | 
						|
    xMPU_SETTINGS * xTaskMPUSettings = NULL;
 | 
						|
 | 
						|
    if( prvPortSchedulerRunning == pdFALSE )
 | 
						|
    {
 | 
						|
        /* Grant access to all the memory before the scheduler is started. It is
 | 
						|
         * necessary because there is no task running yet and therefore, we
 | 
						|
         * cannot use the permissions of any task. */
 | 
						|
        xAccessGranted = pdTRUE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        /* Calling task's MPU settings. */
 | 
						|
        xTaskMPUSettings = xTaskGetMPUSettings( NULL );
 | 
						|
 | 
						|
        if( ( xTaskMPUSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
 | 
						|
        {
 | 
						|
            /* Privileged tasks have access to all the memory. */
 | 
						|
            xAccessGranted = pdTRUE;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            for( ulRegionIndex = 0x0UL; ulRegionIndex < portTOTAL_NUM_REGIONS_IN_TCB; ulRegionIndex++ )
 | 
						|
            {
 | 
						|
                xAccessGranted = prvMPURegionAuthorizesBuffer( &( xTaskMPUSettings->xRegion[ ulRegionIndex ] ),
 | 
						|
                                                               ( uint32_t ) pvBuffer,
 | 
						|
                                                               ulBufferLength,
 | 
						|
                                                               ulAccessRequested );
 | 
						|
 | 
						|
                if( xAccessGranted == pdTRUE )
 | 
						|
                {
 | 
						|
                    break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return xAccessGranted;
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject )
 | 
						|
{
 | 
						|
    uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
 | 
						|
    BaseType_t xAccessGranted = pdFALSE;
 | 
						|
    const xMPU_SETTINGS * xTaskMpuSettings;
 | 
						|
 | 
						|
    if( prvPortSchedulerRunning == pdFALSE )
 | 
						|
    {
 | 
						|
        /* Grant access to all the kernel objects before the scheduler
 | 
						|
         * is started. It is necessary because there is no task running
 | 
						|
         * yet and therefore, we cannot use the permissions of any
 | 
						|
         * task. */
 | 
						|
        xAccessGranted = pdTRUE;
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        /* Calling task's MPU settings. */
 | 
						|
        xTaskMpuSettings = xTaskGetMPUSettings( NULL );
 | 
						|
 | 
						|
        ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject
 | 
						|
                                          / portACL_ENTRY_SIZE_BITS );
 | 
						|
        ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject
 | 
						|
                                        % portACL_ENTRY_SIZE_BITS );
 | 
						|
 | 
						|
        if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
 | 
						|
        {
 | 
						|
            xAccessGranted = pdTRUE;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            if( ( ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] ) &
 | 
						|
                  ( 1U << ulAccessControlListEntryBit ) ) != 0UL )
 | 
						|
            {
 | 
						|
                xAccessGranted = pdTRUE;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return xAccessGranted;
 | 
						|
}
 | 
						|
 | 
						|
#else
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject )
 | 
						|
{
 | 
						|
    ( void ) lInternalIndexOfKernelObject;
 | 
						|
 | 
						|
    /* If Access Control List feature is not used, all the tasks have
 | 
						|
     * access to all the kernel objects. */
 | 
						|
    return pdTRUE;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
 | 
						|
                                     int32_t lInternalIndexOfKernelObject )
 | 
						|
{
 | 
						|
    uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
 | 
						|
    xMPU_SETTINGS * xTaskMpuSettings;
 | 
						|
 | 
						|
    ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject
 | 
						|
                                      / portACL_ENTRY_SIZE_BITS );
 | 
						|
    ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject
 | 
						|
                                    % portACL_ENTRY_SIZE_BITS );
 | 
						|
 | 
						|
    xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle );
 | 
						|
 | 
						|
    xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] |= ( 1U << ulAccessControlListEntryBit );
 | 
						|
}
 | 
						|
 | 
						|
#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
#if( configENABLE_ACCESS_CONTROL_LIST == 1 )
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
void vPortRevokeAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
 | 
						|
                                      int32_t lInternalIndexOfKernelObject )
 | 
						|
{
 | 
						|
    uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
 | 
						|
    xMPU_SETTINGS * xTaskMpuSettings;
 | 
						|
 | 
						|
    ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject
 | 
						|
                                      / portACL_ENTRY_SIZE_BITS );
 | 
						|
    ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject
 | 
						|
                                    % portACL_ENTRY_SIZE_BITS );
 | 
						|
 | 
						|
    xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle );
 | 
						|
 | 
						|
    xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &= ~( 1U << ulAccessControlListEntryBit );
 | 
						|
}
 | 
						|
 | 
						|
#endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
void prvTaskExitError( void )
 | 
						|
{
 | 
						|
    /* 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( ulPortInterruptNesting == ~0UL );
 | 
						|
 | 
						|
    for( ;; )
 | 
						|
    {
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
void vPortEndScheduler( void )
 | 
						|
{
 | 
						|
    prvPortSchedulerRunning = pdFALSE;
 | 
						|
 | 
						|
    /* Not implemented in this port. Artificially force an assert. */
 | 
						|
    configASSERT( prvPortSchedulerRunning == pdTRUE );
 | 
						|
}
 | 
						|
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
void vPortEnterCritical( void )
 | 
						|
{
 | 
						|
    portDISABLE_INTERRUPTS();
 | 
						|
 | 
						|
    /* Now that interrupts are disabled, ulCriticalNesting can be accessed
 | 
						|
     * directly.  Increment ulCriticalNesting to keep a count of how many times
 | 
						|
     * portENTER_CRITICAL() has been called. */
 | 
						|
    ulCriticalNesting++;
 | 
						|
 | 
						|
    /* This is not the interrupt safe version of the enter critical function so
 | 
						|
     * assert() if it is being called from an interrupt context.  Only API
 | 
						|
     * functions that end in "FromISR" can be used in an interrupt.  Only assert
 | 
						|
     * if the critical nesting count is 1 to protect against recursive calls if
 | 
						|
     * the assert function also uses a critical section. */
 | 
						|
    if( ulCriticalNesting == 1 )
 | 
						|
    {
 | 
						|
        configASSERT( ulPortInterruptNesting == 0 );
 | 
						|
    }
 | 
						|
}
 | 
						|
/* ----------------------------------------------------------------------------------- */
 | 
						|
 | 
						|
/* PRIVILEGED_FUNCTION */
 | 
						|
void vPortExitCritical( void )
 | 
						|
{
 | 
						|
    if( ulCriticalNesting > portNO_CRITICAL_NESTING )
 | 
						|
    {
 | 
						|
        /* Decrement the nesting count as the critical section is being
 | 
						|
         * exited. */
 | 
						|
        ulCriticalNesting--;
 | 
						|
 | 
						|
        /* If the nesting level has reached zero then all interrupt
 | 
						|
         * priorities must be re-enabled. */
 | 
						|
        if( ulCriticalNesting == portNO_CRITICAL_NESTING )
 | 
						|
        {
 | 
						|
            /* Critical nesting has reached zero so all interrupt priorities
 | 
						|
             * should be unmasked. */
 | 
						|
            portENABLE_INTERRUPTS();
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
/* ----------------------------------------------------------------------------------- */
 |