Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Flipper-Zero/STM32CubeWB.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7_MPU/r0p1/port.c')
-rw-r--r--Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7_MPU/r0p1/port.c170
1 files changed, 111 insertions, 59 deletions
diff --git a/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7_MPU/r0p1/port.c b/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7_MPU/r0p1/port.c
index 1243f476f..84d0e5e46 100644
--- a/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7_MPU/r0p1/port.c
+++ b/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7_MPU/r0p1/port.c
@@ -1,6 +1,6 @@
/*
- * FreeRTOS Kernel V10.0.1
- * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
@@ -47,12 +47,18 @@ task.h is included from an application file. */
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
+ /* Ensure the SysTick is clocked at the same frequency as the core. */
+ #define portNVIC_SYSTICK_CLK ( 1UL << 2UL )
+#else
+ /* The way the SysTick is clocked is not modified in case it is not the same
+ as the core. */
+ #define portNVIC_SYSTICK_CLK ( 0 )
#endif
/* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
-#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) )
@@ -73,9 +79,7 @@ task.h is included from an application file. */
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
/* Constants required to access and manipulate the SysTick. */
-#define portNVIC_SYSTICK_CLK ( 0x00000004UL )
#define portNVIC_SYSTICK_INT ( 0x00000002UL )
-#define portNVIC_SYSTICK_COUNT_FLAG ( 1UL << 16UL )
#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
@@ -87,7 +91,7 @@ task.h is included from an application file. */
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000UL )
-#define portINITIAL_EXEC_RETURN ( 0xfffffffdUL )
+#define portINITIAL_EXC_RETURN ( 0xfffffffdUL )
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
@@ -141,11 +145,11 @@ static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
/*
- * Checks to see if being called from the context of an unprivileged task, and
- * if so raises the privilege level and returns false - otherwise does nothing
- * other than return true.
+ * Setup the timer to generate the tick interrupts. The implementation in this
+ * file is weak to allow application writers to change the timer used to
+ * generate the tick interrupt.
*/
-BaseType_t xPortRaisePrivilege( void ) __attribute__(( naked ));
+void vPortSetupTimerInterrupt( void );
/*
* Standard FreeRTOS exception handlers.
@@ -169,29 +173,42 @@ static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline ))
* Function to enable the VFP.
*/
static void vPortEnableVFP( void ) __attribute__ (( naked ));
-
-/*
- * The number of SysTick increments that make up one tick period.
+
+/**
+ * @brief Checks whether or not the processor is privileged.
+ *
+ * @return 1 if the processor is already privileged, 0 otherwise.
*/
-#if configUSE_TICKLESS_IDLE == 1
- static uint32_t ulTimerCountsForOneTick = 0;
-#endif /* configUSE_TICKLESS_IDLE */
+BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
-/*
- * The maximum number of tick periods that can be suppressed is limited by the
- * 24 bit resolution of the SysTick timer.
+/**
+ * @brief Lowers the privilege level by setting the bit 0 of the CONTROL
+ * register.
+ *
+ * Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
+ * Bit[0] = 0 --> The processor is running privileged
+ * Bit[0] = 1 --> The processor is running unprivileged.
*/
-#if configUSE_TICKLESS_IDLE == 1
- static uint32_t xMaximumPossibleSuppressedTicks = 0;
-#endif /* configUSE_TICKLESS_IDLE */
+void vResetPrivilege( void ) __attribute__ (( naked ));
-/*
- * Compensate for the CPU cycles that pass while the SysTick is stopped (low
- * power functionality only.
+/**
+ * @brief Calls the port specific code to raise the privilege.
+ *
+ * @return pdFALSE if privilege was raised, pdTRUE otherwise.
*/
-#if configUSE_TICKLESS_IDLE == 1
- static uint32_t ulStoppedTimerCompensation = 0;
-#endif /* configUSE_TICKLESS_IDLE */
+extern BaseType_t xPortRaisePrivilege( void );
+
+/**
+ * @brief If xRunningPrivileged is not pdTRUE, calls the port specific
+ * code to reset the privilege, otherwise does nothing.
+ */
+extern void vPortResetPrivilege( BaseType_t xRunningPrivileged );
+/*-----------------------------------------------------------*/
+
+/* Each task maintains its own interrupt status in the critical nesting
+variable. Note this is not saved as part of the task context as context
+switches can only occur when uxCriticalNesting is zero. */
+static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
@@ -221,12 +238,12 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = 0; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
-
+
/* A save method is being used that requires each task to maintain its
own exec return value. */
pxTopOfStack--;
- *pxTopOfStack = portINITIAL_EXEC_RETURN;
-
+ *pxTopOfStack = portINITIAL_EXC_RETURN;
+
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
if( xRunPrivileged == pdTRUE )
@@ -256,7 +273,7 @@ void vPortSVCHandler( void )
" mrs r0, psp \n"
#endif
" b %0 \n"
- ::"i"(prvSVCHandler):"r0"
+ ::"i"(prvSVCHandler):"r0", "memory"
);
}
/*-----------------------------------------------------------*/
@@ -279,7 +296,7 @@ uint8_t ucSVCNumber;
but do ensure the code is completely
within the specified behaviour for the
architecture. */
- __asm volatile( "dsb" );
+ __asm volatile( "dsb" ::: "memory" );
__asm volatile( "isb" );
break;
@@ -289,7 +306,7 @@ uint8_t ucSVCNumber;
" mrs r1, control \n" /* Obtain current control value. */
" bic r1, #1 \n" /* Set privilege bit. */
" msr control, r1 \n" /* Write back new control value. */
- :::"r1"
+ ::: "r1", "memory"
);
break;
@@ -369,6 +386,24 @@ BaseType_t xPortStartScheduler( void )
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
}
+ #ifdef __NVIC_PRIO_BITS
+ {
+ /* Check the CMSIS configuration that defines the number of
+ priority bits matches the number of priority bits actually queried
+ from the hardware. */
+ configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
+ }
+ #endif
+
+ #ifdef configPRIO_BITS
+ {
+ /* Check the FreeRTOS configuration that defines the number of
+ priority bits matches the number of priority bits actually queried
+ from the hardware. */
+ configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
+ }
+ #endif
+
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
@@ -402,19 +437,24 @@ BaseType_t xPortStartScheduler( void )
/* Lazy save always. */
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
- /* Start the first task. */
+ /* Start the first task. This also clears the bit that indicates the FPU is
+ in use in case the FPU was used before the scheduler was started - which
+ would otherwise result in the unnecessary leaving of space in the SVC stack
+ for lazy saving of FPU registers. */
__asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
+ " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */
+ " msr control, r0 \n"
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
" svc %0 \n" /* System call to start first task. */
" nop \n"
- :: "i" (portSVC_START_SCHEDULER) );
+ :: "i" (portSVC_START_SCHEDULER) : "memory" );
/* Should not get here! */
return 0;
@@ -461,6 +501,7 @@ void xPortPendSVHandler( void )
__asm volatile
(
" mrs r0, psp \n"
+ " isb \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
@@ -473,7 +514,7 @@ void xPortPendSVHandler( void )
" stmdb r0!, {r1, r4-r11, r14} \n" /* Save the remaining registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
- " stmdb sp!, {r3} \n"
+ " stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n"
" cpsid i \n" /* Errata workaround. */
" msr basepri, r0 \n"
@@ -483,8 +524,8 @@ void xPortPendSVHandler( void )
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
- " ldmia sp!, {r3} \n"
- " \n" /* Restore the context. */
+ " ldmia sp!, {r0, r3} \n"
+ " \n" /* Restore the context. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
" add r1, r1, #4 \n" /* Move onto the second item in the TCB... */
@@ -686,14 +727,9 @@ uint32_t ulDummy;
*/
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
- /* Calculate the constants required to configure the tick interrupt. */
- #if configUSE_TICKLESS_IDLE == 1
- {
- ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
- xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
- ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
- }
- #endif /* configUSE_TICKLESS_IDLE */
+ /* Stop and clear the SysTick. */
+ portNVIC_SYSTICK_CTRL_REG = 0UL;
+ portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
@@ -725,6 +761,9 @@ extern uint32_t __FLASH_segment_end__[];
extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[];
+ /* Check the expected MPU is present. */
+ if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
+ {
/* First setup the entire flash for unprivileged read only access. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
@@ -735,7 +774,7 @@ extern uint32_t __privileged_data_end__[];
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
( portMPU_REGION_ENABLE );
- /* Setup the first 16K for privileged only access (even though less
+ /* Setup the first nK for privileged only access (even though less
than 10K is actually being used). This is where the kernel code is
placed. */
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
@@ -773,6 +812,7 @@ extern uint32_t __privileged_data_end__[];
/* Enable the MPU with the background region configured. */
portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE );
+ }
}
/*-----------------------------------------------------------*/
@@ -800,21 +840,33 @@ uint32_t ulRegionSize, ulReturnValue = 4;
}
/*-----------------------------------------------------------*/
-BaseType_t xPortRaisePrivilege( void )
+BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
{
__asm volatile
(
- " mrs r0, control \n"
- " tst r0, #1 \n" /* Is the task running privileged? */
- " itte ne \n"
- " movne r0, #0 \n" /* CONTROL[0]!=0, return false. */
- " svcne %0 \n" /* Switch to privileged. */
- " moveq r0, #1 \n" /* CONTROL[0]==0, return true. */
- " bx lr \n"
- :: "i" (portSVC_RAISE_PRIVILEGE) : "r0"
+ " mrs r0, control \n" /* r0 = CONTROL. */
+ " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
+ " ite ne \n"
+ " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
+ " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
+ " bx lr \n" /* Return. */
+ " \n"
+ " .align 4 \n"
+ ::: "r0", "memory"
);
+}
+/*-----------------------------------------------------------*/
- return 0;
+void vResetPrivilege( void ) /* __attribute__ (( naked )) */
+{
+ __asm volatile
+ (
+ " mrs r0, control \n" /* r0 = CONTROL. */
+ " orr r0, #1 \n" /* r0 = r0 | 1. */
+ " msr control, r0 \n" /* CONTROL = r0. */
+ " bx lr \n" /* Return to the caller. */
+ :::"r0", "memory"
+ );
}
/*-----------------------------------------------------------*/
@@ -922,7 +974,7 @@ uint32_t ul;
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
- __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
+ __asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
/* Is the interrupt number a user defined interrupt? */
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )