I am currently experimenting with FreeRTOS with MPU for Cortex M3.
It seems to me that given the settings in FreeRTOSConfig.h, an unprivileged task will never be able to use taskENTER_CRITICAL.
For instance, this is from the CORTEXMPULM3Sxxxx_Rowley port:
define configKERNELINTERRUPTPRIORITY (( unsigned char ) 7 << configUNUSEDPRIOBITS)
define configMAXSYSCALLINTERRUPTPRIORITY (( unsigned char ) 5 << configUNUSEDPRIO_BITS)
'KERNELINTERRUPTPRIORITY' is the priority that is assigned to SysTick, SVC and pendSV Handlers
'MAXSYSCALLINTERRUPTPRIORITY' is the priority that is used in ENTERCRITICAL. Any exception/interrupt with same or below priority will be masked out between ENTERCRITICAL and EXITCRITICAL.
But if KERNELINTERRUPTPRIORITY is lower or same as MAXSYSCALLINTERRUPTPRIORITY, as it is here (bigger or equal numerical value), after ENTERCRITICAL is called, the task will not be able to execute another SVC (which will have too low a priority now), including calling EXITCRITICAL! (because EXITCRITICAL calls prvRaisePrivilege, which uses SVC 2).
So I could do one of two things:
1. give KERNELINTERRUPTPRIORITY a higher priority than MAXSYSCALLINTERRUPTPRIORITY
2. give just the SVC handler a higher priority than MAXSYSCALLINTERRUPTPRIORITY
In both cases a small test application seems to work ok (i.e. a non privileged call can use ENTER_CRITICAL/EXIT CRITICAL) but I am not sure of the ramifications of this.
The priorities seem to be set this way (KERNELINTERRUPTPRIORITY lower than MAXSYSCALLINTERRUPT_PRIORITY) for most if not all M3/M4 ports, so I guess there must be a good reason for this.
I think it is deliberate that an unprivileged task cannot call enter/exit critical directly as doing so disables a subset of interrupt priorities - which only tasks running with full privileges can do.
The maximum system call priority is normally above the kernel interrupt priority to allow for a full interrupt nesting model where API calls can be made from interrupts that have a priority above the kernel interrupt priority (the kernel must always be the lowest interrupt priority).
Thank you for the prompt answer to my question.
Thinking about it,I guess it makes sense wanting to avoid unprivileged task blocking exceptions.
However if I was stubborn and still wanting to be able to ENTER/EXIT_CRITICAL from unprivileged tasks (maybe because I have just a very short critical section) I guess it would be better to adopt my solution n. 2 (give just the SVC a higher priority).
After all the SVC itself is quite short in itself so putting in at high priority will have a limited impact on interrupt latency.
Waking up this old thread since I ran into exactly the same problem when experimenting with MPU on Coretx-M3.
You say that it is a deliberate design that an unprivileged task shall not be able to enter a critical section. I can understand that, sort of, but if so, why does this code:
void vPortEnterCritical( void )
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
vPortResetPrivilege( xRunningPrivileged );
check if we are unprivileged, and if so, raise the privilege level ? If an unprivileged task should not be allowed to enter a critical section, it would have been better just to assume that the task is privileged, and if it isn't, let it crash when trying to disable interrupts. It will, as the Claudio says, crash anyway when doing EXIT-CRITICAL.
Perhaps this is something that was changed, I would have to look through
the change logs.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.