]> git.sur5r.net Git - freertos/commitdiff
Event Groups: Convert the 'clear bits from ISR' function into a pended function to...
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Wed, 23 Apr 2014 15:23:54 +0000 (15:23 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Wed, 23 Apr 2014 15:23:54 +0000 (15:23 +0000)
Event Groups: Ensure the 'wait bits' and 'sync' functions don't return values that still contain some internal control bits.

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

FreeRTOS/Source/event_groups.c
FreeRTOS/Source/include/event_groups.h
FreeRTOS/Source/include/timers.h
FreeRTOS/Source/portable/GCC/ARM_CA9/port.c
FreeRTOS/Source/portable/GCC/ARM_CA9/portmacro.h
FreeRTOS/Source/portable/MPLAB/PIC24_dsPIC/port.c
FreeRTOS/Source/timers.c

index 5b45f9cc783807abd2aaa34161aa7bf37387e613..5efd432734717b908fe6a807d8d8d6851d4fc475 100644 (file)
@@ -237,7 +237,7 @@ BaseType_t xTimeoutOccurred = pdFALSE;
                                /* 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
@@ -253,13 +253,16 @@ BaseType_t xTimeoutOccurred = pdFALSE;
                }\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
@@ -394,16 +397,19 @@ BaseType_t xTimeoutOccurred = pdFALSE;
                        }\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
@@ -434,26 +440,30 @@ EventBits_t uxReturn;
 }\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
@@ -585,6 +595,14 @@ void vEventGroupSetBitsCallback( void *pvEventGroup, const uint32_t ulBitsToSet
 }\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
@@ -621,6 +639,7 @@ BaseType_t xWaitConditionMet = pdFALSE;
 /*-----------------------------------------------------------*/\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
@@ -630,10 +649,12 @@ BaseType_t xWaitConditionMet = pdFALSE;
 \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
@@ -650,5 +671,6 @@ BaseType_t xWaitConditionMet = pdFALSE;
 \r
                return xReturn;\r
        }\r
+\r
 #endif\r
 \r
index 41e91276f66cb03f9ae549c6e9fa1dd9c8fee8de..3bbb2f74b177631185cb18d80482282be36fd0b3 100644 (file)
@@ -325,16 +325,61 @@ EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBit
 /**\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
@@ -648,7 +693,7 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, const EventBits_t u
  * \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
@@ -666,6 +711,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup );
 \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
index 5cd1f350320c0bc2c2fb2e7959acbf898addde76..68209bcac052015ed91563ca54bd48b215815cd9 100644 (file)
@@ -1097,13 +1097,13 @@ BaseType_t xTimerPendFunctionCall( PendedFunction_t xFunctionToPend, void *pvPar
 /**\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
index 9fed5b649c30a47fb6ad8c2c21161ac3871bf8b8..54bf16623ae7765cd5f0460aa9af05415d1f007f 100644 (file)
        #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
index 23be87c67aafc7e0d31511e86fc8bd6c171db275..6423dc50b0b6235e6f96c3ed1f8a7517386864ac 100644 (file)
@@ -130,6 +130,7 @@ extern void vPortEnterCritical( void );
 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
index dcfb65c4030a648d3367988ed3096b000559e7fd..93d092caa41195b9fb1a33779ef0b0654ff246a5 100644 (file)
@@ -184,6 +184,9 @@ UBaseType_t uxCriticalNesting = 0xef;
 \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
index d7d4295549f28cde471db766338f363abd5b9837..f9d3fa1169ee5231edcc16949cb2294418c5ac1d 100644 (file)
@@ -363,7 +363,7 @@ DaemonTaskMessage_t xMessage;
 #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