+ /* All ports are written to allow a yield in a critical\r
+ section (some will yield immediately, others wait until the\r
+ critical section exits) - but it is not something that\r
+ application code should ever do. */\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ ulReturn = pxCurrentTCB->ulNotifiedValue;\r
+\r
+ if( ulReturn != 0UL )\r
+ {\r
+ if( xClearCountOnExit != pdFALSE )\r
+ {\r
+ pxCurrentTCB->ulNotifiedValue = 0UL;\r
+ }\r
+ else\r
+ {\r
+ ( pxCurrentTCB->ulNotifiedValue )--;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ pxCurrentTCB->eNotifyState = eNotWaitingNotification;\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return ulReturn;\r
+ }\r
+\r
+#endif /* configUSE_TASK_NOTIFICATIONS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+\r
+ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait )\r
+ {\r
+ TickType_t xTimeToWake;\r
+ BaseType_t xReturn;\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ /* Only block if a notification is not already pending. */\r
+ if( pxCurrentTCB->eNotifyState != eNotified )\r
+ {\r
+ /* Clear bits in the task's notification value as bits may get\r
+ set by the notifying task or interrupt. This can be used to\r
+ clear the value to zero. */\r
+ pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;\r
+\r
+ /* Mark this task as waiting for a notification. */\r
+ pxCurrentTCB->eNotifyState = eWaitingNotification;\r
+\r
+ if( xTicksToWait > ( TickType_t ) 0 )\r
+ {\r
+ /* The task is going to block. First it must be removed\r
+ from the ready list. */\r
+ if( uxListRemove( &( pxCurrentTCB->xGenericListItem ) ) == ( UBaseType_t ) 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
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+\r
+ #if ( INCLUDE_vTaskSuspend == 1 )\r
+ {\r
+ if( xTicksToWait == portMAX_DELAY )\r
+ {\r
+ /* Add the task to the suspended task list instead\r
+ of a delayed task list to ensure the task is not\r
+ woken by a timing event. It will block\r
+ indefinitely. */\r
+ vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );\r
+ }\r
+ else\r
+ {\r
+ /* Calculate the time at which the task should be\r
+ woken if no notification events occur. This may\r
+ overflow but this doesn't matter, the scheduler will\r
+ handle it. */\r
+ xTimeToWake = xTickCount + xTicksToWait;\r
+ prvAddCurrentTaskToDelayedList( xTimeToWake );\r
+ }\r
+ }\r
+ #else /* INCLUDE_vTaskSuspend */\r
+ {\r
+ /* Calculate the time at which the task should be\r
+ woken if the event does not occur. This may\r
+ overflow but this doesn't matter, the scheduler will\r
+ handle it. */\r
+ xTimeToWake = xTickCount + xTicksToWait;\r
+ prvAddCurrentTaskToDelayedList( xTimeToWake );\r
+ }\r
+ #endif /* INCLUDE_vTaskSuspend */\r
+\r
+ /* All ports are written to allow a yield in a critical\r
+ section (some will yield immediately, others wait until the\r
+ critical section exits) - but it is not something that\r
+ application code should ever do. */\r
+ portYIELD_WITHIN_API();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ if( pulNotificationValue != NULL )\r
+ {\r
+ /* Output the current notification value, which may or may not\r
+ have changed. */\r
+ *pulNotificationValue = pxCurrentTCB->ulNotifiedValue;\r
+ }\r
+\r
+ /* If eNotifyValue is set then either the task never entered the\r
+ blocked state (because a notification was already pending) or the\r
+ task unblocked because of a notification. Otherwise the task\r
+ unblocked because of a timeout. */\r
+ if( pxCurrentTCB->eNotifyState == eWaitingNotification )\r
+ {\r
+ /* A notification was not received. */\r
+ xReturn = pdFALSE;\r
+ }\r
+ else\r
+ {\r
+ /* A notification was already pending or a notification was\r
+ received while the task was waiting. */\r
+ pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnExit;\r
+ xReturn = pdTRUE;\r
+ }\r
+\r
+ pxCurrentTCB->eNotifyState = eNotWaitingNotification;\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_TASK_NOTIFICATIONS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+\r
+ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue )\r
+ {\r
+ TCB_t * pxTCB;\r
+ eNotifyValue eOriginalNotifyState;\r
+ BaseType_t xReturn = pdPASS;\r
+\r
+ configASSERT( xTaskToNotify );\r
+ pxTCB = ( TCB_t * ) xTaskToNotify;\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ if( pulPreviousNotificationValue != NULL )\r
+ {\r
+ *pulPreviousNotificationValue = pxTCB->ulNotifiedValue;\r
+ }\r
+\r
+ eOriginalNotifyState = pxTCB->eNotifyState;\r
+\r
+ pxTCB->eNotifyState = eNotified;\r
+\r
+ switch( eAction )\r
+ {\r
+ case eSetBits :\r
+ pxTCB->ulNotifiedValue |= ulValue;\r
+ break;\r
+\r
+ case eIncrement :\r
+ ( pxTCB->ulNotifiedValue )++;\r
+ break;\r
+\r
+ case eSetValueWithOverwrite :\r
+ pxTCB->ulNotifiedValue = ulValue;\r
+ break;\r
+\r
+ case eSetValueWithoutOverwrite :\r
+ if( eOriginalNotifyState != eNotified )\r
+ {\r
+ pxTCB->ulNotifiedValue = ulValue;\r
+ }\r
+ else\r
+ {\r
+ /* The value could not be written to the task. */\r
+ xReturn = pdFAIL;\r
+ }\r
+ break;\r
+\r
+ case eNoAction:\r
+ /* The task is being notified without its notify value being\r
+ updated. */\r
+ break;\r
+ }\r
+\r
+\r
+ /* If the task is in the blocked state specifically to wait for a\r
+ notification then unblock it now. */\r
+ if( eOriginalNotifyState == eWaitingNotification )\r
+ {\r
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
+ prvAddTaskToReadyList( pxTCB );\r
+\r
+ /* The task should not have been on an event list. */\r
+ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
+\r
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
+ {\r
+ /* The notified task has a priority above the currently\r
+ executing task so a yield is required. */\r
+ taskYIELD_IF_USING_PREEMPTION();\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ taskEXIT_CRITICAL();\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_TASK_NOTIFICATIONS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+\r
+ BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken )\r
+ {\r
+ TCB_t * pxTCB;\r
+ eNotifyValue eOriginalNotifyState;\r
+ BaseType_t xReturn = pdPASS;\r
+ UBaseType_t uxSavedInterruptStatus;\r
+\r
+ configASSERT( xTaskToNotify );\r
+\r
+ /* RTOS ports that support interrupt nesting have the concept of a\r
+ maximum system call (or maximum API call) interrupt priority.\r
+ Interrupts that are above the maximum system call priority are keep\r
+ permanently enabled, even when the RTOS kernel is in a critical section,\r
+ but cannot make any calls to FreeRTOS API functions. If configASSERT()\r
+ is defined in FreeRTOSConfig.h then\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
+ failure if a FreeRTOS API function is called from an interrupt that has\r
+ been assigned a priority above the configured maximum system call\r
+ priority. Only FreeRTOS functions that end in FromISR can be called\r
+ from interrupts that have been assigned a priority at or (logically)\r
+ below the maximum system call interrupt priority. FreeRTOS maintains a\r
+ separate interrupt safe API to ensure interrupt entry is as fast and as\r
+ simple as possible. More information (albeit Cortex-M specific) is\r
+ provided on the following link:\r
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
+\r
+ pxTCB = ( TCB_t * ) xTaskToNotify;\r
+\r
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
+ {\r
+ eOriginalNotifyState = pxTCB->eNotifyState;\r
+\r
+ pxTCB->eNotifyState = eNotified;\r
+\r
+ switch( eAction )\r
+ {\r
+ case eSetBits :\r
+ pxTCB->ulNotifiedValue |= ulValue;\r
+ break;\r
+\r
+ case eIncrement :\r
+ ( pxTCB->ulNotifiedValue )++;\r
+ break;\r
+\r
+ case eSetValueWithOverwrite :\r
+ pxTCB->ulNotifiedValue = ulValue;\r
+ break;\r
+\r
+ case eSetValueWithoutOverwrite :\r
+ if( eOriginalNotifyState != eNotified )\r
+ {\r
+ pxTCB->ulNotifiedValue = ulValue;\r
+ }\r
+ else\r
+ {\r
+ /* The value could not be written to the task. */\r
+ xReturn = pdFAIL;\r
+ }\r
+ break;\r
+\r
+ case eNoAction :\r
+ /* The task is being notified without its notify value being\r
+ updated. */\r
+ break;\r
+ }\r
+\r
+\r
+ /* If the task is in the blocked state specifically to wait for a\r
+ notification then unblock it now. */\r
+ if( eOriginalNotifyState == eWaitingNotification )\r
+ {\r
+ /* The task should not have been on an event list. */\r
+ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
+\r
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
+ {\r
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
+ prvAddTaskToReadyList( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ /* The delayed and ready lists cannot be accessed, so hold\r
+ this task pending until the scheduler is resumed. */\r
+ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
+ }\r
+\r
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
+ {\r
+ /* The notified task has a priority above the currently\r
+ executing task so a yield is required. */\r
+ if( pxHigherPriorityTaskWoken != NULL )\r
+ {\r
+ *pxHigherPriorityTaskWoken = pdTRUE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ }\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif /* configUSE_TASK_NOTIFICATIONS */\r
+/*-----------------------------------------------------------*/\r
+\r
+#if( configUSE_TASK_NOTIFICATIONS == 1 )\r
+\r
+ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken )\r
+ {\r
+ TCB_t * pxTCB;\r
+ eNotifyValue eOriginalNotifyState;\r
+ UBaseType_t uxSavedInterruptStatus;\r
+\r
+ configASSERT( xTaskToNotify );\r
+\r
+ /* RTOS ports that support interrupt nesting have the concept of a\r
+ maximum system call (or maximum API call) interrupt priority.\r
+ Interrupts that are above the maximum system call priority are keep\r
+ permanently enabled, even when the RTOS kernel is in a critical section,\r
+ but cannot make any calls to FreeRTOS API functions. If configASSERT()\r
+ is defined in FreeRTOSConfig.h then\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion\r
+ failure if a FreeRTOS API function is called from an interrupt that has\r
+ been assigned a priority above the configured maximum system call\r
+ priority. Only FreeRTOS functions that end in FromISR can be called\r
+ from interrupts that have been assigned a priority at or (logically)\r
+ below the maximum system call interrupt priority. FreeRTOS maintains a\r
+ separate interrupt safe API to ensure interrupt entry is as fast and as\r
+ simple as possible. More information (albeit Cortex-M specific) is\r
+ provided on the following link:\r
+ http://www.freertos.org/RTOS-Cortex-M3-M4.html */\r
+ portASSERT_IF_INTERRUPT_PRIORITY_INVALID();\r
+\r
+ pxTCB = ( TCB_t * ) xTaskToNotify;\r
+\r
+ uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
+ {\r
+ eOriginalNotifyState = pxTCB->eNotifyState;\r
+ pxTCB->eNotifyState = eNotified;\r
+\r
+ /* 'Giving' is equivalent to incrementing a count in a counting\r
+ semaphore. */\r
+ ( pxTCB->ulNotifiedValue )++;\r
+\r
+ /* If the task is in the blocked state specifically to wait for a\r
+ notification then unblock it now. */\r
+ if( eOriginalNotifyState == eWaitingNotification )\r
+ {\r
+ /* The task should not have been on an event list. */\r
+ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );\r
+\r
+ if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )\r
+ {\r
+ ( void ) uxListRemove( &( pxTCB->xGenericListItem ) );\r
+ prvAddTaskToReadyList( pxTCB );\r
+ }\r
+ else\r
+ {\r
+ /* The delayed and ready lists cannot be accessed, so hold\r
+ this task pending until the scheduler is resumed. */\r
+ vListInsertEnd( &( xPendingReadyList ), &( pxTCB->xEventListItem ) );\r
+ }\r
+\r
+ if( pxTCB->uxPriority > pxCurrentTCB->uxPriority )\r
+ {\r
+ /* The notified task has a priority above the currently\r
+ executing task so a yield is required. */\r
+ if( pxHigherPriorityTaskWoken != NULL )\r
+ {\r
+ *pxHigherPriorityTaskWoken = pdTRUE;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ mtCOVERAGE_TEST_MARKER();\r
+ }\r
+ }\r
+ }\r
+ portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
+ }\r
+\r
+#endif /* configUSE_TASK_NOTIFICATIONS */\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+\r
+#ifdef FREERTOS_MODULE_TEST\r
+ #include "tasks_test_access_functions.h"\r
+#endif\r