]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Source/portable/GCC/ARM_CA9/port.c
+ New feature added: Task notifications.
[freertos] / FreeRTOS / Source / portable / GCC / ARM_CA9 / port.c
index b05eedecf8da40e0415ffea7690b1fa10f886800..16998062e5d1acaec346bd9d5f8645b8ad44ecbb 100644 (file)
@@ -1,5 +1,5 @@
 /*\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
@@ -120,7 +122,7 @@ this value. */
 \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
@@ -130,8 +132,7 @@ context. */
 #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
@@ -147,24 +148,43 @@ point is zero. */
 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
@@ -173,6 +193,11 @@ mode. */
  */\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
@@ -232,7 +257,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
        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
@@ -275,6 +300,20 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
 }\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
@@ -320,13 +359,6 @@ uint32_t ulAPSR;
        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
@@ -336,18 +368,26 @@ uint32_t ulAPSR;
 \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
@@ -362,13 +402,23 @@ void vPortEndScheduler( void )
 \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
@@ -396,16 +446,14 @@ void FreeRTOS_Tick_Handler( void )
 {\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
@@ -415,6 +463,7 @@ void FreeRTOS_Tick_Handler( void )
 \r
        /* Ensure all interrupt priorities are active again. */\r
        portCLEAR_INTERRUPT_MASK();\r
+       configCLEAR_TICK_INTERRUPT();\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -427,7 +476,7 @@ uint32_t ulInitialFPSCR = 0;
        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
@@ -444,10 +493,10 @@ uint32_t ulPortSetInterruptMask( void )
 {\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
@@ -455,13 +504,11 @@ uint32_t ulReturn;
        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
@@ -484,12 +531,8 @@ uint32_t ulReturn;
                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