]> git.sur5r.net Git - freertos/commitdiff
Add tickless idle support in Cortex-M ports.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 16 Oct 2012 07:55:40 +0000 (07:55 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Tue, 16 Oct 2012 07:55:40 +0000 (07:55 +0000)
Change CCS R4 directory name.

git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1795 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

21 files changed:
FreeRTOS/Source/include/FreeRTOS.h
FreeRTOS/Source/include/task.h
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/port.c [new file with mode: 0644]
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portASM.asm [new file with mode: 0644]
FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portmacro.h [new file with mode: 0644]
FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h
FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
FreeRTOS/Source/portable/IAR/ARM_CM3/port.c
FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s
FreeRTOS/Source/portable/IAR/ARM_CM3/portmacro.h
FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c
FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s
FreeRTOS/Source/portable/IAR/ARM_CM4F/portmacro.h
FreeRTOS/Source/portable/MemMang/heap_1.c
FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c
FreeRTOS/Source/portable/RVDS/ARM_CM3/portmacro.h
FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c
FreeRTOS/Source/portable/RVDS/ARM_CM4F/portmacro.h
FreeRTOS/Source/tasks.c

index 1dc85c8a36934289ae137b7da6a8502905879771..c8c732886cd8f9c2f6357ac1c225537221b41e6d 100644 (file)
@@ -528,5 +528,17 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
        #define vPortFreeAligned( pvBlockToFree ) vPortFree( pvBlockToFree )\r
 #endif\r
 \r
+#ifndef portSUPPRESS_TICKS_AND_SLEEP\r
+       #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )\r
+#endif\r
+\r
+#ifndef portPRE_SLEEP_PROCESSING\r
+       #define portPRE_SLEEP_PROCESSING()\r
+#endif\r
+\r
+#ifndef portPOST_SLEEP_PROCESSING\r
+       #define portPOST_SLEEP_PROCESSING()\r
+#endif\r
+\r
 #endif /* INC_FREERTOS_H */\r
 \r
index 6c6be5248e56092f1cfe6bda4b8306df6da304e7..f38b17719b63262345c990bf51569d1d68b5069a 100644 (file)
@@ -1320,6 +1320,27 @@ unsigned portBASE_TYPE uxTaskGetTaskNumber( xTaskHandle xTask );
  */\r
 void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle );\r
 \r
+/*\r
+ * Return the amount of time, in ticks, that will pass before the kernel will\r
+ * next move a task from the Blocked state to the Running state.\r
+ */\r
+portTickType xTaskGetExpectedIdleTime( void );\r
+\r
+/*\r
+ * If tickless mode is being used, or a low power mode is implemented, then\r
+ * the tick interrupt will not execute during idle periods.  When this is the\r
+ * case, the tick count value maintained by the scheduler needs to be kept up\r
+ * to date with the actual execution time by being skipped forward by the by\r
+ * a time equal to the idle period.\r
+ */\r
+void vTaskStepTick( portTickType xTicksToJump );\r
+\r
+/*\r
+ * Returns the number of tick interrupts that have occurred while the scheduler \r
+ * has been suspended.  The count pending ticks is reset if xResetOnExit is set\r
+ * to pdTRUE.\r
+ */\r
+unsigned portBASE_TYPE uxTaskPendingTicksGet( portBASE_TYPE xResetOnExit );\r
 \r
 #ifdef __cplusplus\r
 }\r
diff --git a/FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/port.c b/FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/port.c
new file mode 100644 (file)
index 0000000..ded4850
--- /dev/null
@@ -0,0 +1,350 @@
+/*\r
+    FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
+\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
+     *    Complete, revised, and edited pdf reference manuals are also       *\r
+     *    available.                                                         *\r
+     *                                                                       *\r
+     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
+     *    ensuring you get running as quickly as possible and with an        *\r
+     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
+     *    the FreeRTOS project to continue with its mission of providing     *\r
+     *    professional grade, cross platform, de facto standard solutions    *\r
+     *    for microcontrollers - completely free of charge!                  *\r
+     *                                                                       *\r
+     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
+     *                                                                       *\r
+     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\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
+    >>>NOTE<<< The modification to the GPL is included to allow you to\r
+    distribute a combined work that includes FreeRTOS without being obliged to\r
+    provide the source code for proprietary components outside of the FreeRTOS\r
+    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
+    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+    more details. You should have received a copy of the GNU General Public\r
+    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+    by writing to Richard Barry, contact details for whom are available on the\r
+    FreeRTOS WEB site.\r
+\r
+    1 tab == 4 spaces!\r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    Having a problem?  Start by reading the FAQ "My application does   *\r
+     *    not run, what could be wrong?                                      *\r
+     *                                                                       *\r
+     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
+    license and contact details.\r
+\r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool.\r
+\r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
+    the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
+    provide a safety engineered and independently SIL3 certified version under\r
+    the SafeRTOS brand: http://www.SafeRTOS.com.\r
+*/\r
+\r
+/* FreeRTOS includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Count of the critical section nesting depth. */\r
+unsigned portLONG ulCriticalNesting = 9999;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Registers required to configure the RTI. */\r
+#define portRTI_GCTRL_REG              ( * ( ( volatile unsigned long * ) 0xFFFFFC00 ) )\r
+#define portRTI_TBCTRL_REG     ( * ( ( volatile unsigned long * ) 0xFFFFFC04 ) )\r
+#define portRTI_COMPCTRL_REG   ( * ( ( volatile unsigned long * ) 0xFFFFFC0C ) )\r
+#define portRTI_CNT0_FRC0_REG          ( * ( ( volatile unsigned long * ) 0xFFFFFC10 ) )\r
+#define portRTI_CNT0_UC0_REG   ( * ( ( volatile unsigned long * ) 0xFFFFFC14 ) )\r
+#define portRTI_CNT0_CPUC0_REG  ( * ( ( volatile unsigned long * ) 0xFFFFFC18 ) )\r
+#define portRTI_CNT0_COMP0_REG  ( * ( ( volatile unsigned long * ) 0xFFFFFC50 ) )\r
+#define portRTI_CNT0_UDCP0_REG  ( * ( ( volatile unsigned long * ) 0xFFFFFC54 ) )\r
+#define portRTI_SETINTENA_REG          ( * ( ( volatile unsigned long * ) 0xFFFFFC80 ) )\r
+#define portRTI_CLEARINTENA_REG ( * ( ( volatile unsigned long * ) 0xFFFFFC84 ) )\r
+#define portRTI_INTFLAG_REG    ( * ( ( volatile unsigned long * ) 0xFFFFFC88 ) )\r
+\r
+\r
+/* Constants required to set up the initial stack of each task. */\r
+#define portINITIAL_SPSR               ( ( portSTACK_TYPE ) 0x1F )\r
+#define portINITIAL_FPSCR              ( ( portSTACK_TYPE ) 0x00 )\r
+#define portINSTRUCTION_SIZE           ( ( portSTACK_TYPE ) 0x04 )\r
+#define portTHUMB_MODE_BIT             ( ( portSTACK_TYPE ) 0x20 )\r
+\r
+/* The number of words on the stack frame between the saved Top Of Stack and\r
+R0 (in which the parameters are passed. */\r
+#define portSPACE_BETWEEN_TOS_AND_PARAMETERS   ( 12 )\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* vPortStartFirstSTask() is defined in portASM.asm */\r
+extern void vPortStartFirstTask( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Saved as part of the task context.  Set to pdFALSE if the task does not\r
+require an FPU context. */\r
+unsigned long ulTaskHasFPUContext = 0;\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+/*\r
+ * See header file for description.\r
+ */\r
+portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
+{\r
+portSTACK_TYPE *pxOriginalTOS;\r
+\r
+       pxOriginalTOS = pxTopOfStack;\r
+\r
+       #if __TI_VFP_SUPPORT__\r
+       {\r
+               /* Ensure the stack is correctly aligned on exit. */\r
+               pxTopOfStack--;\r
+       }\r
+       #endif\r
+\r
+       /* Setup the initial stack of the task.  The stack is set exactly as\r
+       expected by the portRESTORE_CONTEXT() macro. */\r
+\r
+       /* First on the stack is the return address - which is the start of the as\r
+       the task has not executed yet.  The offset is added to make the return\r
+       address appear as it would within an IRQ ISR. */\r
+       *pxTopOfStack = ( portSTACK_TYPE ) pxCode + portINSTRUCTION_SIZE;\r
+       pxTopOfStack--;\r
+\r
+       *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;  /* R14 */\r
+       pxTopOfStack--;\r
+       *pxTopOfStack = ( portSTACK_TYPE ) pxOriginalTOS; /* Stack used when task starts goes in R13. */\r
+       pxTopOfStack--;\r
+\r
+       #ifdef portPRELOAD_TASK_REGISTERS\r
+       {\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x12121212;  /* R12 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x11111111;  /* R11 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x10101010;  /* R10 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x09090909;  /* R9 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x08080808;  /* R8 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x07070707;  /* R7 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x06060606;  /* R6 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x05050505;  /* R5 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x04040404;  /* R4 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x03030303;  /* R3 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x02020202;  /* R2 */\r
+               pxTopOfStack--;\r
+               *pxTopOfStack = ( portSTACK_TYPE ) 0x01010101;  /* R1 */\r
+               pxTopOfStack--;\r
+       }\r
+       #else\r
+       {\r
+               pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;\r
+       }\r
+       #endif\r
+\r
+       /* Function parameters are passed in R0. */\r
+       *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */\r
+       pxTopOfStack--;\r
+\r
+       /* Set the status register for system mode, with interrupts enabled. */\r
+       *pxTopOfStack = ( portSTACK_TYPE ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );\r
+\r
+       if( ( ( unsigned long ) pxCode & 0x01UL ) != 0x00 )\r
+       {\r
+               /* The task will start in thumb mode. */\r
+               *pxTopOfStack |= portTHUMB_MODE_BIT;\r
+       }\r
+\r
+       #ifdef __TI_VFP_SUPPORT__\r
+       {\r
+               pxTopOfStack--;\r
+\r
+               /* The last thing on the stack is the tasks ulUsingFPU value, which by\r
+               default is set to indicate that the stack frame does not include FPU\r
+               registers. */\r
+               *pxTopOfStack = pdFALSE;\r
+       }\r
+       #endif\r
+\r
+       return pxTopOfStack;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupTimerInterrupt(void)\r
+{\r
+       /* Disable timer 0. */\r
+       portRTI_GCTRL_REG &= 0xFFFFFFFEUL;\r
+\r
+       /* Use the internal counter. */\r
+       portRTI_TBCTRL_REG = 0x00000000U;\r
+\r
+       /* COMPSEL0 will use the RTIFRC0 counter. */\r
+       portRTI_COMPCTRL_REG = 0x00000000U;\r
+\r
+       /* Initialise the counter and the prescale counter registers. */\r
+       portRTI_CNT0_UC0_REG =  0x00000000U;\r
+       portRTI_CNT0_FRC0_REG =  0x00000000U;\r
+\r
+       /* Set Prescalar for RTI clock. */\r
+       portRTI_CNT0_CPUC0_REG = 0x00000001U;\r
+       portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;\r
+       portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;\r
+\r
+       /* Clear interrupts. */\r
+       portRTI_INTFLAG_REG =  0x0007000FU;\r
+       portRTI_CLEARINTENA_REG = 0x00070F0FU;\r
+\r
+       /* Enable the compare 0 interrupt. */\r
+       portRTI_SETINTENA_REG = 0x00000001U;\r
+       portRTI_GCTRL_REG |= 0x00000001U;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * See header file for description.\r
+ */\r
+portBASE_TYPE xPortStartScheduler(void)\r
+{\r
+       /* Start the timer that generates the tick ISR. */\r
+       prvSetupTimerInterrupt();\r
+\r
+       /* Reset the critical section nesting count read to execute the first task. */\r
+       ulCriticalNesting = 0;\r
+\r
+       /* Start the first task.  This is done from portASM.asm as ARM mode must be\r
+       used. */\r
+       vPortStartFirstTask();\r
+\r
+       /* Should not get here! */\r
+       return pdFAIL;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * See header file for description.\r
+ */\r
+void vPortEndScheduler(void)\r
+{\r
+       /* It is unlikely that the port will require this function as there\r
+       is nothing to return to. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if configUSE_PREEMPTION == 0\r
+\r
+       /* The cooperative scheduler requires a normal IRQ service routine to\r
+        * simply increment the system tick. */\r
+       __interrupt void vPortNonPreemptiveTick( void )\r
+       {\r
+               /* clear clock interrupt flag */\r
+               RTI->INTFLAG = 0x00000001;\r
+\r
+               /* Increment the tick count - this may make a delaying task ready\r
+               to run - but a context switch is not performed. */\r
+               vTaskIncrementTick();\r
+       }\r
+\r
+ #else\r
+\r
+       /*\r
+        **************************************************************************\r
+        * The preemptive scheduler ISR is written in assembler and can be found\r
+        * in the portASM.asm file. This will only get used if portUSE_PREEMPTION\r
+        * is set to 1 in portmacro.h\r
+        **************************************************************************\r
+        */\r
+       void vPortPreemptiveTick( void );\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+/*\r
+ * Disable interrupts, and keep a count of the nesting depth.\r
+ */\r
+void vPortEnterCritical( void )\r
+{\r
+       /* Disable interrupts as per portDISABLE_INTERRUPTS(); */\r
+       portDISABLE_INTERRUPTS();\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
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Decrement the critical nesting count, and if it has reached zero, re-enable\r
+ * interrupts.\r
+ */\r
+void vPortExitCritical( void )\r
+{\r
+       if( ulCriticalNesting > 0 )\r
+       {\r
+               /* Decrement the nesting count as we are leaving a critical section. */\r
+               ulCriticalNesting--;\r
+\r
+               /* If the nesting level has reached zero then interrupts should be\r
+               re-enabled. */\r
+               if( ulCriticalNesting == 0 )\r
+               {\r
+                       /* Enable interrupts as per portENABLE_INTERRUPTS(). */\r
+                       portENABLE_INTERRUPTS();\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#if __TI_VFP_SUPPORT__\r
+\r
+       void vPortTaskUsesFPU( void )\r
+       {\r
+       extern void vPortInitialiseFPSCR( void );\r
+\r
+               /* A task is registering the fact that it needs an FPU context.  Set the\r
+               FPU flag (saved as part of the task context. */\r
+               ulTaskHasFPUContext = pdTRUE;\r
+\r
+               /* Initialise the floating point status register. */\r
+               vPortInitialiseFPSCR();\r
+       }\r
+\r
+#endif /* __TI_VFP_SUPPORT__ */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
diff --git a/FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portASM.asm b/FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portASM.asm
new file mode 100644 (file)
index 0000000..af28f68
--- /dev/null
@@ -0,0 +1,263 @@
+;/*\r
+;    FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
+;      \r
+;\r
+;    ***************************************************************************\r
+;     *                                                                       *\r
+;     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
+;     *    Complete, revised, and edited pdf reference manuals are also       *\r
+;     *    available.                                                         *\r
+;     *                                                                       *\r
+;     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
+;     *    ensuring you get running as quickly as possible and with an        *\r
+;     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
+;     *    the FreeRTOS project to continue with its mission of providing     *\r
+;     *    professional grade, cross platform, de facto standard solutions    *\r
+;     *    for microcontrollers - completely free of charge!                  *\r
+;     *                                                                       *\r
+;     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
+;     *                                                                       *\r
+;     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+;     *                                                                       *\r
+;    ***************************************************************************\r
+;\r
+;\r
+;    This file is part of the FreeRTOS distribution.\r
+;\r
+;    FreeRTOS is free software; you can redistribute it and/or modify it under\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
+;    >>>NOTE<<< The modification to the GPL is included to allow you to\r
+;    distribute a combined work that includes FreeRTOS without being obliged to\r
+;    provide the source code for proprietary components outside of the FreeRTOS\r
+;    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
+;    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+;    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+;    more details. You should have received a copy of the GNU General Public\r
+;    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+;    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+;    by writing to Richard Barry, contact details for whom are available on the\r
+;    FreeRTOS WEB site.\r
+;\r
+;    1 tab == 4 spaces!\r
+;\r
+;    http://www.FreeRTOS.org - Documentation, latest information, license and\r
+;    contact details.\r
+;\r
+;    http://www.SafeRTOS.com - A version that is certified for use in safety\r
+;    critical systems.\r
+;\r
+;    http://www.OpenRTOS.com - Commercial support, development, porting,\r
+;    licensing and training services.\r
+;*/\r
+\r
+        .text\r
+        .arm\r
+        .ref vTaskSwitchContext\r
+        .ref vTaskIncrementTick\r
+        .ref ulTaskHasFPUContext\r
+               .ref pxCurrentTCB\r
+\r
+;/*-----------------------------------------------------------*/\r
+;\r
+; Save Task Context \r
+;\r
+portSAVE_CONTEXT .macro\r
+               DSB\r
+\r
+               ; Push R0 as we are going to use it\r
+               STMDB   SP!, {R0}\r
+\r
+               ; Set R0 to point to the task stack pointer.\r
+               STMDB   SP,{SP}^\r
+               SUB     SP, SP, #4\r
+               LDMIA   SP!,{R0}\r
+\r
+               ; Push the return address onto the stack.\r
+               STMDB   R0!, {LR}\r
+\r
+               ; Now LR has been saved, it can be used instead of R0.\r
+               MOV     LR, R0\r
+\r
+               ; Pop R0 so it can be saved onto the task stack.\r
+               LDMIA   SP!, {R0}\r
+\r
+               ; Push all the system mode registers onto the task stack.\r
+               STMDB   LR,{R0-LR}^\r
+               SUB     LR, LR, #60\r
+\r
+               ; Push the SPSR onto the task stack.\r
+               MRS     R0, SPSR\r
+               STMDB   LR!, {R0}\r
+\r
+    .if (__TI_VFP_SUPPORT__)\r
+               ;Determine if the task maintains an FPU context.\r
+               LDR     R0, ulFPUContextConst\r
+               LDR     R0, [R0]\r
+\r
+               ; Test the flag\r
+               CMP             R0, #0\r
+\r
+               ; If the task is not using a floating point context then skip the\r
+               ; saving of the FPU registers.\r
+               BEQ             PC+3\r
+               FSTMDBD LR!, {D0-D15}\r
+               FMRX    R1,  FPSCR\r
+               STMFD   LR!, {R1}\r
+\r
+               ; Save the flag\r
+               STMDB   LR!, {R0}\r
+       .endif\r
+\r
+               ; Store the new top of stack for the task.\r
+               LDR     R0, pxCurrentTCBConst\r
+               LDR     R0, [R0]\r
+               STR     LR, [R0]\r
+\r
+        .endm\r
+\r
+;/*-----------------------------------------------------------*/\r
+;\r
+; Restore Task Context\r
+;\r
+portRESTORE_CONTEXT .macro\r
+               LDR             R0, pxCurrentTCBConst\r
+               LDR             R0, [R0]\r
+               LDR             LR, [R0]\r
+\r
+       .if (__TI_VFP_SUPPORT__)\r
+               ; The floating point context flag is the first thing on the stack.\r
+               LDR             R0, ulFPUContextConst\r
+               LDMFD   LR!, {R1}\r
+               STR             R1, [R0]\r
+\r
+               ; Test the flag\r
+               CMP             R1, #0\r
+\r
+               ; If the task is not using a floating point context then skip the\r
+               ; VFP register loads.\r
+               BEQ             PC+3\r
+\r
+               ; Restore the floating point context.\r
+               LDMFD   LR!, {R0}\r
+               FLDMIAD LR!, {D0-D15}\r
+               FMXR    FPSCR, R0\r
+       .endif\r
+\r
+               ; Get the SPSR from the stack.\r
+               LDMFD   LR!, {R0}\r
+               MSR             SPSR_CF, R0\r
+\r
+               ; Restore all system mode registers for the task.\r
+               LDMFD   LR, {R0-R14}^\r
+\r
+               ; Restore the return address.\r
+               LDR             LR, [LR, #+60]\r
+\r
+               ; And return - correcting the offset in the LR to obtain the\r
+               ; correct address.\r
+               SUBS    PC, LR, #4\r
+        .endm\r
+\r
+;/*-----------------------------------------------------------*/\r
+; Start the first task by restoring its context.\r
+\r
+        .def vPortStartFirstTask\r
+\r
+vPortStartFirstTask:\r
+        portRESTORE_CONTEXT\r
+\r
+;/*-----------------------------------------------------------*/\r
+; Yield to another task.\r
+\r
+        .def vPortYieldProcessor\r
+\r
+vPortYieldProcessor:\r
+               ; Within an IRQ ISR the link register has an offset from the true return\r
+               ; address.  SWI doesn't do this. Add the offset manually so the ISR\r
+               ; return code can be used.\r
+        ADD     LR, LR, #4\r
+\r
+        ; First save the context of the current task.\r
+        portSAVE_CONTEXT\r
+\r
+        ; Select the next task to execute. */\r
+        BL      vTaskSwitchContext\r
+\r
+        ; Restore the context of the task selected to execute.\r
+        portRESTORE_CONTEXT\r
+\r
+;/*-----------------------------------------------------------*/\r
+; Yield to another task from within the FreeRTOS API\r
+\r
+               .def vPortYeildWithinAPI\r
+\r
+vPortYeildWithinAPI:\r
+               ; Save the context of the current task.\r
+\r
+        portSAVE_CONTEXT\r
+               ; Clear SSI flag.\r
+               MOVW    R0, #0xFFF4\r
+               MOVT    R0, #0xFFFF\r
+               LDR     R0, [R0]\r
+\r
+               ; Select the next task to execute. */\r
+        BL      vTaskSwitchContext\r
+\r
+        ; Restore the context of the task selected to execute.\r
+        portRESTORE_CONTEXT\r
+\r
+;/*-----------------------------------------------------------*/\r
+; Preemptive Tick\r
+\r
+        .def vPortPreemptiveTick\r
+\r
+vPortPreemptiveTick:\r
+\r
+               ; Save the context of the current task.\r
+        portSAVE_CONTEXT\r
+\r
+        ; Clear interrupt flag\r
+        MOVW    R0, #0xFC88\r
+        MOVT    R0, #0xFFFF\r
+        MOV     R1, #1\r
+        STR     R1, [R0]\r
+\r
+        ; Increment the tick count, making any adjustments to the blocked lists\r
+        ; that may be necessary.\r
+        BL      vTaskIncrementTick\r
+\r
+        ; Select the next task to execute.\r
+        BL      vTaskSwitchContext\r
+\r
+        ; Restore the context of the task selected to execute.\r
+        portRESTORE_CONTEXT\r
+\r
+;-------------------------------------------------------------------------------\r
+\r
+               .def ulPortCountLeadingZeros\r
+\r
+ulPortCountLeadingZeros:\r
+\r
+               CLZ             R0, R0\r
+               BX              LR\r
+\r
+;-------------------------------------------------------------------------------\r
+\r
+       .if (__TI_VFP_SUPPORT__)\r
+\r
+               .def vPortInitialiseFPSCR\r
+\r
+vPortInitialiseFPSCR:\r
+\r
+               MOV             R0, #0\r
+               FMXR    FPSCR, R0\r
+               BX              LR\r
+\r
+       .endif ;__TI_VFP_SUPPORT__\r
+\r
+\r
+pxCurrentTCBConst      .word   pxCurrentTCB\r
+ulFPUContextConst      .word   ulTaskHasFPUContext\r
+;-------------------------------------------------------------------------------\r
+\r
diff --git a/FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portmacro.h b/FreeRTOS/Source/portable/CCS/ARM_Cortex-R4/portmacro.h
new file mode 100644 (file)
index 0000000..22966d9
--- /dev/null
@@ -0,0 +1,145 @@
+/*\r
+    FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
+       \r
+\r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    FreeRTOS tutorial books are available in pdf and paperback.        *\r
+     *    Complete, revised, and edited pdf reference manuals are also       *\r
+     *    available.                                                         *\r
+     *                                                                       *\r
+     *    Purchasing FreeRTOS documentation will not only help you, by       *\r
+     *    ensuring you get running as quickly as possible and with an        *\r
+     *    in-depth knowledge of how to use FreeRTOS, it will also help       *\r
+     *    the FreeRTOS project to continue with its mission of providing     *\r
+     *    professional grade, cross platform, de facto standard solutions    *\r
+     *    for microcontrollers - completely free of charge!                  *\r
+     *                                                                       *\r
+     *    >>> See http://www.FreeRTOS.org/Documentation for details. <<<     *\r
+     *                                                                       *\r
+     *    Thank you for using FreeRTOS, and thank you for your support!      *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+\r
+    This file is part of the FreeRTOS distribution.\r
+\r
+    FreeRTOS is free software; you can redistribute it and/or modify it under\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
+    >>>NOTE<<< The modification to the GPL is included to allow you to\r
+    distribute a combined work that includes FreeRTOS without being obliged to\r
+    provide the source code for proprietary components outside of the FreeRTOS\r
+    kernel.  FreeRTOS is distributed in the hope that it will be useful, but\r
+    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for\r
+    more details. You should have received a copy of the GNU General Public\r
+    License and the FreeRTOS license exception along with FreeRTOS; if not it\r
+    can be viewed here: http://www.freertos.org/a00114.html and also obtained\r
+    by writing to Richard Barry, contact details for whom are available on the\r
+    FreeRTOS WEB site.\r
+\r
+    1 tab == 4 spaces!\r
+    \r
+    ***************************************************************************\r
+     *                                                                       *\r
+     *    Having a problem?  Start by reading the FAQ "My application does   *\r
+     *    not run, what could be wrong?                                      *\r
+     *                                                                       *\r
+     *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
+     *                                                                       *\r
+    ***************************************************************************\r
+\r
+    \r
+    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+    license and contact details.\r
+    \r
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
+    including FreeRTOS+Trace - an indispensable productivity tool.\r
+\r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
+    the code with commercial support, indemnification, and middleware, under \r
+    the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
+    provide a safety engineered and independently SIL3 certified version under \r
+    the SafeRTOS brand: http://www.SafeRTOS.com.\r
+*/\r
+\r
+#ifndef __PORTMACRO_H__\r
+#define __PORTMACRO_H__\r
+\r
+/*-----------------------------------------------------------\r
+ * Port specific definitions.\r
+ *\r
+ * The settings in this file configure FreeRTOS correctly for the\r
+ * given hardware and compiler.\r
+ *\r
+ * These settings should not be altered.\r
+ *-----------------------------------------------------------\r
+ */\r
+\r
+/* Type definitions. */\r
+#define portCHAR        char\r
+#define portFLOAT       float\r
+#define portDOUBLE      double\r
+#define portLONG        long\r
+#define portSHORT       short\r
+#define portSTACK_TYPE  unsigned long\r
+#define portBASE_TYPE   long\r
+\r
+#if (configUSE_16_BIT_TICKS == 1)\r
+    typedef unsigned portSHORT portTickType;\r
+    #define portMAX_DELAY (portTickType) 0xFFFF\r
+#else\r
+    typedef unsigned portLONG portTickType;\r
+    #define portMAX_DELAY (portTickType) 0xFFFFFFFFF\r
+#endif\r
+\r
+\r
+/* Architecture specifics. */\r
+#define portSTACK_GROWTH    (-1)\r
+#define portTICK_RATE_MS    ((portTickType) 1000 / configTICK_RATE_HZ)         \r
+#define portBYTE_ALIGNMENT  8\r
+\r
+/* Critical section handling. */\r
+extern void vPortEnterCritical(void);\r
+extern void vPortExitCritical(void);\r
+#define portENTER_CRITICAL()           vPortEnterCritical()\r
+#define portEXIT_CRITICAL()                    vPortExitCritical()\r
+#define portDISABLE_INTERRUPTS()       asm( " CPSID I" )\r
+#define portENABLE_INTERRUPTS()                asm( " CPSIE I" )\r
+\r
+/* Scheduler utilities. */\r
+#define portYIELD()                    _call_swi( 0 )\r
+#define portSYS_SSIR1_REG                      ( * ( ( volatile unsigned long * ) 0xFFFFFFB0 ) )\r
+#define portSYS_SSIR1_SSKEY                    ( 0x7500UL )\r
+#define portYIELD_WITHIN_API()         { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY;  ( void ) portSYS_SSIR1_REG; }\r
+#define portYIELD_FROM_ISR()           { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY;  ( void ) portSYS_SSIR1_REG; }\r
+\r
+/* Architecture specific optimisations. */\r
+#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
+\r
+       /* Generic helper function. */\r
+       unsigned long ulPortCountLeadingZeros( unsigned long ulBitmap );\r
+\r
+       /* Check the configuration. */\r
+       #if( configMAX_PRIORITIES > 32 )\r
+               #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.\r
+       #endif\r
+\r
+       /* Store/clear the ready priorities in a bit map. */\r
+       #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )\r
+       #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )\r
+\r
+       /*-----------------------------------------------------------*/\r
+\r
+       #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) )\r
+\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+\r
+\r
+/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+#define portTASK_FUNCTION(vFunction, pvParameters)       void vFunction(void *pvParameters)\r
+#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)\r
+\r
+#endif /* __PORTMACRO_H__ */\r
+\r
index a02804adeefeb9af2046be4fbec410392d4d99c3..15bf7b4e59d1ca324c3ee7bb996eae3e5d0fa811 100644 (file)
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
@@ -79,17 +79,35 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
        #define configKERNEL_INTERRUPT_PRIORITY 255\r
 #endif\r
 \r
-/* Constants required to manipulate the NVIC. */\r
-#define portNVIC_SYSTICK_CTRL          ( ( volatile unsigned long *) 0xe000e010 )\r
-#define portNVIC_SYSTICK_LOAD          ( ( volatile unsigned long *) 0xe000e014 )\r
-#define portNVIC_INT_CTRL                      ( ( volatile unsigned long *) 0xe000ed04 )\r
-#define portNVIC_SYSPRI2                       ( ( volatile unsigned long *) 0xe000ed20 )\r
-#define portNVIC_SYSTICK_CLK           0x00000004\r
-#define portNVIC_SYSTICK_INT           0x00000002\r
-#define portNVIC_SYSTICK_ENABLE                0x00000001\r
-#define portNVIC_PENDSVSET                     0x10000000\r
-#define portNVIC_PENDSV_PRI                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
-#define portNVIC_SYSTICK_PRI           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
+#ifndef configSYSTICK_CLOCK_HZ\r
+       #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL;\r
+       #endif\r
+#else /* configSYSTICK_CLOCK_HZ */\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               /* Assumes the SysTick clock is slower than the CPU clock. */\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );\r
+       #endif\r
+#endif /* configSYSTICK_CLOCK_HZ */\r
+\r
+/* Constants required to manipulate the core.  Registers first... */\r
+#define portNVIC_SYSTICK_CTRL_REG                      ( * ( ( volatile unsigned long * ) 0xe000e010 ) )\r
+#define portNVIC_SYSTICK_LOAD_REG                      ( * ( ( volatile unsigned long * ) 0xe000e014 ) )\r
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG     ( * ( ( volatile unsigned long * ) 0xe000e018 ) )\r
+#define portNVIC_INT_CTRL_REG                          ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )\r
+#define portNVIC_SYSPRI2_REG                           ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )\r
+/* ...then bits in the registers. */\r
+#define portNVIC_SYSTICK_CLK_BIT                       ( 1UL << 2UL )\r
+#define portNVIC_SYSTICK_INT_BIT                       ( 1UL << 1UL )\r
+#define portNVIC_SYSTICK_ENABLE_BIT                    ( 1UL << 0UL )\r
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT                ( 1UL << 16UL )\r
+#define portNVIC_PENDSVSET_BIT                         ( 1UL << 28UL )\r
+#define portNVIC_PENDSVCLEAR_BIT                       ( 1UL << 27UL )\r
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT                ( 1UL << 25UL )\r
+\r
+#define portNVIC_PENDSV_PRI                            ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
+#define portNVIC_SYSTICK_PRI                   ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
 /* Constants required to set up the initial stack. */\r
 #define portINITIAL_XPSR                       ( 0x01000000 )\r
@@ -119,6 +137,22 @@ void vPortSVCHandler( void ) __attribute__ (( naked ));
  */\r
 static void prvPortStartFirstTask( void ) __attribute__ (( naked ));\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The number of SysTick increments that make up one tick period.\r
+ */\r
+static unsigned long ulTimerReloadValueForOneTick = 0;\r
+\r
+/*\r
+ * The maximum number of tick periods that can be suppressed is limited by the\r
+ * 24 bit resolution of the SysTick timer.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+       static unsigned long xMaximumPossibleSuppressedTicks = 0;\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 /*\r
@@ -180,13 +214,13 @@ static void prvPortStartFirstTask( void )
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
-       /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  \r
+       /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.\r
        See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */\r
        configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
 \r
        /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */\r
-       *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;\r
-       *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
 \r
        /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
        here already. */\r
@@ -213,7 +247,7 @@ void vPortEndScheduler( void )
 void vPortYieldFromISR( void )\r
 {\r
        /* Set a PendSV to request a context switch. */\r
-       *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+       portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -234,6 +268,34 @@ void vPortExitCritical( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+__attribute__(( naked )) unsigned long ulPortSetInterruptMask( void )\r
+{\r
+       __asm volatile                                                                                                          \\r
+       (                                                                                                                                       \\r
+               "       mrs r0, basepri                                                                                 \n" \\r
+               "       mov r1, %0                                                                                              \n"     \\r
+               "       msr basepri, r1                                                                                 \n" \\r
+               "       bx lr                                                                                                   \n" \\r
+               :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1"    \\r
+       );\r
+\r
+       /* This return will not be reached but is necessary to prevent compiler\r
+       warnings. */\r
+       return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+__attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskValue )\r
+{\r
+       __asm volatile                                                                                                  \\r
+       (                                                                                                                               \\r
+               "       msr basepri, r0                                                                         \n"     \\r
+               "       bx lr                                                                                           \n" \\r
+               :::"r0"                                                                                                         \\r
+       );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 void xPortPendSVHandler( void )\r
 {\r
        /* This is a naked function. */\r
@@ -271,30 +333,142 @@ void xPortPendSVHandler( void )
 \r
 void xPortSysTickHandler( void )\r
 {\r
-unsigned long ulDummy;\r
-\r
        /* If using preemption, also force a context switch. */\r
        #if configUSE_PREEMPTION == 1\r
-               *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+               portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
        #endif\r
 \r
-       ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       #endif\r
+\r
+       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
                vTaskIncrementTick();\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+       __attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+       {\r
+       unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+\r
+               /* Make sure the SysTick reload value does not overflow the counter. */\r
+               if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+               {\r
+                       xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+               }\r
+\r
+               /* Calculate the reload value required to wait xExpectedIdleTime\r
+               tick periods.  -1 is used because this code will execute part way\r
+               through one of the tick periods, and the fraction of a tick period is\r
+               accounted for later. */\r
+               ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+               if( ulReloadValue > ulStoppedTimerCompensation )\r
+               {\r
+                       ulReloadValue -= ulStoppedTimerCompensation;\r
+               }\r
+\r
+               /* Stop the SysTick momentarily.  The time the SysTick is stopped for\r
+               is accounted for as best it can be, but using the tickless mode will\r
+               inevitably result in some tiny drift of the time maintained by the\r
+               kernel with respect to calendar time. */\r
+               portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+               /* If a context switch is pending then abandon the low power entry as\r
+               the context switch might have been pended by an external interrupt that\r
+               requires processing. */\r
+               if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+               {\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+               }\r
+               else\r
+               {\r
+                       /* Adjust the reload value to take into account that the current\r
+                       time slice is already partially complete. */\r
+                       ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+                       portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
+\r
+                       /* Clear the SysTick count flag and set the count value back to\r
+                       zero. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       /* Sleep until something happens. */\r
+                       portPRE_SLEEP_PROCESSING();\r
+                       __asm volatile( "wfi" );\r
+                       portPOST_SLEEP_PROCESSING();\r
+\r
+                       /* Stop SysTick.  Again, the time the SysTick is stopped for is\r
+                       accounted for as best it can be, but using the tickless mode will\r
+                       inevitably result in some tiny drift of the time maintained by the\r
+                       kernel with respect to calendar time. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+                       if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
+                       {\r
+                               /* The tick interrupt has already executed, and the SysTick\r
+                               count reloaded with the portNVIC_SYSTICK_LOAD_REG value.\r
+                               Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of\r
+                               this tick period. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );\r
+\r
+                               /* The tick interrupt handler will already have pended the tick\r
+                               processing in the kernel.  As the pending tick will be\r
+                               processed as soon as this function exits, the tick value\r
+                               maintained by the tick is stepped forward by one less than the\r
+                               time spent waiting. */\r
+                               ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Something other than the tick interrupt ended the sleep.\r
+                               Work out how long the sleep lasted. */\r
+                               ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;\r
+\r
+                               /* How many complete tick periods passed while the processor\r
+                               was waiting? */\r
+                               ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;\r
+\r
+                               /* The reload value is set to whatever fraction of a single tick\r
+                               period remains. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;\r
+                       }\r
+\r
+                       /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
+                       again, then set portNVIC_SYSTICK_LOAD_REG back to its standard\r
+                       value. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       vTaskStepTick( ulCompleteTickPeriods );\r
+               }\r
+       }\r
+\r
+#endif /* #if configUSE_TICKLESS_IDLE */\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * Setup the systick timer to generate the tick interrupts at the required\r
  * frequency.\r
  */\r
 void prvSetupTimerInterrupt( void )\r
 {\r
+       /* Calculate the constants required to configure the tick interrupt. */\r
+       ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
+       #endif /* configUSE_TICKLESS_IDLE */\r
+\r
        /* Configure SysTick to interrupt at the requested rate. */\r
-       *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
-       *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;\r
+       portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index 75979f303b7e726e46c1566178f407825e2c3b85..d244b78960708828c06553256ece405428920edf 100644 (file)
@@ -109,62 +109,36 @@ extern "C" {
 \r
 /* Scheduler utilities. */\r
 extern void vPortYieldFromISR( void );\r
-\r
 #define portYIELD()                                    vPortYieldFromISR()\r
-\r
 #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()\r
 /*-----------------------------------------------------------*/\r
 \r
-\r
 /* Critical section management. */\r
-\r
-/*\r
- * Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other\r
- * registers.  r0 is clobbered.\r
- */\r
-#define portSET_INTERRUPT_MASK()                                               \\r
-       __asm volatile                                                                          \\r
-       (                                                                                                       \\r
-               "       mov r0, %0                                                              \n"     \\r
-               "       msr basepri, r0                                                 \n" \\r
-               ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0"        \\r
-       )\r
-\r
-/*\r
- * Set basepri back to 0 without effective other registers.\r
- * r0 is clobbered.  FAQ:  Setting BASEPRI to 0 is not a bug.  Please see\r
- * http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing.\r
- */\r
-#define portCLEAR_INTERRUPT_MASK()                     \\r
-       __asm volatile                                                  \\r
-       (                                                                               \\r
-               "       mov r0, #0                                      \n"     \\r
-               "       msr basepri, r0                         \n"     \\r
-               :::"r0"                                                         \\r
-       )\r
-\r
-/* FAQ:  Setting BASEPRI to 0 in portCLEAR_INTERRUPT_MASK_FROM_ISR() is not a\r
-bug.  Please see http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before\r
-disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              0;portSET_INTERRUPT_MASK()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   portCLEAR_INTERRUPT_MASK();(void)x\r
-\r
-\r
 extern void vPortEnterCritical( void );\r
 extern void vPortExitCritical( void );\r
-\r
-#define portDISABLE_INTERRUPTS()       portSET_INTERRUPT_MASK()\r
-#define portENABLE_INTERRUPTS()                portCLEAR_INTERRUPT_MASK()\r
-#define portENTER_CRITICAL()           vPortEnterCritical()\r
-#define portEXIT_CRITICAL()                    vPortExitCritical()\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMaskValue );\r
+#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask(x)\r
+#define portDISABLE_INTERRUPTS()                               ulPortSetInterruptMask()\r
+#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask(0)\r
+#define portENTER_CRITICAL()                                   vPortEnterCritical()\r
+#define portEXIT_CRITICAL()                                            vPortExitCritical()\r
 /*-----------------------------------------------------------*/\r
 \r
-/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+not necessary for to use this port.  They are defined so the common demo files\r
+(which build with all the ports) will build. */\r
 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+/*-----------------------------------------------------------*/\r
 \r
-#define portNOP()\r
+/* Tickless idle/low power functionality. */\r
+extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* Architecture specific optimisations. */\r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
        /* Generic helper function. */\r
@@ -189,8 +163,12 @@ extern void vPortExitCritical( void );
 \r
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )\r
 \r
-#endif /* taskRECORD_READY_PRIORITY */\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+\r
+/*-----------------------------------------------------------*/\r
 \r
+/* portNOP() is not required by this port. */\r
+#define portNOP()\r
 \r
 #ifdef __cplusplus\r
 }\r
index c2c143fe2c24ea99f547d2220c7da7a581df411e..34e0a463213032a9a55c9c1128dd2d5361d97e70 100644 (file)
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
        #error This port can only be used when the project options are configured to enable hardware floating point support.\r
 #endif\r
 \r
-/* Constants required to manipulate the NVIC. */\r
-#define portNVIC_SYSTICK_CTRL          ( ( volatile unsigned long * ) 0xe000e010 )\r
-#define portNVIC_SYSTICK_LOAD          ( ( volatile unsigned long * ) 0xe000e014 )\r
-#define portNVIC_INT_CTRL                      ( ( volatile unsigned long * ) 0xe000ed04 )\r
-#define portNVIC_SYSPRI2                       ( ( volatile unsigned long * ) 0xe000ed20 )\r
-#define portNVIC_SYSTICK_CLK           0x00000004\r
-#define portNVIC_SYSTICK_INT           0x00000002\r
-#define portNVIC_SYSTICK_ENABLE                0x00000001\r
-#define portNVIC_PENDSVSET                     0x10000000\r
-#define portNVIC_PENDSV_PRI                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
-#define portNVIC_SYSTICK_PRI           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
+#ifndef configSYSTICK_CLOCK_HZ\r
+       #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL;\r
+       #endif\r
+#else /* configSYSTICK_CLOCK_HZ */\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               /* Assumes the SysTick clock is slower than the CPU clock. */\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );\r
+       #endif\r
+#endif /* configSYSTICK_CLOCK_HZ */\r
+\r
+/* Constants required to manipulate the core.  Registers first... */\r
+#define portNVIC_SYSTICK_CTRL_REG                      ( * ( ( volatile unsigned long * ) 0xe000e010 ) )\r
+#define portNVIC_SYSTICK_LOAD_REG                      ( * ( ( volatile unsigned long * ) 0xe000e014 ) )\r
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG     ( * ( ( volatile unsigned long * ) 0xe000e018 ) )\r
+#define portNVIC_INT_CTRL_REG                          ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )\r
+#define portNVIC_SYSPRI2_REG                           ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )\r
+/* ...then bits in the registers. */\r
+#define portNVIC_SYSTICK_CLK_BIT                       ( 1UL << 2UL )\r
+#define portNVIC_SYSTICK_INT_BIT                       ( 1UL << 1UL )\r
+#define portNVIC_SYSTICK_ENABLE_BIT                    ( 1UL << 0UL )\r
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT                ( 1UL << 16UL )\r
+#define portNVIC_PENDSVSET_BIT                         ( 1UL << 28UL )\r
+#define portNVIC_PENDSVCLEAR_BIT                       ( 1UL << 27UL )\r
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT                ( 1UL << 25UL )\r
+\r
+#define portNVIC_PENDSV_PRI                            ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )\r
+#define portNVIC_SYSTICK_PRI                   ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )\r
 \r
 /* Constants required to manipulate the VFP. */\r
 #define portFPCCR                                      ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */\r
@@ -119,13 +137,28 @@ void vPortSVCHandler( void ) __attribute__ (( naked ));
 /*\r
  * Start first task is a separate function so it can be tested in isolation.\r
  */\r
-static void vPortStartFirstTask( void ) __attribute__ (( naked ));\r
+static void prvPortStartFirstTask( void ) __attribute__ (( naked ));\r
 \r
 /*\r
  * Function to enable the VFP.\r
  */\r
  static void vPortEnableVFP( void ) __attribute__ (( naked ));\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The number of SysTick increments that make up one tick period.\r
+ */\r
+static unsigned long ulTimerReloadValueForOneTick = 0;\r
+\r
+/*\r
+ * The maximum number of tick periods that can be suppressed is limited by the\r
+ * 24 bit resolution of the SysTick timer.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+       static unsigned long xMaximumPossibleSuppressedTicks = 0;\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -180,7 +213,7 @@ void vPortSVCHandler( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void vPortStartFirstTask( void )\r
+static void prvPortStartFirstTask( void )\r
 {\r
        __asm volatile(\r
                                        " ldr r0, =0xE000ED08   \n" /* Use the NVIC offset register to locate the stack. */\r
@@ -199,13 +232,13 @@ static void vPortStartFirstTask( void )
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
-       /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  \r
+       /* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.\r
        See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */\r
        configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
 \r
-       /* Make PendSV and SysTick the lowest priority interrupts. */\r
-       *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;\r
-       *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;\r
+       /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */\r
+       portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
 \r
        /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
        here already. */\r
@@ -221,7 +254,7 @@ portBASE_TYPE xPortStartScheduler( void )
        *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;\r
 \r
        /* Start the first task. */\r
-       vPortStartFirstTask();\r
+       prvPortStartFirstTask();\r
 \r
        /* Should not get here! */\r
        return 0;\r
@@ -238,7 +271,7 @@ void vPortEndScheduler( void )
 void vPortYieldFromISR( void )\r
 {\r
        /* Set a PendSV to request a context switch. */\r
-       *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+       portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -259,6 +292,34 @@ void vPortExitCritical( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+__attribute__(( naked )) unsigned long ulPortSetInterruptMask( void )\r
+{\r
+       __asm volatile                                                                                                          \\r
+       (                                                                                                                                       \\r
+               "       mrs r0, basepri                                                                                 \n" \\r
+               "       mov r1, %0                                                                                              \n"     \\r
+               "       msr basepri, r1                                                                                 \n" \\r
+               "       bx lr                                                                                                   \n" \\r
+               :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "r0", "r1"    \\r
+       );\r
+\r
+       /* This return will not be reached but is necessary to prevent compiler\r
+       warnings. */\r
+       return 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+__attribute__(( naked )) void vPortClearInterruptMask( unsigned long ulNewMaskValue )\r
+{\r
+       __asm volatile                                                                                                  \\r
+       (                                                                                                                               \\r
+               "       msr basepri, r0                                                                         \n"     \\r
+               "       bx lr                                                                                           \n" \\r
+               :::"r0"                                                                                                         \\r
+       );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
 void xPortPendSVHandler( void )\r
 {\r
        /* This is a naked function. */\r
@@ -307,30 +368,143 @@ void xPortPendSVHandler( void )
 \r
 void xPortSysTickHandler( void )\r
 {\r
-unsigned long ulDummy;\r
-\r
        /* If using preemption, also force a context switch. */\r
        #if configUSE_PREEMPTION == 1\r
-               *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+               portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
+       #endif\r
+\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
        #endif\r
 \r
-       ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
                vTaskIncrementTick();\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+       __attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+       {\r
+       unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+\r
+               /* Make sure the SysTick reload value does not overflow the counter. */\r
+               if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+               {\r
+                       xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+               }\r
+\r
+               /* Calculate the reload value required to wait xExpectedIdleTime\r
+               tick periods.  -1 is used because this code will execute part way\r
+               through one of the tick periods, and the fraction of a tick period is\r
+               accounted for later. */\r
+               ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+               if( ulReloadValue > ulStoppedTimerCompensation )\r
+               {\r
+                       ulReloadValue -= ulStoppedTimerCompensation;\r
+               }\r
+\r
+               /* Stop the SysTick momentarily.  The time the SysTick is stopped for\r
+               is accounted for as best it can be, but using the tickless mode will\r
+               inevitably result in some tiny drift of the time maintained by the\r
+               kernel with respect to calendar time. */\r
+               portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+               /* If a context switch is pending then abandon the low power entry as\r
+               the context switch might have been pended by an external interrupt that\r
+               requires processing. */\r
+               if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+               {\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+               }\r
+               else\r
+               {\r
+                       /* Adjust the reload value to take into account that the current\r
+                       time slice is already partially complete. */\r
+                       ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+                       portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
+\r
+                       /* Clear the SysTick count flag and set the count value back to\r
+                       zero. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       /* Sleep until something happens. */\r
+                       portPRE_SLEEP_PROCESSING();\r
+                       __asm volatile( "wfi" );\r
+                       portPOST_SLEEP_PROCESSING();\r
+\r
+                       /* Stop SysTick.  Again, the time the SysTick is stopped for is\r
+                       accounted for as best it can be, but using the tickless mode will\r
+                       inevitably result in some tiny drift of the time maintained by the\r
+                       kernel with respect to calendar time. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+                       if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
+                       {\r
+                               /* The tick interrupt has already executed, and the SysTick\r
+                               count reloaded with the portNVIC_SYSTICK_LOAD_REG value.\r
+                               Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of\r
+                               this tick period. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );\r
+\r
+                               /* The tick interrupt handler will already have pended the tick\r
+                               processing in the kernel.  As the pending tick will be\r
+                               processed as soon as this function exits, the tick value\r
+                               maintained by the tick is stepped forward by one less than the\r
+                               time spent waiting. */\r
+                               ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Something other than the tick interrupt ended the sleep.\r
+                               Work out how long the sleep lasted. */\r
+                               ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;\r
+\r
+                               /* How many complete tick periods passed while the processor\r
+                               was waiting? */\r
+                               ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;\r
+\r
+                               /* The reload value is set to whatever fraction of a single tick\r
+                               period remains. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;\r
+                       }\r
+\r
+                       /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
+                       again, then set portNVIC_SYSTICK_LOAD_REG back to its standard\r
+                       value. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       vTaskStepTick( ulCompleteTickPeriods );\r
+               }\r
+       }\r
+\r
+#endif /* #if configUSE_TICKLESS_IDLE */\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * Setup the systick timer to generate the tick interrupts at the required\r
  * frequency.\r
  */\r
 void prvSetupTimerInterrupt( void )\r
 {\r
+       /* Calculate the constants required to configure the tick interrupt. */\r
+       ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
+       #endif /* configUSE_TICKLESS_IDLE */\r
+\r
+\r
        /* Configure SysTick to interrupt at the requested rate. */\r
-       *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
-       *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;\r
+       portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index afd7256e1427b5a022245e64350eaa4ae6c5de62..e710eb96ac42e63e77da94f783de75ce40b0a9b5 100644 (file)
@@ -115,48 +115,17 @@ extern void vPortYieldFromISR( void );
 #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()\r
 /*-----------------------------------------------------------*/\r
 \r
-\r
 /* Critical section management. */\r
-\r
-/* \r
- * Set basepri to portMAX_SYSCALL_INTERRUPT_PRIORITY without effecting other\r
- * registers.  r0 is clobbered.\r
- */ \r
-#define portSET_INTERRUPT_MASK()                                               \\r
-       __asm volatile                                                                          \\r
-       (                                                                                                       \\r
-               "       mov r0, %0                                                              \n"     \\r
-               "       msr basepri, r0                                                 \n" \\r
-               ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY):"r0"        \\r
-       )\r
-       \r
-/*\r
- * Set basepri back to 0 without effective other registers.\r
- * r0 is clobbered.  FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
- * http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing.\r
- */\r
-#define portCLEAR_INTERRUPT_MASK()                     \\r
-       __asm volatile                                                  \\r
-       (                                                                               \\r
-               "       mov r0, #0                                      \n"     \\r
-               "       msr basepri, r0                         \n"     \\r
-               :::"r0"                                                         \\r
-       )\r
-\r
-/* FAQ:  Setting BASEPRI to 0 in portCLEAR_INTERRUPT_MASK_FROM_ISR() is not a \r
-bug.  Please see http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before \r
-disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              0;portSET_INTERRUPT_MASK()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   portCLEAR_INTERRUPT_MASK();(void)x\r
-\r
-\r
 extern void vPortEnterCritical( void );\r
 extern void vPortExitCritical( void );\r
-\r
-#define portDISABLE_INTERRUPTS()       portSET_INTERRUPT_MASK()\r
-#define portENABLE_INTERRUPTS()                portCLEAR_INTERRUPT_MASK()\r
-#define portENTER_CRITICAL()           vPortEnterCritical()\r
-#define portEXIT_CRITICAL()                    vPortExitCritical()\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMaskValue );\r
+#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask(x)\r
+#define portDISABLE_INTERRUPTS()                               ulPortSetInterruptMask()\r
+#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask(0)\r
+#define portENTER_CRITICAL()                                   vPortEnterCritical()\r
+#define portEXIT_CRITICAL()                                            vPortExitCritical()\r
 \r
 /* There are an uneven number of items on the initial stack, so \r
 portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */\r
@@ -164,16 +133,23 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
 \r
 /*-----------------------------------------------------------*/\r
 \r
-/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+not necessary for to use this port.  They are defined so the common demo files\r
+(which build with all the ports) will build. */\r
 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+/*-----------------------------------------------------------*/\r
 \r
-#define portNOP()\r
+/* Tickless idle/low power functionality. */\r
+extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* Architecture specific optimisations. */\r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
        /* Generic helper function. */\r
-       __attribute__( ( always_inline ) ) static inline unsigned char ucPortCountLeadingZeros( ulBitmap )\r
+       __attribute__( ( always_inline ) ) static inline unsigned char ucPortCountLeadingZeros( unsigned long ulBitmap )\r
        {\r
        unsigned char ucReturn;\r
 \r
@@ -194,8 +170,12 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
 \r
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )\r
 \r
-#endif /* taskRECORD_READY_PRIORITY */\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
 \r
+/*-----------------------------------------------------------*/\r
+\r
+/* portNOP() is not required by this port. */\r
+#define portNOP()\r
 \r
 #ifdef __cplusplus\r
 }\r
index 44f3ac89690015bbd29de3c7406bb9e1cb824bd0..c4368b68b1c1ba4eeb1f3c4071589013c08f1ae9 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
        #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html\r
 #endif\r
 \r
-/* Constants required to manipulate the NVIC. */\r
-#define portNVIC_SYSTICK_CTRL          ( ( volatile unsigned long *) 0xe000e010 )\r
-#define portNVIC_SYSTICK_LOAD          ( ( volatile unsigned long *) 0xe000e014 )\r
-#define portNVIC_INT_CTRL                      ( ( volatile unsigned long *) 0xe000ed04 )\r
-#define portNVIC_SYSPRI2                       ( ( volatile unsigned long *) 0xe000ed20 )\r
-#define portNVIC_SYSTICK_CLK           0x00000004\r
-#define portNVIC_SYSTICK_INT           0x00000002\r
-#define portNVIC_SYSTICK_ENABLE                0x00000001\r
-#define portNVIC_PENDSVSET                     0x10000000\r
+#ifndef configSYSTICK_CLOCK_HZ\r
+       #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL;\r
+       #endif\r
+#else /* configSYSTICK_CLOCK_HZ */\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               /* Assumes the SysTick clock is slower than the CPU clock. */\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );\r
+       #endif\r
+#endif /* configSYSTICK_CLOCK_HZ */\r
+\r
+/* Constants required to manipulate the core.  Registers first... */\r
+#define portNVIC_SYSTICK_CTRL_REG                      ( * ( ( volatile unsigned long * ) 0xe000e010 ) )\r
+#define portNVIC_SYSTICK_LOAD_REG                      ( * ( ( volatile unsigned long * ) 0xe000e014 ) )\r
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG     ( * ( ( volatile unsigned long * ) 0xe000e018 ) )\r
+#define portNVIC_INT_CTRL_REG                          ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )\r
+#define portNVIC_SYSPRI2_REG                           ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )\r
+/* ...then bits in the registers. */\r
+#define portNVIC_SYSTICK_CLK_BIT                       ( 1UL << 2UL )\r
+#define portNVIC_SYSTICK_INT_BIT                       ( 1UL << 1UL )\r
+#define portNVIC_SYSTICK_ENABLE_BIT                    ( 1UL << 0UL )\r
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT                ( 1UL << 16UL )\r
+#define portNVIC_PENDSVSET_BIT                         ( 1UL << 28UL )\r
+#define portNVIC_PENDSVCLEAR_BIT                       ( 1UL << 27UL )\r
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT                ( 1UL << 25UL )\r
+\r
 #define portNVIC_PENDSV_PRI                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
 #define portNVIC_SYSTICK_PRI           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
 \r
@@ -119,6 +137,21 @@ extern void vPortStartFirstTask( void );
 \r
 /*-----------------------------------------------------------*/\r
 \r
+/*\r
+ * The number of SysTick increments that make up one tick period.\r
+ */\r
+static unsigned long ulTimerReloadValueForOneTick = 0;\r
+\r
+/*\r
+ * The maximum number of tick periods that can be suppressed is limited by the\r
+ * 24 bit resolution of the SysTick timer.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+       static unsigned long xMaximumPossibleSuppressedTicks = 0;\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * See header file for description.\r
  */\r
@@ -146,13 +179,13 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
-       *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;\r
-       *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
 \r
        /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
        here already. */\r
        prvSetupTimerInterrupt();\r
-       \r
+\r
        /* Initialise the critical nesting count ready for the first task. */\r
        uxCriticalNesting = 0;\r
 \r
@@ -174,7 +207,7 @@ void vPortEndScheduler( void )
 void vPortYieldFromISR( void )\r
 {\r
        /* Set a PendSV to request a context switch. */\r
-       *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+       portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -197,30 +230,142 @@ void vPortExitCritical( void )
 \r
 void xPortSysTickHandler( void )\r
 {\r
-unsigned long ulDummy;\r
-\r
        /* If using preemption, also force a context switch. */\r
        #if configUSE_PREEMPTION == 1\r
-               *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;      \r
+               portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
        #endif\r
 \r
-       ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       #endif\r
+\r
+       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
                vTaskIncrementTick();\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+       __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+       {\r
+       unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+\r
+               /* Make sure the SysTick reload value does not overflow the counter. */\r
+               if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+               {\r
+                       xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+               }\r
+\r
+               /* Calculate the reload value required to wait xExpectedIdleTime\r
+               tick periods.  -1 is used because this code will execute part way\r
+               through one of the tick periods, and the fraction of a tick period is\r
+               accounted for later. */\r
+               ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+               if( ulReloadValue > ulStoppedTimerCompensation )\r
+               {\r
+                       ulReloadValue -= ulStoppedTimerCompensation;\r
+               }\r
+\r
+               /* Stop the SysTick momentarily.  The time the SysTick is stopped for\r
+               is accounted for as best it can be, but using the tickless mode will\r
+               inevitably result in some tiny drift of the time maintained by the\r
+               kernel with respect to calendar time. */\r
+               portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+               /* If a context switch is pending then abandon the low power entry as\r
+               the context switch might have been pended by an external interrupt that\r
+               requires processing. */\r
+               if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+               {\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+               }\r
+               else\r
+               {\r
+                       /* Adjust the reload value to take into account that the current\r
+                       time slice is already partially complete. */\r
+                       ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+                       portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
+\r
+                       /* Clear the SysTick count flag and set the count value back to\r
+                       zero. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       /* Sleep until something happens. */\r
+                       portPRE_SLEEP_PROCESSING();\r
+                       __WFI();\r
+                       portPOST_SLEEP_PROCESSING();\r
+\r
+                       /* Stop SysTick.  Again, the time the SysTick is stopped for is\r
+                       accounted for as best it can be, but using the tickless mode will\r
+                       inevitably result in some tiny drift of the time maintained by the\r
+                       kernel with respect to calendar time. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+                       if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
+                       {\r
+                               /* The tick interrupt has already executed, and the SysTick\r
+                               count reloaded with the portNVIC_SYSTICK_LOAD_REG value.\r
+                               Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of\r
+                               this tick period. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );\r
+\r
+                               /* The tick interrupt handler will already have pended the tick\r
+                               processing in the kernel.  As the pending tick will be\r
+                               processed as soon as this function exits, the tick value\r
+                               maintained by the tick is stepped forward by one less than the\r
+                               time spent waiting. */\r
+                               ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Something other than the tick interrupt ended the sleep.\r
+                               Work out how long the sleep lasted. */\r
+                               ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;\r
+\r
+                               /* How many complete tick periods passed while the processor\r
+                               was waiting? */\r
+                               ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;\r
+\r
+                               /* The reload value is set to whatever fraction of a single tick\r
+                               period remains. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;\r
+                       }\r
+\r
+                       /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
+                       again, then set portNVIC_SYSTICK_LOAD_REG back to its standard\r
+                       value. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       vTaskStepTick( ulCompleteTickPeriods );\r
+               }\r
+       }\r
+\r
+#endif /* #if configUSE_TICKLESS_IDLE */\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * Setup the systick timer to generate the tick interrupts at the required\r
  * frequency.\r
  */\r
 void prvSetupTimerInterrupt( void )\r
 {\r
+       /* Configure the constants required to setup the tick interrupt. */\r
+       ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
+       #endif /* configUSE_TICKLESS_IDLE */\r
+\r
        /* Configure SysTick to interrupt at the requested rate. */\r
-       *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
-       *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;\r
+       portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index c9e0bb3caf370eea6d3f33746b00b834631d1270..9c766460ba6d8cfcf9a47ef97b88a784e167d767 100644 (file)
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
 #include <FreeRTOSConfig.h>\r
 \r
-/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is\r
-defined.  The value zero should also ensure backward compatibility.\r
-FreeRTOS.org versions prior to V4.3.0 did not include this definition. */\r
-#ifndef configKERNEL_INTERRUPT_PRIORITY\r
-       #define configKERNEL_INTERRUPT_PRIORITY 0\r
-#endif\r
-\r
-       \r
        RSEG    CODE:CODE(2)\r
        thumb\r
 \r
-       EXTERN vPortYieldFromISR\r
        EXTERN pxCurrentTCB\r
        EXTERN vTaskSwitchContext\r
 \r
-       PUBLIC vSetMSP\r
        PUBLIC xPortPendSVHandler\r
-       PUBLIC vPortSetInterruptMask\r
+       PUBLIC ulPortSetInterruptMask\r
        PUBLIC vPortClearInterruptMask\r
        PUBLIC vPortSVCHandler\r
        PUBLIC vPortStartFirstTask\r
 \r
 \r
-/*-----------------------------------------------------------*/\r
 \r
-vSetMSP\r
-       msr msp, r0\r
-       bx lr\r
-       \r
 /*-----------------------------------------------------------*/\r
 \r
 xPortPendSVHandler:\r
@@ -122,28 +107,26 @@ xPortPendSVHandler:
 \r
 /*-----------------------------------------------------------*/\r
 \r
-vPortSetInterruptMask:\r
-       mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
-       msr BASEPRI, r0\r
-\r
+ulPortSetInterruptMask:\r
+       mrs r0, basepri\r
+       mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
+       msr basepri, r1\r
        bx r14\r
        \r
 /*-----------------------------------------------------------*/\r
 \r
 vPortClearInterruptMask:\r
-       /* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-       http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-       mov r0, #0\r
-       msr BASEPRI, r0\r
-\r
+       msr basepri, r0\r
        bx r14\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-vPortSVCHandler;\r
+vPortSVCHandler:\r
+       /* Get the location of the current TCB. */\r
        ldr     r3, =pxCurrentTCB\r
        ldr r1, [r3]\r
        ldr r0, [r1]\r
+       /* Pop the core registers. */\r
        ldmia r0!, {r4-r11}\r
        msr psp, r0\r
        mov r0, #0\r
index 662451a61e4261e1460b6309ba3c2fcd72de8265..034f06c44d36b0673d4a6aac2e31c4a14143495e 100644 (file)
@@ -106,15 +106,13 @@ extern "C" {
 #define portBYTE_ALIGNMENT                     8\r
 /*-----------------------------------------------------------*/        \r
 \r
-\r
 /* Scheduler utilities. */\r
 extern void vPortYieldFromISR( void );\r
-\r
 #define portYIELD()                                    vPortYieldFromISR()\r
-\r
 #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()\r
 /*-----------------------------------------------------------*/\r
 \r
+/* Architecture specific optimisations. */\r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
        /* Check the configuration. */\r
@@ -131,32 +129,36 @@ extern void vPortYieldFromISR( void );
        #include <intrinsics.h>\r
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )\r
 \r
-#endif /* taskRECORD_READY_PRIORITY */\r
-\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+/*-----------------------------------------------------------*/\r
 \r
 /* Critical section management. */\r
-\r
 extern void vPortEnterCritical( void );\r
 extern void vPortExitCritical( void );\r
-extern void vPortSetInterruptMask( void );\r
-extern void vPortClearInterruptMask( void );\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMask );\r
 \r
-#define portDISABLE_INTERRUPTS()       vPortSetInterruptMask()\r
-#define portENABLE_INTERRUPTS()                vPortClearInterruptMask()\r
+#define portDISABLE_INTERRUPTS()                               ulPortSetInterruptMask()\r
+#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask( 0 )\r
 #define portENTER_CRITICAL()                                   vPortEnterCritical()\r
 #define portEXIT_CRITICAL()                                            vPortExitCritical()\r
+#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask( x )\r
+/*-----------------------------------------------------------*/\r
 \r
-/* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see\r
-http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              0;vPortSetInterruptMask()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask();(void)x\r
-\r
+/* Tickless/low power functionality. */\r
+extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
 /*-----------------------------------------------------------*/\r
 \r
-/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+not necessary for to use this port.  They are defined so the common demo files\r
+(which build with all the ports) will build. */\r
 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
 #ifdef __cplusplus\r
index 1ca5e6877e28d188987cc783c9d3b9e3914cb860..6d958c2dcbf66bd9d1cbf23178cc24d071b6c54c 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
        #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html\r
 #endif\r
 \r
-/* Constants required to manipulate the NVIC. */\r
-#define portNVIC_SYSTICK_CTRL          ( ( volatile unsigned long * ) 0xe000e010 )\r
-#define portNVIC_SYSTICK_LOAD          ( ( volatile unsigned long * ) 0xe000e014 )\r
-#define portNVIC_INT_CTRL                      ( ( volatile unsigned long * ) 0xe000ed04 )\r
-#define portNVIC_SYSPRI2                       ( ( volatile unsigned long * ) 0xe000ed20 )\r
-#define portNVIC_SYSTICK_CLK           0x00000004\r
-#define portNVIC_SYSTICK_INT           0x00000002\r
-#define portNVIC_SYSTICK_ENABLE                0x00000001\r
-#define portNVIC_PENDSVSET                     0x10000000\r
+#ifndef configSYSTICK_CLOCK_HZ\r
+       #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL;\r
+       #endif\r
+#else /* configSYSTICK_CLOCK_HZ */\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               /* Assumes the SysTick clock is slower than the CPU clock. */\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );\r
+       #endif\r
+#endif /* configSYSTICK_CLOCK_HZ */\r
+\r
+/* Constants required to manipulate the core.  Registers first... */\r
+#define portNVIC_SYSTICK_CTRL_REG                      ( * ( ( volatile unsigned long * ) 0xe000e010 ) )\r
+#define portNVIC_SYSTICK_LOAD_REG                      ( * ( ( volatile unsigned long * ) 0xe000e014 ) )\r
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG     ( * ( ( volatile unsigned long * ) 0xe000e018 ) )\r
+#define portNVIC_INT_CTRL_REG                          ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )\r
+#define portNVIC_SYSPRI2_REG                           ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )\r
+/* ...then bits in the registers. */\r
+#define portNVIC_SYSTICK_CLK_BIT                       ( 1UL << 2UL )\r
+#define portNVIC_SYSTICK_INT_BIT                       ( 1UL << 1UL )\r
+#define portNVIC_SYSTICK_ENABLE_BIT                    ( 1UL << 0UL )\r
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT                ( 1UL << 16UL )\r
+#define portNVIC_PENDSVSET_BIT                         ( 1UL << 28UL )\r
+#define portNVIC_PENDSVCLEAR_BIT                       ( 1UL << 27UL )\r
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT                ( 1UL << 25UL )\r
+\r
 #define portNVIC_PENDSV_PRI                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
 #define portNVIC_SYSTICK_PRI           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
 \r
@@ -120,12 +138,27 @@ void xPortSysTickHandler( void );
 extern void vPortStartFirstTask( void );\r
 \r
 /*\r
- * Functions defined in portasm.s to enable the VFP.\r
+ * Turn the VFP on.\r
  */\r
 extern void vPortEnableVFP( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
+/*\r
+ * The number of SysTick increments that make up one tick period.\r
+ */\r
+static unsigned long ulTimerReloadValueForOneTick = 0;\r
+\r
+/*\r
+ * The maximum number of tick periods that can be suppressed is limited by the\r
+ * 24 bit resolution of the SysTick timer.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+       static unsigned long xMaximumPossibleSuppressedTicks = 0;\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * See header file for description.\r
  */\r
@@ -133,17 +166,17 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
 {\r
        /* Simulate the stack frame as it would be created by a context switch\r
        interrupt. */\r
-       \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
        pxTopOfStack--;\r
-               \r
+\r
        *pxTopOfStack = portINITIAL_XPSR;       /* xPSR */\r
        pxTopOfStack--;\r
        *pxTopOfStack = ( portSTACK_TYPE ) pxCode;      /* PC */\r
        pxTopOfStack--;\r
        *pxTopOfStack = 0;      /* LR */\r
-       \r
+\r
        /* Save code space by skipping register initialisation. */\r
        pxTopOfStack -= 5;      /* R12, R3, R2 and R1. */\r
        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;        /* R0 */\r
@@ -154,7 +187,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
        *pxTopOfStack = portINITIAL_EXEC_RETURN;\r
 \r
        pxTopOfStack -= 8;      /* R11, R10, R9, R8, R7, R6, R5 and R4. */\r
-       \r
+\r
        return pxTopOfStack;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -165,22 +198,22 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
        /* Make PendSV and SysTick the lowest priority interrupts. */\r
-       *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;\r
-       *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
 \r
        /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
        here already. */\r
        prvSetupTimerInterrupt();\r
-       \r
+\r
        /* Initialise the critical nesting count ready for the first task. */\r
        uxCriticalNesting = 0;\r
 \r
        /* Ensure the VFP is enabled - it should be anyway. */\r
        vPortEnableVFP();\r
-       \r
+\r
        /* Lazy save always. */\r
        *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;\r
-       \r
+\r
        /* Start the first task. */\r
        vPortStartFirstTask();\r
 \r
@@ -199,7 +232,7 @@ void vPortEndScheduler( void )
 void vPortYieldFromISR( void )\r
 {\r
        /* Set a PendSV to request a context switch. */\r
-       *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+       portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -222,30 +255,142 @@ void vPortExitCritical( void )
 \r
 void xPortSysTickHandler( void )\r
 {\r
-unsigned long ulDummy;\r
-\r
        /* If using preemption, also force a context switch. */\r
        #if configUSE_PREEMPTION == 1\r
-               *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;      \r
+               portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
+       #endif\r
+\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
        #endif\r
 \r
-       ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
                vTaskIncrementTick();\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+       __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+       {\r
+       unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+\r
+               /* Make sure the SysTick reload value does not overflow the counter. */\r
+               if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+               {\r
+                       xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+               }\r
+\r
+               /* Calculate the reload value required to wait xExpectedIdleTime\r
+               tick periods.  -1 is used because this code will execute part way\r
+               through one of the tick periods, and the fraction of a tick period is\r
+               accounted for later. */\r
+               ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+               if( ulReloadValue > ulStoppedTimerCompensation )\r
+               {\r
+                       ulReloadValue -= ulStoppedTimerCompensation;\r
+               }\r
+\r
+               /* Stop the SysTick momentarily.  The time the SysTick is stopped for\r
+               is accounted for as best it can be, but using the tickless mode will\r
+               inevitably result in some tiny drift of the time maintained by the\r
+               kernel with respect to calendar time. */\r
+               portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+               /* If a context switch is pending then abandon the low power entry as\r
+               the context switch might have been pended by an external interrupt that\r
+               requires processing. */\r
+               if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+               {\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+               }\r
+               else\r
+               {\r
+                       /* Adjust the reload value to take into account that the current\r
+                       time slice is already partially complete. */\r
+                       ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+                       portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
+\r
+                       /* Clear the SysTick count flag and set the count value back to\r
+                       zero. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       /* Sleep until something happens. */\r
+                       portPRE_SLEEP_PROCESSING();\r
+                       __WFI();\r
+                       portPOST_SLEEP_PROCESSING();\r
+\r
+                       /* Stop SysTick.  Again, the time the SysTick is stopped for is\r
+                       accounted for as best it can be, but using the tickless mode will\r
+                       inevitably result in some tiny drift of the time maintained by the\r
+                       kernel with respect to calendar time. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+                       if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
+                       {\r
+                               /* The tick interrupt has already executed, and the SysTick\r
+                               count reloaded with the portNVIC_SYSTICK_LOAD_REG value.\r
+                               Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of\r
+                               this tick period. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );\r
+\r
+                               /* The tick interrupt handler will already have pended the tick\r
+                               processing in the kernel.  As the pending tick will be\r
+                               processed as soon as this function exits, the tick value\r
+                               maintained by the tick is stepped forward by one less than the\r
+                               time spent waiting. */\r
+                               ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Something other than the tick interrupt ended the sleep.\r
+                               Work out how long the sleep lasted. */\r
+                               ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;\r
+\r
+                               /* How many complete tick periods passed while the processor\r
+                               was waiting? */\r
+                               ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;\r
+\r
+                               /* The reload value is set to whatever fraction of a single tick\r
+                               period remains. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;\r
+                       }\r
+\r
+                       /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
+                       again, then set portNVIC_SYSTICK_LOAD_REG back to its standard\r
+                       value. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       vTaskStepTick( ulCompleteTickPeriods );\r
+               }\r
+       }\r
+\r
+#endif /* #if configUSE_TICKLESS_IDLE */\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * Setup the systick timer to generate the tick interrupts at the required\r
  * frequency.\r
  */\r
 void prvSetupTimerInterrupt( void )\r
 {\r
+       /* Configure the constants required to setup the tick interrupt. */\r
+       ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
+       #endif /* configUSE_TICKLESS_IDLE */\r
+\r
        /* Configure SysTick to interrupt at the requested rate. */\r
-       *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
-       *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;\r
+       portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
index 26eb6267e98350bfbc03691fc564be6138d673a7..5ecd502d1e2897765eba04de3a6a1bb0e22d7b8c 100644 (file)
@@ -73,7 +73,7 @@
        EXTERN vTaskSwitchContext\r
 \r
        PUBLIC xPortPendSVHandler\r
-       PUBLIC vPortSetInterruptMask\r
+       PUBLIC ulPortSetInterruptMask\r
        PUBLIC vPortClearInterruptMask\r
        PUBLIC vPortSVCHandler\r
        PUBLIC vPortStartFirstTask\r
@@ -127,20 +127,16 @@ xPortPendSVHandler:
 \r
 /*-----------------------------------------------------------*/\r
 \r
-vPortSetInterruptMask:\r
-       mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
-       msr BASEPRI, r0\r
-\r
+ulPortSetInterruptMask:\r
+       mrs r0, basepri\r
+       mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
+       msr basepri, r1\r
        bx r14\r
        \r
 /*-----------------------------------------------------------*/\r
 \r
 vPortClearInterruptMask:\r
-       /* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-       http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-       mov r0, #0\r
-       msr BASEPRI, r0\r
-\r
+       msr basepri, r0\r
        bx r14\r
 \r
 /*-----------------------------------------------------------*/\r
@@ -159,7 +155,7 @@ vPortSVCHandler:
 \r
 /*-----------------------------------------------------------*/\r
 \r
-vPortStartFirstTask:\r
+vPortStartFirstTask\r
        /* Use the NVIC offset register to locate the stack. */\r
        ldr r0, =0xE000ED08\r
        ldr r0, [r0]\r
index c218de87f0dd65df7b116e379f6344fc0d10fb46..f825609b46be1ca68bb410ceba93dd8729cf8775 100644 (file)
@@ -106,15 +106,13 @@ extern "C" {
 #define portBYTE_ALIGNMENT                     8\r
 /*-----------------------------------------------------------*/        \r
 \r
-\r
 /* Scheduler utilities. */\r
 extern void vPortYieldFromISR( void );\r
-\r
 #define portYIELD()                                    vPortYieldFromISR()\r
-\r
 #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()\r
 /*-----------------------------------------------------------*/\r
 \r
+/* Architecture specific optimisations. */\r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
        /* Check the configuration. */\r
@@ -131,36 +129,42 @@ extern void vPortYieldFromISR( void );
        #include <intrinsics.h>\r
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( ( uxReadyPriorities ) ) )\r
 \r
-#endif /* taskRECORD_READY_PRIORITY */\r
-\r
+#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
+/*-----------------------------------------------------------*/\r
 \r
 /* Critical section management. */\r
-\r
 extern void vPortEnterCritical( void );\r
 extern void vPortExitCritical( void );\r
-extern void vPortSetInterruptMask( void );\r
-extern void vPortClearInterruptMask( void );\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMask );\r
 \r
-#define portDISABLE_INTERRUPTS()       vPortSetInterruptMask()\r
-#define portENABLE_INTERRUPTS()                vPortClearInterruptMask()\r
+#define portDISABLE_INTERRUPTS()                               ulPortSetInterruptMask()\r
+#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask( 0 )\r
 #define portENTER_CRITICAL()                                   vPortEnterCritical()\r
 #define portEXIT_CRITICAL()                                            vPortExitCritical()\r
-\r
-/* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              0;vPortSetInterruptMask()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask();(void)x\r
+#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask( x )\r
+/*-----------------------------------------------------------*/\r
 \r
 /* There are an uneven number of items on the initial stack, so \r
 portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */\r
 #define portALIGNMENT_ASSERT_pxCurrentTCB ( void )\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Tickless/low power functionality. */\r
+extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+not necessary for to use this port.  They are defined so the common demo files\r
+(which build with all the ports) will build. */\r
 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* portNOP() is not required by this port. */\r
 #define portNOP()\r
 \r
 #ifdef __cplusplus\r
index fa45fc3fa11a30c6e4109d260d6bcb737cb55b32..e44b32d7eb07195d47d543212da20db1fa0bda6e 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
@@ -69,7 +69,7 @@
  * The simplest possible implementation of pvPortMalloc().  Note that this\r
  * implementation does NOT allow allocated memory to be freed again.\r
  *\r
- * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the \r
+ * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the\r
  * memory management pages of http://www.FreeRTOS.org for more information.\r
  */\r
 #include <stdlib.h>\r
@@ -92,7 +92,7 @@ static union xRTOS_HEAP
                volatile portDOUBLE dDummy;\r
        #else\r
                volatile unsigned long ulDummy;\r
-       #endif  \r
+       #endif\r
        unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];\r
 } xHeap;\r
 \r
@@ -101,7 +101,7 @@ static size_t xNextFreeByte = ( size_t ) 0;
 \r
 void *pvPortMalloc( size_t xWantedSize )\r
 {\r
-void *pvReturn = NULL; \r
+void *pvReturn = NULL;\r
 \r
        /* Ensure that blocks are always aligned to the required number of bytes. */\r
        #if portBYTE_ALIGNMENT != 1\r
@@ -121,11 +121,11 @@ void *pvReturn = NULL;
                        /* Return the next free byte then increment the index past this\r
                        block. */\r
                        pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] );\r
-                       xNextFreeByte += xWantedSize;                   \r
-               }       \r
+                       xNextFreeByte += xWantedSize;\r
+               }\r
        }\r
        xTaskResumeAll();\r
-       \r
+\r
        #if( configUSE_MALLOC_FAILED_HOOK == 1 )\r
        {\r
                if( pvReturn == NULL )\r
@@ -134,7 +134,7 @@ void *pvReturn = NULL;
                        vApplicationMallocFailedHook();\r
                }\r
        }\r
-       #endif  \r
+       #endif\r
 \r
        return pvReturn;\r
 }\r
@@ -143,10 +143,10 @@ void *pvReturn = NULL;
 void vPortFree( void *pv )\r
 {\r
        /* Memory cannot be freed using this scheme.  See heap_2.c, heap_3.c and\r
-       heap_4.c for alternative implementations, and the memory management pages of \r
+       heap_4.c for alternative implementations, and the memory management pages of\r
        http://www.FreeRTOS.org for more information. */\r
        ( void ) pv;\r
-       \r
+\r
        /* Force an assert as it is invalid to call this function. */\r
        configASSERT( pv == NULL );\r
 }\r
index d109cecd3932af1faa0ebe7d145a3d1eb2f31f9d..94b8384845d7ba7f6fc4b7dc2acc9e878a09ac62 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
        #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html\r
 #endif\r
 \r
-/* Constants required to manipulate the NVIC. */\r
-#define portNVIC_SYSTICK_CTRL          ( ( volatile unsigned long *) 0xe000e010 )\r
-#define portNVIC_SYSTICK_LOAD          ( ( volatile unsigned long *) 0xe000e014 )\r
-#define portNVIC_INT_CTRL                      ( ( volatile unsigned long *) 0xe000ed04 )\r
-#define portNVIC_SYSPRI2                       ( ( volatile unsigned long *) 0xe000ed20 )\r
-#define portNVIC_SYSTICK_CLK           0x00000004\r
-#define portNVIC_SYSTICK_INT           0x00000002\r
-#define portNVIC_SYSTICK_ENABLE                0x00000001\r
-#define portNVIC_PENDSVSET                     0x10000000\r
-#define portNVIC_PENDSV_PRI                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
-#define portNVIC_SYSTICK_PRI           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
+#ifndef configSYSTICK_CLOCK_HZ\r
+       #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL;\r
+       #endif\r
+#else /* configSYSTICK_CLOCK_HZ */\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               /* Assumes the SysTick clock is slower than the CPU clock. */\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );\r
+       #endif\r
+#endif /* configSYSTICK_CLOCK_HZ */\r
+\r
+/* Constants required to manipulate the core.  Registers first... */\r
+#define portNVIC_SYSTICK_CTRL_REG                      ( * ( ( volatile unsigned long * ) 0xe000e010 ) )\r
+#define portNVIC_SYSTICK_LOAD_REG                      ( * ( ( volatile unsigned long * ) 0xe000e014 ) )\r
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG     ( * ( ( volatile unsigned long * ) 0xe000e018 ) )\r
+#define portNVIC_INT_CTRL_REG                          ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )\r
+#define portNVIC_SYSPRI2_REG                           ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )\r
+/* ...then bits in the registers. */\r
+#define portNVIC_SYSTICK_CLK_BIT                       ( 1UL << 2UL )\r
+#define portNVIC_SYSTICK_INT_BIT                       ( 1UL << 1UL )\r
+#define portNVIC_SYSTICK_ENABLE_BIT                    ( 1UL << 0UL )\r
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT                ( 1UL << 16UL )\r
+#define portNVIC_PENDSVSET_BIT                         ( 1UL << 28UL )\r
+#define portNVIC_PENDSVCLEAR_BIT                       ( 1UL << 27UL )\r
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT                ( 1UL << 25UL )\r
+\r
+#define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
+#define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
 \r
 /* Constants required to set up the initial stack. */\r
 #define portINITIAL_XPSR                       ( 0x01000000 )\r
 variable. */\r
 static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;\r
 \r
-/* \r
+/*\r
  * Setup the timer to generate the tick interrupts.\r
  */\r
 static void prvSetupTimerInterrupt( void );\r
@@ -114,12 +132,27 @@ void vPortSVCHandler( void );
 /*\r
  * Start first task is a separate function so it can be tested in isolation.\r
  */\r
-void vPortStartFirstTask( void );\r
+static void prvStartFirstTask( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-/* \r
- * See header file for description. \r
+/*\r
+ * The number of SysTick increments that make up one tick period.\r
+ */\r
+static unsigned long ulTimerReloadValueForOneTick = 0;\r
+\r
+/*\r
+ * The maximum number of tick periods that can be suppressed is limited by the\r
+ * 24 bit resolution of the SysTick timer.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+       static unsigned long xMaximumPossibleSuppressedTicks = 0;\r
+#endif /* configUSE_TICKLESS_IDLE */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * See header file for description.\r
  */\r
 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
 {\r
@@ -143,15 +176,15 @@ __asm void vPortSVCHandler( void )
 {\r
        PRESERVE8\r
 \r
-       ldr     r3, =pxCurrentTCB               /* Restore the context. */\r
-       ldr r1, [r3]                            /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */\r
-       ldr r0, [r1]                            /* The first item in pxCurrentTCB is the task top of stack. */\r
+       ldr     r3, =pxCurrentTCB       /* Restore the context. */\r
+       ldr r1, [r3]                    /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */\r
+       ldr r0, [r1]                    /* The first item in pxCurrentTCB is the task top of stack. */\r
        ldmia r0!, {r4-r11}             /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */\r
-       msr psp, r0                                     /* Restore the task stack pointer. */\r
+       msr psp, r0                             /* Restore the task stack pointer. */\r
        mov r0, #0\r
        msr     basepri, r0\r
-       orr r14, #0xd                           \r
-       bx r14                                          \r
+       orr r14, #0xd\r
+       bx r14\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -173,24 +206,24 @@ __asm void vPortStartFirstTask( void )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/* \r
- * See header file for description. \r
+/*\r
+ * See header file for description.\r
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
-       /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */\r
-       *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;\r
-       *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;\r
+       /* Make PendSV, CallSV and SysTick the same priority as the kernel. */\r
+       portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
 \r
        /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
        here already. */\r
        prvSetupTimerInterrupt();\r
-       \r
+\r
        /* Initialise the critical nesting count ready for the first task. */\r
        uxCriticalNesting = 0;\r
 \r
        /* Start the first task. */\r
-       vPortStartFirstTask();\r
+       prvStartFirstTask();\r
 \r
        /* Should not get here! */\r
        return 0;\r
@@ -207,7 +240,7 @@ void vPortEndScheduler( void )
 void vPortYieldFromISR( void )\r
 {\r
        /* Set a PendSV to request a context switch. */\r
-       *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+       portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -236,26 +269,26 @@ __asm void xPortPendSVHandler( void )
 \r
        PRESERVE8\r
 \r
-       mrs r0, psp                                              \r
+       mrs r0, psp\r
 \r
-       ldr     r3, =pxCurrentTCB                        /* Get the location of the current TCB. */\r
-       ldr     r2, [r3]                                                \r
+       ldr     r3, =pxCurrentTCB               /* Get the location of the current TCB. */\r
+       ldr     r2, [r3]\r
 \r
-       stmdb r0!, {r4-r11}                              /* Save the remaining registers. */\r
-       str r0, [r2]                                     /* Save the new top of stack into the first member of the TCB. */\r
+       stmdb r0!, {r4-r11}                     /* Save the remaining registers. */\r
+       str r0, [r2]                            /* Save the new top of stack into the first member of the TCB. */\r
 \r
-       stmdb sp!, {r3, r14}            \r
+       stmdb sp!, {r3, r14}\r
        mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
-       msr basepri, r0          \r
+       msr basepri, r0\r
        bl vTaskSwitchContext\r
        mov r0, #0\r
        msr basepri, r0\r
-       ldmia sp!, {r3, r14}                    \r
+       ldmia sp!, {r3, r14}\r
 \r
-       ldr r1, [r3]                                     \r
-       ldr r0, [r1]                                     /* The first item in pxCurrentTCB is the task top of stack. */\r
-       ldmia r0!, {r4-r11}                      /* Pop the registers and the critical nesting count. */\r
-       msr psp, r0                                              \r
+       ldr r1, [r3]\r
+       ldr r0, [r1]                            /* The first item in pxCurrentTCB is the task top of stack. */\r
+       ldmia r0!, {r4-r11}                     /* Pop the registers and the critical nesting count. */\r
+       msr psp, r0\r
        bx r14\r
        nop\r
 }\r
@@ -263,51 +296,164 @@ __asm void xPortPendSVHandler( void )
 \r
 void xPortSysTickHandler( void )\r
 {\r
-unsigned long ulDummy;\r
-\r
-       /* If using preemption, also force a context switch. */\r
        #if configUSE_PREEMPTION == 1\r
-               *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;      \r
+       {\r
+               /* If using preemption, also force a context switch. */\r
+               portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
+       }\r
+       #endif\r
+\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
        #endif\r
 \r
-       ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
                vTaskIncrementTick();\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+       __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+       {\r
+       unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+\r
+               /* Make sure the SysTick reload value does not overflow the counter. */\r
+               if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+               {\r
+                       xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+               }\r
+\r
+               /* Calculate the reload value required to wait xExpectedIdleTime\r
+               tick periods.  -1 is used because this code will execute part way\r
+               through one of the tick periods, and the fraction of a tick period is\r
+               accounted for later. */\r
+               ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+               if( ulReloadValue > ulStoppedTimerCompensation )\r
+               {\r
+                       ulReloadValue -= ulStoppedTimerCompensation;\r
+               }\r
+\r
+               /* Stop the SysTick momentarily.  The time the SysTick is stopped for\r
+               is accounted for as best it can be, but using the tickless mode will\r
+               inevitably result in some tiny drift of the time maintained by the\r
+               kernel with respect to calendar time. */\r
+               portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+               /* If a context switch is pending then abandon the low power entry as\r
+               the context switch might have been pended by an external interrupt that\r
+               requires processing. */\r
+               if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+               {\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+               }\r
+               else\r
+               {\r
+                       /* Adjust the reload value to take into account that the current\r
+                       time slice is already partially complete. */\r
+                       ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+                       portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
+\r
+                       /* Clear the SysTick count flag and set the count value back to\r
+                       zero. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       /* Sleep until something happens. */\r
+                       portPRE_SLEEP_PROCESSING();\r
+                       __wfi();\r
+                       portPOST_SLEEP_PROCESSING();\r
+\r
+                       /* Stop SysTick.  Again, the time the SysTick is stopped for is\r
+                       accounted for as best it can be, but using the tickless mode will\r
+                       inevitably result in some tiny drift of the time maintained by the\r
+                       kernel with respect to calendar time. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+                       if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
+                       {\r
+                               /* The tick interrupt has already executed, and the SysTick\r
+                               count reloaded with the portNVIC_SYSTICK_LOAD_REG value.\r
+                               Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of\r
+                               this tick period. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );\r
+\r
+                               /* The tick interrupt handler will already have pended the tick\r
+                               processing in the kernel.  As the pending tick will be\r
+                               processed as soon as this function exits, the tick value\r
+                               maintained by the tick is stepped forward by one less than the\r
+                               time spent waiting. */\r
+                               ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Something other than the tick interrupt ended the sleep.\r
+                               Work out how long the sleep lasted. */\r
+                               ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;\r
+\r
+                               /* How many complete tick periods passed while the processor\r
+                               was waiting? */\r
+                               ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;\r
+\r
+                               /* The reload value is set to whatever fraction of a single tick\r
+                               period remains. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;\r
+                       }\r
+\r
+                       /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
+                       again, then set portNVIC_SYSTICK_LOAD_REG back to its standard\r
+                       value. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       vTaskStepTick( ulCompleteTickPeriods );\r
+               }\r
+       }\r
+\r
+#endif /* #if configUSE_TICKLESS_IDLE */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
- * Setup the systick timer to generate the tick interrupts at the required\r
+ * Setup the SysTick timer to generate the tick interrupts at the required\r
  * frequency.\r
  */\r
 void prvSetupTimerInterrupt( void )\r
 {\r
+       /* Calculate the constants required to configure the tick interrupt. */\r
+       ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
+       #endif /* configUSE_TICKLESS_IDLE */\r
+\r
        /* Configure SysTick to interrupt at the requested rate. */\r
-       *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
-       *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;\r
+       portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-__asm void vPortSetInterruptMask( void )\r
+__asm unsigned long ulPortSetInterruptMask( void )\r
 {\r
        PRESERVE8\r
 \r
-       mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
-       msr basepri, r0\r
+       mrs r0, basepri\r
+       mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
+       msr basepri, r1\r
        bx r14\r
 }\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-__asm void vPortClearInterruptMask( void )\r
+__asm void vPortClearInterruptMask( unsigned long ulNewMask )\r
 {\r
        PRESERVE8\r
 \r
-       /* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-       http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-       mov r0, #0\r
        msr basepri, r0\r
        bx r14\r
 }\r
index b252093cb5b305138b6440ecd027fb58557f561c..012c11e1a97144c6ed3d6f15c77a1ef72895e255 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
@@ -73,7 +73,7 @@ extern "C" {
 #endif\r
 \r
 /*-----------------------------------------------------------\r
- * Port specific definitions.  \r
+ * Port specific definitions.\r
  *\r
  * The settings in this file configure FreeRTOS correctly for the\r
  * given hardware and compiler.\r
@@ -98,50 +98,41 @@ extern "C" {
        typedef unsigned portLONG portTickType;\r
        #define portMAX_DELAY ( portTickType ) 0xffffffff\r
 #endif\r
-/*-----------------------------------------------------------*/        \r
+/*-----------------------------------------------------------*/\r
 \r
 /* Architecture specifics. */\r
 #define portSTACK_GROWTH                       ( -1 )\r
-#define portTICK_RATE_MS                       ( ( portTickType ) 1000 / configTICK_RATE_HZ )          \r
+#define portTICK_RATE_MS                       ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
 #define portBYTE_ALIGNMENT                     8\r
-/*-----------------------------------------------------------*/        \r
-\r
+/*-----------------------------------------------------------*/\r
 \r
 /* Scheduler utilities. */\r
 extern void vPortYield( void );\r
 extern void vPortYieldFromISR( void );\r
-\r
 #define portYIELD()                                    vPortYieldFromISR()\r
 #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()\r
 /*-----------------------------------------------------------*/\r
 \r
-\r
 /* Critical section management. */\r
-\r
-extern void vPortSetInterruptMask( void );\r
-extern void vPortClearInterruptMask( void );\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMask );\r
 extern void vPortEnterCritical( void );\r
 extern void vPortExitCritical( void );\r
 \r
-#define portDISABLE_INTERRUPTS()                               vPortSetInterruptMask()\r
-#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask()\r
+#define portDISABLE_INTERRUPTS()                               ulPortSetInterruptMask()\r
+#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask( 0 )\r
 #define portENTER_CRITICAL()                                   vPortEnterCritical()\r
 #define portEXIT_CRITICAL()                                            vPortExitCritical()\r
-\r
-/* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              0;vPortSetInterruptMask()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask();(void)x\r
-\r
+#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask(x)\r
 /*-----------------------------------------------------------*/\r
 \r
-/* Task function macros as described on the FreeRTOS.org WEB site. */\r
-#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
-#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
-\r
-#define portNOP()\r
-\r
+/* Tickless/low power optimisations. */\r
+extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* Port specific optimisations. */\r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
        /* Check the configuration. */\r
@@ -154,11 +145,21 @@ http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */
        #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )\r
 \r
        /*-----------------------------------------------------------*/\r
-       \r
+\r
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )\r
 \r
 #endif /* taskRECORD_READY_PRIORITY */\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+not necessary for to use this port.  They are defined so the common demo files\r
+(which build with all the ports) will build. */\r
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* portNOP() is not required by this port. */\r
+#define portNOP()\r
 \r
 #ifdef __cplusplus\r
 }\r
index a8fdad6868f72c8642958f5528da3a858dbbab30..9676f65be7ae9ea7ce06c157af98f03043552233 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
@@ -72,7 +72,7 @@
 #include "FreeRTOS.h"\r
 #include "task.h"\r
 \r
-#ifndef __TARGET_FPU_VFP \r
+#ifndef __TARGET_FPU_VFP\r
        #error This port can only be used when the project options are configured to enable hardware floating point support.\r
 #endif\r
 \r
        #error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.  See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html\r
 #endif\r
 \r
-/* Constants required to manipulate the NVIC. */\r
-#define portNVIC_SYSTICK_CTRL          ( ( volatile unsigned long *) 0xe000e010 )\r
-#define portNVIC_SYSTICK_LOAD          ( ( volatile unsigned long *) 0xe000e014 )\r
-#define portNVIC_INT_CTRL                      ( ( volatile unsigned long *) 0xe000ed04 )\r
-#define portNVIC_SYSPRI2                       ( ( volatile unsigned long *) 0xe000ed20 )\r
-#define portNVIC_SYSTICK_CLK           0x00000004\r
-#define portNVIC_SYSTICK_INT           0x00000002\r
-#define portNVIC_SYSTICK_ENABLE                0x00000001\r
-#define portNVIC_PENDSVSET                     0x10000000\r
-#define portNVIC_PENDSV_PRI                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
-#define portNVIC_SYSTICK_PRI           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
+#ifndef configSYSTICK_CLOCK_HZ\r
+       #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL;\r
+       #endif\r
+#else /* configSYSTICK_CLOCK_HZ */\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               /* Assumes the SysTick clock is slower than the CPU clock. */\r
+               static const unsigned long ulStoppedTimerCompensation = 45UL / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );\r
+       #endif\r
+#endif /* configSYSTICK_CLOCK_HZ */\r
+\r
+/* Constants required to manipulate the core.  Registers first... */\r
+#define portNVIC_SYSTICK_CTRL_REG                      ( * ( ( volatile unsigned long * ) 0xe000e010 ) )\r
+#define portNVIC_SYSTICK_LOAD_REG                      ( * ( ( volatile unsigned long * ) 0xe000e014 ) )\r
+#define portNVIC_SYSTICK_CURRENT_VALUE_REG     ( * ( ( volatile unsigned long * ) 0xe000e018 ) )\r
+#define portNVIC_INT_CTRL_REG                          ( * ( ( volatile unsigned long * ) 0xe000ed04 ) )\r
+#define portNVIC_SYSPRI2_REG                           ( * ( ( volatile unsigned long * ) 0xe000ed20 ) )\r
+/* ...then bits in the registers. */\r
+#define portNVIC_SYSTICK_CLK_BIT                       ( 1UL << 2UL )\r
+#define portNVIC_SYSTICK_INT_BIT                       ( 1UL << 1UL )\r
+#define portNVIC_SYSTICK_ENABLE_BIT                    ( 1UL << 0UL )\r
+#define portNVIC_SYSTICK_COUNT_FLAG_BIT                ( 1UL << 16UL )\r
+#define portNVIC_PENDSVSET_BIT                         ( 1UL << 28UL )\r
+#define portNVIC_PENDSVCLEAR_BIT                       ( 1UL << 27UL )\r
+#define portNVIC_PEND_SYSTICK_CLEAR_BIT                ( 1UL << 25UL )\r
+\r
+#define portNVIC_PENDSV_PRI                                    ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16 )\r
+#define portNVIC_SYSTICK_PRI                           ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24 )\r
 \r
 /* Constants required to manipulate the VFP. */\r
 #define portFPCCR                                      ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */\r
 variable. */\r
 static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;\r
 \r
-/* \r
+/*\r
  * Setup the timer to generate the tick interrupts.\r
  */\r
 static void prvSetupTimerInterrupt( void );\r
@@ -125,27 +143,41 @@ static void prvStartFirstTask( void );
  * Functions defined in portasm.s to enable the VFP.\r
  */\r
 static void prvEnableVFP( void );\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * The number of SysTick increments that make up one tick period.\r
+ */\r
+static unsigned long ulTimerReloadValueForOneTick = 0;\r
+\r
+/*\r
+ * The maximum number of tick periods that can be suppressed is limited by the\r
+ * 24 bit resolution of the SysTick timer.\r
+ */\r
+#if configUSE_TICKLESS_IDLE == 1\r
+       static unsigned long xMaximumPossibleSuppressedTicks = 0;\r
+#endif /* configUSE_TICKLESS_IDLE */\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-/* \r
- * See header file for description. \r
+/*\r
+ * See header file for description.\r
  */\r
 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
 {\r
        /* Simulate the stack frame as it would be created by a context switch\r
        interrupt. */\r
-       \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
        pxTopOfStack--;\r
-               \r
+\r
        *pxTopOfStack = portINITIAL_XPSR;       /* xPSR */\r
        pxTopOfStack--;\r
        *pxTopOfStack = ( portSTACK_TYPE ) pxCode;      /* PC */\r
        pxTopOfStack--;\r
        *pxTopOfStack = 0;      /* LR */\r
-       \r
+\r
        /* Save code space by skipping register initialisation. */\r
        pxTopOfStack -= 5;      /* R12, R3, R2 and R1. */\r
        *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;        /* R0 */\r
@@ -156,7 +188,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
        *pxTopOfStack = portINITIAL_EXEC_RETURN;\r
 \r
        pxTopOfStack -= 8;      /* R11, R10, R9, R8, R7, R6, R5 and R4. */\r
-       \r
+\r
        return pxTopOfStack;\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -173,7 +205,7 @@ __asm void vPortSVCHandler( void )
        ldmia r0!, {r4-r11, r14}\r
        msr psp, r0\r
        mov r0, #0\r
-       msr     basepri, r0     \r
+       msr     basepri, r0\r
        bx r14\r
 }\r
 /*-----------------------------------------------------------*/\r
@@ -199,41 +231,41 @@ __asm void prvStartFirstTask( void )
 __asm void prvEnableVFP( void )\r
 {\r
        PRESERVE8\r
-       \r
+\r
        /* The FPU enable bits are in the CPACR. */\r
        ldr.w r0, =0xE000ED88\r
        ldr     r1, [r0]\r
-       \r
+\r
        /* Enable CP10 and CP11 coprocessors, then save back. */\r
        orr     r1, r1, #( 0xf << 20 )\r
        str r1, [r0]\r
-       bx      r14     \r
+       bx      r14\r
        nop\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-/* \r
- * See header file for description. \r
+/*\r
+ * See header file for description.\r
  */\r
 portBASE_TYPE xPortStartScheduler( void )\r
 {\r
        /* Make PendSV, CallSV and SysTick the same priroity as the kernel. */\r
-       *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;\r
-       *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;\r
+       portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;\r
 \r
        /* Start the timer that generates the tick ISR.  Interrupts are disabled\r
        here already. */\r
        prvSetupTimerInterrupt();\r
-       \r
+\r
        /* Initialise the critical nesting count ready for the first task. */\r
        uxCriticalNesting = 0;\r
 \r
        /* Ensure the VFP is enabled - it should be anyway. */\r
        prvEnableVFP();\r
-       \r
+\r
        /* Lazy save always. */\r
        *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;\r
-       \r
+\r
        /* Start the first task. */\r
        prvStartFirstTask();\r
 \r
@@ -252,7 +284,7 @@ void vPortEndScheduler( void )
 void vPortYieldFromISR( void )\r
 {\r
        /* Set a PendSV to request a context switch. */\r
-       *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;\r
+       portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -281,11 +313,11 @@ __asm void xPortPendSVHandler( void )
 \r
        PRESERVE8\r
 \r
-       mrs r0, psp                                             \r
-       \r
+       mrs r0, psp\r
+\r
        /* Get the location of the current TCB. */\r
-       ldr     r3, =pxCurrentTCB                       \r
-       ldr     r2, [r3]                                                \r
+       ldr     r3, =pxCurrentTCB\r
+       ldr     r2, [r3]\r
 \r
        /* Is the task using the FPU context?  If so, push high vfp registers. */\r
        tst r14, #0x10\r
@@ -293,85 +325,198 @@ __asm void xPortPendSVHandler( void )
        vstmdbeq r0!, {s16-s31}\r
 \r
        /* Save the core registers. */\r
-       stmdb r0!, {r4-r11, r14}                                \r
-       \r
+       stmdb r0!, {r4-r11, r14}\r
+\r
        /* Save the new top of stack into the first member of the TCB. */\r
        str r0, [r2]\r
-       \r
+\r
        stmdb sp!, {r3, r14}\r
        mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
        msr basepri, r0\r
-       bl vTaskSwitchContext                   \r
+       bl vTaskSwitchContext\r
        mov r0, #0\r
        msr basepri, r0\r
        ldmia sp!, {r3, r14}\r
 \r
        /* The first item in pxCurrentTCB is the task top of stack. */\r
-       ldr r1, [r3]    \r
+       ldr r1, [r3]\r
        ldr r0, [r1]\r
-       \r
+\r
        /* Pop the core registers. */\r
        ldmia r0!, {r4-r11, r14}\r
 \r
-       /* Is the task using the FPU context?  If so, pop the high vfp registers \r
+       /* Is the task using the FPU context?  If so, pop the high vfp registers\r
        too. */\r
        tst r14, #0x10\r
        it eq\r
        vldmiaeq r0!, {s16-s31}\r
-       \r
-       msr psp, r0                                             \r
-       bx r14          \r
-       nop                                     \r
+\r
+       msr psp, r0\r
+       bx r14\r
+       nop\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void xPortSysTickHandler( void )\r
 {\r
-unsigned long ulDummy;\r
-\r
-       /* If using preemption, also force a context switch. */\r
        #if configUSE_PREEMPTION == 1\r
-               *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;      \r
+       {\r
+               /* If using preemption, also force a context switch. */\r
+               portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;\r
+       }\r
        #endif\r
 \r
-       ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       #endif\r
+\r
+       ( void ) portSET_INTERRUPT_MASK_FROM_ISR();\r
        {\r
                vTaskIncrementTick();\r
        }\r
-       portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy );\r
+       portCLEAR_INTERRUPT_MASK_FROM_ISR( 0 );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
+#if configUSE_TICKLESS_IDLE == 1\r
+\r
+       __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )\r
+       {\r
+       unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickIncrements;\r
+\r
+               /* Make sure the SysTick reload value does not overflow the counter. */\r
+               if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )\r
+               {\r
+                       xExpectedIdleTime = xMaximumPossibleSuppressedTicks;\r
+               }\r
+\r
+               /* Calculate the reload value required to wait xExpectedIdleTime\r
+               tick periods.  -1 is used because this code will execute part way\r
+               through one of the tick periods, and the fraction of a tick period is\r
+               accounted for later. */\r
+               ulReloadValue = ( ulTimerReloadValueForOneTick * ( xExpectedIdleTime - 1UL ) );\r
+               if( ulReloadValue > ulStoppedTimerCompensation )\r
+               {\r
+                       ulReloadValue -= ulStoppedTimerCompensation;\r
+               }\r
+\r
+               /* Stop the SysTick momentarily.  The time the SysTick is stopped for\r
+               is accounted for as best it can be, but using the tickless mode will\r
+               inevitably result in some tiny drift of the time maintained by the\r
+               kernel with respect to calendar time. */\r
+               portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+               /* If a context switch is pending then abandon the low power entry as\r
+               the context switch might have been pended by an external interrupt that\r
+               requires processing. */\r
+               if( ( portNVIC_INT_CTRL_REG & portNVIC_PENDSVSET_BIT ) != 0 )\r
+               {\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+               }\r
+               else\r
+               {\r
+                       /* Adjust the reload value to take into account that the current\r
+                       time slice is already partially complete. */\r
+                       ulReloadValue += ( portNVIC_SYSTICK_LOAD_REG - ( portNVIC_SYSTICK_LOAD_REG - portNVIC_SYSTICK_CURRENT_VALUE_REG ) );\r
+                       portNVIC_SYSTICK_LOAD_REG = ulReloadValue;\r
+\r
+                       /* Clear the SysTick count flag and set the count value back to\r
+                       zero. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+\r
+                       /* Restart SysTick. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       /* Sleep until something happens. */\r
+                       portPRE_SLEEP_PROCESSING();\r
+                       __wfi();\r
+                       portPOST_SLEEP_PROCESSING();\r
+\r
+                       /* Stop SysTick.  Again, the time the SysTick is stopped for is\r
+                       accounted for as best it can be, but using the tickless mode will\r
+                       inevitably result in some tiny drift of the time maintained by the\r
+                       kernel with respect to calendar time. */\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;\r
+\r
+                       if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )\r
+                       {\r
+                               /* The tick interrupt has already executed, and the SysTick\r
+                               count reloaded with the portNVIC_SYSTICK_LOAD_REG value.\r
+                               Reset the portNVIC_SYSTICK_LOAD_REG with whatever remains of\r
+                               this tick period. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );\r
+\r
+                               /* The tick interrupt handler will already have pended the tick\r
+                               processing in the kernel.  As the pending tick will be\r
+                               processed as soon as this function exits, the tick value\r
+                               maintained by the tick is stepped forward by one less than the\r
+                               time spent waiting. */\r
+                               ulCompleteTickPeriods = xExpectedIdleTime - 1UL;\r
+                       }\r
+                       else\r
+                       {\r
+                               /* Something other than the tick interrupt ended the sleep.\r
+                               Work out how long the sleep lasted. */\r
+                               ulCompletedSysTickIncrements = ( xExpectedIdleTime * ulTimerReloadValueForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;\r
+\r
+                               /* How many complete tick periods passed while the processor\r
+                               was waiting? */\r
+                               ulCompleteTickPeriods = ulCompletedSysTickIncrements / ulTimerReloadValueForOneTick;\r
+\r
+                               /* The reload value is set to whatever fraction of a single tick\r
+                               period remains. */\r
+                               portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1 ) * ulTimerReloadValueForOneTick ) - ulCompletedSysTickIncrements;\r
+                       }\r
+\r
+                       /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG\r
+                       again, then set portNVIC_SYSTICK_LOAD_REG back to its standard\r
+                       value. */\r
+                       portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;\r
+                       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
+\r
+                       vTaskStepTick( ulCompleteTickPeriods );\r
+               }\r
+       }\r
+\r
+#endif /* #if configUSE_TICKLESS_IDLE */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
 /*\r
  * Setup the systick timer to generate the tick interrupts at the required\r
  * frequency.\r
  */\r
 void prvSetupTimerInterrupt( void )\r
 {\r
+       /* Calculate the constants required to configure the tick interrupt. */\r
+       ulTimerReloadValueForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
+       #if configUSE_TICKLESS_IDLE == 1\r
+               xMaximumPossibleSuppressedTicks = 0xffffffUL / ( ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL );\r
+       #endif /* configUSE_TICKLESS_IDLE */\r
+\r
        /* Configure SysTick to interrupt at the requested rate. */\r
-       *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;\r
-       *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;\r
+       portNVIC_SYSTICK_LOAD_REG = ulTimerReloadValueForOneTick;\r
+       portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-__asm void vPortSetInterruptMask( void )\r
+__asm unsigned long ulPortSetInterruptMask( void )\r
 {\r
        PRESERVE8\r
 \r
-       mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
-       msr basepri, r0\r
+       mrs r0, basepri\r
+       mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY\r
+       msr basepri, r1\r
        bx r14\r
 }\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
-__asm void vPortClearInterruptMask( void )\r
+__asm void vPortClearInterruptMask( unsigned long ulNewMask )\r
 {\r
        PRESERVE8\r
 \r
-       /* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-       http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-       mov r0, #0\r
        msr basepri, r0\r
        bx r14\r
 }\r
index 9301eddc1148848f6cc4cbf821749312d8bfb8a6..a32b6de0dff1b16c61cb0394e50f76770a7a530f 100644 (file)
@@ -106,46 +106,39 @@ extern "C" {
 #define portBYTE_ALIGNMENT                     8\r
 /*-----------------------------------------------------------*/        \r
 \r
-\r
 /* Scheduler utilities. */\r
 extern void vPortYield( void );\r
 extern void vPortYieldFromISR( void );\r
-\r
 #define portYIELD()                                    vPortYieldFromISR()\r
 #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR()\r
 /*-----------------------------------------------------------*/\r
 \r
-\r
 /* Critical section management. */\r
-\r
-extern void vPortSetInterruptMask( void );\r
-extern void vPortClearInterruptMask( void );\r
+extern unsigned long ulPortSetInterruptMask( void );\r
+extern void vPortClearInterruptMask( unsigned long ulNewMask );\r
 extern void vPortEnterCritical( void );\r
 extern void vPortExitCritical( void );\r
 \r
-#define portDISABLE_INTERRUPTS()                               vPortSetInterruptMask()\r
-#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask()\r
+#define portDISABLE_INTERRUPTS()                               ulPortSetInterruptMask()\r
+#define portENABLE_INTERRUPTS()                                        vPortClearInterruptMask( 0 )\r
 #define portENTER_CRITICAL()                                   vPortEnterCritical()\r
 #define portEXIT_CRITICAL()                                            vPortExitCritical()\r
+#define portSET_INTERRUPT_MASK_FROM_ISR()              ulPortSetInterruptMask()\r
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask(x)\r
 \r
-/* FAQ:  Setting BASEPRI to 0 is not a bug.  Please see \r
-http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html before disagreeing. */\r
-#define portSET_INTERRUPT_MASK_FROM_ISR()              0;vPortSetInterruptMask()\r
-#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)   vPortClearInterruptMask();(void)x\r
+/*-----------------------------------------------------------*/\r
 \r
 /* There are an uneven number of items on the initial stack, so \r
 portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */\r
 #define portALIGNMENT_ASSERT_pxCurrentTCB ( void )\r
-\r
 /*-----------------------------------------------------------*/\r
 \r
-/* Task function macros as described on the FreeRTOS.org WEB site. */\r
-#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
-#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
-\r
-#define portNOP()\r
-\r
+/* Tickless/low power optimisations. */\r
+extern void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime );\r
+#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )\r
+/*-----------------------------------------------------------*/\r
 \r
+/* Port specific optimisations. */\r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1\r
 \r
        /* Check the configuration. */\r
@@ -158,11 +151,21 @@ portALIGNMENT_ASSERT_pxCurrentTCB() will trigger false positive asserts. */
        #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )\r
 \r
        /*-----------------------------------------------------------*/\r
-       \r
+\r
        #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )\r
 \r
 #endif /* taskRECORD_READY_PRIORITY */\r
+/*-----------------------------------------------------------*/\r
 \r
+/* Task function macros as described on the FreeRTOS.org WEB site.  These are\r
+not necessary for to use this port.  They are defined so the common demo files\r
+(which build with all the ports) will build. */\r
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+/*-----------------------------------------------------------*/\r
+\r
+/* portNOP() is not required by this port. */\r
+#define portNOP()\r
 \r
 #ifdef __cplusplus\r
 }\r
index e04232b33b7b67a08553121c4959e8f4632151e4..c8edef19bea1ef35ed2b87f9bfb445886667d4df 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
     FreeRTOS V7.2.0 - Copyright (C) 2012 Real Time Engineers Ltd.\r
-       \r
+\r
 \r
     ***************************************************************************\r
      *                                                                       *\r
@@ -40,7 +40,7 @@
     FreeRTOS WEB site.\r
 \r
     1 tab == 4 spaces!\r
-    \r
+\r
     ***************************************************************************\r
      *                                                                       *\r
      *    Having a problem?  Start by reading the FAQ "My application does   *\r
      *                                                                       *\r
     ***************************************************************************\r
 \r
-    \r
-    http://www.FreeRTOS.org - Documentation, training, latest information, \r
+\r
+    http://www.FreeRTOS.org - Documentation, training, latest information,\r
     license and contact details.\r
-    \r
+\r
     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
     including FreeRTOS+Trace - an indispensable productivity tool.\r
 \r
-    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell \r
-    the code with commercial support, indemnification, and middleware, under \r
+    Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell\r
+    the code with commercial support, indemnification, and middleware, under\r
     the OpenRTOS brand: http://www.OpenRTOS.com.  High Integrity Systems also\r
-    provide a safety engineered and independently SIL3 certified version under \r
+    provide a safety engineered and independently SIL3 certified version under\r
     the SafeRTOS brand: http://www.SafeRTOS.com.\r
 */\r
 \r
-\r
+/* Standard includes. */\r
 #include <stdio.h>\r
 #include <stdlib.h>\r
 #include <string.h>\r
@@ -74,6 +74,7 @@ all the API functions to use the MPU wrappers.  That should only be done when
 task.h is included from an application file. */\r
 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
 \r
+/* FreeRTOS includes. */\r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
 #include "timers.h"\r
@@ -82,39 +83,40 @@ task.h is included from an application file. */
 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE\r
 \r
 /*\r
- * Macro to define the amount of stack available to the idle task.\r
+ * Defines the size, in words, of the stack allocated to the idle task.\r
  */\r
 #define tskIDLE_STACK_SIZE     configMINIMAL_STACK_SIZE\r
 \r
 /*\r
- * Task control block.  A task control block (TCB) is allocated to each task,\r
- * and stores the context of the task.\r
+ * Task control block.  A task control block (TCB) is allocated for each task,\r
+ * and stores task state information, including a pointer to the task's context\r
+ * (the task's run time environment, including register values)\r
  */\r
 typedef struct tskTaskControlBlock\r
 {\r
-       volatile portSTACK_TYPE *pxTopOfStack;          /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */\r
+       volatile portSTACK_TYPE *pxTopOfStack;          /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */\r
 \r
        #if ( portUSING_MPU_WRAPPERS == 1 )\r
-               xMPU_SETTINGS xMPUSettings;                             /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE STRUCT. */\r
-       #endif  \r
-       \r
-       xListItem                               xGenericListItem;       /*< List item used to place the TCB in ready and blocked queues. */\r
-       xListItem                               xEventListItem;         /*< List item used to place the TCB in event lists. */\r
-       unsigned portBASE_TYPE  uxPriority;                     /*< The priority of the task where 0 is the lowest priority. */\r
+               xMPU_SETTINGS xMPUSettings;                             /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */\r
+       #endif\r
+\r
+       xListItem                               xGenericListItem;               /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */\r
+       xListItem                               xEventListItem;         /*< Used to reference a task from an event list. */\r
+       unsigned portBASE_TYPE  uxPriority;                     /*< The priority of the task 0 is the lowest priority. */\r
        portSTACK_TYPE                  *pxStack;                       /*< Points to the start of the stack. */\r
        signed char                             pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */\r
 \r
        #if ( portSTACK_GROWTH > 0 )\r
-               portSTACK_TYPE *pxEndOfStack;                   /*< Used for stack overflow checking on architectures where the stack grows up from low memory. */\r
+               portSTACK_TYPE *pxEndOfStack;                   /*< Points to the end of the stack on architectures where the stack grows up from low memory. */\r
        #endif\r
 \r
        #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
-               unsigned portBASE_TYPE uxCriticalNesting;\r
+               unsigned portBASE_TYPE uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */\r
        #endif\r
 \r
        #if ( configUSE_TRACE_FACILITY == 1 )\r
-               unsigned portBASE_TYPE  uxTCBNumber;    /*< This stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */\r
-               unsigned portBASE_TYPE  uxTaskNumber;   /*< This stores a number specifically for use by third party trace code. */\r
+               unsigned portBASE_TYPE  uxTCBNumber;    /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */\r
+               unsigned portBASE_TYPE  uxTaskNumber;   /*< Stores a number specifically for use by third party trace code. */\r
        #endif\r
 \r
        #if ( configUSE_MUTEXES == 1 )\r
@@ -126,15 +128,15 @@ typedef struct tskTaskControlBlock
        #endif\r
 \r
        #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
-               unsigned long ulRunTimeCounter;         /*< Used for calculating how much CPU time each task is utilising. */\r
+               unsigned long ulRunTimeCounter;                 /*< Stores the amount of time the task has spent in the Running state. */\r
        #endif\r
 \r
 } tskTCB;\r
 \r
 \r
 /*\r
- * Some kernel aware debuggers require data to be viewed to be global, rather\r
- * than file scope.\r
+ * Some kernel aware debuggers require the data the debugger needs access to to\r
+ * be global, rather than file scope.\r
  */\r
 #ifdef portREMOVE_STATIC_QUALIFIER\r
        #define static\r
@@ -144,7 +146,6 @@ typedef struct tskTaskControlBlock
 PRIVILEGED_DATA tskTCB * volatile pxCurrentTCB = NULL;\r
 \r
 /* Lists for ready and blocked tasks. --------------------*/\r
-\r
 PRIVILEGED_DATA static xList pxReadyTasksLists[ configMAX_PRIORITIES ];        /*< Prioritised ready tasks. */\r
 PRIVILEGED_DATA static xList xDelayedTaskList1;                                                        /*< Delayed tasks. */\r
 PRIVILEGED_DATA static xList xDelayedTaskList2;                                                        /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */\r
@@ -166,9 +167,9 @@ PRIVILEGED_DATA static xList xPendingReadyList;                                                     /*< Tasks that have been r
 #endif\r
 \r
 #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )\r
-       \r
-       PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL;\r
-       \r
+\r
+       PRIVILEGED_DATA static xTaskHandle xIdleTaskHandle = NULL;                      /*< Holds the handle of the idle task.  The idle task is created automatically when the scheduler is started. */\r
+\r
 #endif\r
 \r
 /* File private variables. --------------------------------*/\r
@@ -182,7 +183,7 @@ PRIVILEGED_DATA static volatile unsigned portBASE_TYPE uxMissedTicks                        = ( unsi
 PRIVILEGED_DATA static volatile portBASE_TYPE xMissedYield                                             = ( portBASE_TYPE ) pdFALSE;\r
 PRIVILEGED_DATA static volatile portBASE_TYPE xNumOfOverflows                                  = ( portBASE_TYPE ) 0;\r
 PRIVILEGED_DATA static unsigned portBASE_TYPE uxTaskNumber                                             = ( unsigned portBASE_TYPE ) 0U;\r
-PRIVILEGED_DATA static portTickType xNextTaskUnblockTime                                               = ( portTickType ) portMAX_DELAY;\r
+PRIVILEGED_DATA static volatile portTickType xNextTaskUnblockTime                              = ( portTickType ) portMAX_DELAY;\r
 \r
 #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
 \r
@@ -211,10 +212,13 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime                                          = ( portTickType )
 /*-----------------------------------------------------------*/\r
 \r
 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 0\r
-       /* \r
-        * uxTopReadyPriority holds the priority of the highest priority ready\r
-        * state task.\r
-        */\r
+\r
+       /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 0 then task selection is\r
+       performed in a generic way that is not optimised to any particular\r
+       microcontroller architecture. */\r
+\r
+       /* uxTopReadyPriority holds the priority of the highest priority ready\r
+       state task. */\r
        #define taskRECORD_READY_PRIORITY( uxPriority )                                                                                                                                         \\r
        {                                                                                                                                                                                                                                       \\r
                if( ( uxPriority ) > uxTopReadyPriority )                                                                                                                                               \\r
@@ -241,26 +245,46 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime                                          = ( portTickType )
 \r
        /*-----------------------------------------------------------*/\r
 \r
-       /* Define away portRESET_READY_PRIORITY() as it is not required in this\r
-       configuration. */\r
+       /* Define away taskRESET_READY_PRIORITY() and portRESET_READY_PRIORITY() as\r
+       they are only required when a port optimised method of task selection is\r
+       being used. */\r
+       #define taskRESET_READY_PRIORITY( uxPriority )\r
        #define portRESET_READY_PRIORITY( uxPriority, uxTopReadyPriority )\r
 \r
 #else /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
 \r
+       /* If configUSE_PORT_OPTIMISED_TASK_SELECTION is 1 then task selection is\r
+       performed in a way that is tailored to the particular microcontroller\r
+       architecture being used. */\r
+\r
        /* A port optimised version is provided.  Call the port defined macros. */\r
        #define taskRECORD_READY_PRIORITY( uxPriority ) portRECORD_READY_PRIORITY( uxPriority, uxTopReadyPriority )\r
 \r
        /*-----------------------------------------------------------*/\r
 \r
-       #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                                                                      \\r
-       {                                                                                                                                                                                                                                       \\r
-       unsigned portBASE_TYPE uxTopPriority;                                                                                                                                                           \\r
-                                                                                                                                                                                                                                               \\r
-               /* Find the highest priority queue that contains ready tasks. */                                                                                                \\r
-               portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                                                                                                  \\r
-               listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );                                                   \\r
+       #define taskSELECT_HIGHEST_PRIORITY_TASK()                                                                                                              \\r
+       {                                                                                                                                                                                               \\r
+       unsigned portBASE_TYPE uxTopPriority;                                                                                                                   \\r
+                                                                                                                                                                                                       \\r
+               /* Find the highest priority queue that contains ready tasks. */                                                        \\r
+               portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                                                          \\r
+               configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );         \\r
+               listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );           \\r
        } /* taskSELECT_HIGHEST_PRIORITY_TASK() */\r
 \r
+       /*-----------------------------------------------------------*/\r
+\r
+       /* A port optimised version is provided, call it only if the TCB being reset\r
+       is being referenced from a ready list.  If it is referenced from a delayed\r
+       or suspended list then it won't be in a ready list. */\r
+       #define taskRESET_READY_PRIORITY( uxPriority )                                                                                                  \\r
+       {                                                                                                                                                                                               \\r
+               if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == 0 )                          \\r
+               {                                                                                                                                                                                       \\r
+                       portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) );                                             \\r
+               }                                                                                                                                                                                       \\r
+       }\r
+\r
 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */\r
 \r
 /*\r
@@ -270,9 +294,9 @@ PRIVILEGED_DATA static portTickType xNextTaskUnblockTime                                            = ( portTickType )
  * executing task, then it will only be rescheduled after the currently\r
  * executing task has been rescheduled.\r
  */\r
-#define prvAddTaskToReadyQueue( pxTCB )                                                                                                                                                                        \\r
-       traceMOVED_TASK_TO_READY_STATE( pxTCB )                                                                                                                                                         \\r
-       taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                                                                                                     \\r
+#define prvAddTaskToReadyQueue( pxTCB )                                                                                                                                                                \\r
+       traceMOVED_TASK_TO_READY_STATE( pxTCB )                                                                                                                                                 \\r
+       taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                                                                                             \\r
        vListInsertEnd( ( xList * ) &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xGenericListItem ) )\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -348,7 +372,7 @@ portTickType xItemValue;                                                                                                                            \
 /* Callback function prototypes. --------------------------*/\r
 extern void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName );\r
 extern void vApplicationTickHook( void );\r
-               \r
+\r
 /* File private functions. --------------------------------*/\r
 \r
 /*\r
@@ -488,7 +512,7 @@ tskTCB * pxNewTCB;
                #else\r
                {\r
                        pxTopOfStack = pxNewTCB->pxStack;\r
-                       \r
+\r
                        /* Check the alignment of the stack buffer is correct. */\r
                        configASSERT( ( ( ( unsigned long ) pxNewTCB->pxStack & ( unsigned long ) portBYTE_ALIGNMENT_MASK ) == 0UL ) );\r
 \r
@@ -526,7 +550,7 @@ tskTCB * pxNewTCB;
                        required.*/\r
                        *pxCreatedTask = ( xTaskHandle ) pxNewTCB;\r
                }\r
-               \r
+\r
                /* We are going to manipulate the task queues to add this task to a\r
                ready list, so must make sure no interrupts occur. */\r
                taskENTER_CRITICAL();\r
@@ -630,7 +654,7 @@ tskTCB * pxNewTCB;
                        scheduler for the TCB and stack. */\r
                        if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )\r
                        {\r
-                               portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );\r
+                               taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
                        }\r
 \r
                        /* Is the task waiting on an event also? */\r
@@ -725,6 +749,9 @@ tskTCB * pxNewTCB;
                                both lists. */\r
                                if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )\r
                                {\r
+                                       /* The current task must be in a ready list, so there is\r
+                                       no need to check, and the port reset macro can be called\r
+                                       directly. */\r
                                        portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
                                }\r
 \r
@@ -775,6 +802,9 @@ tskTCB * pxNewTCB;
                                both lists. */\r
                                if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )\r
                                {\r
+                                       /* The current task must be in a ready list, so there is\r
+                                       no need to check, and the port reset macro can be called\r
+                                       directly. */\r
                                        portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
                                }\r
                                prvAddCurrentTaskToDelayedList( xTimeToWake );\r
@@ -794,7 +824,7 @@ tskTCB * pxNewTCB;
 /*-----------------------------------------------------------*/\r
 \r
 #if ( INCLUDE_eTaskStateGet == 1 )\r
-       \r
+\r
        eTaskState eTaskStateGet( xTaskHandle pxTask )\r
        {\r
        eTaskState eReturn;\r
@@ -818,7 +848,7 @@ tskTCB * pxNewTCB;
 \r
                        if( ( pxStateList == pxDelayedTaskList ) || ( pxStateList == pxOverflowDelayedTaskList ) )\r
                        {\r
-                               /* The task being queried is referenced from one of the Blocked \r
+                               /* The task being queried is referenced from one of the Blocked\r
                                lists. */\r
                                eReturn = eBlocked;\r
                        }\r
@@ -826,7 +856,7 @@ tskTCB * pxNewTCB;
                        #if ( INCLUDE_vTaskSuspend == 1 )\r
                                else if( pxStateList == &xSuspendedTaskList )\r
                                {\r
-                                       /* The task being queried is referenced from the suspended \r
+                                       /* The task being queried is referenced from the suspended\r
                                        list. */\r
                                        eReturn = eSuspended;\r
                                }\r
@@ -835,7 +865,7 @@ tskTCB * pxNewTCB;
                        #if ( INCLUDE_vTaskDelete == 1 )\r
                                else if( pxStateList == &xTasksWaitingTermination )\r
                                {\r
-                                       /* The task being queried is referenced from the deleted \r
+                                       /* The task being queried is referenced from the deleted\r
                                        tasks list. */\r
                                        eReturn = eDeleted;\r
                                }\r
@@ -882,7 +912,7 @@ tskTCB * pxNewTCB;
        void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority )\r
        {\r
        tskTCB *pxTCB;\r
-       unsigned portBASE_TYPE uxCurrentPriority;\r
+       unsigned portBASE_TYPE uxCurrentPriority, uxPriorityUsedOnEntry;\r
        portBASE_TYPE xYieldRequired = pdFALSE;\r
 \r
                configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );\r
@@ -938,7 +968,10 @@ tskTCB * pxNewTCB;
                                        xYieldRequired = pdTRUE;\r
                                }\r
 \r
-\r
+                               /* Remember the ready list the task might be referenced from\r
+                               before its uxPriority member is changed so the\r
+                               taskRESET_READY_PRIORITY() macro can function correctly. */\r
+                               uxPriorityUsedOnEntry = pxTCB->uxPriority;\r
 \r
                                #if ( configUSE_MUTEXES == 1 )\r
                                {\r
@@ -971,7 +1004,7 @@ tskTCB * pxNewTCB;
                                        can do this even if the scheduler is suspended. */\r
                                        if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )\r
                                        {\r
-                                               portRESET_READY_PRIORITY( uxCurrentPriority, uxTopReadyPriority );\r
+                                               taskRESET_READY_PRIORITY( uxPriorityUsedOnEntry );\r
                                        }\r
                                        prvAddTaskToReadyQueue( pxTCB );\r
                                }\r
@@ -983,6 +1016,10 @@ tskTCB * pxNewTCB;
                        }\r
                }\r
                taskEXIT_CRITICAL();\r
+\r
+               /* Remove compiler warning about unused parameter when the port\r
+               optimised task selection is not being used. */\r
+               ( void ) uxPriorityUsedOnEntry;\r
        }\r
 \r
 #endif\r
@@ -1011,7 +1048,7 @@ tskTCB * pxNewTCB;
                        /* Remove task from the ready/delayed list and place in the     suspended list. */\r
                        if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )\r
                        {\r
-                               portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );\r
+                               taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
                        }\r
 \r
                        /* Is the task waiting on an event also? */\r
@@ -1228,7 +1265,7 @@ portBASE_TYPE xReturn;
                macro must be defined to configure the timer/counter used to generate\r
                the run time counter time base. */\r
                portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();\r
-               \r
+\r
                /* Setting up the timer tick is hardware specific and thus in the\r
                portable interface. */\r
                if( xPortStartScheduler() != pdFALSE )\r
@@ -1266,6 +1303,30 @@ void vTaskSuspendAll( void )
 }\r
 /*----------------------------------------------------------*/\r
 \r
+portTickType xTaskGetExpectedIdleTime( void )\r
+{\r
+portTickType xReturn;\r
+\r
+       if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )\r
+       {\r
+               xReturn = 0;\r
+       }\r
+       else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )\r
+       {\r
+               /* There are other idle priority tasks in the ready state.  If\r
+               time slicing is used then the very next tick interrupt must be\r
+               processed. */\r
+               xReturn = 0;\r
+       }\r
+       else\r
+       {\r
+               xReturn = xNextTaskUnblockTime - xTickCount;\r
+       }\r
+\r
+       return xReturn;\r
+}\r
+/*----------------------------------------------------------*/\r
+\r
 signed portBASE_TYPE xTaskResumeAll( void )\r
 {\r
 register tskTCB *pxTCB;\r
@@ -1488,7 +1549,7 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
                        /* Divide ulTotalRunTime by 100 to make the percentage caluclations\r
                        simpler in the prvGenerateRunTimeStatsForTasksInList() function. */\r
                        ulTotalRunTime /= 100UL;\r
-                       \r
+\r
                        /* Run through all the lists that could potentially contain a TCB,\r
                        generating a table of run timer percentages in the provided\r
                        buffer. */\r
@@ -1551,8 +1612,15 @@ unsigned portBASE_TYPE uxTaskGetNumberOfTasks( void )
                configASSERT( ( xIdleTaskHandle != NULL ) );\r
                return xIdleTaskHandle;\r
        }\r
-       \r
+\r
 #endif\r
+/*----------------------------------------------------------*/\r
+\r
+void vTaskStepTick( portTickType xTicksToJump )\r
+{\r
+       configASSERT( xTicksToJump <= xNextTaskUnblockTime );\r
+       xTickCount += xTicksToJump;\r
+}\r
 \r
 /*-----------------------------------------------------------\r
  * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES\r
@@ -1566,6 +1634,7 @@ tskTCB * pxTCB;
        /* Called by the portable layer each time a tick interrupt occurs.\r
        Increments the tick then checks to see if the new tick value will cause any\r
        tasks to be unblocked. */\r
+       traceTASK_INCREMENT_TICK( xTickCount );\r
        if( uxSchedulerSuspended == ( unsigned portBASE_TYPE ) pdFALSE )\r
        {\r
                ++xTickCount;\r
@@ -1577,17 +1646,17 @@ tskTCB * pxTCB;
                        If there are any items in pxDelayedTaskList here then there is\r
                        an error! */\r
                        configASSERT( ( listLIST_IS_EMPTY( pxDelayedTaskList ) ) );\r
-                       \r
+\r
                        pxTemp = pxDelayedTaskList;\r
                        pxDelayedTaskList = pxOverflowDelayedTaskList;\r
                        pxOverflowDelayedTaskList = pxTemp;\r
                        xNumOfOverflows++;\r
-       \r
+\r
                        if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE )\r
                        {\r
                                /* The new current delayed list is empty.  Set\r
                                xNextTaskUnblockTime to the maximum possible value so it is\r
-                               extremely unlikely that the     \r
+                               extremely unlikely that the\r
                                if( xTickCount >= xNextTaskUnblockTime ) test will pass until\r
                                there is an item in the delayed list. */\r
                                xNextTaskUnblockTime = portMAX_DELAY;\r
@@ -1629,8 +1698,6 @@ tskTCB * pxTCB;
                }\r
        }\r
        #endif\r
-\r
-       traceTASK_INCREMENT_TICK( xTickCount );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -1732,17 +1799,17 @@ void vTaskSwitchContext( void )
        else\r
        {\r
                traceTASK_SWITCHED_OUT();\r
-       \r
+\r
                #if ( configGENERATE_RUN_TIME_STATS == 1 )\r
                {\r
                        unsigned long ulTempCounter;\r
-                       \r
+\r
                                #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE\r
                                        portALT_GET_RUN_TIME_COUNTER_VALUE( ulTempCounter );\r
                                #else\r
                                        ulTempCounter = portGET_RUN_TIME_COUNTER_VALUE();\r
                                #endif\r
-       \r
+\r
                                /* Add the amount of time the task has been running to the accumulated\r
                                time so far.  The time the task started running was stored in\r
                                ulTaskSwitchedInTime.  Note that there is no overflow protection here\r
@@ -1752,12 +1819,12 @@ void vTaskSwitchContext( void )
                                ulTaskSwitchedInTime = ulTempCounter;\r
                }\r
                #endif\r
-       \r
+\r
                taskFIRST_CHECK_FOR_STACK_OVERFLOW();\r
                taskSECOND_CHECK_FOR_STACK_OVERFLOW();\r
-       \r
+\r
                taskSELECT_HIGHEST_PRIORITY_TASK();\r
-                       \r
+\r
                traceTASK_SWITCHED_IN();\r
        }\r
 }\r
@@ -1782,6 +1849,8 @@ portTickType xTimeToWake;
        exclusive access to the ready lists as the scheduler is locked. */\r
        if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )\r
        {\r
+               /* The current task must be in a ready list, so there is no need to\r
+               check, and the port reset macro can be called directly. */\r
                portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
        }\r
 \r
@@ -1826,7 +1895,7 @@ portTickType xTimeToWake;
                designed for use by kernel code, and has special calling requirements -\r
                it should be called from a critical section. */\r
 \r
-       \r
+\r
                /* Place the event list item of the TCB in the appropriate event list.\r
                In this case it is assume that this is the only task that is going to\r
                be waiting on this event list, so the faster vListInsertEnd() function\r
@@ -1838,6 +1907,8 @@ portTickType xTimeToWake;
                function is called form a critical section. */\r
                if( uxListRemove( ( xListItem * ) &( pxCurrentTCB->xGenericListItem ) ) == 0 )\r
                {\r
+                       /* The current task must be in a ready list, so there is no need to\r
+                       check, and the port reset macro can be called directly. */\r
                        portRESET_READY_PRIORITY( pxCurrentTCB->uxPriority, uxTopReadyPriority );\r
                }\r
 \r
@@ -1846,7 +1917,7 @@ portTickType xTimeToWake;
                xTimeToWake = xTickCount + xTicksToWait;\r
                prvAddCurrentTaskToDelayedList( xTimeToWake );\r
        }\r
-       \r
+\r
 #endif /* configUSE_TIMERS */\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -1865,7 +1936,7 @@ portBASE_TYPE xReturn;
        If an event is for a queue that is locked then this function will never\r
        get called - the lock count on the queue will get modified instead.  This\r
        means we can always expect exclusive access to the event list here.\r
-       \r
+\r
        This function assumes that a check has already been made to ensure that\r
        pxEventList is not empty. */\r
        pxUnblockedTCB = ( tskTCB * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );\r
@@ -1966,7 +2037,7 @@ void vTaskMissedYield( void )
        {\r
        unsigned portBASE_TYPE uxReturn;\r
        tskTCB *pxTCB;\r
-       \r
+\r
                if( xTask != NULL )\r
                {\r
                        pxTCB = ( tskTCB * ) xTask;\r
@@ -1976,7 +2047,7 @@ void vTaskMissedYield( void )
                {\r
                        uxReturn = 0U;\r
                }\r
-               \r
+\r
                return uxReturn;\r
        }\r
 #endif\r
@@ -1986,7 +2057,7 @@ void vTaskMissedYield( void )
        void vTaskSetTaskNumber( xTaskHandle xTask, unsigned portBASE_TYPE uxHandle )\r
        {\r
        tskTCB *pxTCB;\r
-       \r
+\r
                if( xTask != NULL )\r
                {\r
                        pxTCB = ( tskTCB * ) xTask;\r
@@ -2057,6 +2128,48 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
                        vApplicationIdleHook();\r
                }\r
                #endif\r
+\r
+               #if ( configUSE_TICKLESS_IDLE == 1 )\r
+               {\r
+               portTickType xExpectedIdleTime;\r
+               /* If the expected idle time is 1 then the idle time would end at\r
+               the end of the current time slice.  The idle time must be at least\r
+               2 to ensure any pended ticks between this point and the tick being\r
+               stopped can be legitimately stepped over when the tick suppression\r
+               routines returns. */\r
+               const portTickType xMinimumExpectedIdleTime = ( portTickType ) 2;\r
+\r
+                       /* Don't enter low power if there are still tasks waiting\r
+                       deletion. */\r
+                       if( uxTasksDeleted == 0 )\r
+                       {\r
+                               /* It is not desirable to suspend then resume the scheduler on\r
+                               each iteration of the idle task.  Therefore, a preliminary\r
+                               test of the expected idle time is performed without the\r
+                               scheduler suspended.  The result here is not necessarily\r
+                               valid. */\r
+                               xExpectedIdleTime = xTaskGetExpectedIdleTime();\r
+\r
+                               if( xExpectedIdleTime >= xMinimumExpectedIdleTime )\r
+                               {\r
+                                       vTaskSuspendAll();\r
+                                       {\r
+                                               /* Now the scheduler is suspended, the expected idle\r
+                                               time can be sampled again, and this time its value can\r
+                                               be used. */\r
+                                               configASSERT( xNextTaskUnblockTime >= xTickCount );\r
+                                               xExpectedIdleTime = xTaskGetExpectedIdleTime();\r
+\r
+                                               if( xExpectedIdleTime >= xMinimumExpectedIdleTime )\r
+                                               {\r
+                                                       portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );\r
+                                               }\r
+                                       }\r
+                                       xTaskResumeAll();\r
+                               }\r
+                       }\r
+               }\r
+               #endif\r
        }\r
 } /*lint !e715 pvParameters is not accessed but all task functions require the same prototype. */\r
 \r
@@ -2144,7 +2257,7 @@ static void prvInitialiseTCBVariables( tskTCB *pxTCB, const signed char * const
        void vTaskAllocateMPURegions( xTaskHandle xTaskToModify, const xMemoryRegion * const xRegions )\r
        {\r
        tskTCB *pxTCB;\r
-       \r
+\r
                if( xTaskToModify == pxCurrentTCB )\r
                {\r
                        xTaskToModify = NULL;\r
@@ -2304,8 +2417,8 @@ tskTCB *pxNewTCB;
                        {\r
                                usStackRemaining = usTaskCheckFreeStackSpace( ( unsigned char * ) pxNextTCB->pxStack );\r
                        }\r
-                       #endif                  \r
-                       \r
+                       #endif\r
+\r
                        sprintf( pcStatusString, ( char * ) "%s\t\t%c\t%u\t%u\t%u\r\n", pxNextTCB->pcTaskName, cStatus, ( unsigned int ) pxNextTCB->uxPriority, usStackRemaining, ( unsigned int ) pxNextTCB->uxTCBNumber );\r
                        strcat( ( char * ) pcWriteBuffer, ( char * ) pcStatusString );\r
 \r
@@ -2349,7 +2462,7 @@ tskTCB *pxNewTCB;
                                        {\r
                                                #ifdef portLU_PRINTF_SPECIFIER_REQUIRED\r
                                                {\r
-                                                       sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );                                                 \r
+                                                       sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t%lu%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter, ulStatsAsPercentage );\r
                                                }\r
                                                #else\r
                                                {\r
@@ -2365,7 +2478,7 @@ tskTCB *pxNewTCB;
                                                consumed less than 1% of the total run time. */\r
                                                #ifdef portLU_PRINTF_SPECIFIER_REQUIRED\r
                                                {\r
-                                                       sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );                                                       \r
+                                                       sprintf( pcStatsString, ( char * ) "%s\t\t%lu\t\t<1%%\r\n", pxNextTCB->pcTaskName, pxNextTCB->ulRunTimeCounter );\r
                                                }\r
                                                #else\r
                                                {\r
@@ -2516,12 +2629,12 @@ tskTCB *pxNewTCB;
                                listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), configMAX_PRIORITIES - ( portTickType ) pxCurrentTCB->uxPriority );\r
 \r
                                /* If the task being modified is in the ready state it will need to\r
-                               be moved in to a new list. */\r
+                               be moved into a new list. */\r
                                if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ pxTCB->uxPriority ] ), &( pxTCB->xGenericListItem ) ) != pdFALSE )\r
                                {\r
                                        if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )\r
                                        {\r
-                                               portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );\r
+                                               taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
                                        }\r
 \r
                                        /* Inherit the priority before being moved into the new list. */\r
@@ -2556,7 +2669,7 @@ tskTCB *pxNewTCB;
                                Remove ourselves from the ready list we currently appear in. */\r
                                if( uxListRemove( ( xListItem * ) &( pxTCB->xGenericListItem ) ) == 0 )\r
                                {\r
-                                       portRESET_READY_PRIORITY( pxTCB->uxPriority, uxTopReadyPriority );\r
+                                       taskRESET_READY_PRIORITY( pxTCB->uxPriority );\r
                                }\r
 \r
                                /* Disinherit the priority before adding the task into the new\r
@@ -2589,21 +2702,40 @@ tskTCB *pxNewTCB;
 \r
 #if ( portCRITICAL_NESTING_IN_TCB == 1 )\r
 \r
-void vTaskExitCritical( void )\r
-{\r
-       if( xSchedulerRunning != pdFALSE )\r
+       void vTaskExitCritical( void )\r
        {\r
-               if( pxCurrentTCB->uxCriticalNesting > 0U )\r
+               if( xSchedulerRunning != pdFALSE )\r
                {\r
-                       ( pxCurrentTCB->uxCriticalNesting )--;\r
-\r
-                       if( pxCurrentTCB->uxCriticalNesting == 0U )\r
+                       if( pxCurrentTCB->uxCriticalNesting > 0U )\r
                        {\r
-                               portENABLE_INTERRUPTS();\r
+                               ( pxCurrentTCB->uxCriticalNesting )--;\r
+\r
+                               if( pxCurrentTCB->uxCriticalNesting == 0U )\r
+                               {\r
+                                       portENABLE_INTERRUPTS();\r
+                               }\r
                        }\r
                }\r
        }\r
-}\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+#if ( configUSE_TICKLESS_IDLE == 1 )\r
+\r
+       unsigned portBASE_TYPE uxTaskPendingTicksGet( portBASE_TYPE xResetOnExit )\r
+       {\r
+       unsigned portBASE_TYPE uxReturn;\r
+\r
+               uxReturn = uxMissedTicks;\r
+\r
+               if( xResetOnExit == pdTRUE )\r
+               {\r
+                       uxMissedTicks = 0;\r
+               }\r
+\r
+               return uxReturn;\r
+       }\r
 \r
 #endif\r
 /*-----------------------------------------------------------*/\r