Skip to content

Commit e41b129

Browse files
committed
Fixed rtx calls when inside critical sections
Before, rtx calls would hard fault in critical sections when an svc instruction was attempted with interrupts disabled. Required changes: - Added check for CPSR I bit in cortex A rtx - Added check for PRIMASK and BASEPRI in cortex M rtx - Modified critical sections in cortex M rtx to be recursive (already recursive in cortex A)
1 parent 0712b8a commit e41b129

File tree

3 files changed

+112
-44
lines changed

3 files changed

+112
-44
lines changed

rtos/rtx/TARGET_CORTEX_A/rt_CMSIS.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,11 @@ static __inline char __get_mode(void) {
539539
}
540540

541541
static __inline char __exceptional_mode(void) {
542+
// Interrupts disabled
543+
if (__get_CPSR() & 0x80) {
544+
return 1;
545+
}
546+
542547
switch(__get_mode()) {
543548
case MODE_USR:
544549
case MODE_SYS:

rtos/rtx/TARGET_CORTEX_M/rt_CMSIS.c

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ uint32_t svcKernelSysTick (void) {
546546

547547
/// Initialize the RTOS Kernel for creating objects
548548
osStatus osKernelInitialize (void) {
549-
if (__get_IPSR() != 0U) {
549+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
550550
return osErrorISR; // Not allowed in ISR
551551
}
552552
if ((__get_CONTROL() & 1U) == 0U) { // Privileged mode
@@ -560,7 +560,7 @@ osStatus osKernelInitialize (void) {
560560
osStatus osKernelStart (void) {
561561
uint32_t stack[8];
562562

563-
if (__get_IPSR() != 0U) {
563+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
564564
return osErrorISR; // Not allowed in ISR
565565
}
566566

@@ -601,7 +601,7 @@ osStatus osKernelStart (void) {
601601

602602
/// Check if the RTOS kernel is already started
603603
int32_t osKernelRunning (void) {
604-
if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {
604+
if ((__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {
605605
// in ISR or Privileged
606606
return (int32_t)os_running;
607607
} else {
@@ -611,7 +611,7 @@ int32_t osKernelRunning (void) {
611611

612612
/// Get the RTOS kernel system timer counter
613613
uint32_t osKernelSysTick (void) {
614-
if (__get_IPSR() != 0U) { return 0U; } // Not allowed in ISR
614+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { return 0U; } // Not allowed in ISR
615615
return __svcKernelSysTick();
616616
}
617617

@@ -799,7 +799,7 @@ osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
799799
return osThreadContextCreate(thread_def, argument, NULL);
800800
}
801801
osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argument, void *context) {
802-
if (__get_IPSR() != 0U) {
802+
if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
803803
return NULL; // Not allowed in ISR
804804
}
805805
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -812,39 +812,39 @@ osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argumen
812812

813813
/// Return the thread ID of the current running thread
814814
osThreadId osThreadGetId (void) {
815-
if (__get_IPSR() != 0U) {
815+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
816816
return NULL; // Not allowed in ISR
817817
}
818818
return __svcThreadGetId();
819819
}
820820

821821
/// Terminate execution of a thread and remove it from ActiveThreads
822822
osStatus osThreadTerminate (osThreadId thread_id) {
823-
if (__get_IPSR() != 0U) {
823+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
824824
return osErrorISR; // Not allowed in ISR
825825
}
826826
return __svcThreadTerminate(thread_id);
827827
}
828828

829829
/// Pass control to next thread that is in state READY
830830
osStatus osThreadYield (void) {
831-
if (__get_IPSR() != 0U) {
831+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
832832
return osErrorISR; // Not allowed in ISR
833833
}
834834
return __svcThreadYield();
835835
}
836836

837837
/// Change priority of an active thread
838838
osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) {
839-
if (__get_IPSR() != 0U) {
839+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
840840
return osErrorISR; // Not allowed in ISR
841841
}
842842
return __svcThreadSetPriority(thread_id, priority);
843843
}
844844

845845
/// Get current priority of an active thread
846846
osPriority osThreadGetPriority (osThreadId thread_id) {
847-
if (__get_IPSR() != 0U) {
847+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
848848
return osPriorityError; // Not allowed in ISR
849849
}
850850
return __svcThreadGetPriority(thread_id);
@@ -862,7 +862,7 @@ __NO_RETURN void osThreadExit (void) {
862862
uint8_t osThreadGetState (osThreadId thread_id) {
863863
P_TCB ptcb;
864864

865-
if (__get_IPSR() != 0U) return osErrorISR; // Not allowed in ISR
865+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) return osErrorISR; // Not allowed in ISR
866866

867867
ptcb = rt_tid2ptcb(thread_id); // Get TCB pointer
868868
if (ptcb == NULL) return INACTIVE;
@@ -911,7 +911,7 @@ os_InRegs osEvent_type svcWait (uint32_t millisec) {
911911

912912
/// Wait for Timeout (Time Delay)
913913
osStatus osDelay (uint32_t millisec) {
914-
if (__get_IPSR() != 0U) {
914+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
915915
return osErrorISR; // Not allowed in ISR
916916
}
917917
return __svcDelay(millisec);
@@ -925,7 +925,7 @@ os_InRegs osEvent osWait (uint32_t millisec) {
925925
ret.status = osErrorOS;
926926
return ret;
927927
#else
928-
if (__get_IPSR() != 0U) { // Not allowed in ISR
928+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // Not allowed in ISR
929929
ret.status = osErrorISR;
930930
return ret;
931931
}
@@ -1208,7 +1208,7 @@ void sysUserTimerUpdate (uint32_t sleep_time) {
12081208

12091209
/// Create timer
12101210
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
1211-
if (__get_IPSR() != 0U) {
1211+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
12121212
return NULL; // Not allowed in ISR
12131213
}
12141214
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1221,23 +1221,23 @@ osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void
12211221

12221222
/// Start or restart timer
12231223
osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
1224-
if (__get_IPSR() != 0U) {
1224+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
12251225
return osErrorISR; // Not allowed in ISR
12261226
}
12271227
return __svcTimerStart(timer_id, millisec);
12281228
}
12291229

12301230
/// Stop timer
12311231
osStatus osTimerStop (osTimerId timer_id) {
1232-
if (__get_IPSR() != 0U) {
1232+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
12331233
return osErrorISR; // Not allowed in ISR
12341234
}
12351235
return __svcTimerStop(timer_id);
12361236
}
12371237

12381238
/// Delete timer
12391239
osStatus osTimerDelete (osTimerId timer_id) {
1240-
if (__get_IPSR() != 0U) {
1240+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
12411241
return osErrorISR; // Not allowed in ISR
12421242
}
12431243
return __svcTimerDelete(timer_id);
@@ -1374,7 +1374,7 @@ int32_t isrSignalSet (osThreadId thread_id, int32_t signals) {
13741374

13751375
/// Set the specified Signal Flags of an active thread
13761376
int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
1377-
if (__get_IPSR() != 0U) { // in ISR
1377+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
13781378
return isrSignalSet(thread_id, signals);
13791379
} else { // in Thread
13801380
return __svcSignalSet(thread_id, signals);
@@ -1383,7 +1383,7 @@ int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
13831383

13841384
/// Clear the specified Signal Flags of an active thread
13851385
int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
1386-
if (__get_IPSR() != 0U) {
1386+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
13871387
return (int32_t)0x80000000U; // Not allowed in ISR
13881388
}
13891389
return __svcSignalClear(thread_id, signals);
@@ -1393,7 +1393,7 @@ int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
13931393
os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
13941394
osEvent ret;
13951395

1396-
if (__get_IPSR() != 0U) { // Not allowed in ISR
1396+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // Not allowed in ISR
13971397
ret.status = osErrorISR;
13981398
return ret;
13991399
}
@@ -1505,7 +1505,7 @@ osStatus svcMutexDelete (osMutexId mutex_id) {
15051505

15061506
/// Create and Initialize a Mutex object
15071507
osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
1508-
if (__get_IPSR() != 0U) {
1508+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
15091509
return NULL; // Not allowed in ISR
15101510
}
15111511
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1518,23 +1518,23 @@ osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
15181518

15191519
/// Wait until a Mutex becomes available
15201520
osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
1521-
if (__get_IPSR() != 0U) {
1521+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
15221522
return osErrorISR; // Not allowed in ISR
15231523
}
15241524
return __svcMutexWait(mutex_id, millisec);
15251525
}
15261526

15271527
/// Release a Mutex that was obtained with osMutexWait
15281528
osStatus osMutexRelease (osMutexId mutex_id) {
1529-
if (__get_IPSR() != 0U) {
1529+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
15301530
return osErrorISR; // Not allowed in ISR
15311531
}
15321532
return __svcMutexRelease(mutex_id);
15331533
}
15341534

15351535
/// Delete a Mutex that was created by osMutexCreate
15361536
osStatus osMutexDelete (osMutexId mutex_id) {
1537-
if (__get_IPSR() != 0U) {
1537+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
15381538
return osErrorISR; // Not allowed in ISR
15391539
}
15401540
return __svcMutexDelete(mutex_id);
@@ -1672,7 +1672,7 @@ osStatus isrSemaphoreRelease (osSemaphoreId semaphore_id) {
16721672

16731673
/// Create and Initialize a Semaphore object
16741674
osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
1675-
if (__get_IPSR() != 0U) {
1675+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
16761676
return NULL; // Not allowed in ISR
16771677
}
16781678
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1685,24 +1685,24 @@ osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t
16851685

16861686
/// Wait until a Semaphore becomes available
16871687
int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
1688-
if (__get_IPSR() != 0U) {
1688+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
16891689
return -1; // Not allowed in ISR
16901690
}
16911691
return __svcSemaphoreWait(semaphore_id, millisec);
16921692
}
16931693

16941694
/// Release a Semaphore
16951695
osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
1696-
if (__get_IPSR() != 0U) { // in ISR
1696+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
16971697
return isrSemaphoreRelease(semaphore_id);
1698-
} else { // in Thread
1698+
} else { // in Thread
16991699
return __svcSemaphoreRelease(semaphore_id);
17001700
}
17011701
}
17021702

17031703
/// Delete a Semaphore that was created by osSemaphoreCreate
17041704
osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
1705-
if (__get_IPSR() != 0U) {
1705+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
17061706
return osErrorISR; // Not allowed in ISR
17071707
}
17081708
return __svcSemaphoreDelete(semaphore_id);
@@ -1785,7 +1785,7 @@ osStatus sysPoolFree (osPoolId pool_id, void *block) {
17851785

17861786
/// Create and Initialize memory pool
17871787
osPoolId osPoolCreate (const osPoolDef_t *pool_def) {
1788-
if (__get_IPSR() != 0U) {
1788+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
17891789
return NULL; // Not allowed in ISR
17901790
}
17911791
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1798,7 +1798,7 @@ osPoolId osPoolCreate (const osPoolDef_t *pool_def) {
17981798

17991799
/// Allocate a memory block from a memory pool
18001800
void *osPoolAlloc (osPoolId pool_id) {
1801-
if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
1801+
if ((__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
18021802
return sysPoolAlloc(pool_id);
18031803
} else { // in Thread
18041804
return __sysPoolAlloc(pool_id);
@@ -1809,7 +1809,7 @@ void *osPoolAlloc (osPoolId pool_id) {
18091809
void *osPoolCAlloc (osPoolId pool_id) {
18101810
void *mem;
18111811

1812-
if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
1812+
if ((__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
18131813
mem = sysPoolAlloc(pool_id);
18141814
} else { // in Thread
18151815
mem = __sysPoolAlloc(pool_id);
@@ -1822,7 +1822,7 @@ void *osPoolCAlloc (osPoolId pool_id) {
18221822

18231823
/// Return an allocated memory block back to a specific memory pool
18241824
osStatus osPoolFree (osPoolId pool_id, void *block) {
1825-
if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
1825+
if ((__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) { // in ISR or Privileged
18261826
return sysPoolFree(pool_id, block);
18271827
} else { // in Thread
18281828
return __sysPoolFree(pool_id, block);
@@ -1962,7 +1962,7 @@ os_InRegs osEvent isrMessageGet (osMessageQId queue_id, uint32_t millisec) {
19621962

19631963
/// Create and Initialize Message Queue
19641964
osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
1965-
if (__get_IPSR() != 0U) {
1965+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
19661966
return NULL; // Not allowed in ISR
19671967
}
19681968
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1975,7 +1975,7 @@ osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId threa
19751975

19761976
/// Put a Message to a Queue
19771977
osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
1978-
if (__get_IPSR() != 0U) { // in ISR
1978+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
19791979
return isrMessagePut(queue_id, info, millisec);
19801980
} else { // in Thread
19811981
return __svcMessagePut(queue_id, info, millisec);
@@ -1984,7 +1984,7 @@ osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec)
19841984

19851985
/// Get a Message or Wait for a Message from a Queue
19861986
os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
1987-
if (__get_IPSR() != 0U) { // in ISR
1987+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
19881988
return isrMessageGet(queue_id, millisec);
19891989
} else { // in Thread
19901990
return __svcMessageGet(queue_id, millisec);
@@ -2121,7 +2121,7 @@ osStatus sysMailFree (osMailQId queue_id, void *mail, uint32_t isr) {
21212121

21222122
/// Create and Initialize mail queue
21232123
osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
2124-
if (__get_IPSR() != 0U) {
2124+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) {
21252125
return NULL; // Not allowed in ISR
21262126
}
21272127
if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -2134,7 +2134,7 @@ osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
21342134

21352135
/// Allocate a memory block from a mail
21362136
void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
2137-
if (__get_IPSR() != 0U) { // in ISR
2137+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
21382138
return sysMailAlloc(queue_id, millisec, 1U);
21392139
} else { // in Thread
21402140
return __sysMailAlloc(queue_id, millisec, 0U);
@@ -2146,7 +2146,7 @@ void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
21462146
void *pool;
21472147
void *mem;
21482148

2149-
if (__get_IPSR() != 0U) { // in ISR
2149+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
21502150
mem = sysMailAlloc(queue_id, millisec, 1U);
21512151
} else { // in Thread
21522152
mem = __sysMailAlloc(queue_id, millisec, 0U);
@@ -2161,7 +2161,7 @@ void *osMailCAlloc (osMailQId queue_id, uint32_t millisec) {
21612161

21622162
/// Free a memory block from a mail
21632163
osStatus osMailFree (osMailQId queue_id, void *mail) {
2164-
if (__get_IPSR() != 0U) { // in ISR
2164+
if (__get_PRIMASK() != 0U || __get_BASEPRI() != 0U || __get_IPSR() != 0U) { // in ISR
21652165
return sysMailFree(queue_id, mail, 1U);
21662166
} else { // in Thread
21672167
return __sysMailFree(queue_id, mail, 0U);

0 commit comments

Comments
 (0)