#include <intrinsics.h>\r
\r
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining\r
-all the API functions to use the MPU wrappers. That should only be done when\r
-task.h is included from an application file. */\r
+ * all the API functions to use the MPU wrappers. That should only be done when\r
+ * task.h is included from an application file. */\r
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
\r
/* Scheduler includes. */\r
\r
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
\r
-#warning This is not yet a documented port as it has not been fully tested, so no demo projects that use this port are provided.\r
-\r
#ifndef __ARMVFP__\r
#error This port can only be used when the project options are configured to enable hardware floating point support.\r
#endif\r
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )\r
\r
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7\r
-r0p1 port. */\r
+ * r0p1 port. */\r
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )\r
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )\r
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )\r
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )\r
{\r
/* Simulate the stack frame as it would be created by a context switch\r
- interrupt. */\r
+ * interrupt. */\r
\r
/* Offset added to account for the way the MCU uses the stack on entry/exit\r
- of interrupts, and to ensure alignment. */\r
+ * of interrupts, and to ensure alignment. */\r
pxTopOfStack--;\r
\r
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */\r
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */\r
\r
/* A save method is being used that requires each task to maintain its\r
- own exec return value. */\r
+ * own exec return value. */\r
pxTopOfStack--;\r
*pxTopOfStack = portINITIAL_EXC_RETURN;\r
\r
void vPortSVCHandler_C( uint32_t *pulParam )\r
{\r
uint8_t ucSVCNumber;\r
-\r
- /* The stack contains: r0, r1, r2, r3, r12, r14, the return address and\r
- xPSR. The first argument (r0) is pulParam[ 0 ]. */\r
- ucSVCNumber = ( ( uint8_t * ) pulParam[ portOFFSET_TO_PC ] )[ -2 ];\r
+uint32_t ulPC;\r
+#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )\r
+ extern uint32_t __syscalls_flash_start__[];\r
+ extern uint32_t __syscalls_flash_end__[];\r
+#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */\r
+\r
+ /* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first\r
+ * argument (r0) is pulParam[ 0 ]. */\r
+ ulPC = pulParam[ portOFFSET_TO_PC ];\r
+ ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];\r
switch( ucSVCNumber )\r
{\r
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;\r
\r
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
/* Barriers are normally not required\r
- but do ensure the code is completely\r
- within the specified behaviour for the\r
- architecture. */\r
+ * but do ensure the code is completely\r
+ * within the specified behaviour for the\r
+ * architecture. */\r
__asm volatile( "dsb" ::: "memory" );\r
__asm volatile( "isb" );\r
\r
break;\r
\r
+ #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )\r
+ case portSVC_RAISE_PRIVILEGE : /* Only raise the privilege, if the\r
+ * svc was raised from any of the\r
+ * system calls. */\r
+ if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&\r
+ ulPC <= ( uint32_t ) __syscalls_flash_end__ )\r
+ {\r
+ __asm volatile\r
+ (\r
+ " mrs r1, control \n" /* Obtain current control value. */\r
+ " bic r1, r1, #1 \n" /* Set privilege bit. */\r
+ " msr control, r1 \n" /* Write back new control value. */\r
+ ::: "r1", "memory"\r
+ );\r
+ }\r
+ break;\r
+ #else\r
case portSVC_RAISE_PRIVILEGE : __asm volatile\r
(\r
" mrs r1, control \n" /* Obtain current control value. */\r
::: "r1", "memory"\r
);\r
break;\r
+ #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */\r
\r
default : /* Unknown SVC call. */\r
break;\r
BaseType_t xPortStartScheduler( void )\r
{\r
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.\r
- See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */\r
+ * See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */\r
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
\r
/* This port can be used on all revisions of the Cortex-M7 core other than\r
- the r0p1 parts. r0p1 parts should use the port from the\r
- /source/portable/GCC/ARM_CM7/r0p1 directory. */\r
+ * the r0p1 parts. r0p1 parts should use the port from the\r
+ * /source/portable/GCC/ARM_CM7/r0p1 directory. */\r
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );\r
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );\r
\r
volatile uint8_t ucMaxPriorityValue;\r
\r
/* Determine the maximum priority from which ISR safe FreeRTOS API\r
- functions can be called. ISR safe functions are those that end in\r
- "FromISR". FreeRTOS maintains separate thread and ISR API functions to\r
- ensure interrupt entry is as fast and simple as possible.\r
+ * functions can be called. ISR safe functions are those that end in\r
+ * "FromISR". FreeRTOS maintains separate thread and ISR API functions to\r
+ * ensure interrupt entry is as fast and simple as possible.\r
\r
Save the interrupt priority value that is about to be clobbered. */\r
ulOriginalPriority = *pucFirstUserPriorityRegister;\r
\r
/* Determine the number of priority bits available. First write to all\r
- possible bits. */\r
+ * possible bits. */\r
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;\r
\r
/* Read the value back to see how many bits stuck. */\r
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;\r
\r
/* Calculate the maximum acceptable priority group value for the number\r
- of bits read back. */\r
+ * of bits read back. */\r
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;\r
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )\r
{\r
#ifdef __NVIC_PRIO_BITS\r
{\r
/* Check the CMSIS configuration that defines the number of\r
- priority bits matches the number of priority bits actually queried\r
- from the hardware. */\r
+ * priority bits matches the number of priority bits actually queried\r
+ * from the hardware. */\r
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );\r
}\r
#endif\r
#ifdef configPRIO_BITS\r
{\r
/* Check the FreeRTOS configuration that defines the number of\r
- priority bits matches the number of priority bits actually queried\r
- from the hardware. */\r
+ * priority bits matches the number of priority bits actually queried\r
+ * from the hardware. */\r
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );\r
}\r
#endif\r
\r
/* Shift the priority group value back to its position within the AIRCR\r
- register. */\r
+ * register. */\r
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;\r
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;\r
\r
/* Restore the clobbered interrupt priority register to its original\r
- value. */\r
+ * value. */\r
*pucFirstUserPriorityRegister = ulOriginalPriority;\r
}\r
#endif /* conifgASSERT_DEFINED */\r
prvSetupMPU();\r
\r
/* Start the timer that generates the tick ISR. Interrupts are disabled\r
- here already. */\r
+ * here already. */\r
vPortSetupTimerInterrupt();\r
\r
/* Initialise the critical nesting count ready for the first task. */\r
void vPortEndScheduler( void )\r
{\r
/* Not implemented in ports where there is nothing to return to.\r
- Artificially force an assert. */\r
+ * Artificially force an assert. */\r
configASSERT( uxCriticalNesting == 1000UL );\r
}\r
/*-----------------------------------------------------------*/\r
vPortResetPrivilege( xRunningPrivileged );\r
\r
/* This is not the interrupt safe version of the enter critical function so\r
- assert() if it is being called from an interrupt context. Only API\r
- functions that end in "FromISR" can be used in an interrupt. Only assert if\r
- the critical nesting count is 1 to protect against recursive calls if the\r
- assert function also uses a critical section. */\r
+ * assert() if it is being called from an interrupt context. Only API\r
+ * functions that end in "FromISR" can be used in an interrupt. Only assert if\r
+ * the critical nesting count is 1 to protect against recursive calls if the\r
+ * assert function also uses a critical section. */\r
if( uxCriticalNesting == 1 )\r
{\r
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );\r
void xPortSysTickHandler( void )\r
{\r
/* The SysTick runs at the lowest interrupt priority, so when this interrupt\r
- executes all interrupts must be unmasked. There is therefore no need to\r
- save and then restore the interrupt mask value as its value is already\r
- known. */\r
+ * executes all interrupts must be unmasked. There is therefore no need to\r
+ * save and then restore the interrupt mask value as its value is already\r
+ * known. */\r
portDISABLE_INTERRUPTS();\r
{\r
/* Increment the RTOS tick. */\r
if( xTaskIncrementTick() != pdFALSE )\r
{\r
/* A context switch is required. Context switching is performed in\r
- the PendSV interrupt. Pend the PendSV interrupt. */\r
+ * the PendSV interrupt. Pend the PendSV interrupt. */\r
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
}\r
}\r
( portMPU_REGION_ENABLE );\r
\r
/* Setup the first 16K for privileged only access (even though less\r
- than 10K is actually being used). This is where the kernel code is\r
- placed. */\r
+ * than 10K is actually being used). This is where the kernel code is\r
+ * placed. */\r
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */\r
( portMPU_REGION_VALID ) |\r
( portPRIVILEGED_FLASH_REGION );\r
( portMPU_REGION_ENABLE );\r
\r
/* Setup the privileged data RAM region. This is where the kernel data\r
- is placed. */\r
+ * is placed. */\r
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */\r
( portMPU_REGION_VALID ) |\r
( portPRIVILEGED_RAM_REGION );\r
( portMPU_REGION_ENABLE );\r
\r
/* By default allow everything to access the general peripherals. The\r
- system peripherals and registers are protected. */\r
+ * system peripherals and registers are protected. */\r
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |\r
( portMPU_REGION_VALID ) |\r
( portGENERAL_PERIPHERALS_REGION );\r
uint32_t ulRegionSize, ulReturnValue = 4;\r
\r
/* 32 is the smallest region size, 31 is the largest valid value for\r
- ulReturnValue. */\r
+ * ulReturnValue. */\r
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )\r
{\r
if( ulActualSizeInBytes <= ulRegionSize )\r
}\r
\r
/* Shift the code by one before returning so it can be written directly\r
- into the the correct bit position of the attribute register. */\r
+ * into the the correct bit position of the attribute register. */\r
return ( ulReturnValue << 1UL );\r
}\r
/*-----------------------------------------------------------*/\r
( portMPU_REGION_ENABLE );\r
\r
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have\r
- just removed the privileged only parameters. */\r
+ * just removed the privileged only parameters. */\r
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =\r
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */\r
( portMPU_REGION_VALID ) |\r
else\r
{\r
/* This function is called automatically when the task is created - in\r
- which case the stack region parameters will be valid. At all other\r
- times the stack parameters will not be valid and it is assumed that the\r
- stack region has already been configured. */\r
+ * which case the stack region parameters will be valid. At all other\r
+ * times the stack parameters will not be valid and it is assumed that the\r
+ * stack region has already been configured. */\r
if( ulStackDepth > 0 )\r
{\r
/* Define the region that allows access to the stack. */\r
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )\r
{\r
/* Translate the generic region definition contained in\r
- xRegions into the CM3 specific MPU settings that are then\r
- stored in xMPUSettings. */\r
+ * xRegions into the CM3 specific MPU settings that are then\r
+ * stored in xMPUSettings. */\r
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =\r
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |\r
( portMPU_REGION_VALID ) |\r
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];\r
\r
/* The following assertion will fail if a service routine (ISR) for\r
- an interrupt that has been assigned a priority above\r
- configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API\r
- function. ISR safe FreeRTOS API functions must *only* be called\r
- from interrupts that have been assigned a priority at or below\r
- configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
-\r
- Numerically low interrupt priority numbers represent logically high\r
- interrupt priorities, therefore the priority of the interrupt must\r
- be set to a value equal to or numerically *higher* than\r
- configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
-\r
- Interrupts that use the FreeRTOS API must not be left at their\r
- default priority of zero as that is the highest possible priority,\r
- which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,\r
- and therefore also guaranteed to be invalid.\r
-\r
- FreeRTOS maintains separate thread and ISR API functions to ensure\r
- interrupt entry is as fast and simple as possible.\r
-\r
- The following links provide detailed information:\r
- http://www.freertos.org/RTOS-Cortex-M3-M4.html\r
- http://www.freertos.org/FAQHelp.html */\r
+ * an interrupt that has been assigned a priority above\r
+ * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API\r
+ * function. ISR safe FreeRTOS API functions must *only* be called\r
+ * from interrupts that have been assigned a priority at or below\r
+ * configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+\r
+ * Numerically low interrupt priority numbers represent logically high\r
+ * interrupt priorities, therefore the priority of the interrupt must\r
+ * be set to a value equal to or numerically *higher* than\r
+ * configMAX_SYSCALL_INTERRUPT_PRIORITY.\r
+\r
+ * Interrupts that use the FreeRTOS API must not be left at their\r
+ * default priority of zero as that is the highest possible priority,\r
+ * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,\r
+ * and therefore also guaranteed to be invalid.\r
+\r
+ * FreeRTOS maintains separate thread and ISR API functions to ensure\r
+ * interrupt entry is as fast and simple as possible.\r
+\r
+ * The following links provide detailed information:\r
+ * http://www.freertos.org/RTOS-Cortex-M3-M4.html\r
+ * http://www.freertos.org/FAQHelp.html */\r
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );\r
}\r
\r
/* Priority grouping: The interrupt controller (NVIC) allows the bits\r
- that define each interrupt's priority to be split between bits that\r
- define the interrupt's pre-emption priority bits and bits that define\r
- the interrupt's sub-priority. For simplicity all bits must be defined\r
- to be pre-emption priority bits. The following assertion will fail if\r
- this is not the case (if some bits represent a sub-priority).\r
-\r
- If the application only uses CMSIS libraries for interrupt\r
- configuration then the correct setting can be achieved on all Cortex-M\r
- devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the\r
- scheduler. Note however that some vendor specific peripheral libraries\r
- assume a non-zero priority group setting, in which cases using a value\r
- of zero will result in unpredictable behaviour. */\r
+ * that define each interrupt's priority to be split between bits that\r
+ * define the interrupt's pre-emption priority bits and bits that define\r
+ * the interrupt's sub-priority. For simplicity all bits must be defined\r
+ * to be pre-emption priority bits. The following assertion will fail if\r
+ * this is not the case (if some bits represent a sub-priority).\r
+\r
+ * If the application only uses CMSIS libraries for interrupt\r
+ * configuration then the correct setting can be achieved on all Cortex-M\r
+ * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the\r
+ * scheduler. Note however that some vendor specific peripheral libraries\r
+ * assume a non-zero priority group setting, in which cases using a value\r
+ * of zero will result in unpredictable behaviour. */\r
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );\r
}\r
\r
#endif /* configASSERT_DEFINED */\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
+/*-----------------------------------------------------------*/\r