]> granicus.if.org Git - esp-idf/commitdiff
freertos: port*_CRITICAL_SAFE API added
authorSachin Parekh <sachin.parekh@espressif.com>
Mon, 25 Mar 2019 10:25:57 +0000 (15:55 +0530)
committerSachin Parekh <sachin.parekh@espressif.com>
Mon, 13 May 2019 11:09:19 +0000 (16:39 +0530)
port*_CRITICAL_SAFE API calls port*_CRITICAL or port*_CRITICAL_ISR
depending on the context (Non-ISR or ISR respectively).

FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE Kconfig option added

Signed-off-by: Sachin Parekh <sachin.parekh@espressif.com>
components/freertos/Kconfig
components/freertos/include/freertos/portmacro.h
docs/en/api-guides/freertos-smp.rst

index 8063c266bc9ad01d96be65b5710837d4ab85a4c8..7eeec02b93a4d70a4fd8b0350d8b798b14992190 100644 (file)
@@ -426,4 +426,11 @@ menu "FreeRTOS"
             If enabled, assert that when a mutex semaphore is given, the task giving the
             semaphore is the task which is currently holding the mutex.
 
+    config FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
+        bool "Tests compliance with Vanilla FreeRTOS port*_CRITICAL calls"
+        default n
+        help
+            If enabled, context of port*_CRITICAL calls (ISR or Non-ISR) would be checked to be in compliance with Vanilla FreeRTOS.
+            e.g Calling port*_CRITICAL from ISR context would cause assert failure
+
 endmenu
index d0023fee95ef5b661ed75f09e245254a5f310a5a..88da1c0c0e3e747673698683e65f9baffcbf1468 100644 (file)
@@ -216,8 +216,23 @@ void vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *function, int line);
 
 void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line );
 void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line );
+
+#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
+/* Calling port*_CRITICAL from ISR context would cause an assert failure.
+ * If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE
+ **/
+#define portENTER_CRITICAL(mux)        do {                                             \
+                                       configASSERT(!xPortInIsrContext());              \
+                                       vTaskEnterCritical(mux, __FUNCTION__, __LINE__); \
+                                       } while(0)
+#define portEXIT_CRITICAL(mux)         do {                                             \
+                                       configASSERT(!xPortInIsrContext());              \
+                                       vTaskExitCritical(mux, __FUNCTION__, __LINE__);  \
+                                       } while(0)
+#else
 #define portENTER_CRITICAL(mux)        vTaskEnterCritical(mux, __FUNCTION__, __LINE__)
 #define portEXIT_CRITICAL(mux)         vTaskExitCritical(mux, __FUNCTION__, __LINE__)
+#endif
 #define portENTER_CRITICAL_ISR(mux)    vTaskEnterCritical(mux, __FUNCTION__, __LINE__)
 #define portEXIT_CRITICAL_ISR(mux)     vTaskExitCritical(mux, __FUNCTION__, __LINE__)
 #else
@@ -236,12 +251,43 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux);
 bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
 void vPortCPUReleaseMutex(portMUX_TYPE *mux);
 
+#ifdef CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE
+/* Calling port*_CRITICAL from ISR context would cause an assert failure.
+ * If the parent function is called from both ISR and Non-ISR context then call port*_CRITICAL_SAFE
+ **/
+#define portENTER_CRITICAL(mux)        do {                                            \
+                                       configASSERT(!xPortInIsrContext());             \
+                                       vTaskEnterCritical(mux);                        \
+                                       } while(0)
+#define portEXIT_CRITICAL(mux)         do {                                            \
+                                       configASSERT(!xPortInIsrContext());             \
+                                       vTaskExitCritical(mux);                         \
+                                       } while(0)
+#else
 #define portENTER_CRITICAL(mux)        vTaskEnterCritical(mux)
 #define portEXIT_CRITICAL(mux)         vTaskExitCritical(mux)
+#endif
 #define portENTER_CRITICAL_ISR(mux)    vTaskEnterCritical(mux)
 #define portEXIT_CRITICAL_ISR(mux)     vTaskExitCritical(mux)
 #endif
 
+#define portENTER_CRITICAL_SAFE(mux)  do {                                             \
+                                         if (xPortInIsrContext()) {                    \
+                                             portENTER_CRITICAL_ISR(mux);              \
+                                         } else {                                      \
+                                             portENTER_CRITICAL(mux);                  \
+                                         }                                             \
+                                      } while(0)
+
+#define portEXIT_CRITICAL_SAFE(mux)  do {                                              \
+                                         if (xPortInIsrContext()) {                    \
+                                             portEXIT_CRITICAL_ISR(mux);               \
+                                         } else {                                      \
+                                             portEXIT_CRITICAL(mux);                   \
+                                         }                                             \
+                                      } while(0)
+
+
 // Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any?
 // These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level.
 //
index 96738c45afd77db46671509394c8a856c24aa25c..5e765a00a25fecd03cadbd510b10f4c928ff5d2f 100644 (file)
@@ -377,6 +377,11 @@ The ESP-IDF FreeRTOS critical section functions have been modified as follows…
    ``portEXIT_CRITICAL(mux)``, ``portEXIT_CRITICAL_ISR(mux)`` are all macro 
    defined to call :cpp:func:`vTaskExitCritical`
 
+ - ``portENTER_CRITICAL_SAFE(mux)``, ``portEXIT_CRITICAL_SAFE(mux)`` macro identifies
+   the context of execution, i.e ISR or Non-ISR, and calls appropriate critical
+   section functions (``port*_CRITICAL`` in Non-ISR and ``port*_CRITICAL_ISR`` in ISR)
+   in order to be in compliance with Vanilla FreeRTOS.
+
 For more details see :component_file:`freertos/include/freertos/portmacro.h` 
 and :component_file:`freertos/task.c`