mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-11-03 18:22:45 -05:00 
			
		
		
		
	Merge branch 'main' into posix_port
This commit is contained in:
		
						commit
						18f62681ef
					
				
					 3 changed files with 308 additions and 148 deletions
				
			
		| 
						 | 
				
			
			@ -28,6 +28,7 @@
 | 
			
		|||
 | 
			
		||||
/* Standard includes. */
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
/* Scheduler includes. */
 | 
			
		||||
#include "FreeRTOS.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -80,13 +81,22 @@
 | 
			
		|||
    #define portTASK_RETURN_ADDRESS    prvTaskExitError
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The space on the stack required to hold the FPU registers. */
 | 
			
		||||
#if ( configFPU_D32 == 1 )
 | 
			
		||||
    #define portFPU_REGISTER_WORDS     ( ( 32 * 2 ) + 1 ) /* D0-D31 and FPSCR. */
 | 
			
		||||
#else
 | 
			
		||||
    #define portFPU_REGISTER_WORDS     ( ( 16 * 2 ) + 1 ) /* D0-D15 and FPSCR. */
 | 
			
		||||
#endif /* configFPU_D32 */
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Starts the first task executing.  This function is necessarily written in
 | 
			
		||||
 * assembly code so is implemented in portASM.s.
 | 
			
		||||
 * These functions are necessarily written in assembly code, so are implemented
 | 
			
		||||
 * in portASM.S.
 | 
			
		||||
 */
 | 
			
		||||
extern void vPortRestoreTaskContext( void );
 | 
			
		||||
extern void vPortInitialiseFPSCR( void );
 | 
			
		||||
extern uint32_t ulReadAPSR( void );
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Used to catch tasks that attempt to return from their implementing function.
 | 
			
		||||
| 
						 | 
				
			
			@ -184,12 +194,33 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
 | 
			
		|||
    /* The task will start with a critical nesting count of 0 as interrupts are
 | 
			
		||||
     * enabled. */
 | 
			
		||||
    *pxTopOfStack = portNO_CRITICAL_NESTING;
 | 
			
		||||
    pxTopOfStack--;
 | 
			
		||||
 | 
			
		||||
    #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. */
 | 
			
		||||
        pxTopOfStack--;
 | 
			
		||||
        *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
 | 
			
		||||
    }
 | 
			
		||||
    #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 initialised to 0. */
 | 
			
		||||
        pxTopOfStack -= portFPU_REGISTER_WORDS;
 | 
			
		||||
        memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
 | 
			
		||||
 | 
			
		||||
        /* Initialise the slot containing ulPortTaskHasFPUContext to true as
 | 
			
		||||
         * the task starts with a floating point context. */
 | 
			
		||||
        pxTopOfStack--;
 | 
			
		||||
        *pxTopOfStack = pdTRUE;
 | 
			
		||||
        ulPortTaskHasFPUContext = pdTRUE;
 | 
			
		||||
    }
 | 
			
		||||
    #else
 | 
			
		||||
    {
 | 
			
		||||
        #error "Invalid configUSE_TASK_FPU_SUPPORT value - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined."
 | 
			
		||||
    }
 | 
			
		||||
    #endif /* if ( configUSE_TASK_FPU_SUPPORT == 1 ) */
 | 
			
		||||
 | 
			
		||||
    return pxTopOfStack;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -218,7 +249,7 @@ BaseType_t xPortStartScheduler( void )
 | 
			
		|||
 | 
			
		||||
    /* 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 = ulReadAPSR();
 | 
			
		||||
 | 
			
		||||
    ulAPSR &= portAPSR_MODE_BITS_MASK;
 | 
			
		||||
    configASSERT( ulAPSR != portAPSR_USER_MODE );
 | 
			
		||||
| 
						 | 
				
			
			@ -310,15 +341,17 @@ void FreeRTOS_Tick_Handler( void )
 | 
			
		|||
}
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
void vPortTaskUsesFPU( void )
 | 
			
		||||
{
 | 
			
		||||
    uint32_t ulInitialFPSCR = 0;
 | 
			
		||||
#if ( configUSE_TASK_FPU_SUPPORT != 2 )
 | 
			
		||||
 | 
			
		||||
    void vPortTaskUsesFPU( void )
 | 
			
		||||
    {
 | 
			
		||||
        /* 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" );
 | 
			
		||||
}
 | 
			
		||||
        vPortInitialiseFPSCR();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif /* configUSE_TASK_FPU_SUPPORT */
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,14 +28,14 @@
 | 
			
		|||
 | 
			
		||||
    .text
 | 
			
		||||
    .arm
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
    .set SYS_MODE,   0x1f
 | 
			
		||||
    .set SVC_MODE,   0x13
 | 
			
		||||
    .set IRQ_MODE,   0x12
 | 
			
		||||
    .set CPSR_I_BIT, 0x80
 | 
			
		||||
 | 
			
		||||
    /* Variables and functions. */
 | 
			
		||||
    .extern ulMaxAPIPriorityMask
 | 
			
		||||
    .extern _freertos_vector_table
 | 
			
		||||
    .extern pxCurrentTCB
 | 
			
		||||
    .extern vTaskSwitchContext
 | 
			
		||||
    .extern vApplicationIRQHandler
 | 
			
		||||
| 
						 | 
				
			
			@ -47,29 +47,38 @@
 | 
			
		|||
    .global FreeRTOS_IRQ_Handler
 | 
			
		||||
    .global FreeRTOS_SVC_Handler
 | 
			
		||||
    .global vPortRestoreTaskContext
 | 
			
		||||
    .global vPortInitialiseFPSCR
 | 
			
		||||
    .global ulReadAPSR
 | 
			
		||||
    .global vPortYield
 | 
			
		||||
    .global vPortEnableInterrupts
 | 
			
		||||
    .global vPortDisableInterrupts
 | 
			
		||||
    .global ulPortSetInterruptMaskFromISR
 | 
			
		||||
    .global ulPortCountLeadingZeros
 | 
			
		||||
 | 
			
		||||
    .weak   vApplicationSVCHandler
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.macro portSAVE_CONTEXT
 | 
			
		||||
 | 
			
		||||
    /* Save the LR and SPSR onto the system mode stack before switching to
 | 
			
		||||
    system mode to save the remaining system mode registers. */
 | 
			
		||||
    SRSDB   sp!, #SYS_MODE
 | 
			
		||||
     * system mode to save the remaining system mode registers. */
 | 
			
		||||
    SRSDB   SP!, #SYS_MODE
 | 
			
		||||
    CPS     #SYS_MODE
 | 
			
		||||
    PUSH    {R0-R12, R14}
 | 
			
		||||
 | 
			
		||||
    /* Push the critical nesting count. */
 | 
			
		||||
    LDR     R2, ulCriticalNestingConst
 | 
			
		||||
    LDR     R2, =ulCriticalNesting
 | 
			
		||||
    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
 | 
			
		||||
     * ulPortTaskHasFPUContext is 0 then no. */
 | 
			
		||||
    LDR     R2, =ulPortTaskHasFPUContext
 | 
			
		||||
    LDR     R3, [R2]
 | 
			
		||||
    CMP     R3, #0
 | 
			
		||||
 | 
			
		||||
    /* Save the floating point context, if any. */
 | 
			
		||||
    FMRXNE  R1,  FPSCR
 | 
			
		||||
    VMRSNE  R1,  FPSCR
 | 
			
		||||
    VPUSHNE {D0-D15}
 | 
			
		||||
#if configFPU_D32 == 1
 | 
			
		||||
    VPUSHNE {D16-D31}
 | 
			
		||||
| 
						 | 
				
			
			@ -80,24 +89,24 @@
 | 
			
		|||
    PUSH    {R3}
 | 
			
		||||
 | 
			
		||||
    /* Save the stack pointer in the TCB. */
 | 
			
		||||
    LDR     R0, pxCurrentTCBConst
 | 
			
		||||
    LDR     R0, =pxCurrentTCB
 | 
			
		||||
    LDR     R1, [R0]
 | 
			
		||||
    STR     SP, [R1]
 | 
			
		||||
 | 
			
		||||
    .endm
 | 
			
		||||
 | 
			
		||||
; /**********************************************************************/
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.macro portRESTORE_CONTEXT
 | 
			
		||||
 | 
			
		||||
    /* Set the SP to point to the stack of the task being restored. */
 | 
			
		||||
    LDR     R0, pxCurrentTCBConst
 | 
			
		||||
    LDR     R0, =pxCurrentTCB
 | 
			
		||||
    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
 | 
			
		||||
     * ulPortTaskHasFPUContext is zero then no. */
 | 
			
		||||
    LDR     R0, =ulPortTaskHasFPUContext
 | 
			
		||||
    POP     {R1}
 | 
			
		||||
    STR     R1, [R0]
 | 
			
		||||
    CMP     R1, #0
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +120,7 @@
 | 
			
		|||
    VMSRNE  FPSCR, R0
 | 
			
		||||
 | 
			
		||||
    /* Restore the critical section nesting depth. */
 | 
			
		||||
    LDR     R0, ulCriticalNestingConst
 | 
			
		||||
    LDR     R0, =ulCriticalNesting
 | 
			
		||||
    POP     {R1}
 | 
			
		||||
    STR     R1, [R0]
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,29 +129,17 @@
 | 
			
		|||
    POP     {R0-R12, R14}
 | 
			
		||||
 | 
			
		||||
    /* Return to the task code, loading CPSR on the way. */
 | 
			
		||||
    RFEIA   sp!
 | 
			
		||||
    RFEIA   SP!
 | 
			
		||||
 | 
			
		||||
    .endm
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
 * SVC handler is used to yield.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
.align 4
 | 
			
		||||
.type FreeRTOS_SVC_Handler, %function
 | 
			
		||||
FreeRTOS_SVC_Handler:
 | 
			
		||||
    /* Save the context of the current task and select a new task to run. */
 | 
			
		||||
    portSAVE_CONTEXT
 | 
			
		||||
    LDR R0, vTaskSwitchContextConst
 | 
			
		||||
    BLX R0
 | 
			
		||||
    portRESTORE_CONTEXT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/******************************************************************************
 | 
			
		||||
/*
 | 
			
		||||
 * void vPortRestoreTaskContext( void );
 | 
			
		||||
 *
 | 
			
		||||
 * vPortRestoreTaskContext is used to start the scheduler.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type vPortRestoreTaskContext, %function
 | 
			
		||||
vPortRestoreTaskContext:
 | 
			
		||||
| 
						 | 
				
			
			@ -150,72 +147,212 @@ vPortRestoreTaskContext:
 | 
			
		|||
    CPS     #SYS_MODE
 | 
			
		||||
    portRESTORE_CONTEXT
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * void vPortInitialiseFPSCR( void );
 | 
			
		||||
 *
 | 
			
		||||
 * vPortInitialiseFPSCR is used to initialize the FPSCR register.
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type vPortInitialiseFPSCR, %function
 | 
			
		||||
vPortInitialiseFPSCR:
 | 
			
		||||
    MOV     R0, #0
 | 
			
		||||
    VMSR    FPSCR, R0
 | 
			
		||||
    BX      LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * uint32_t ulReadAPSR( void );
 | 
			
		||||
 *
 | 
			
		||||
 * ulReadAPSR is used to read the value of APSR context.
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type ulReadAPSR, %function
 | 
			
		||||
ulReadAPSR:
 | 
			
		||||
    MRS R0, APSR
 | 
			
		||||
    BX  LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * void vPortYield( void );
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type vPortYield, %function
 | 
			
		||||
vPortYield:
 | 
			
		||||
    SVC 0
 | 
			
		||||
    ISB
 | 
			
		||||
    BX  LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * void vPortEnableInterrupts( void );
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type vPortEnableInterrupts, %function
 | 
			
		||||
vPortEnableInterrupts:
 | 
			
		||||
    CPSIE   I
 | 
			
		||||
    BX      LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * void vPortDisableInterrupts( void );
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type vPortDisableInterrupts, %function
 | 
			
		||||
vPortDisableInterrupts:
 | 
			
		||||
    CPSID    I
 | 
			
		||||
    DSB
 | 
			
		||||
    ISB
 | 
			
		||||
    BX      LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * uint32_t ulPortSetInterruptMaskFromISR( void );
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type ulPortSetInterruptMaskFromISR, %function
 | 
			
		||||
ulPortSetInterruptMaskFromISR:
 | 
			
		||||
    MRS     R0, CPSR
 | 
			
		||||
    AND     R0, R0, #CPSR_I_BIT
 | 
			
		||||
    CPSID   I
 | 
			
		||||
    DSB
 | 
			
		||||
    ISB
 | 
			
		||||
    BX      LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * void vApplicationSVCHandler( uint32_t ulSvcNumber );
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type vApplicationSVCHandler, %function
 | 
			
		||||
vApplicationSVCHandler:
 | 
			
		||||
    B vApplicationSVCHandler
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
 | 
			
		||||
 *
 | 
			
		||||
 * According to the Procedure Call Standard for the ARM Architecture (AAPCS):
 | 
			
		||||
 * - Parameter ulBitmap is passed in R0.
 | 
			
		||||
 * - Return value must be in R0.
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type ulPortCountLeadingZeros, %function
 | 
			
		||||
ulPortCountLeadingZeros:
 | 
			
		||||
    CLZ     R0, R0
 | 
			
		||||
    BX      LR
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * SVC handler is used to yield.
 | 
			
		||||
 */
 | 
			
		||||
.align 4
 | 
			
		||||
.type FreeRTOS_SVC_Handler, %function
 | 
			
		||||
FreeRTOS_SVC_Handler:
 | 
			
		||||
    PUSH    { R0-R1 }
 | 
			
		||||
 | 
			
		||||
    /* ---------------------------- Get Caller SVC Number ---------------------------- */
 | 
			
		||||
    MRS     R0, SPSR               /* R0 = CPSR at the time of SVC. */
 | 
			
		||||
    TST     R0, #0x20              /* Check Thumb bit (5) in CPSR. */
 | 
			
		||||
    LDRHNE  R0, [LR, #-0x2]        /* If Thumb, load halfword. */
 | 
			
		||||
    BICNE   R0, R0, #0xFF00        /* And extract immidiate field (i.e. SVC number). */
 | 
			
		||||
    LDREQ   R0, [LR, #-0x4]        /* If ARM, load word. */
 | 
			
		||||
    BICEQ   R0, R0, #0xFF000000    /* And extract immidiate field (i.e. SVC number). */
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------- SVC Routing --------------------------------- */
 | 
			
		||||
    CMP     R0, #0
 | 
			
		||||
    BEQ     svcPortYield
 | 
			
		||||
    BNE     svcApplicationCall
 | 
			
		||||
 | 
			
		||||
svcPortYield:
 | 
			
		||||
    POP     { R0-R1 }
 | 
			
		||||
    portSAVE_CONTEXT
 | 
			
		||||
    BLX     vTaskSwitchContext
 | 
			
		||||
    portRESTORE_CONTEXT
 | 
			
		||||
 | 
			
		||||
svcApplicationCall:
 | 
			
		||||
    POP     { R0-R1 }
 | 
			
		||||
    portSAVE_CONTEXT
 | 
			
		||||
    BLX     vApplicationSVCHandler
 | 
			
		||||
    portRESTORE_CONTEXT
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.align 4
 | 
			
		||||
.type FreeRTOS_IRQ_Handler, %function
 | 
			
		||||
FreeRTOS_IRQ_Handler:
 | 
			
		||||
    /* Return to the interrupted instruction. */
 | 
			
		||||
    SUB     lr, lr, #4
 | 
			
		||||
    SUB     LR, LR, #4
 | 
			
		||||
 | 
			
		||||
    /* Push the return address and SPSR. */
 | 
			
		||||
    PUSH    {lr}
 | 
			
		||||
    MRS     lr, SPSR
 | 
			
		||||
    PUSH    {lr}
 | 
			
		||||
    PUSH    {LR}
 | 
			
		||||
    MRS     LR, SPSR
 | 
			
		||||
    PUSH    {LR}
 | 
			
		||||
 | 
			
		||||
    /* Change to supervisor mode to allow reentry. */
 | 
			
		||||
    CPS     #0x13
 | 
			
		||||
    CPS     #SVC_MODE
 | 
			
		||||
 | 
			
		||||
    /* Push used registers. */
 | 
			
		||||
    PUSH    {r0-r3, r12}
 | 
			
		||||
    PUSH    {R0-R3, R12}
 | 
			
		||||
 | 
			
		||||
    /* Increment nesting count.  r3 holds the address of ulPortInterruptNesting
 | 
			
		||||
    for future use.  r1 holds the original ulPortInterruptNesting value for
 | 
			
		||||
    future use. */
 | 
			
		||||
    LDR     r3, ulPortInterruptNestingConst
 | 
			
		||||
    LDR     r1, [r3]
 | 
			
		||||
    ADD     r0, r1, #1
 | 
			
		||||
    STR     r0, [r3]
 | 
			
		||||
     * for future use.  r1 holds the original ulPortInterruptNesting value for
 | 
			
		||||
     * future use. */
 | 
			
		||||
    LDR     R3, =ulPortInterruptNesting
 | 
			
		||||
    LDR     R1, [R3]
 | 
			
		||||
    ADD     R0, R1, #1
 | 
			
		||||
    STR     R0, [R3]
 | 
			
		||||
 | 
			
		||||
    /* Ensure bit 2 of the stack pointer is clear.  r2 holds the bit 2 value for
 | 
			
		||||
    future use. */
 | 
			
		||||
    MOV     r0, sp
 | 
			
		||||
    AND     r2, r0, #4
 | 
			
		||||
    SUB     sp, sp, r2
 | 
			
		||||
     * future use. */
 | 
			
		||||
    MOV     R0, SP
 | 
			
		||||
    AND     R2, R0, #4
 | 
			
		||||
    SUB     SP, SP, R2
 | 
			
		||||
 | 
			
		||||
    /* Call the interrupt handler. */
 | 
			
		||||
    PUSH    {r0-r3, lr}
 | 
			
		||||
    LDR     r1, vApplicationIRQHandlerConst
 | 
			
		||||
    BLX     r1
 | 
			
		||||
    POP     {r0-r3, lr}
 | 
			
		||||
    ADD     sp, sp, r2
 | 
			
		||||
    PUSH    {R0-R3, LR}
 | 
			
		||||
    BLX     vApplicationIRQHandler
 | 
			
		||||
    POP     {R0-R3, LR}
 | 
			
		||||
    ADD     SP, SP, R2
 | 
			
		||||
 | 
			
		||||
    /* Disable IRQs incase vApplicationIRQHandler enabled them for re-entry. */
 | 
			
		||||
    CPSID   i
 | 
			
		||||
    DSB
 | 
			
		||||
    ISB
 | 
			
		||||
 | 
			
		||||
    /* Write to the EOI register. */
 | 
			
		||||
    LDR     r0, ulICCEOIRConst
 | 
			
		||||
    LDR     r2, [r0]
 | 
			
		||||
    STR     r0, [r2]
 | 
			
		||||
    LDR     R0, =ulICCEOIR
 | 
			
		||||
    LDR     R2, [R0]
 | 
			
		||||
    STR     R0, [R2]
 | 
			
		||||
 | 
			
		||||
    /* Restore the old nesting count. */
 | 
			
		||||
    STR     r1, [r3]
 | 
			
		||||
    STR     R1, [R3]
 | 
			
		||||
 | 
			
		||||
    /* A context switch is never performed if the nesting count is not 0. */
 | 
			
		||||
    CMP     r1, #0
 | 
			
		||||
    CMP     R1, #0
 | 
			
		||||
    BNE     exit_without_switch
 | 
			
		||||
 | 
			
		||||
    /* Did the interrupt request a context switch?  r1 holds the address of
 | 
			
		||||
    ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
 | 
			
		||||
    use. */
 | 
			
		||||
    LDR     r1, ulPortYieldRequiredConst
 | 
			
		||||
    LDR     r0, [r1]
 | 
			
		||||
    CMP     r0, #0
 | 
			
		||||
     * ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
 | 
			
		||||
     * use. */
 | 
			
		||||
    LDR     R1, =ulPortYieldRequired
 | 
			
		||||
    LDR     R0, [R1]
 | 
			
		||||
    CMP     R0, #0
 | 
			
		||||
    BNE     switch_before_exit
 | 
			
		||||
 | 
			
		||||
exit_without_switch:
 | 
			
		||||
    /* No context switch.  Restore used registers, LR_irq and SPSR before
 | 
			
		||||
    returning. */
 | 
			
		||||
    POP     {r0-r3, r12}
 | 
			
		||||
     * returning. */
 | 
			
		||||
    POP     {R0-R3, R12}
 | 
			
		||||
    CPS     #IRQ_MODE
 | 
			
		||||
    POP     {LR}
 | 
			
		||||
    MSR     SPSR_cxsf, LR
 | 
			
		||||
| 
						 | 
				
			
			@ -224,13 +361,13 @@ exit_without_switch:
 | 
			
		|||
 | 
			
		||||
switch_before_exit:
 | 
			
		||||
    /* A context switch is to be performed.  Clear the context switch pending
 | 
			
		||||
    flag. */
 | 
			
		||||
    MOV     r0, #0
 | 
			
		||||
    STR     r0, [r1]
 | 
			
		||||
     * flag. */
 | 
			
		||||
    MOV     R0, #0
 | 
			
		||||
    STR     R0, [R1]
 | 
			
		||||
 | 
			
		||||
    /* Restore used registers, LR-irq and SPSR before saving the context
 | 
			
		||||
    to the task stack. */
 | 
			
		||||
    POP     {r0-r3, r12}
 | 
			
		||||
     * to the task stack. */
 | 
			
		||||
    POP     {R0-R3, R12}
 | 
			
		||||
    CPS     #IRQ_MODE
 | 
			
		||||
    POP     {LR}
 | 
			
		||||
    MSR     SPSR_cxsf, LR
 | 
			
		||||
| 
						 | 
				
			
			@ -238,23 +375,15 @@ switch_before_exit:
 | 
			
		|||
    portSAVE_CONTEXT
 | 
			
		||||
 | 
			
		||||
    /* Call the function that selects the new task to execute.
 | 
			
		||||
    vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
 | 
			
		||||
    instructions, or 8 byte aligned stack allocated data.  LR does not need
 | 
			
		||||
    saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
 | 
			
		||||
    LDR     R0, vTaskSwitchContextConst
 | 
			
		||||
    BLX     R0
 | 
			
		||||
     * vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
 | 
			
		||||
     * instructions, or 8 byte aligned stack allocated data.  LR does not need
 | 
			
		||||
     * saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
 | 
			
		||||
    BLX     vTaskSwitchContext
 | 
			
		||||
 | 
			
		||||
    /* Restore the context of, and branch to, the task selected to execute
 | 
			
		||||
    next. */
 | 
			
		||||
     * next. */
 | 
			
		||||
    portRESTORE_CONTEXT
 | 
			
		||||
 | 
			
		||||
ulICCEOIRConst: .word ulICCEOIR
 | 
			
		||||
pxCurrentTCBConst: .word pxCurrentTCB
 | 
			
		||||
ulCriticalNestingConst: .word ulCriticalNesting
 | 
			
		||||
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
 | 
			
		||||
vTaskSwitchContextConst: .word vTaskSwitchContext
 | 
			
		||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
 | 
			
		||||
ulPortInterruptNestingConst: .word ulPortInterruptNesting
 | 
			
		||||
ulPortYieldRequiredConst: .word ulPortYieldRequired
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
.end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,47 +88,31 @@ typedef uint32_t         TickType_t;
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
#define portYIELD_FROM_ISR( x )    portEND_SWITCHING_ISR( x )
 | 
			
		||||
#define portYIELD()                 \
 | 
			
		||||
    __asm volatile ( "SWI 0     \n" \
 | 
			
		||||
                     "ISB         " ::: "memory" );
 | 
			
		||||
 | 
			
		||||
void vPortYield( void );
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------
 | 
			
		||||
* Critical section control
 | 
			
		||||
*----------------------------------------------------------*/
 | 
			
		||||
#define portYIELD()     vPortYield();
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Critical section management.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern void vPortEnterCritical( void );
 | 
			
		||||
extern void vPortExitCritical( void );
 | 
			
		||||
extern uint32_t ulPortSetInterruptMask( void );
 | 
			
		||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
 | 
			
		||||
extern void vPortInstallFreeRTOSVectorTable( void );
 | 
			
		||||
 | 
			
		||||
/* The I bit within the CPSR. */
 | 
			
		||||
#define portINTERRUPT_ENABLE_BIT    ( 1 << 7 )
 | 
			
		||||
extern void vPortEnableInterrupts( void );
 | 
			
		||||
extern void vPortDisableInterrupts( void );
 | 
			
		||||
extern uint32_t ulPortSetInterruptMaskFromISR( void );
 | 
			
		||||
 | 
			
		||||
/* In the absence of a priority mask register, these functions and macros
 | 
			
		||||
 * globally enable and disable interrupts. */
 | 
			
		||||
#define portENTER_CRITICAL()                    vPortEnterCritical();
 | 
			
		||||
#define portEXIT_CRITICAL()                     vPortExitCritical();
 | 
			
		||||
#define portENABLE_INTERRUPTS()    __asm volatile ( "CPSIE i   \n" ::: "memory" );
 | 
			
		||||
#define portDISABLE_INTERRUPTS()    \
 | 
			
		||||
    __asm volatile ( "CPSID i   \n" \
 | 
			
		||||
                     "DSB       \n" \
 | 
			
		||||
                     "ISB         " ::: "memory" );
 | 
			
		||||
 | 
			
		||||
__attribute__( ( always_inline ) ) static __inline uint32_t portINLINE_SET_INTERRUPT_MASK_FROM_ISR( void )
 | 
			
		||||
{
 | 
			
		||||
    volatile uint32_t ulCPSR;
 | 
			
		||||
 | 
			
		||||
    __asm volatile ( "MRS %0, CPSR" : "=r" ( ulCPSR )::"memory" );
 | 
			
		||||
 | 
			
		||||
    ulCPSR &= portINTERRUPT_ENABLE_BIT;
 | 
			
		||||
    portDISABLE_INTERRUPTS();
 | 
			
		||||
    return ulCPSR;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define portSET_INTERRUPT_MASK_FROM_ISR()         portINLINE_SET_INTERRUPT_MASK_FROM_ISR()
 | 
			
		||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )    do { if( x == 0 ) portENABLE_INTERRUPTS( ); } while( 0 )
 | 
			
		||||
#define portENABLE_INTERRUPTS()                 vPortEnableInterrupts();
 | 
			
		||||
#define portDISABLE_INTERRUPTS()                vPortDisableInterrupts();
 | 
			
		||||
#define portSET_INTERRUPT_MASK_FROM_ISR()       ulPortSetInterruptMaskFromISR();
 | 
			
		||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x )  do { if( x == 0 ) portENABLE_INTERRUPTS(); } while( 0 )
 | 
			
		||||
 | 
			
		||||
/*-----------------------------------------------------------*/
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -148,9 +132,27 @@ __attribute__( ( always_inline ) ) static __inline uint32_t portINLINE_SET_INTER
 | 
			
		|||
 * handler for whichever peripheral is used to generate the RTOS tick. */
 | 
			
		||||
void FreeRTOS_Tick_Handler( void );
 | 
			
		||||
 | 
			
		||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
 | 
			
		||||
 * before any floating point instructions are executed. */
 | 
			
		||||
void vPortTaskUsesFPU( void );
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Returns the number of leading zeros in a 32 bit variable.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] ulBitmap 32-Bit number to count leading zeros in.
 | 
			
		||||
 *
 | 
			
		||||
 * @return The number of leading zeros in ulBitmap.
 | 
			
		||||
 */
 | 
			
		||||
UBaseType_t ulPortCountLeadingZeros( UBaseType_t ulBitmap );
 | 
			
		||||
 | 
			
		||||
/* 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 )
 | 
			
		||||
    void vPortTaskUsesFPU( void );
 | 
			
		||||
#else
 | 
			
		||||
    /* Each task has an FPU context already, so define this function as a
 | 
			
		||||
     * no-op. */
 | 
			
		||||
    #define vPortTaskUsesFPU()
 | 
			
		||||
#endif
 | 
			
		||||
#define portTASK_USES_FLOATING_POINT()    vPortTaskUsesFPU()
 | 
			
		||||
 | 
			
		||||
#define portLOWEST_INTERRUPT_PRIORITY           ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
 | 
			
		||||
| 
						 | 
				
			
			@ -163,19 +165,15 @@ void vPortTaskUsesFPU( void );
 | 
			
		|||
 | 
			
		||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
 | 
			
		||||
 | 
			
		||||
/* Store/clear the ready priorities in a bit map. */
 | 
			
		||||
    /* Store, clear and get 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 portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )    uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
 | 
			
		||||
    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )  uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxTopReadyPriority ) ) )
 | 
			
		||||
 | 
			
		||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
 | 
			
		||||
 | 
			
		||||
#define portNOP()               __asm volatile ( "NOP" )
 | 
			
		||||
#define portINLINE              __inline
 | 
			
		||||
 | 
			
		||||
#define portMEMORY_BARRIER()    __asm volatile ( "" ::: "memory" )
 | 
			
		||||
 | 
			
		||||
/* *INDENT-OFF* */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue