I know that Thread-mode software can be privileged or unprivileged, and Handler-mode (exceptions/interrupts) software is always privileged. I need a function that I can call to decide if I'm running privileged or not (because I want to be able to directly access e.g. the basepri register if privileged, or perform an SVC call first if not privileged). In the RTOS I use (SAFERTOS), there is a function "xPortIsPrivilegedMode" that you can call (only from a task i.e. Thread mode SW) as follows:
mrs r0, control
tst r0, #UNPRIVILEGED_BIT /* Is the task running privileged? */
movne r0, #FALSE /* CONTROL[ 0 ] == 1; return false. */
moveq r0, #TRUE /* CONTROL[ 0 ] == 0; return true. */
I have two questions regarding this function:
1. If the task is running unprivileged, how can it access the CONTROL register in the first place to read the unprivileged bit?
2. This function cannot be called from an ISR because, according to the CONTROL register specs from the programming manual of my MCU, the "nPRIV" bit determines the privilege level in Thread mode only, not in handler mode. So an ISR can be running while nPRIV == 1 (unprivileged) because (I think?) the task that was interrupted by the ISR was unprivileged. Thus the function would return "false" when it should have returned "true". How can we generalize a function so that it can be called from both Handler mode and Thread mode?
I can answer half of the question. If you read xPSR, the low 9 bits (sometimes called the IPSR, and I think there is a CMSIS Core call to obtain the IPSR from C) will reveal the current exception/interrupt number. if non zero, you are in some handler, so by definition are in privileged mode.
Alas if those bits read 0, you still can't tell the mode. Perhaps this could be used in conjunction with the CONTROL register, bit 0 (nPRIV)? Looking at Yiu's Definitive Guide to M3/M4, I think this will work. On p86 it says CONTROL reg can be _read_ in both priv and unpriv modes. Is that not the case for the M7? I got this book for 10 bucks used, best ten dollars I ever spent.
Thanks, tobermory, this is exactly what I need!
Pleased to hear it. Just to flesh out the answer in code, the CMSIS Core routines to implement this is
bool inPrivMode = (__get_IPSR()>0) || ((__get_CONTROL() & CONTROL_nPRIV_Msk) == 0);