/* Although the task got here because it timed out before the\r
bits it was waiting for were set, it is possible that since it\r
unblocked another task has set the bits. If this is the case\r
- then it may be required to clear the bits before exiting. */\r
+ then it needs to clear the bits before exiting. */\r
if( ( uxReturn & uxBitsToWaitFor ) == uxBitsToWaitFor )\r
{\r
pxEventBits->uxEventBits &= ~uxBitsToWaitFor;\r
}\r
else\r
{\r
- /* The task unblocked because the bits were set. Clear the control\r
- bits before returning the value. */\r
- uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;\r
+ /* The task unblocked because the bits were set. */\r
}\r
+\r
+ /* Control bits might be set as the task had blocked should not be\r
+ returned. */\r
+ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;\r
}\r
\r
traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred );\r
+\r
return uxReturn;\r
}\r
/*-----------------------------------------------------------*/\r
}\r
taskEXIT_CRITICAL();\r
\r
+ /* Prevent compiler warnings when trace macros are not used. */\r
xTimeoutOccurred = pdFALSE;\r
}\r
else\r
{\r
- /* The task unblocked because the bits were set. Clear the control\r
- bits before returning the value. */\r
- uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;\r
+ /* The task unblocked because the bits were set. */\r
}\r
+\r
+ /* The task blocked so control bits may have been set. */\r
+ uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;\r
}\r
traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );\r
+\r
return uxReturn;\r
}\r
/*-----------------------------------------------------------*/\r
}\r
/*-----------------------------------------------------------*/\r
\r
-EventBits_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )\r
+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )\r
+\r
+ BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear )\r
+ {\r
+ BaseType_t xReturn;\r
+\r
+ traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );\r
+ xReturn = xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL );\r
+\r
+ return xReturn;\r
+ }\r
+\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )\r
{\r
UBaseType_t uxSavedInterruptStatus;\r
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;\r
EventBits_t uxReturn;\r
\r
- /* Check the user is not attempting to clear the bits used by the kernel\r
- itself. */\r
- configASSERT( ( uxBitsToClear & eventEVENT_BITS_CONTROL_BYTES ) == 0 );\r
-\r
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
{\r
- traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear );\r
-\r
- /* The value returned is the event group value prior to the bits being\r
- cleared. */\r
uxReturn = pxEventBits->uxEventBits;\r
-\r
- /* Clear the bits. */\r
- pxEventBits->uxEventBits &= ~uxBitsToClear;\r
}\r
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
+/* For internal use only - execute a 'clear bits' command that was pended from\r
+an interrupt. */\r
+void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear )\r
+{\r
+ ( void ) xEventGroupClearBits( pvEventGroup, ( EventBits_t ) ulBitsToClear );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
static BaseType_t prvTestWaitCondition( const EventBits_t uxCurrentEventBits, const EventBits_t uxBitsToWaitFor, const BaseType_t xWaitForAllBits )\r
{\r
BaseType_t xWaitConditionMet = pdFALSE;\r
/*-----------------------------------------------------------*/\r
\r
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )\r
+\r
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken )\r
{\r
BaseType_t xReturn;\r
\r
return xReturn;\r
}\r
+\r
#endif\r
/*-----------------------------------------------------------*/\r
\r
#if (configUSE_TRACE_FACILITY == 1)\r
+\r
UBaseType_t uxEventGroupGetNumber( void* xEventGroup )\r
{\r
UBaseType_t xReturn;\r
\r
return xReturn;\r
}\r
+\r
#endif\r
\r
/**\r
* event_groups.h\r
*<pre>\r
- EventBits_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear );\r
+ BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );\r
</pre>\r
*\r
- * A version of xEventGroupClearBits() that can be called from an interrupt\r
- * service routine. See the xEventGroupClearBits() documentation.\r
+ * A version of xEventGroupClearBits() that can be called from an interrupt.\r
*\r
- * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR\r
+ * Setting bits in an event group is not a deterministic operation because there\r
+ * are an unknown number of tasks that may be waiting for the bit or bits being\r
+ * set. FreeRTOS does not allow nondeterministic operations to be performed\r
+ * while interrupts are disabled, so protects event groups that are accessed\r
+ * from tasks by suspending the scheduler rather than disabling interrupts. As\r
+ * a result event groups cannot be accessed directly from an interrupt service\r
+ * routine. Therefore xEventGroupClearBitsFromISR() sends a message to the \r
+ * timer task to have the clear operation performed in the context of the timer \r
+ * task.\r
+ *\r
+ * @param xEventGroup The event group in which the bits are to be cleared.\r
+ *\r
+ * @param uxBitsToClear A bitwise value that indicates the bit or bits to clear.\r
+ * For example, to clear bit 3 only, set uxBitsToClear to 0x08. To clear bit 3\r
+ * and bit 0 set uxBitsToClear to 0x09.\r
+ *\r
+ * @return If the request to execute the function was posted successfully then \r
+ * pdPASS is returned, otherwise pdFALSE is returned. pdFALSE will be returned \r
+ * if the timer service queue was full.\r
+ *\r
+ * Example usage:\r
+ <pre>\r
+ #define BIT_0 ( 1 << 0 )\r
+ #define BIT_4 ( 1 << 4 )\r
+\r
+ // An event group which it is assumed has already been created by a call to\r
+ // xEventGroupCreate().\r
+ EventGroupHandle_t xEventGroup;\r
+\r
+ void anInterruptHandler( void )\r
+ {\r
+ // Clear bit 0 and bit 4 in xEventGroup.\r
+ xResult = xEventGroupClearBitsFromISR(\r
+ xEventGroup, // The event group being updated.\r
+ BIT_0 | BIT_4 ); // The bits being set.\r
+\r
+ if( xResult == pdPASS )\r
+ {\r
+ // The message was posted successfully.\r
+ }\r
+ }\r
+ </pre>\r
+ * \defgroup xEventGroupSetBitsFromISR xEventGroupSetBitsFromISR\r
* \ingroup EventGroup\r
*/\r
-EventBits_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;\r
+#if( configUSE_TRACE_FACILITY == 1 )\r
+ BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet );\r
+#else\r
+ #define xEventGroupClearBitsFromISR( xEventGroup, uxBitsToClear ) xTimerPendFunctionCallFromISR( vEventGroupClearBitsCallback, ( void * ) xEventGroup, ( uint32_t ) uxBitsToClear, NULL )\r
+#endif\r
\r
/**\r
* event_groups.h\r
* \defgroup xEventGroupGetBitsFromISR xEventGroupGetBitsFromISR\r
* \ingroup EventGroup\r
*/\r
-#define xEventGroupGetBitsFromISR( xEventGroup ) xEventGroupClearBitsFromISR( xEventGroup, 0 )\r
+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup );\r
\r
/**\r
* event_groups.h\r
\r
/* For internal use only. */\r
void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet );\r
+void vEventGroupClearBitsCallback( void *pvEventGroup, const uint32_t ulBitsToClear );\r
\r
#if (configUSE_TRACE_FACILITY == 1)\r
UBaseType_t uxEventGroupGetNumber( void* xEventGroup );\r
/**\r
* const char * const pcTimerGetTimerName( TimerHandle_t xTimer );\r
*\r
- * Returns the name that was asigned to a timer when the timer was created.\r
+ * Returns the name that was assigned to a timer when the timer was created.\r
*\r
* @param xTimer The handle of the timer being queried.\r
*\r
- * @return The name asigned to the timer specified by the xTimer parameter.\r
+ * @return The name assigned to the timer specified by the xTimer parameter.\r
*/\r
-const char * const pcTimerGetTimerName( TimerHandle_t xTimer );\r
+const char * pcTimerGetTimerName( TimerHandle_t xTimer );\r
\r
/*\r
* Functions beyond this part are not part of the public API and are intended\r
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )\r
#endif\r
\r
+/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in\r
+portmacro.h. */\r
#ifndef configCLEAR_TICK_INTERRUPT\r
#define configCLEAR_TICK_INTERRUPT()\r
#endif\r
extern void vPortExitCritical( void );\r
extern uint32_t ulPortSetInterruptMask( void );\r
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );\r
+extern void vPortInstallFreeRTOSVectorTable( void );\r
\r
/* These macros do not globally disable/enable interrupts. They do mask off\r
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */\r
\r
#ifndef portRESTORE_CONTEXT\r
#error Unrecognised device selected\r
+\r
+ /* Note: dsPIC parts with EDS are not supported as there is no easy way to\r
+ recover the hardware stacked copies for DOCOUNT, DOHIGH, DOLOW. */\r
#endif\r
\r
/*\r
#endif\r
/*-----------------------------------------------------------*/\r
\r
-const char * const pcTimerGetTimerName( TimerHandle_t xTimer )\r
+const char * pcTimerGetTimerName( TimerHandle_t xTimer )\r
{\r
Timer_t *pxTimer = ( Timer_t * ) xTimer;\r
\r