/*\r
- FreeRTOS V8.0.0:rc1 - Copyright (C) 2014 Real Time Engineers Ltd.\r
+ FreeRTOS V8.1.2 - Copyright (C) 2014 Real Time Engineers Ltd.\r
All rights reserved\r
\r
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
the terms of the GNU General Public License (version 2) as published by the\r
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
\r
- >>! NOTE: The modification to the GPL is included to allow you to distribute\r
- >>! a combined work that includes FreeRTOS without being obliged to provide\r
- >>! the source code for proprietary components outside of the FreeRTOS\r
- >>! kernel.\r
+ >>! NOTE: The modification to the GPL is included to allow you to !<<\r
+ >>! distribute a combined work that includes FreeRTOS without being !<<\r
+ >>! obliged to provide the source code for proprietary components !<<\r
+ >>! outside of the FreeRTOS kernel. !<<\r
\r
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )\r
#endif\r
\r
-#ifndef configINSTALL_FREERTOS_VECTOR_TABLE\r
- #warning configINSTALL_FREERTOS_VECTOR_TABLE was undefined. Defaulting configINSTALL_FREERTOS_VECTOR_TABLE to 0.\r
+/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in\r
+portmacro.h. */\r
+#ifndef configCLEAR_TICK_INTERRUPT\r
+ #define configCLEAR_TICK_INTERRUPT()\r
#endif\r
\r
/* A critical section is exited when the critical section nesting count reaches\r
\r
/* In all GICs 255 can be written to the priority mask register to unmask all\r
(but the lowest) interrupt priority. */\r
-#define portUNMASK_VALUE ( 0xFF )\r
+#define portUNMASK_VALUE ( 0xFFUL )\r
\r
/* Tasks are not created with a floating point context, but can be given a\r
floating point context after they have been created. A variable is stored as\r
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )\r
\r
/* Constants required to setup the initial task context. */\r
-#warning FIQ is disabled\r
-#define portINITIAL_SPSR ( ( StackType_t ) 0x5f ) /* System mode, ARM mode, IRQ enabled FIQ disabled. 1f is required to enable FIQ. */\r
+#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */\r
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )\r
#define portINTERRUPT_ENABLE_BIT ( 0x80UL )\r
#define portTHUMB_MODE_ADDRESS ( 0x01UL )\r
mode. */\r
#define portAPSR_USER_MODE ( 0x10 )\r
\r
+/* The critical section macros only mask interrupts up to an application\r
+determined priority level. Sometimes it is necessary to turn interrupt off in\r
+the CPU itself before modifying certain hardware registers. */\r
+#define portCPU_IRQ_DISABLE() \\r
+ __asm volatile ( "CPSID i" ); \\r
+ __asm volatile ( "DSB" ); \\r
+ __asm volatile ( "ISB" );\r
+\r
+#define portCPU_IRQ_ENABLE() \\r
+ __asm volatile ( "CPSIE i" ); \\r
+ __asm volatile ( "DSB" ); \\r
+ __asm volatile ( "ISB" );\r
+\r
+\r
/* Macro to unmask all interrupt priorities. */\r
-#define portCLEAR_INTERRUPT_MASK() \\r
-{ \\r
- __asm volatile ( "cpsid i" ); \\r
- __asm volatile ( "dsb" ); \\r
- __asm volatile ( "isb" ); \\r
- portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \\r
- __asm( "DSB \n" \\r
- "ISB \n" ); \\r
- __asm volatile( "cpsie i" ); \\r
- __asm volatile ( "dsb" ); \\r
- __asm volatile ( "isb" ); \\r
+#define portCLEAR_INTERRUPT_MASK() \\r
+{ \\r
+ portCPU_IRQ_DISABLE(); \\r
+ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \\r
+ __asm volatile ( "DSB \n" \\r
+ "ISB \n" ); \\r
+ portCPU_IRQ_ENABLE(); \\r
}\r
\r
#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL\r
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )\r
#define portBIT_0_SET ( ( uint8_t ) 0x01 )\r
\r
+/* Let the user override the pre-loading of the initial LR with the address of\r
+prvTaskExitError() in case is messes up unwinding of the stack in the\r
+debugger. */\r
+#ifdef configTASK_RETURN_ADDRESS\r
+ #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS\r
+#else\r
+ #define portTASK_RETURN_ADDRESS prvTaskExitError\r
+#endif\r
+\r
/*-----------------------------------------------------------*/\r
\r
/*\r
*/\r
extern void vPortRestoreTaskContext( void );\r
\r
+/*\r
+ * Used to catch tasks that attempt to return from their implementing function.\r
+ */\r
+static void prvTaskExitError( void );\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* A variable is used to keep track of the critical section nesting. This\r
pxTopOfStack--;\r
\r
/* Next all the registers other than the stack pointer. */\r
- *pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */\r
+ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */\r
pxTopOfStack--;\r
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */\r
pxTopOfStack--;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvTaskExitError( void )\r
+{\r
+ /* A function that implements a task must not exit or attempt to return to\r
+ its caller as there is nothing to return to. If a task wants to exit it\r
+ should instead call vTaskDelete( NULL ).\r
+\r
+ Artificially force an assert() to be triggered if configASSERT() is\r
+ defined, then stop here so application writers can catch the error. */\r
+ configASSERT( ulPortInterruptNesting == ~0UL );\r
+ portDISABLE_INTERRUPTS();\r
+ for( ;; );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
BaseType_t xPortStartScheduler( void )\r
{\r
uint32_t ulAPSR;\r
ulAPSR &= portAPSR_MODE_BITS_MASK;\r
configASSERT( ulAPSR != portAPSR_USER_MODE );\r
\r
- #if configINSTALL_FREERTOS_VECTOR_TABLE == 1\r
- {\r
- vPortInstallFreeRTOSVectorTable();\r
- }\r
- #endif\r
-\r
-\r
if( ulAPSR != portAPSR_USER_MODE )\r
{\r
/* Only continue if the binary point value is set to its lowest possible\r
\r
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )\r
{\r
+ /* Interrupts are turned off in the CPU itself to ensure tick does\r
+ not execute while the scheduler is being started. Interrupts are\r
+ automatically turned back on in the CPU when the first task starts\r
+ executing. */\r
+ portCPU_IRQ_DISABLE();\r
+\r
/* Start the timer that generates the tick ISR. */\r
- __asm volatile( "cpsid i" );\r
configSETUP_TICK_INTERRUPT();\r
\r
-// __asm volatile( "cpsie i" );\r
+ /* Start the first task executing. */\r
vPortRestoreTaskContext();\r
}\r
}\r
\r
/* Will only get here if xTaskStartScheduler() was called with the CPU in\r
a non-privileged mode or the binary point register was not set to its lowest\r
- possible value. */\r
+ possible value. prvTaskExitError() is referenced to prevent a compiler\r
+ warning about it being defined but not referenced in the case that the user\r
+ defines their own exit address. */\r
+ ( void ) prvTaskExitError;\r
return 0;\r
}\r
/*-----------------------------------------------------------*/\r
\r
void vPortEnterCritical( void )\r
{\r
- /* Disable interrupts as per portDISABLE_INTERRUPTS(); */\r
+ /* Mask interrupts up to the max syscall interrupt priority. */\r
ulPortSetInterruptMask();\r
\r
/* Now interrupts are disabled ulCriticalNesting can be accessed\r
directly. Increment ulCriticalNesting to keep a count of how many times\r
portENTER_CRITICAL() has been called. */\r
ulCriticalNesting++;\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
+ if( ulCriticalNesting == 1 )\r
+ {\r
+ configASSERT( ulPortInterruptNesting == 0 );\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
/* Set interrupt mask before altering scheduler structures. The tick\r
handler runs at the lowest priority, so interrupts cannot already be masked,\r
- so there is no need to save and restore the current mask value. */\r
- __asm volatile( "cpsid i" );\r
- __asm volatile ( "dsb" );\r
- __asm volatile ( "isb" );\r
- portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
- __asm( "dsb \n"\r
- "isb \n"\r
- "cpsie i \n"\r
- "dsb \n"\r
- "isb" );\r
+ so there is no need to save and restore the current mask value. It is\r
+ necessary to turn off interrupts in the CPU itself while the ICCPMR is being\r
+ updated. */\r
+ portCPU_IRQ_DISABLE();\r
+ portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
+ __asm volatile ( "dsb \n"\r
+ "isb \n" );\r
+ portCPU_IRQ_ENABLE();\r
\r
/* Increment the RTOS tick. */\r
if( xTaskIncrementTick() != pdFALSE )\r
\r
/* Ensure all interrupt priorities are active again. */\r
portCLEAR_INTERRUPT_MASK();\r
+ configCLEAR_TICK_INTERRUPT();\r
}\r
/*-----------------------------------------------------------*/\r
\r
ulPortTaskHasFPUContext = pdTRUE;\r
\r
/* Initialise the floating point status register. */\r
- __asm( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );\r
+ __asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );\r
}\r
/*-----------------------------------------------------------*/\r
\r
{\r
uint32_t ulReturn;\r
\r
- __asm volatile ( "cpsid i" );\r
- __asm volatile ( "dsb" );\r
- __asm volatile ( "isb" );\r
- if( portICCPMR_PRIORITY_MASK_REGISTER == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )\r
+ /* Interrupt in the CPU must be turned off while the ICCPMR is being\r
+ updated. */\r
+ portCPU_IRQ_DISABLE();\r
+ if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )\r
{\r
/* Interrupts were already masked. */\r
ulReturn = pdTRUE;\r
else\r
{\r
ulReturn = pdFALSE;\r
- portICCPMR_PRIORITY_MASK_REGISTER = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
- __asm( "dsb \n"\r
- "isb \n" );\r
+ portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );\r
+ __asm volatile ( "dsb \n"\r
+ "isb \n" );\r
}\r
- __asm volatile ( "cpsie i" );\r
- __asm volatile ( "dsb" );\r
- __asm volatile ( "isb" );\r
+ portCPU_IRQ_ENABLE();\r
\r
return ulReturn;\r
}\r
configMAX_SYSCALL_INTERRUPT_PRIORITY.\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( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );\r
+ interrupt entry is as fast and simple as possible. */\r
+ configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );\r
\r
/* Priority grouping: The interrupt controller (GIC) allows the bits\r
that define each interrupt's priority to be split between bits that\r