portENTER_CRITICAL() and portEXIT_CRITICAL() implementation case

Hello,

I have a silicon vendor FreeRTOS port that does this

#define portENTER_CRITICAL() vTaskEnterCritical()

#define portEXIT_CRITICAL() vTaskExitCritical()

which does not seem to be correct port implementation to me.

What is the expert opinion on this approach of “short-circuiting” port onto FreeRTOS internal API?

Regards,
Eugene

That’s normal for SMP applications and for ports that keep a critical-section nesting count in the TCB. The implementation provided by the kernel (vTask…) implements some common logic for these scenarios, but it still uses the port’s implementation for actually masking and unmasking interrupts.

See for reference the description of these functions in task.h.

Ok. That makes sense. However that port expects interrupts for some other non FreeRTOS APIs and those calls create semaphores. That makes it impossible to run those APIs with the provided port mapping before starting scheduler. That contradicts to some suggestions I saw here about creating primitives before starting RTOS scheduler.

I’m not sure I followed your comment correctly, so this comment may not address yours very well. But the kernel tolerates entering critical sections before the scheduler is started. Kernel and port code both explicitly handle that case. For example:

For clarity, the SDK code can successfully create FreeRTOS primitives prior to starting the OS. That is fully supported. However, the SDK code shouldn’t try to use those primitives from ISRs before the scheduler has started. That’s actually why FreeRTOS leaves interrupts masked until the scheduler starts. It’s doing you a favor.

Are you seeing a problem with the SDK code creating kernel objects before starting the scheduler?

Yes. SDK uses its own delay API which seems to rely on interrupt which is being disabled with above mapping.

This is not a FreeRTOS limitation; it is a consequence of how the port and the surrounding SDK are implemented. However, it does reduce some of the flexibility normally associated with FreeRTOS, particularly in light of discussions such as How to create Semaphores (/kernel objects) before Scheduler start and Using FreeRTOS primitives before starting scheduler, where creating RTOS objects prior to starting the scheduler is presented as a supported use case.

My goal was simply to get an expert opinion on whether this type of critical-section mapping is considered a sound port design. In practice, it appears to force users to move initialization into a dedicated startup task and allocate resources for that task, even in cases where the RTOS itself or application design do not require such an approach.

Since the SDK delay interrupt doesn’t interact with FreeRTOS, you can raise its priority above the levels that FreeRTOS masks. That is, if your architecture supports that. The same is true for any SDK interrupt that doesn’t interact with FreeRTOS.

What silicon are you using, and who provided the FreeRTOS port?

Actually it does. SDK APIs use the same objects that are used by RTOS port to provide timing services and construct timers. That’s where it all gets really interesting and that is the reason of my question.

I am still not convinced that that SDK port approach is sound one. IMHO, port is separate from RTOS and mapping port services to internal RTOS implementation does not look like good approach.

Regards,

Eugene

Oh that’s good news - I think this whole issue just got a lot simpler. If your SDK interrupt handlers interact with FreeRTOS, then it’s up to you to start FreeRTOS first. Your SDK is written to expect that FreeRTOS is already running. I wish more SDKs were written this way – to actually use FreeRTOS services.

You are probably worrying about the wrong thing. The way your vendor’s FreeRTOS port implements critical sections is probably ideal. I would be happy to confirm that if you share the silicon you are using and who provided the FreeRTOS port.

Hi @jefftenney , @EugeneK

will it give any issue if we are initialising the freeRtos premitives in a particular startUp task and after deleting or suspending that task permenantly?

There is no problem with creating resources in a task and then that task deleting itself.

You could also do the initialization in the Timer Daemon startup hook to not need a task.

Also, it sounds like there is no problem using the SDK API to set up the system and recreate the needed resources, you just can’t use the SDK to do any I/O in the process, if they need to use interrupts.

My normal procedure is to create as many of the tasks and resources as possible before starting the scheduler (to avoid timing issues like races), and only create things after that which NEED some interrupt based I/O to determine what is needed (like system configuration that was stored in a device that needs I/O).

Few points:

  1. I believe that Timer is optional in FreeRTOS: configUSE_TIMERS
  2. SDK that is discussed here uses interrupts for HW initialization delay loops and the same SDK object is used as the base for Timers. IMHO, that is in conflict with suggested RTOS primitive handling and general startup HW initialization best practice.
  3. What will happen to TCB and stack for statically created task after it is deleted? AFAIK, these resources stay allocated forever? Is it safe to reuse them?

All of these makes me to question the approach of using vTaskEnterCritical/vTaskExitCritical for portENTER_CRITICAL/portEXIT_CRITICAL and thus the original question.

Regards,

Eugene

Yeas, timers are optional, and that would remove the option.

If they are using timers for HW initialization delay loops, then those timers need to be above the turned off level (if the processor allows for that), or it just is badly designed and they don’t allow its use before the scheduler is started.

You wouldn’t statically create a task that you plan to delete, unless you have a plan to reuse that memory somehow. One the task has been FULLY deleted (for self-delete, that means after Idle has completed the process) the memory is totally unreferenced by FreeRTOS and safe to use.

This really seems to be a question to put before the vendor of the SDK.

Their issue isn’t the implementation of vTaskEnterCritical, but the use of interrupts in setup code that might be run before the scheduler is started. It is EXPECTED and a FEATURE that FreeRTOS disables interrupts until the scheduler is started, so any code that needs interrupts before then needs very special care.

I do not question FreeRTOS approach but rather SDK port that “short circuit” RTOS API onto a port. That approach does not look as the sound one.

As I said, the problem isn’t the “short circuit” that you call, as the design of FreeRTOS allows that. The problem is that they use the interrupts for initialization. After all, portENTER_CRITICAL() is SUPPOSED to disable the interrupts. And if their port re-enables interrupts before the scheduler is enabled, THAT is an “incorrect” behavior.

They do not re-enable interrupts in SDK driver initialization APIs. They use services that expect interrupts to be enabled. Those services create primitives. That would only work from a task context and thus forces users not to to call SDK APIs before stating scheduler. This looks like unjustified constraint on FreeRTOS port because FreeRTOS itself does not have this constraint as you have explained.

Right, so the error is in THAT part of the design, not the implementation of portENTER_CRITICAL and portEXIT_CRITICAL, which, if implemented to the expectation of FreeRTOS without using the “short circuit” api you complain about, would still be expected to leave the interrupts disabled when used before the scheduler was started.

Why do you consider that design expectation as "unjustified?

It is a long-established pattern because it is PROHIBITED for any ISR to use a FreeRTOS primitive before the scheduler has been started, and thus leaving the interrupts disabled is a reasonable safety measure.

Thus, at best that SDK should document that you can’t use it before enabling the scheduler, which means you can’t use the normal pattern to avoid the race conditions.

The problem is NOT them using the internal routine designed for that purpose, but in that they don’t follow the design principles to allow themselves to be used before the scheduler has been started because they expect to be able to use interrupt before the scheduler has started.

@richard-damon That is exactly my point.

“unjustified constraint on FreeRTOS port” means that SDK port forces users to call SDK initialization APIs from a task rather than before starting scheduler as is allowed by FreeRTOS design principle. SDK ISRs themselves do not use FreeRTOS primitive but initialization APIs do and those routines use SDK objects that expect interrupts to be enabled.

That isn’t a constraint on the “FreeRTOS port”, that is a limitation of how you USE that port.

It isn’t a constraint on the port, by by the port on the user.

As I have pointed out several times, the constraint is NOT because of the use of the internal routines provided by the kernel by the port, but of the basic design of the SDK to need interrupts to do its initialization.

At least their documentation should mention that the API is to be used only in Tasks after the scheduler has been started.

Things like this are unfortunately a common issue with some vendor provided libaries, that they didn’t take the time to do a good job, or even explain the limitations of their library. The vendor provides just enough to claim to support the system, which gets you to use their parts, and then you find that it isn’t as usable as you would want.