documentation on portENTER_CRITCAL

xintersecty wrote on Tuesday, November 03, 2009:

I have been going through the freeRTOS site and trying to find a solid explanation on portENTER_CRITCAL and related functions.  I have also done a search and read the posts with the keyword portENTER_CRITCAL.   For example, looking through the code, vPortEnterCritcal is the same as portENTER_CRITCAL.  But most of the demo code uses portENTER_CRITCAL. So, which is the perfered freeRTIS way of doing things?

I understand the need to disable interrupts while doing a hardware operation, but the API documentation does not seem to cover this topic.  Is this why I should buy the PDF API reference?


richard_damon wrote on Tuesday, November 03, 2009:

portENTER_CRITICAL is the documented interface, the function vPortEnterCritical is  just an implementation detail, so using portENTER_CRITICAL is the prefered method. And actually portENTER_CRITICAL is just intended for the portability layer, user level code should actually use taskENTER_CRITICAL (which currrently just uses portENTER_CRITICAL, so for now it doesn’t really matter).

The purpose of Critical Sections is a standard Programing concept, so the documentation for freeRTOS doesn’t go into much detail, but they are basically (short) pieces of code that manipulate resourced that might be shared with other code, and that manipulation needs to be able to be completed without interference by the other code that might access it. If the other code is an interrupt, then it must be done via some form of interrupt control (either total disabling, or raising the allowed level above the level of the interrupt that shares the resource).

xintersecty wrote on Wednesday, November 04, 2009:

Richard, THANKS.  That got me to the relevant sections of the documentation.  From the documentation:

taskENTER_CRITICAL task. h
Macro to mark the start of a critical code region. Preemptive context switches cannot occur when in a critical region.

NOTE: This may alter the stack (depending on the portable implementation) so must be used with care!

Macro to disable all maskable interrupts.

I could not find taskDISABLE_INTERRUPTS in the code base I have (v5.4.2).  I do have portDISABLE_INTERRUPTS.  That changes the level of interrupt priority level down to level 1.  I am trying to understand the differences between the two commands.  From what I understand once I use taskDISABLE_INTERRUPTS, the processor will NOT make a context switch.  But if I use portDISABLE_INTERRUPTS, a context switch can be made, but most of the interrupts will be still disabled.  Is that a correct conclusion?

I just want to make sure I do understand the differences between to the two functions. 

rtel wrote on Wednesday, November 04, 2009:

taskDISABLE_INTERRUPTS just calls portDISABLE_INTERRUPTS, likewise taskENABLE_INTERRUPTS just calls portENABLE_INTERRUPTS.  The idea being that macros starting with ‘task’ form part of the published API while macros starting with ‘port’ are not intended for direct use by application writers.  In practice I tend to interchange the two quite liberally.

What taskDISABLE/ENABLE_INTERRUPTS actually does depends on the port.  They will either disable/enable interrupts completely or up to a certain level (as defined by configMAX_SYSCALL_INTERRUPT_PRIORITY).  It is not really advisable for these macros to be called directly.

taskENTER_CRITICAL will have the same effect as taskDISABLE_INTERRUPTS, but will also count the number of times it is called.  taskEXIT_CRITICAL() will not re-enable interrupts until the count depth has unwound back to 0.

It is possible in some ports to switch context within a critical section, but only when taskYIELD() is called.  Tick interrupts will not occur in critical sections.


xintersecty wrote on Wednesday, November 04, 2009:

Richard Barry,  I really appreciate the explanation of what is really going on.  I have changed my own code to use taskENTER_CRITICAL as per the API. And I will stick with it.  THANKS!