diff options
author | rtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2> | 2015-05-20 15:46:40 +0000 |
---|---|---|
committer | rtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2> | 2015-05-20 15:46:40 +0000 |
commit | c54f58d075701840fa025cfe7c55d95a778951cd (patch) | |
tree | acbc3ead5b4215fdbd7b0b7e8fdfe47022307d0a | |
parent | e479b26226c6d196bcab1a258f933db200c830a4 (diff) | |
download | freertos-c54f58d075701840fa025cfe7c55d95a778951cd.tar.gz |
Kernel changes to improve power saving:
+ The timer task now blocks indefinitely if there are no timers active, allowing eTaskConfirmSleepModeStatus to return eNoTasksWaitingTimeout when configUSE_TIMERS is set to 1.
+ The next unblock time is calculated automatically after a task unblocks when waiting for a notification, allowing deep sleep to be entered earlier.
git-svn-id: http://svn.code.sf.net/p/freertos/code/trunk@2350 1d2547de-c912-0410-9cb9-b8ca96c0e9e2
-rw-r--r-- | FreeRTOS/Source/include/portable.h | 8 | ||||
-rw-r--r-- | FreeRTOS/Source/include/projdefs.h | 4 | ||||
-rw-r--r-- | FreeRTOS/Source/include/queue.h | 2 | ||||
-rw-r--r-- | FreeRTOS/Source/include/task.h | 4 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/GCC/ARM_CA9/portmacro.h | 2 | ||||
-rw-r--r-- | FreeRTOS/Source/portable/MPLAB/PIC32MZ/portmacro.h | 8 | ||||
-rw-r--r-- | FreeRTOS/Source/queue.c | 4 | ||||
-rw-r--r-- | FreeRTOS/Source/tasks.c | 103 | ||||
-rw-r--r-- | FreeRTOS/Source/timers.c | 4 |
9 files changed, 96 insertions, 43 deletions
diff --git a/FreeRTOS/Source/include/portable.h b/FreeRTOS/Source/include/portable.h index 73386cb58..9188fe930 100644 --- a/FreeRTOS/Source/include/portable.h +++ b/FreeRTOS/Source/include/portable.h @@ -94,6 +94,14 @@ must be set in the compiler's include path. */ #include "portmacro.h"
#endif
+#if portBYTE_ALIGNMENT == 32
+ #define portBYTE_ALIGNMENT_MASK ( 0x001f )
+#endif
+
+#if portBYTE_ALIGNMENT == 16
+ #define portBYTE_ALIGNMENT_MASK ( 0x000f )
+#endif
+
#if portBYTE_ALIGNMENT == 8
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif
diff --git a/FreeRTOS/Source/include/projdefs.h b/FreeRTOS/Source/include/projdefs.h index 2dedeb807..115d35670 100644 --- a/FreeRTOS/Source/include/projdefs.h +++ b/FreeRTOS/Source/include/projdefs.h @@ -103,7 +103,7 @@ typedef void (*TaskFunction_t)( void * ); #define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL
#endif
-/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
+/* The following errno values are used by FreeRTOS+ components, not FreeRTOS
itself. */
#define pdFREERTOS_ERRNO_NONE 0 /* No errors */
#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */
@@ -145,7 +145,7 @@ itself. */ #define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */
#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */
-/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
+/* The following endian values are used by FreeRTOS+ components, not FreeRTOS
itself. */
#define pdFREERTOS_LITTLE_ENDIAN 0
#define pdFREERTOS_BIG_ENDIAN 1
diff --git a/FreeRTOS/Source/include/queue.h b/FreeRTOS/Source/include/queue.h index c3e2ed500..438a426bd 100644 --- a/FreeRTOS/Source/include/queue.h +++ b/FreeRTOS/Source/include/queue.h @@ -1676,7 +1676,7 @@ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, const Ti QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) PRIVILEGED_FUNCTION;
/* Not public API functions. */
-void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) PRIVILEGED_FUNCTION;
void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) PRIVILEGED_FUNCTION;
UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) PRIVILEGED_FUNCTION;
diff --git a/FreeRTOS/Source/include/task.h b/FreeRTOS/Source/include/task.h index a62eafc6e..63b02fca9 100644 --- a/FreeRTOS/Source/include/task.h +++ b/FreeRTOS/Source/include/task.h @@ -1684,7 +1684,7 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * \defgroup xTaskNotifyGive xTaskNotifyGive
* \ingroup TaskNotifications
*/
-#define xTaskNotifyGive( xTaskToNotify ) xTaskNotify( ( xTaskToNotify ), 0, eIncrement );
+#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL )
/**
* task. h
@@ -1876,7 +1876,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte * indefinitely, whereas vTaskPlaceOnEventList() does.
*
*/
-void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
+void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
/*
* THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN
diff --git a/FreeRTOS/Source/portable/GCC/ARM_CA9/portmacro.h b/FreeRTOS/Source/portable/GCC/ARM_CA9/portmacro.h index 1b7f18a7f..ba1ca3d9b 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CA9/portmacro.h +++ b/FreeRTOS/Source/portable/GCC/ARM_CA9/portmacro.h @@ -192,7 +192,7 @@ void vPortTaskUsesFPU( void ); #endif /* configASSERT */
#define portNOP() __asm volatile( "NOP" )
-
+#define portINLINE __inline
#ifdef __cplusplus
} /* extern C */
diff --git a/FreeRTOS/Source/portable/MPLAB/PIC32MZ/portmacro.h b/FreeRTOS/Source/portable/MPLAB/PIC32MZ/portmacro.h index 95d13b87a..86bd8b0c4 100644 --- a/FreeRTOS/Source/portable/MPLAB/PIC32MZ/portmacro.h +++ b/FreeRTOS/Source/portable/MPLAB/PIC32MZ/portmacro.h @@ -137,7 +137,7 @@ ensure API function and interrupt entry is as fast and as simple as possible. */ #ifdef configASSERT
#define portDISABLE_INTERRUPTS() \
{ \
- uint32_t ulStatus; \
+ uint32_t ulStatus; \
\
/* Mask interrupts at and below the kernel interrupt priority. */ \
ulStatus = _CP0_GET_STATUS(); \
@@ -152,7 +152,7 @@ ensure API function and interrupt entry is as fast and as simple as possible. */ #else /* configASSERT */
#define portDISABLE_INTERRUPTS() \
{ \
- uint32_t ulStatus; \
+ uint32_t ulStatus; \
\
/* Mask interrupts at and below the kernel interrupt priority. */ \
ulStatus = _CP0_GET_STATUS(); \
@@ -163,7 +163,7 @@ ensure API function and interrupt entry is as fast and as simple as possible. */ #define portENABLE_INTERRUPTS() \
{ \
-uint32_t ulStatus; \
+uint32_t ulStatus; \
\
/* Unmask all interrupts. */ \
ulStatus = _CP0_GET_STATUS(); \
@@ -210,7 +210,7 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); #define portYIELD() \
{ \
-uint32_t ulCause; \
+uint32_t ulCause; \
\
/* Trigger software interrupt. */ \
ulCause = _CP0_GET_CAUSE(); \
diff --git a/FreeRTOS/Source/queue.c b/FreeRTOS/Source/queue.c index d25cdc8d3..931116fb8 100644 --- a/FreeRTOS/Source/queue.c +++ b/FreeRTOS/Source/queue.c @@ -2403,7 +2403,7 @@ BaseType_t xReturn; #if ( configUSE_TIMERS == 1 )
- void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait )
+ void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
{
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
@@ -2425,7 +2425,7 @@ BaseType_t xReturn; if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U )
{
/* There is nothing in the queue, block for the specified period. */
- vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait );
+ vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely );
}
else
{
diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index c07e88f2a..d3ec721c8 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -99,8 +99,8 @@ functions but without including stdio.h here. */ #endif /* configUSE_STATS_FORMATTING_FUNCTIONS == 1 ) */
/* Sanity check the configuration. */
-#if configUSE_TICKLESS_IDLE != 0
- #if INCLUDE_vTaskSuspend != 1
+#if( configUSE_TICKLESS_IDLE != 0 )
+ #if( INCLUDE_vTaskSuspend != 1 )
#error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0
#endif /* INCLUDE_vTaskSuspend */
#endif /* configUSE_TICKLESS_IDLE */
@@ -2387,7 +2387,7 @@ TickType_t xTimeToWake; #if configUSE_TIMERS == 1
- void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait )
+ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList, const TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely )
{
TickType_t xTimeToWake;
@@ -2420,12 +2420,44 @@ TickType_t xTimeToWake; mtCOVERAGE_TEST_MARKER();
}
- /* Calculate the time at which the task should be woken if the event does
- not occur. This may overflow but this doesn't matter. */
- xTimeToWake = xTickCount + xTicksToWait;
+ /* If vTaskSuspend() is available then the suspended task list is also
+ available and a task that is blocking indefinitely can enter the
+ suspended state (it is not really suspended as it will re-enter the
+ Ready state when the event it is waiting indefinitely for occurs).
+ Blocking indefinitely is useful when using tickless idle mode as when
+ all tasks are blocked indefinitely all timers can be turned off. */
+ #if( INCLUDE_vTaskSuspend == 1 )
+ {
+ if( xWaitIndefinitely == pdTRUE )
+ {
+ /* Add the task to the suspended task list instead of a delayed
+ task list to ensure the task is not woken by a timing event. It
+ will block indefinitely. */
+ vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );
+ }
+ else
+ {
+ /* Calculate the time at which the task should be woken if the
+ event does not occur. This may overflow but this doesn't
+ matter. */
+ xTimeToWake = xTickCount + xTicksToWait;
+ traceTASK_DELAY_UNTIL();
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
+ }
+ }
+ #else
+ {
+ /* Calculate the time at which the task should be woken if the event
+ does not occur. This may overflow but this doesn't matter. */
+ xTimeToWake = xTickCount + xTicksToWait;
+ traceTASK_DELAY_UNTIL();
+ prvAddCurrentTaskToDelayedList( xTimeToWake );
- traceTASK_DELAY_UNTIL();
- prvAddCurrentTaskToDelayedList( xTimeToWake );
+ /* Remove compiler warnings when INCLUDE_vTaskSuspend() is not
+ defined. */
+ ( void ) xWaitIndefinitely;
+ }
+ #endif
}
#endif /* configUSE_TIMERS */
@@ -2481,12 +2513,12 @@ BaseType_t xReturn; xReturn = pdFALSE;
}
- #if( configUSE_TICKLESS_IDLE == 1 )
+ #if( configUSE_TICKLESS_IDLE != 0 )
{
/* If a task is blocked on a kernel object then xNextTaskUnblockTime
might be set to the blocked task's time out time. If the task is
unblocked for a reason other than a timeout xNextTaskUnblockTime is
- normally left unchanged, because it is automatically get reset to a new
+ normally left unchanged, because it is automatically reset to a new
value when the tick count equals xNextTaskUnblockTime. However if
tickless idling is used it might be more important to enter sleep mode
at the earliest possible time - so reset xNextTaskUnblockTime here to
@@ -2759,10 +2791,12 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) }
/*-----------------------------------------------------------*/
-#if configUSE_TICKLESS_IDLE != 0
+#if( configUSE_TICKLESS_IDLE != 0 )
eSleepModeStatus eTaskConfirmSleepModeStatus( void )
{
+ /* The idle task exists in addition to the application tasks. */
+ const UBaseType_t uxNonApplicationTasks = 1;
eSleepModeStatus eReturn = eStandardSleep;
if( listCURRENT_LIST_LENGTH( &xPendingReadyList ) != 0 )
@@ -2777,29 +2811,23 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) }
else
{
- #if configUSE_TIMERS == 0
+ /* If all the tasks are in the suspended list (which might mean they
+ have an infinite block time rather than actually being suspended)
+ then it is safe to turn all clocks off and just wait for external
+ interrupts. */
+ if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
{
- /* The idle task exists in addition to the application tasks. */
- const UBaseType_t uxNonApplicationTasks = 1;
-
- /* If timers are not being used and all the tasks are in the
- suspended list (which might mean they have an infinite block
- time rather than actually being suspended) then it is safe to
- turn all clocks off and just wait for external interrupts. */
- if( listCURRENT_LIST_LENGTH( &xSuspendedTaskList ) == ( uxCurrentNumberOfTasks - uxNonApplicationTasks ) )
- {
- eReturn = eNoTasksWaitingTimeout;
- }
- else
- {
- mtCOVERAGE_TEST_MARKER();
- }
+ eReturn = eNoTasksWaitingTimeout;
+ }
+ else
+ {
+ mtCOVERAGE_TEST_MARKER();
}
- #endif /* configUSE_TIMERS */
}
return eReturn;
}
+
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
@@ -2958,7 +2986,8 @@ UBaseType_t x; {
TCB_t *pxTCB;
- /* If null is passed in here then we are deleting ourselves. */
+ /* If null is passed in here then we are modifying the MPU settings of
+ the calling task. */
pxTCB = prvGetTCBFromHandle( xTaskToModify );
vPortStoreTaskMPUSettings( &( pxTCB->xMPUSettings ), xRegions, NULL, 0 );
@@ -4165,6 +4194,22 @@ TickType_t uxReturn; /* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
+ #if( configUSE_TICKLESS_IDLE != 0 )
+ {
+ /* If a task is blocked waiting for a notification then
+ xNextTaskUnblockTime might be set to the blocked task's time
+ out time. If the task is unblocked for a reason other than
+ a timeout xNextTaskUnblockTime is normally left unchanged,
+ because it will automatically get reset to a new value when
+ the tick count equals xNextTaskUnblockTime. However if
+ tickless idling is used it might be more important to enter
+ sleep mode at the earliest possible time - so reset
+ xNextTaskUnblockTime here to ensure it is updated at the
+ earliest possible time. */
+ prvResetNextTaskUnblockTime();
+ }
+ #endif
+
if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )
{
/* The notified task has a priority above the currently
diff --git a/FreeRTOS/Source/timers.c b/FreeRTOS/Source/timers.c index 797b25226..e1de26f11 100644 --- a/FreeRTOS/Source/timers.c +++ b/FreeRTOS/Source/timers.c @@ -195,7 +195,7 @@ static void prvTimerTask( void *pvParameters ) PRIVILEGED_FUNCTION; * Called by the timer service task to interpret and process a command it
* received on the timer queue.
*/
-static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
+static void prvProcessReceivedCommands( void ) PRIVILEGED_FUNCTION;
/*
* Insert the timer into either xActiveTimerList1, or xActiveTimerList2,
@@ -468,7 +468,7 @@ BaseType_t xTimerListsWereSwitched; received - whichever comes first. The following line cannot
be reached unless xNextExpireTime > xTimeNow, except in the
case when the current timer list is empty. */
- vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ) );
+ vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );
if( xTaskResumeAll() == pdFALSE )
{
|