forked from epagris/FreeRTOS-Kernel
		
	Enable building the GCC Cortex-R5 port without an FPU (#586)
* Ensure configUSE_TASK_FPU_SUPPORT option is set correctly If one does enable the FPU of the Cortex-R5 processor, then the GCC compiler will define the macro __ARM_FP. This can be used to ensure, that the configUSE_TASK_FPU_SUPPORT is set accordingly. * Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1 * Remove error case in pxPortInitialiseStack The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled * Enable access to FPU registers only if FPU is enabled * Make minor formating changes * Format ARM Cortex-R5 port * Address review comments from @ChristosZosi * Minor code review suggestions Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> --------- Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com> Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com> Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com> Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
This commit is contained in:
		
							parent
							
								
									563c57e7da
								
							
						
					
					
						commit
						7b26ea6263
					
				@ -74,25 +74,52 @@
 | 
			
		||||
    #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
 | 
			
		||||
 * portmacro.h. */
 | 
			
		||||
/*
 | 
			
		||||
 * __ARM_FP is defined by the c preprocessor when FPU support is enabled,
 | 
			
		||||
 * usually with the -mfpu= argument and -mfloat-abi=.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: Some implementations of the c standard library may use FPU registers
 | 
			
		||||
 *       for generic memory operations (memcpy, etc).
 | 
			
		||||
 *       When setting configUSE_TASK_FPU_SUPPORT == 1, care must be taken to
 | 
			
		||||
 *       ensure that the FPU registers are not used without an FPU context.
 | 
			
		||||
 */
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT == 0 )
 | 
			
		||||
    #ifdef __ARM_FP
 | 
			
		||||
        #error __ARM_FP is defined, so configUSE_TASK_FPU_SUPPORT must be set to either to 1 or 2.
 | 
			
		||||
    #endif /* __ARM_FP */
 | 
			
		||||
#elif ( configUSE_TASK_FPU_SUPPORT == 1 ) || ( configUSE_TASK_FPU_SUPPORT == 2 )
 | 
			
		||||
    #ifndef __ARM_FP
 | 
			
		||||
        #error __ARM_FP is not defined, so configUSE_TASK_FPU_SUPPORT must be set to 0.
 | 
			
		||||
    #endif /* __ARM_FP */
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
 | 
			
		||||
 * portmacro.h.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef configCLEAR_TICK_INTERRUPT
 | 
			
		||||
    #define configCLEAR_TICK_INTERRUPT()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* A critical section is exited when the critical section nesting count reaches
 | 
			
		||||
 * this value. */
 | 
			
		||||
/*
 | 
			
		||||
 * A critical section is exited when the critical section nesting count reaches
 | 
			
		||||
 * this value.
 | 
			
		||||
 */
 | 
			
		||||
#define portNO_CRITICAL_NESTING          ( ( uint32_t ) 0 )
 | 
			
		||||
 | 
			
		||||
/* In all GICs 255 can be written to the priority mask register to unmask all
 | 
			
		||||
 * (but the lowest) interrupt priority. */
 | 
			
		||||
/*
 | 
			
		||||
 * In all GICs 255 can be written to the priority mask register to unmask all
 | 
			
		||||
 * (but the lowest) interrupt priority.
 | 
			
		||||
 */
 | 
			
		||||
#define portUNMASK_VALUE                 ( 0xFFUL )
 | 
			
		||||
 | 
			
		||||
/* Tasks are not created with a floating point context, but can be given a
 | 
			
		||||
/*
 | 
			
		||||
 * Tasks are not created with a floating point context, but can be given a
 | 
			
		||||
 * floating point context after they have been created.  A variable is stored as
 | 
			
		||||
 * part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
 | 
			
		||||
 * does not have an FPU context, or any other value if the task does have an FPU
 | 
			
		||||
 * context. */
 | 
			
		||||
 * context.
 | 
			
		||||
 */
 | 
			
		||||
#define portNO_FLOATING_POINT_CONTEXT    ( ( StackType_t ) 0 )
 | 
			
		||||
 | 
			
		||||
/* Constants required to setup the initial task context. */
 | 
			
		||||
@ -101,8 +128,10 @@
 | 
			
		||||
#define portINTERRUPT_ENABLE_BIT         ( 0x80UL )
 | 
			
		||||
#define portTHUMB_MODE_ADDRESS           ( 0x01UL )
 | 
			
		||||
 | 
			
		||||
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
 | 
			
		||||
 * point is zero. */
 | 
			
		||||
/*
 | 
			
		||||
 * Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
 | 
			
		||||
 * point is zero.
 | 
			
		||||
 */
 | 
			
		||||
#define portBINARY_POINT_BITS            ( ( uint8_t ) 0x03 )
 | 
			
		||||
 | 
			
		||||
/* Masks all bits in the APSR other than the mode bits. */
 | 
			
		||||
@ -140,15 +169,19 @@
 | 
			
		||||
#define portMAX_8_BIT_VALUE                       ( ( uint8_t ) 0xff )
 | 
			
		||||
#define portBIT_0_SET                             ( ( uint8_t ) 0x01 )
 | 
			
		||||
 | 
			
		||||
/* Let the user override the pre-loading of the initial LR with the address of
 | 
			
		||||
/*
 | 
			
		||||
 * Let the user override the pre-loading of the initial LR with the address of
 | 
			
		||||
 * prvTaskExitError() in case is messes up unwinding of the stack in the
 | 
			
		||||
 * debugger. */
 | 
			
		||||
 * debugger.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef configTASK_RETURN_ADDRESS
 | 
			
		||||
    #define portTASK_RETURN_ADDRESS    configTASK_RETURN_ADDRESS
 | 
			
		||||
#else
 | 
			
		||||
    #define portTASK_RETURN_ADDRESS    prvTaskExitError
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT != 0 )
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The space on the stack required to hold the FPU registers.
 | 
			
		||||
 *
 | 
			
		||||
@ -160,7 +193,8 @@
 | 
			
		||||
 * the size of the bank remains the same. The FPU has also a 32-bit
 | 
			
		||||
 * status register.
 | 
			
		||||
 */
 | 
			
		||||
#define portFPU_REGISTER_WORDS    ( ( 16 * 2 ) + 1 )
 | 
			
		||||
    #define portFPU_REGISTER_WORDS    ( ( 16 * 2 ) + 1 )
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
@ -175,6 +209,8 @@ extern void vPortRestoreTaskContext( void );
 | 
			
		||||
 */
 | 
			
		||||
static void prvTaskExitError( void );
 | 
			
		||||
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT != 0 )
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * If the application provides an implementation of vApplicationIRQHandler(),
 | 
			
		||||
 * then it will get called directly without saving the FPU registers on
 | 
			
		||||
@ -194,26 +230,36 @@ static void prvTaskExitError( void );
 | 
			
		||||
 * FPU registers to be saved on interrupt entry their IRQ handler must be
 | 
			
		||||
 * called vApplicationIRQHandler().
 | 
			
		||||
 */
 | 
			
		||||
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) );
 | 
			
		||||
    void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__( ( weak ) );
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* A variable is used to keep track of the critical section nesting.  This
 | 
			
		||||
/*
 | 
			
		||||
 * A variable is used to keep track of the critical section nesting.  This
 | 
			
		||||
 * variable has to be 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
 | 
			
		||||
 * automatically be set to 0 when the first task is started. */
 | 
			
		||||
 * automatically be set to 0 when the first task is started.
 | 
			
		||||
 */
 | 
			
		||||
volatile uint32_t ulCriticalNesting = 9999UL;
 | 
			
		||||
 | 
			
		||||
/* Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then
 | 
			
		||||
 * a floating point context must be saved and restored for the task. */
 | 
			
		||||
uint32_t ulPortTaskHasFPUContext = pdFALSE;
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT != 0 )
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Saved as part of the task context.  If ulPortTaskHasFPUContext is non-zero then
 | 
			
		||||
 * a floating point context must be saved and restored for the task.
 | 
			
		||||
 */
 | 
			
		||||
    uint32_t ulPortTaskHasFPUContext = pdFALSE;
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 | 
			
		||||
 | 
			
		||||
/* Set to 1 to pend a context switch from an ISR. */
 | 
			
		||||
uint32_t ulPortYieldRequired = pdFALSE;
 | 
			
		||||
 | 
			
		||||
/* Counts the interrupt nesting depth.  A context switch is only performed if
 | 
			
		||||
 * if the nesting depth is 0. */
 | 
			
		||||
/*
 | 
			
		||||
 * Counts the interrupt nesting depth.  A context switch is only performed if
 | 
			
		||||
 * if the nesting depth is 0.
 | 
			
		||||
 */
 | 
			
		||||
uint32_t ulPortInterruptNesting = 0UL;
 | 
			
		||||
 | 
			
		||||
/* Used in asm code. */
 | 
			
		||||
@ -231,12 +277,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
 | 
			
		||||
                                     TaskFunction_t pxCode,
 | 
			
		||||
                                     void * pvParameters )
 | 
			
		||||
{
 | 
			
		||||
    /* Setup the initial stack of the task.  The stack is set exactly as
 | 
			
		||||
    /*
 | 
			
		||||
     * Setup the initial stack of the task.  The stack is set exactly as
 | 
			
		||||
     * expected by the portRESTORE_CONTEXT() macro.
 | 
			
		||||
     *
 | 
			
		||||
     * The fist real value on the stack is the status register, which is set for
 | 
			
		||||
     * system mode, with interrupts enabled.  A few NULLs are added first to ensure
 | 
			
		||||
     * GDB does not try decoding a non-existent return address. */
 | 
			
		||||
     * GDB does not try decoding a non-existent return address.
 | 
			
		||||
     */
 | 
			
		||||
    *pxTopOfStack = ( StackType_t ) NULL;
 | 
			
		||||
    pxTopOfStack--;
 | 
			
		||||
    *pxTopOfStack = ( StackType_t ) NULL;
 | 
			
		||||
@ -285,24 +333,31 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
 | 
			
		||||
    *pxTopOfStack = ( StackType_t ) 0x01010101;              /* R1 */
 | 
			
		||||
    pxTopOfStack--;
 | 
			
		||||
    *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0 */
 | 
			
		||||
    pxTopOfStack--;
 | 
			
		||||
 | 
			
		||||
    /* The task will start with a critical nesting count of 0 as interrupts are
 | 
			
		||||
     * enabled. */
 | 
			
		||||
    /*
 | 
			
		||||
     * The task will start with a critical nesting count of 0 as interrupts are
 | 
			
		||||
     * enabled.
 | 
			
		||||
     */
 | 
			
		||||
    pxTopOfStack--;
 | 
			
		||||
    *pxTopOfStack = portNO_CRITICAL_NESTING;
 | 
			
		||||
 | 
			
		||||
    #if( configUSE_TASK_FPU_SUPPORT == 1 )
 | 
			
		||||
    #if ( configUSE_TASK_FPU_SUPPORT == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        /* The task will start without a floating point context.  A task that
 | 
			
		||||
        uses the floating point hardware must call vPortTaskUsesFPU() before
 | 
			
		||||
        executing any floating point instructions. */
 | 
			
		||||
        /*
 | 
			
		||||
         * The task will start without a floating point context.
 | 
			
		||||
         * A task that uses the floating point hardware must call
 | 
			
		||||
         * vPortTaskUsesFPU() before executing any floating point
 | 
			
		||||
         * instructions.
 | 
			
		||||
         */
 | 
			
		||||
        pxTopOfStack--;
 | 
			
		||||
        *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
 | 
			
		||||
    }
 | 
			
		||||
    #elif( configUSE_TASK_FPU_SUPPORT == 2 )
 | 
			
		||||
    #elif ( configUSE_TASK_FPU_SUPPORT == 2 )
 | 
			
		||||
    {
 | 
			
		||||
        /* The task will start with a floating point context.  Leave enough
 | 
			
		||||
        space for the registers - and ensure they are initialized to 0. */
 | 
			
		||||
        /*
 | 
			
		||||
         * The task will start with a floating point context. Leave enough
 | 
			
		||||
         * space for the registers and ensure they are initialized to 0.
 | 
			
		||||
         */
 | 
			
		||||
        pxTopOfStack -= portFPU_REGISTER_WORDS;
 | 
			
		||||
        memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
 | 
			
		||||
 | 
			
		||||
@ -310,9 +365,9 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
 | 
			
		||||
        *pxTopOfStack = pdTRUE;
 | 
			
		||||
        ulPortTaskHasFPUContext = pdTRUE;
 | 
			
		||||
    }
 | 
			
		||||
    #else
 | 
			
		||||
    #elif ( configUSE_TASK_FPU_SUPPORT != 0 )
 | 
			
		||||
    {
 | 
			
		||||
        #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined.
 | 
			
		||||
        #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 0, 1, or 2.
 | 
			
		||||
    }
 | 
			
		||||
    #endif /* configUSE_TASK_FPU_SUPPORT */
 | 
			
		||||
 | 
			
		||||
@ -322,12 +377,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
 | 
			
		||||
 | 
			
		||||
static void prvTaskExitError( void )
 | 
			
		||||
{
 | 
			
		||||
    /* A function that implements a task must not exit or attempt to return to
 | 
			
		||||
    /*
 | 
			
		||||
     * 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. */
 | 
			
		||||
     * defined, then stop here so application writers can catch the error.
 | 
			
		||||
     */
 | 
			
		||||
    configASSERT( ulPortInterruptNesting == ~0UL );
 | 
			
		||||
    portDISABLE_INTERRUPTS();
 | 
			
		||||
 | 
			
		||||
@ -337,11 +394,15 @@ static void prvTaskExitError( void )
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR )
 | 
			
		||||
{
 | 
			
		||||
    ( void ) ulICCIAR;
 | 
			
		||||
    configASSERT( ( volatile void * ) NULL );
 | 
			
		||||
}
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT != 0 )
 | 
			
		||||
 | 
			
		||||
    void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) /* __attribute__( ( weak ) ) */
 | 
			
		||||
    {
 | 
			
		||||
        ( void ) ulICCIAR;
 | 
			
		||||
        configASSERT( ( volatile void * ) NULL );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
BaseType_t xPortStartScheduler( void )
 | 
			
		||||
@ -349,67 +410,82 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
    uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
 | 
			
		||||
 | 
			
		||||
    #if ( configASSERT_DEFINED == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        volatile uint32_t ulOriginalPriority;
 | 
			
		||||
        volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
 | 
			
		||||
        volatile uint8_t ucMaxPriorityValue;
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Determine how many priority bits are implemented in the GIC.
 | 
			
		||||
         * Save the interrupt priority value that is about to be clobbered.
 | 
			
		||||
         */
 | 
			
		||||
        ulOriginalPriority = *pucFirstUserPriorityRegister;
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Determine the number of priority bits available.  First write to
 | 
			
		||||
         * all possible bits.
 | 
			
		||||
         */
 | 
			
		||||
        *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
 | 
			
		||||
 | 
			
		||||
        /* Read the value back to see how many bits stuck. */
 | 
			
		||||
        ucMaxPriorityValue = *pucFirstUserPriorityRegister;
 | 
			
		||||
 | 
			
		||||
        /* Shift to the least significant bits. */
 | 
			
		||||
        while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
 | 
			
		||||
        {
 | 
			
		||||
            volatile uint32_t ulOriginalPriority;
 | 
			
		||||
            volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
 | 
			
		||||
            volatile uint8_t ucMaxPriorityValue;
 | 
			
		||||
            ucMaxPriorityValue >>= ( uint8_t ) 0x01;
 | 
			
		||||
 | 
			
		||||
            /* Determine how many priority bits are implemented in the GIC.
 | 
			
		||||
             *
 | 
			
		||||
             * Save the interrupt priority value that is about to be clobbered. */
 | 
			
		||||
            ulOriginalPriority = *pucFirstUserPriorityRegister;
 | 
			
		||||
            /*
 | 
			
		||||
             * If ulCycles reaches 0 then ucMaxPriorityValue must have been
 | 
			
		||||
             * read as 0, indicating a misconfiguration.
 | 
			
		||||
             */
 | 
			
		||||
            ulCycles--;
 | 
			
		||||
 | 
			
		||||
            /* Determine the number of priority bits available.  First write to
 | 
			
		||||
             * all possible bits. */
 | 
			
		||||
            *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
 | 
			
		||||
 | 
			
		||||
            /* Read the value back to see how many bits stuck. */
 | 
			
		||||
            ucMaxPriorityValue = *pucFirstUserPriorityRegister;
 | 
			
		||||
 | 
			
		||||
            /* Shift to the least significant bits. */
 | 
			
		||||
            while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET )
 | 
			
		||||
            if( ulCycles == 0 )
 | 
			
		||||
            {
 | 
			
		||||
                ucMaxPriorityValue >>= ( uint8_t ) 0x01;
 | 
			
		||||
 | 
			
		||||
                /* If ulCycles reaches 0 then ucMaxPriorityValue must have been
 | 
			
		||||
                 * read as 0, indicating a misconfiguration. */
 | 
			
		||||
                ulCycles--;
 | 
			
		||||
 | 
			
		||||
                if( ulCycles == 0 )
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
 | 
			
		||||
             * value. */
 | 
			
		||||
            configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
 | 
			
		||||
 | 
			
		||||
            /* Restore the clobbered interrupt priority register to its original
 | 
			
		||||
             * value. */
 | 
			
		||||
            *pucFirstUserPriorityRegister = ulOriginalPriority;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
 | 
			
		||||
         * value.
 | 
			
		||||
         */
 | 
			
		||||
        configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
         * Restore the clobbered interrupt priority register to its original
 | 
			
		||||
         * value.
 | 
			
		||||
         */
 | 
			
		||||
        *pucFirstUserPriorityRegister = ulOriginalPriority;
 | 
			
		||||
    }
 | 
			
		||||
    #endif /* configASSERT_DEFINED */
 | 
			
		||||
 | 
			
		||||
    /* Only continue if the CPU is not in User mode.  The CPU must be in a
 | 
			
		||||
     * Privileged mode for the scheduler to start. */
 | 
			
		||||
    /*
 | 
			
		||||
     * Only continue if the CPU is not in User mode.  The CPU must be in a
 | 
			
		||||
     * Privileged mode for the scheduler to start.
 | 
			
		||||
     */
 | 
			
		||||
    __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
 | 
			
		||||
    ulAPSR &= portAPSR_MODE_BITS_MASK;
 | 
			
		||||
    configASSERT( ulAPSR != portAPSR_USER_MODE );
 | 
			
		||||
 | 
			
		||||
    if( ulAPSR != portAPSR_USER_MODE )
 | 
			
		||||
    {
 | 
			
		||||
        /* Only continue if the binary point value is set to its lowest possible
 | 
			
		||||
        /*
 | 
			
		||||
         * Only continue if the binary point value is set to its lowest possible
 | 
			
		||||
         * setting.  See the comments in vPortValidateInterruptPriority() below for
 | 
			
		||||
         * more information. */
 | 
			
		||||
         * more information.
 | 
			
		||||
         */
 | 
			
		||||
        configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
 | 
			
		||||
 | 
			
		||||
        if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
 | 
			
		||||
        {
 | 
			
		||||
            /* Interrupts are turned off in the CPU itself to ensure tick does
 | 
			
		||||
            /*
 | 
			
		||||
             * Interrupts are turned off in the CPU itself to ensure tick does
 | 
			
		||||
             * not execute  while the scheduler is being started.  Interrupts are
 | 
			
		||||
             * automatically turned back on in the CPU when the first task starts
 | 
			
		||||
             * executing. */
 | 
			
		||||
             * executing.
 | 
			
		||||
             */
 | 
			
		||||
            portCPU_IRQ_DISABLE();
 | 
			
		||||
 | 
			
		||||
            /* Start the timer that generates the tick ISR. */
 | 
			
		||||
@ -420,20 +496,25 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Will only get here if vTaskStartScheduler() was called with the CPU in
 | 
			
		||||
    /*
 | 
			
		||||
     * 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. */
 | 
			
		||||
     * defines their own exit address.
 | 
			
		||||
     */
 | 
			
		||||
    ( void ) prvTaskExitError;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortEndScheduler( void )
 | 
			
		||||
{
 | 
			
		||||
    /* Not implemented in ports where there is nothing to return to.
 | 
			
		||||
     * Artificially force an assert. */
 | 
			
		||||
    /*
 | 
			
		||||
     * Not implemented in ports where there is nothing to return to.
 | 
			
		||||
     * Artificially force an assert.
 | 
			
		||||
     */
 | 
			
		||||
    configASSERT( ulCriticalNesting == 1000UL );
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
@ -443,16 +524,20 @@ void vPortEnterCritical( void )
 | 
			
		||||
    /* Mask interrupts up to the max syscall interrupt priority. */
 | 
			
		||||
    ulPortSetInterruptMask();
 | 
			
		||||
 | 
			
		||||
    /* Now interrupts are disabled ulCriticalNesting can be accessed
 | 
			
		||||
    /*
 | 
			
		||||
     * Now interrupts are disabled ulCriticalNesting can be accessed
 | 
			
		||||
     * directly.  Increment ulCriticalNesting to keep a count of how many times
 | 
			
		||||
     * portENTER_CRITICAL() has been called. */
 | 
			
		||||
     * portENTER_CRITICAL() has been called.
 | 
			
		||||
     */
 | 
			
		||||
    ulCriticalNesting++;
 | 
			
		||||
 | 
			
		||||
    /* This is not the interrupt safe version of the enter critical function so
 | 
			
		||||
    /*
 | 
			
		||||
     * 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. */
 | 
			
		||||
     * assert function also uses a critical section.
 | 
			
		||||
     */
 | 
			
		||||
    if( ulCriticalNesting == 1 )
 | 
			
		||||
    {
 | 
			
		||||
        configASSERT( ulPortInterruptNesting == 0 );
 | 
			
		||||
@ -464,16 +549,19 @@ void vPortExitCritical( void )
 | 
			
		||||
{
 | 
			
		||||
    if( ulCriticalNesting > portNO_CRITICAL_NESTING )
 | 
			
		||||
    {
 | 
			
		||||
        /* Decrement the nesting count as the critical section is being
 | 
			
		||||
         * exited. */
 | 
			
		||||
        /* 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 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. */
 | 
			
		||||
            /*
 | 
			
		||||
             * Critical nesting has reached zero so all interrupt priorities
 | 
			
		||||
             * should be unmasked.
 | 
			
		||||
             */
 | 
			
		||||
            portCLEAR_INTERRUPT_MASK();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -482,11 +570,13 @@ void vPortExitCritical( void )
 | 
			
		||||
 | 
			
		||||
void FreeRTOS_Tick_Handler( void )
 | 
			
		||||
{
 | 
			
		||||
    /* Set interrupt mask before altering scheduler structures.   The tick
 | 
			
		||||
    /*
 | 
			
		||||
     * Set interrupt mask before altering scheduler structures.   The tick
 | 
			
		||||
     * handler runs at the lowest priority, so interrupts cannot already be masked,
 | 
			
		||||
     * so there is no need to save and restore the current mask value.  It is
 | 
			
		||||
     * necessary to turn off interrupts in the CPU itself while the ICCPMR is being
 | 
			
		||||
     * updated. */
 | 
			
		||||
     * updated.
 | 
			
		||||
     */
 | 
			
		||||
    portCPU_IRQ_DISABLE();
 | 
			
		||||
    portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
 | 
			
		||||
    __asm volatile ( "dsb       \n"
 | 
			
		||||
@ -505,21 +595,23 @@ void FreeRTOS_Tick_Handler( void )
 | 
			
		||||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT == 1 )
 | 
			
		||||
 | 
			
		||||
    void vPortTaskUsesFPU( void )
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t ulInitialFPSCR = 0;
 | 
			
		||||
 | 
			
		||||
        /* A task is registering the fact that it needs an FPU context.  Set the
 | 
			
		||||
         * FPU flag (which is saved as part of the task context). */
 | 
			
		||||
        /*
 | 
			
		||||
         * A task is registering the fact that it needs an FPU context. Set the
 | 
			
		||||
         * FPU flag (which is saved as part of the task context).
 | 
			
		||||
         */
 | 
			
		||||
        ulPortTaskHasFPUContext = pdTRUE;
 | 
			
		||||
 | 
			
		||||
        /* Initialise the floating point status register. */
 | 
			
		||||
        __asm volatile ( "FMXR  FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT */
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT == 1 */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
 | 
			
		||||
@ -535,8 +627,7 @@ uint32_t ulPortSetInterruptMask( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulReturn;
 | 
			
		||||
 | 
			
		||||
    /* Interrupt in the CPU must be turned off while the ICCPMR is being
 | 
			
		||||
     * updated. */
 | 
			
		||||
    /* Interrupts must be masked while ICCPMR is updated. */
 | 
			
		||||
    portCPU_IRQ_DISABLE();
 | 
			
		||||
 | 
			
		||||
    if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
 | 
			
		||||
@ -562,7 +653,8 @@ uint32_t ulPortSetInterruptMask( void )
 | 
			
		||||
 | 
			
		||||
    void vPortValidateInterruptPriority( void )
 | 
			
		||||
    {
 | 
			
		||||
        /* The following assertion will fail if a service routine (ISR) for
 | 
			
		||||
        /*
 | 
			
		||||
         * The following assertion will fail if a service routine (ISR) for
 | 
			
		||||
         * an interrupt that has been assigned a priority above
 | 
			
		||||
         * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
 | 
			
		||||
         * function.  ISR safe FreeRTOS API functions must *only* be called
 | 
			
		||||
@ -575,11 +667,13 @@ uint32_t ulPortSetInterruptMask( void )
 | 
			
		||||
         * configMAX_SYSCALL_INTERRUPT_PRIORITY.
 | 
			
		||||
         *
 | 
			
		||||
         * FreeRTOS maintains separate thread and ISR API functions to ensure
 | 
			
		||||
         * interrupt entry is as fast and simple as possible. */
 | 
			
		||||
         * interrupt entry is as fast and simple as possible.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
        configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
 | 
			
		||||
 | 
			
		||||
        /* Priority grouping:  The interrupt controller (GIC) allows the bits
 | 
			
		||||
        /*
 | 
			
		||||
         * Priority grouping:  The interrupt controller (GIC) allows the bits
 | 
			
		||||
         * that define each interrupt's priority to be split between bits that
 | 
			
		||||
         * define the interrupt's pre-emption priority bits and bits that define
 | 
			
		||||
         * the interrupt's sub-priority.  For simplicity all bits must be defined
 | 
			
		||||
@ -588,7 +682,8 @@ uint32_t ulPortSetInterruptMask( void )
 | 
			
		||||
         *
 | 
			
		||||
         * The priority grouping is configured by the GIC's binary point register
 | 
			
		||||
         * (ICCBPR).  Writing 0 to ICCBPR will ensure it is set to its lowest
 | 
			
		||||
         * possible value (which may be above 0). */
 | 
			
		||||
         * possible value (which may be above 0).
 | 
			
		||||
         */
 | 
			
		||||
        configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,10 @@
 | 
			
		||||
    .extern vTaskSwitchContext
 | 
			
		||||
    .extern vApplicationIRQHandler
 | 
			
		||||
    .extern ulPortInterruptNesting
 | 
			
		||||
 | 
			
		||||
#if defined( __ARM_FP )
 | 
			
		||||
    .extern ulPortTaskHasFPUContext
 | 
			
		||||
#endif /* __ARM_FP */
 | 
			
		||||
 | 
			
		||||
    .global FreeRTOS_IRQ_Handler
 | 
			
		||||
    .global FreeRTOS_SWI_Handler
 | 
			
		||||
@ -64,20 +67,21 @@
 | 
			
		||||
    LDR     R1, [R2]
 | 
			
		||||
    PUSH    {R1}
 | 
			
		||||
 | 
			
		||||
    /* Does the task have a floating point context that needs saving?  If
 | 
			
		||||
    ulPortTaskHasFPUContext is 0 then no. */
 | 
			
		||||
    LDR     R2, ulPortTaskHasFPUContextConst
 | 
			
		||||
    LDR     R3, [R2]
 | 
			
		||||
    CMP     R3, #0
 | 
			
		||||
    #if defined( __ARM_FP )
 | 
			
		||||
        /* Does the task have a floating point context that needs saving?  If
 | 
			
		||||
        ulPortTaskHasFPUContext is 0 then no. */
 | 
			
		||||
        LDR     R2, ulPortTaskHasFPUContextConst
 | 
			
		||||
        LDR     R3, [R2]
 | 
			
		||||
        CMP     R3, #0
 | 
			
		||||
 | 
			
		||||
    /* Save the floating point context, if any. */
 | 
			
		||||
    FMRXNE  R1,  FPSCR
 | 
			
		||||
    VPUSHNE {D0-D15}
 | 
			
		||||
    /*VPUSHNE   {D16-D31}*/
 | 
			
		||||
    PUSHNE  {R1}
 | 
			
		||||
        /* Save the floating point context, if any. */
 | 
			
		||||
        FMRXNE  R1,  FPSCR
 | 
			
		||||
        VPUSHNE {D0-D15}
 | 
			
		||||
        PUSHNE  {R1}
 | 
			
		||||
 | 
			
		||||
    /* Save ulPortTaskHasFPUContext itself. */
 | 
			
		||||
    PUSH    {R3}
 | 
			
		||||
        /* Save ulPortTaskHasFPUContext itself. */
 | 
			
		||||
        PUSH    {R3}
 | 
			
		||||
    #endif /* __ARM_FP */
 | 
			
		||||
 | 
			
		||||
    /* Save the stack pointer in the TCB. */
 | 
			
		||||
    LDR     R0, pxCurrentTCBConst
 | 
			
		||||
@ -95,18 +99,21 @@
 | 
			
		||||
    LDR     R1, [R0]
 | 
			
		||||
    LDR     SP, [R1]
 | 
			
		||||
 | 
			
		||||
    /* Is there a floating point context to restore?  If the restored
 | 
			
		||||
    ulPortTaskHasFPUContext is zero then no. */
 | 
			
		||||
    LDR     R0, ulPortTaskHasFPUContextConst
 | 
			
		||||
    POP     {R1}
 | 
			
		||||
    STR     R1, [R0]
 | 
			
		||||
    CMP     R1, #0
 | 
			
		||||
    #if defined( __ARM_FP )
 | 
			
		||||
        /*
 | 
			
		||||
         * Is there a floating point context to restore?  If the restored
 | 
			
		||||
         * ulPortTaskHasFPUContext is zero then no.
 | 
			
		||||
         */
 | 
			
		||||
        LDR     R0, ulPortTaskHasFPUContextConst
 | 
			
		||||
        POP     {R1}
 | 
			
		||||
        STR     R1, [R0]
 | 
			
		||||
        CMP     R1, #0
 | 
			
		||||
 | 
			
		||||
    /* Restore the floating point context, if any. */
 | 
			
		||||
    POPNE   {R0}
 | 
			
		||||
    /*VPOPNE    {D16-D31}*/
 | 
			
		||||
    VPOPNE  {D0-D15}
 | 
			
		||||
    VMSRNE  FPSCR, R0
 | 
			
		||||
        /* Restore the floating point context, if any. */
 | 
			
		||||
        POPNE   {R0}
 | 
			
		||||
        VPOPNE  {D0-D15}
 | 
			
		||||
        VMSRNE  FPSCR, R0
 | 
			
		||||
    #endif /* __ARM_FP */
 | 
			
		||||
 | 
			
		||||
    /* Restore the critical section nesting depth. */
 | 
			
		||||
    LDR     R0, ulCriticalNestingConst
 | 
			
		||||
@ -132,8 +139,6 @@
 | 
			
		||||
    .endm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 * SVC handler is used to start the scheduler.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
@ -279,22 +284,25 @@ switch_before_exit:
 | 
			
		||||
 * FPU registers to be saved on interrupt entry their IRQ handler must be
 | 
			
		||||
 * called vApplicationIRQHandler().
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
.align 4
 | 
			
		||||
.weak vApplicationIRQHandler
 | 
			
		||||
.type vApplicationIRQHandler, %function
 | 
			
		||||
vApplicationIRQHandler:
 | 
			
		||||
 | 
			
		||||
    PUSH    {LR}
 | 
			
		||||
    FMRX    R1,  FPSCR
 | 
			
		||||
    VPUSH   {D0-D15}
 | 
			
		||||
    PUSH    {R1}
 | 
			
		||||
 | 
			
		||||
    LDR     r1, vApplicationFPUSafeIRQHandlerConst
 | 
			
		||||
    BLX     r1
 | 
			
		||||
    #if defined( __ARM_FP )
 | 
			
		||||
        FMRX    R1,  FPSCR
 | 
			
		||||
        VPUSH   {D0-D15}
 | 
			
		||||
        PUSH    {R1}
 | 
			
		||||
 | 
			
		||||
    POP     {R0}
 | 
			
		||||
    VPOP    {D0-D15}
 | 
			
		||||
    VMSR    FPSCR, R0
 | 
			
		||||
        LDR     r1, vApplicationFPUSafeIRQHandlerConst
 | 
			
		||||
        BLX     r1
 | 
			
		||||
 | 
			
		||||
        POP     {R0}
 | 
			
		||||
        VPOP    {D0-D15}
 | 
			
		||||
        VMSR    FPSCR, R0
 | 
			
		||||
    #endif /* __ARM_FP */
 | 
			
		||||
 | 
			
		||||
    POP {PC}
 | 
			
		||||
 | 
			
		||||
@ -303,11 +311,15 @@ ulICCEOIRConst: .word ulICCEOIR
 | 
			
		||||
ulICCPMRConst: .word ulICCPMR
 | 
			
		||||
pxCurrentTCBConst: .word pxCurrentTCB
 | 
			
		||||
ulCriticalNestingConst: .word ulCriticalNesting
 | 
			
		||||
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
 | 
			
		||||
 | 
			
		||||
#if defined( __ARM_FP )
 | 
			
		||||
    ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
 | 
			
		||||
    vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
 | 
			
		||||
#endif /* __ARM_FP */
 | 
			
		||||
 | 
			
		||||
ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
 | 
			
		||||
vTaskSwitchContextConst: .word vTaskSwitchContext
 | 
			
		||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
 | 
			
		||||
ulPortInterruptNestingConst: .word ulPortInterruptNesting
 | 
			
		||||
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
 | 
			
		||||
 | 
			
		||||
.end
 | 
			
		||||
 | 
			
		||||
@ -27,11 +27,13 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef PORTMACRO_H
 | 
			
		||||
    #define PORTMACRO_H
 | 
			
		||||
#define PORTMACRO_H
 | 
			
		||||
 | 
			
		||||
    #ifdef __cplusplus
 | 
			
		||||
        extern "C" {
 | 
			
		||||
    #endif
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
    extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
/* *INDENT-ON* */
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------
 | 
			
		||||
 * Port specific definitions.
 | 
			
		||||
@ -44,161 +46,175 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Type definitions. */
 | 
			
		||||
    #define portCHAR          char
 | 
			
		||||
    #define portFLOAT         float
 | 
			
		||||
    #define portDOUBLE        double
 | 
			
		||||
    #define portLONG          long
 | 
			
		||||
    #define portSHORT         short
 | 
			
		||||
    #define portSTACK_TYPE    uint32_t
 | 
			
		||||
    #define portBASE_TYPE     long
 | 
			
		||||
#define portCHAR          char
 | 
			
		||||
#define portFLOAT         float
 | 
			
		||||
#define portDOUBLE        double
 | 
			
		||||
#define portLONG          long
 | 
			
		||||
#define portSHORT         short
 | 
			
		||||
#define portSTACK_TYPE    uint32_t
 | 
			
		||||
#define portBASE_TYPE     long
 | 
			
		||||
 | 
			
		||||
    typedef portSTACK_TYPE   StackType_t;
 | 
			
		||||
    typedef long             BaseType_t;
 | 
			
		||||
    typedef unsigned long    UBaseType_t;
 | 
			
		||||
typedef portSTACK_TYPE   StackType_t;
 | 
			
		||||
typedef long             BaseType_t;
 | 
			
		||||
typedef unsigned long    UBaseType_t;
 | 
			
		||||
 | 
			
		||||
    typedef uint32_t         TickType_t;
 | 
			
		||||
    #define portMAX_DELAY    ( TickType_t ) 0xffffffffUL
 | 
			
		||||
typedef uint32_t         TickType_t;
 | 
			
		||||
#define portMAX_DELAY    ( TickType_t ) 0xffffffffUL
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Hardware specifics. */
 | 
			
		||||
    #define portSTACK_GROWTH      ( -1 )
 | 
			
		||||
    #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
 | 
			
		||||
    #define portBYTE_ALIGNMENT    8
 | 
			
		||||
#define portSTACK_GROWTH      ( -1 )
 | 
			
		||||
#define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
 | 
			
		||||
#define portBYTE_ALIGNMENT    8
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Task utilities. */
 | 
			
		||||
 | 
			
		||||
/* Called at the end of an ISR that can cause a context switch. */
 | 
			
		||||
    #define portEND_SWITCHING_ISR( xSwitchRequired ) \
 | 
			
		||||
    {                                                \
 | 
			
		||||
        extern uint32_t ulPortYieldRequired;         \
 | 
			
		||||
                                                     \
 | 
			
		||||
        if( xSwitchRequired != pdFALSE )             \
 | 
			
		||||
        {                                            \
 | 
			
		||||
            ulPortYieldRequired = pdTRUE;            \
 | 
			
		||||
        }                                            \
 | 
			
		||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
 | 
			
		||||
    {                                            \
 | 
			
		||||
        extern uint32_t ulPortYieldRequired;     \
 | 
			
		||||
                                                 \
 | 
			
		||||
        if( xSwitchRequired != pdFALSE )         \
 | 
			
		||||
        {                                        \
 | 
			
		||||
            ulPortYieldRequired = pdTRUE;        \
 | 
			
		||||
        }                                        \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #define portYIELD_FROM_ISR( x )    portEND_SWITCHING_ISR( x )
 | 
			
		||||
    #define portYIELD()                __asm volatile ( "SWI 0" ::: "memory" );
 | 
			
		||||
#define portYIELD_FROM_ISR( x )    portEND_SWITCHING_ISR( x )
 | 
			
		||||
#define portYIELD()                __asm volatile ( "SWI 0" ::: "memory" );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------
 | 
			
		||||
* Critical section control
 | 
			
		||||
*----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
    extern void vPortEnterCritical( void );
 | 
			
		||||
    extern void vPortExitCritical( void );
 | 
			
		||||
    extern uint32_t ulPortSetInterruptMask( void );
 | 
			
		||||
    extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
 | 
			
		||||
    extern void vPortInstallFreeRTOSVectorTable( void );
 | 
			
		||||
extern void vPortEnterCritical( void );
 | 
			
		||||
extern void vPortExitCritical( void );
 | 
			
		||||
extern uint32_t ulPortSetInterruptMask( void );
 | 
			
		||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
 | 
			
		||||
extern void vPortInstallFreeRTOSVectorTable( void );
 | 
			
		||||
 | 
			
		||||
/* These macros do not globally disable/enable interrupts.  They do mask off
 | 
			
		||||
 * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
 | 
			
		||||
    #define portENTER_CRITICAL()                      vPortEnterCritical();
 | 
			
		||||
    #define portEXIT_CRITICAL()                       vPortExitCritical();
 | 
			
		||||
    #define portDISABLE_INTERRUPTS()                  ulPortSetInterruptMask()
 | 
			
		||||
    #define portENABLE_INTERRUPTS()                   vPortClearInterruptMask( 0 )
 | 
			
		||||
    #define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortSetInterruptMask()
 | 
			
		||||
    #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortClearInterruptMask( x )
 | 
			
		||||
/*
 | 
			
		||||
 * These macros do not globally disable/enable interrupts. They do mask off
 | 
			
		||||
 * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY.
 | 
			
		||||
 */
 | 
			
		||||
#define portENTER_CRITICAL()                      vPortEnterCritical();
 | 
			
		||||
#define portEXIT_CRITICAL()                       vPortExitCritical();
 | 
			
		||||
#define portDISABLE_INTERRUPTS()                  ulPortSetInterruptMask()
 | 
			
		||||
#define portENABLE_INTERRUPTS()                   vPortClearInterruptMask( 0 )
 | 
			
		||||
#define portSET_INTERRUPT_MASK_FROM_ISR()         ulPortSetInterruptMask()
 | 
			
		||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    vPortClearInterruptMask( x )
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/* Task function macros as described on the FreeRTOS.org WEB site.  These are
 | 
			
		||||
/*
 | 
			
		||||
 * Task function macros as described on the FreeRTOS.org WEB site.  These are
 | 
			
		||||
 * not required for this port but included in case common demo code that uses these
 | 
			
		||||
 * macros is used. */
 | 
			
		||||
    #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
 | 
			
		||||
    #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
 | 
			
		||||
 * macros is used.
 | 
			
		||||
 */
 | 
			
		||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
 | 
			
		||||
#define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
 | 
			
		||||
 | 
			
		||||
/* Prototype of the FreeRTOS tick handler.  This must be installed as the
 | 
			
		||||
 * handler for whichever peripheral is used to generate the RTOS tick. */
 | 
			
		||||
    void FreeRTOS_Tick_Handler( void );
 | 
			
		||||
/*
 | 
			
		||||
 * Prototype of the FreeRTOS tick handler.  This must be installed as the
 | 
			
		||||
 * handler for whichever peripheral is used to generate the RTOS tick.
 | 
			
		||||
 */
 | 
			
		||||
void FreeRTOS_Tick_Handler( void );
 | 
			
		||||
 | 
			
		||||
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
 | 
			
		||||
created without an FPU context and must call vPortTaskUsesFPU() to give
 | 
			
		||||
themselves an FPU context before using any FPU instructions. If
 | 
			
		||||
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
 | 
			
		||||
by default. */
 | 
			
		||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
 | 
			
		||||
/*
 | 
			
		||||
 * If configUSE_TASK_FPU_SUPPORT is set to 1, then tasks are created without an
 | 
			
		||||
 * FPU context and must call vPortTaskUsesFPU() to allocate an FPU context
 | 
			
		||||
 * prior to any FPU instructions. If configUSE_TASK_FPU_SUPPORT is set to 2,
 | 
			
		||||
 * then all tasks have an FPU context allocated by default.
 | 
			
		||||
 */
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT == 1 )
 | 
			
		||||
    void vPortTaskUsesFPU( void );
 | 
			
		||||
#else
 | 
			
		||||
    /* Each task has an FPU context already, so define this function away to
 | 
			
		||||
    nothing to prevent it being called accidentally. */
 | 
			
		||||
    #define vPortTaskUsesFPU()
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT */
 | 
			
		||||
    #define portTASK_USES_FLOATING_POINT()    vPortTaskUsesFPU()
 | 
			
		||||
#elif ( configUSE_TASK_FPU_SUPPORT == 2 )
 | 
			
		||||
 | 
			
		||||
    #define portLOWEST_INTERRUPT_PRIORITY           ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
 | 
			
		||||
    #define portLOWEST_USABLE_INTERRUPT_PRIORITY    ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
 | 
			
		||||
/*
 | 
			
		||||
 * Each task has an FPU context already, so define this function away to
 | 
			
		||||
 * prevent it being called accidentally.
 | 
			
		||||
 */
 | 
			
		||||
    #define vPortTaskUsesFPU()
 | 
			
		||||
    #define portTASK_USES_FLOATING_POINT()
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT */
 | 
			
		||||
 | 
			
		||||
#define portLOWEST_INTERRUPT_PRIORITY           ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
 | 
			
		||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY    ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
 | 
			
		||||
 | 
			
		||||
/* Architecture specific optimisations. */
 | 
			
		||||
    #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
 | 
			
		||||
        #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
 | 
			
		||||
    #endif
 | 
			
		||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
 | 
			
		||||
    #define configUSE_PORT_OPTIMISED_TASK_SELECTION    1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
 | 
			
		||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
 | 
			
		||||
 | 
			
		||||
/* Store/clear the ready priorities in a bit map. */
 | 
			
		||||
        #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )    ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
 | 
			
		||||
        #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )     ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
 | 
			
		||||
    #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities )    ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
 | 
			
		||||
    #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities )     ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
 | 
			
		||||
    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
 | 
			
		||||
 | 
			
		||||
    #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 | 
			
		||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 | 
			
		||||
 | 
			
		||||
    #ifdef configASSERT
 | 
			
		||||
        void vPortValidateInterruptPriority( void );
 | 
			
		||||
        #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()    vPortValidateInterruptPriority()
 | 
			
		||||
    #endif /* configASSERT */
 | 
			
		||||
#ifdef configASSERT
 | 
			
		||||
    void vPortValidateInterruptPriority( void );
 | 
			
		||||
    #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()    vPortValidateInterruptPriority()
 | 
			
		||||
#endif /* configASSERT */
 | 
			
		||||
 | 
			
		||||
    #define portNOP()                                         __asm volatile ( "NOP" )
 | 
			
		||||
#define portNOP()                                         __asm volatile ( "NOP" )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #ifdef __cplusplus
 | 
			
		||||
        } /* extern C */
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* The number of bits to shift for an interrupt priority is dependent on the
 | 
			
		||||
 * number of bits implemented by the interrupt controller. */
 | 
			
		||||
    #if configUNIQUE_INTERRUPT_PRIORITIES == 16
 | 
			
		||||
        #define portPRIORITY_SHIFT            4
 | 
			
		||||
        #define portMAX_BINARY_POINT_VALUE    3
 | 
			
		||||
    #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
 | 
			
		||||
        #define portPRIORITY_SHIFT            3
 | 
			
		||||
        #define portMAX_BINARY_POINT_VALUE    2
 | 
			
		||||
    #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
 | 
			
		||||
        #define portPRIORITY_SHIFT            2
 | 
			
		||||
        #define portMAX_BINARY_POINT_VALUE    1
 | 
			
		||||
    #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
 | 
			
		||||
        #define portPRIORITY_SHIFT            1
 | 
			
		||||
        #define portMAX_BINARY_POINT_VALUE    0
 | 
			
		||||
    #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
 | 
			
		||||
        #define portPRIORITY_SHIFT            0
 | 
			
		||||
        #define portMAX_BINARY_POINT_VALUE    0
 | 
			
		||||
    #else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
 | 
			
		||||
        #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting.  configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
 | 
			
		||||
    #endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
 | 
			
		||||
/*
 | 
			
		||||
 * The number of bits to shift for an interrupt priority is dependent on the
 | 
			
		||||
 * number of bits implemented by the interrupt controller.
 | 
			
		||||
 */
 | 
			
		||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
 | 
			
		||||
    #define portPRIORITY_SHIFT            4
 | 
			
		||||
    #define portMAX_BINARY_POINT_VALUE    3
 | 
			
		||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
 | 
			
		||||
    #define portPRIORITY_SHIFT            3
 | 
			
		||||
    #define portMAX_BINARY_POINT_VALUE    2
 | 
			
		||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
 | 
			
		||||
    #define portPRIORITY_SHIFT            2
 | 
			
		||||
    #define portMAX_BINARY_POINT_VALUE    1
 | 
			
		||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
 | 
			
		||||
    #define portPRIORITY_SHIFT            1
 | 
			
		||||
    #define portMAX_BINARY_POINT_VALUE    0
 | 
			
		||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
 | 
			
		||||
    #define portPRIORITY_SHIFT            0
 | 
			
		||||
    #define portMAX_BINARY_POINT_VALUE    0
 | 
			
		||||
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
 | 
			
		||||
    #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting.  configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
 | 
			
		||||
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
 | 
			
		||||
 | 
			
		||||
/* Interrupt controller access addresses. */
 | 
			
		||||
    #define portICCPMR_PRIORITY_MASK_OFFSET                      ( 0x04 )
 | 
			
		||||
    #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET              ( 0x0C )
 | 
			
		||||
    #define portICCEOIR_END_OF_INTERRUPT_OFFSET                  ( 0x10 )
 | 
			
		||||
    #define portICCBPR_BINARY_POINT_OFFSET                       ( 0x08 )
 | 
			
		||||
    #define portICCRPR_RUNNING_PRIORITY_OFFSET                   ( 0x14 )
 | 
			
		||||
#define portICCPMR_PRIORITY_MASK_OFFSET                      ( 0x04 )
 | 
			
		||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET              ( 0x0C )
 | 
			
		||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET                  ( 0x10 )
 | 
			
		||||
#define portICCBPR_BINARY_POINT_OFFSET                       ( 0x08 )
 | 
			
		||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET                   ( 0x14 )
 | 
			
		||||
 | 
			
		||||
    #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS       ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
 | 
			
		||||
    #define portICCPMR_PRIORITY_MASK_REGISTER                    ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
 | 
			
		||||
    #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS    ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
 | 
			
		||||
    #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS        ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
 | 
			
		||||
    #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS            ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
 | 
			
		||||
    #define portICCBPR_BINARY_POINT_REGISTER                     ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
 | 
			
		||||
    #define portICCRPR_RUNNING_PRIORITY_REGISTER                 ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
 | 
			
		||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS       ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
 | 
			
		||||
#define portICCPMR_PRIORITY_MASK_REGISTER                    ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
 | 
			
		||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS    ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
 | 
			
		||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS        ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
 | 
			
		||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS            ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
 | 
			
		||||
#define portICCBPR_BINARY_POINT_REGISTER                     ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
 | 
			
		||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER                 ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
 | 
			
		||||
 | 
			
		||||
    #define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )
 | 
			
		||||
#define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )
 | 
			
		||||
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
    } /* extern C */
 | 
			
		||||
#endif
 | 
			
		||||
/* *INDENT-ON* */
 | 
			
		||||
 | 
			
		||||
#endif /* PORTMACRO_H */
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user