How to run RTX threads in unprivileged mode, yet access privileged resources(e.g. SCB) when needed. Uses user-defined SVC calls.
In our example, the idler thread wants to put the CPU into low-power mode.
CPPFLAGS += -DOS_PRIVILEGE_MODE=0 __NO_RETURN void osRtxIdleThread (void *unused) { while(2) { __asm( "svc 1" ); /* Vendor-specific low-power mode api, likely writes to SCB->SCR, which is a privileged operation. Yet we are in thread mode here. */ EMU_EnterEM1(); __asm( "svc 2" ); } } static void svcThreadModePrivileged(void) { __set_CONTROL( __get_CONTROL() & ~CONTROL_nPRIV_Msk ); } static void svcThreadModeUnprivileged(void) { __set_CONTROL( __get_CONTROL() | CONTROL_nPRIV_Msk ); } void * const osRtxUserSVC[3] = { (void*)2, (void*)svcThreadModePrivileged, (void*)svcThreadModeUnprivileged, };
Of course the snag is that when the 'main' thread(s) are woken by some event (likely the event that returns from sleep), THEY get to run, and will run in PRIV mode. Only when the idler gets its next look in will it be able to switch back to nPRIV. Perhaps the idler's own priority could be bumped ??
Yes, that would be a more disciplined way of doing things, just would take more code. For each block of code B you would want to run in priv mode, you'd need one slot in the SVC table, correct? But access to those entries is O(1) so no time impact.