rtx_kernel.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. /*
  2. * Copyright (c) 2013-2023 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------------
  19. *
  20. * Project: CMSIS-RTOS RTX
  21. * Title: Kernel functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // OS Runtime Information
  27. osRtxInfo_t osRtxInfo __attribute__((section(".data.os"))) =
  28. //lint -e{785} "Initialize only OS ID, OS Version and Kernel State"
  29. { .os_id = osRtxKernelId, .version = osRtxVersionKernel, .kernel.state = osRtxKernelInactive };
  30. // ==== Helper functions ====
  31. /// Block Kernel (disable: thread switching, time tick, post ISR processing).
  32. static void KernelBlock (void) {
  33. OS_Tick_Disable();
  34. osRtxInfo.kernel.blocked = 1U;
  35. __DSB();
  36. if (GetPendSV() != 0U) {
  37. ClrPendSV();
  38. osRtxInfo.kernel.pendSV = 1U;
  39. }
  40. }
  41. /// Unblock Kernel
  42. static void KernelUnblock (void) {
  43. osRtxInfo.kernel.blocked = 0U;
  44. __DSB();
  45. if (osRtxInfo.kernel.pendSV != 0U) {
  46. osRtxInfo.kernel.pendSV = 0U;
  47. SetPendSV();
  48. }
  49. OS_Tick_Enable();
  50. }
  51. // Get Kernel sleep time
  52. static uint32_t GetKernelSleepTime (void) {
  53. const os_thread_t *thread;
  54. const os_timer_t *timer;
  55. uint32_t delay;
  56. delay = osWaitForever;
  57. // Check Thread Delay list
  58. thread = osRtxInfo.thread.delay_list;
  59. if (thread != NULL) {
  60. delay = thread->delay;
  61. }
  62. #ifdef RTX_THREAD_WATCHDOG
  63. // Check Thread Watchdog list
  64. thread = osRtxInfo.thread.wdog_list;
  65. if (thread != NULL) {
  66. if (thread->wdog_tick < delay) {
  67. delay = thread->wdog_tick;
  68. }
  69. }
  70. #endif
  71. // Check Active Timer list
  72. timer = osRtxInfo.timer.list;
  73. if (timer != NULL) {
  74. if (timer->tick < delay) {
  75. delay = timer->tick;
  76. }
  77. }
  78. return delay;
  79. }
  80. // ==== Service Calls ====
  81. /// Initialize the RTOS Kernel.
  82. /// \note API identical to osKernelInitialize
  83. static osStatus_t svcRtxKernelInitialize (void) {
  84. if (osRtxInfo.kernel.state == osRtxKernelReady) {
  85. EvrRtxKernelInitialized();
  86. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  87. return osOK;
  88. }
  89. if (osRtxInfo.kernel.state != osRtxKernelInactive) {
  90. EvrRtxKernelError((int32_t)osError);
  91. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  92. return osError;
  93. }
  94. #ifdef RTX_TZ_CONTEXT
  95. // Initialize Secure Process Stack
  96. if (TZ_InitContextSystem_S() == 0U) {
  97. EvrRtxKernelError(osRtxErrorTZ_InitContext_S);
  98. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  99. return osError;
  100. }
  101. #endif
  102. // Initialize osRtxInfo
  103. (void)memset(&osRtxInfo.kernel, 0, sizeof(osRtxInfo) - offsetof(osRtxInfo_t, kernel));
  104. osRtxInfo.isr_queue.data = osRtxConfig.isr_queue.data;
  105. osRtxInfo.isr_queue.max = osRtxConfig.isr_queue.max;
  106. osRtxInfo.thread.robin.timeout = osRtxConfig.robin_timeout;
  107. // Initialize Memory Pools (Variable Block Size)
  108. if (osRtxMemoryInit(osRtxConfig.mem.common_addr, osRtxConfig.mem.common_size) != 0U) {
  109. osRtxInfo.mem.common = osRtxConfig.mem.common_addr;
  110. }
  111. if (osRtxMemoryInit(osRtxConfig.mem.stack_addr, osRtxConfig.mem.stack_size) != 0U) {
  112. osRtxInfo.mem.stack = osRtxConfig.mem.stack_addr;
  113. } else {
  114. osRtxInfo.mem.stack = osRtxInfo.mem.common;
  115. }
  116. if (osRtxMemoryInit(osRtxConfig.mem.mp_data_addr, osRtxConfig.mem.mp_data_size) != 0U) {
  117. osRtxInfo.mem.mp_data = osRtxConfig.mem.mp_data_addr;
  118. } else {
  119. osRtxInfo.mem.mp_data = osRtxInfo.mem.common;
  120. }
  121. if (osRtxMemoryInit(osRtxConfig.mem.mq_data_addr, osRtxConfig.mem.mq_data_size) != 0U) {
  122. osRtxInfo.mem.mq_data = osRtxConfig.mem.mq_data_addr;
  123. } else {
  124. osRtxInfo.mem.mq_data = osRtxInfo.mem.common;
  125. }
  126. // Initialize Memory Pools (Fixed Block Size)
  127. if (osRtxConfig.mpi.stack != NULL) {
  128. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.stack,
  129. osRtxConfig.mpi.stack->max_blocks,
  130. osRtxConfig.mpi.stack->block_size,
  131. osRtxConfig.mpi.stack->block_base);
  132. osRtxInfo.mpi.stack = osRtxConfig.mpi.stack;
  133. }
  134. if (osRtxConfig.mpi.thread != NULL) {
  135. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.thread,
  136. osRtxConfig.mpi.thread->max_blocks,
  137. osRtxConfig.mpi.thread->block_size,
  138. osRtxConfig.mpi.thread->block_base);
  139. osRtxInfo.mpi.thread = osRtxConfig.mpi.thread;
  140. }
  141. if (osRtxConfig.mpi.timer != NULL) {
  142. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.timer,
  143. osRtxConfig.mpi.timer->max_blocks,
  144. osRtxConfig.mpi.timer->block_size,
  145. osRtxConfig.mpi.timer->block_base);
  146. osRtxInfo.mpi.timer = osRtxConfig.mpi.timer;
  147. }
  148. if (osRtxConfig.mpi.event_flags != NULL) {
  149. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.event_flags,
  150. osRtxConfig.mpi.event_flags->max_blocks,
  151. osRtxConfig.mpi.event_flags->block_size,
  152. osRtxConfig.mpi.event_flags->block_base);
  153. osRtxInfo.mpi.event_flags = osRtxConfig.mpi.event_flags;
  154. }
  155. if (osRtxConfig.mpi.mutex != NULL) {
  156. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.mutex,
  157. osRtxConfig.mpi.mutex->max_blocks,
  158. osRtxConfig.mpi.mutex->block_size,
  159. osRtxConfig.mpi.mutex->block_base);
  160. osRtxInfo.mpi.mutex = osRtxConfig.mpi.mutex;
  161. }
  162. if (osRtxConfig.mpi.semaphore != NULL) {
  163. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.semaphore,
  164. osRtxConfig.mpi.semaphore->max_blocks,
  165. osRtxConfig.mpi.semaphore->block_size,
  166. osRtxConfig.mpi.semaphore->block_base);
  167. osRtxInfo.mpi.semaphore = osRtxConfig.mpi.semaphore;
  168. }
  169. if (osRtxConfig.mpi.memory_pool != NULL) {
  170. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.memory_pool,
  171. osRtxConfig.mpi.memory_pool->max_blocks,
  172. osRtxConfig.mpi.memory_pool->block_size,
  173. osRtxConfig.mpi.memory_pool->block_base);
  174. osRtxInfo.mpi.memory_pool = osRtxConfig.mpi.memory_pool;
  175. }
  176. if (osRtxConfig.mpi.message_queue != NULL) {
  177. (void)osRtxMemoryPoolInit(osRtxConfig.mpi.message_queue,
  178. osRtxConfig.mpi.message_queue->max_blocks,
  179. osRtxConfig.mpi.message_queue->block_size,
  180. osRtxConfig.mpi.message_queue->block_base);
  181. osRtxInfo.mpi.message_queue = osRtxConfig.mpi.message_queue;
  182. }
  183. osRtxInfo.kernel.state = osRtxKernelReady;
  184. EvrRtxKernelInitialized();
  185. return osOK;
  186. }
  187. /// Get RTOS Kernel Information.
  188. /// \note API identical to osKernelGetInfo
  189. static osStatus_t svcRtxKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
  190. uint32_t size;
  191. if (version != NULL) {
  192. version->api = osRtxVersionAPI;
  193. version->kernel = osRtxVersionKernel;
  194. }
  195. if ((id_buf != NULL) && (id_size != 0U)) {
  196. if (id_size > sizeof(osRtxKernelId)) {
  197. size = sizeof(osRtxKernelId);
  198. } else {
  199. size = id_size;
  200. }
  201. (void)memcpy(id_buf, osRtxKernelId, size);
  202. }
  203. EvrRtxKernelInfoRetrieved(version, id_buf, id_size);
  204. return osOK;
  205. }
  206. /// Get the current RTOS Kernel state.
  207. /// \note API identical to osKernelGetState
  208. static osKernelState_t svcRtxKernelGetState (void) {
  209. osKernelState_t state = osRtxKernelState();
  210. EvrRtxKernelGetState(state);
  211. return state;
  212. }
  213. /// Start the RTOS Kernel scheduler.
  214. /// \note API identical to osKernelStart
  215. static osStatus_t svcRtxKernelStart (void) {
  216. os_thread_t *thread;
  217. if (osRtxInfo.kernel.state != osRtxKernelReady) {
  218. EvrRtxKernelError(osRtxErrorKernelNotReady);
  219. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  220. return osError;
  221. }
  222. // Thread startup (Idle and Timer Thread)
  223. if (!osRtxThreadStartup()) {
  224. EvrRtxKernelError((int32_t)osError);
  225. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  226. return osError;
  227. }
  228. // Setup SVC and PendSV System Service Calls
  229. SVC_Setup();
  230. // Setup RTOS Tick
  231. if (OS_Tick_Setup(osRtxConfig.tick_freq, OS_TICK_HANDLER) != 0) {
  232. EvrRtxKernelError((int32_t)osError);
  233. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  234. return osError;
  235. }
  236. osRtxInfo.tick_irqn = OS_Tick_GetIRQn();
  237. // Enable RTOS Tick
  238. OS_Tick_Enable();
  239. // Switch to Ready Thread with highest Priority
  240. thread = osRtxThreadListGet(&osRtxInfo.thread.ready);
  241. osRtxThreadSwitch(thread);
  242. osRtxInfo.kernel.state = osRtxKernelRunning;
  243. EvrRtxKernelStarted();
  244. return osOK;
  245. }
  246. /// Lock the RTOS Kernel scheduler.
  247. /// \note API identical to osKernelLock
  248. static int32_t svcRtxKernelLock (void) {
  249. int32_t lock;
  250. switch (osRtxInfo.kernel.state) {
  251. case osRtxKernelRunning:
  252. #ifdef RTX_SAFETY_CLASS
  253. // Check the safety class
  254. if ((osRtxThreadGetRunning()->attr >> osRtxAttrClass_Pos) <
  255. (osRtxInfo.kernel.protect >> osRtxKernelProtectClass_Pos)) {
  256. EvrRtxKernelError((int32_t)osErrorSafetyClass);
  257. lock = (int32_t)osErrorSafetyClass;
  258. break;
  259. }
  260. #endif
  261. osRtxInfo.kernel.state = osRtxKernelLocked;
  262. EvrRtxKernelLocked(0);
  263. lock = 0;
  264. break;
  265. case osRtxKernelLocked:
  266. EvrRtxKernelLocked(1);
  267. lock = 1;
  268. break;
  269. default:
  270. EvrRtxKernelError((int32_t)osError);
  271. lock = (int32_t)osError;
  272. break;
  273. }
  274. return lock;
  275. }
  276. /// Unlock the RTOS Kernel scheduler.
  277. /// \note API identical to osKernelUnlock
  278. static int32_t svcRtxKernelUnlock (void) {
  279. int32_t lock;
  280. switch (osRtxInfo.kernel.state) {
  281. case osRtxKernelRunning:
  282. EvrRtxKernelUnlocked(0);
  283. lock = 0;
  284. break;
  285. case osRtxKernelLocked:
  286. osRtxInfo.kernel.state = osRtxKernelRunning;
  287. EvrRtxKernelUnlocked(1);
  288. lock = 1;
  289. break;
  290. default:
  291. EvrRtxKernelError((int32_t)osError);
  292. lock = (int32_t)osError;
  293. break;
  294. }
  295. return lock;
  296. }
  297. /// Restore the RTOS Kernel scheduler lock state.
  298. /// \note API identical to osKernelRestoreLock
  299. static int32_t svcRtxKernelRestoreLock (int32_t lock) {
  300. int32_t lock_new;
  301. switch (osRtxInfo.kernel.state) {
  302. case osRtxKernelRunning:
  303. case osRtxKernelLocked:
  304. #ifdef RTX_SAFETY_CLASS
  305. // Check the safety class
  306. if ((osRtxThreadGetRunning()->attr >> osRtxAttrClass_Pos) <
  307. (osRtxInfo.kernel.protect >> osRtxKernelProtectClass_Pos)) {
  308. EvrRtxKernelError((int32_t)osErrorSafetyClass);
  309. lock_new = (int32_t)osErrorSafetyClass;
  310. break;
  311. }
  312. #endif
  313. switch (lock) {
  314. case 0:
  315. osRtxInfo.kernel.state = osRtxKernelRunning;
  316. EvrRtxKernelLockRestored(0);
  317. lock_new = 0;
  318. break;
  319. case 1:
  320. osRtxInfo.kernel.state = osRtxKernelLocked;
  321. EvrRtxKernelLockRestored(1);
  322. lock_new = 1;
  323. break;
  324. default:
  325. EvrRtxKernelError((int32_t)osError);
  326. lock_new = (int32_t)osError;
  327. break;
  328. }
  329. break;
  330. default:
  331. EvrRtxKernelError((int32_t)osError);
  332. lock_new = (int32_t)osError;
  333. break;
  334. }
  335. return lock_new;
  336. }
  337. /// Suspend the RTOS Kernel scheduler.
  338. /// \note API identical to osKernelSuspend
  339. static uint32_t svcRtxKernelSuspend (void) {
  340. uint32_t delay;
  341. if (osRtxInfo.kernel.state != osRtxKernelRunning) {
  342. EvrRtxKernelError(osRtxErrorKernelNotRunning);
  343. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  344. return 0U;
  345. }
  346. #ifdef RTX_SAFETY_CLASS
  347. // Check the safety class
  348. if ((osRtxThreadGetRunning()->attr >> osRtxAttrClass_Pos) <
  349. (osRtxInfo.kernel.protect >> osRtxKernelProtectClass_Pos)) {
  350. EvrRtxKernelError((int32_t)osErrorSafetyClass);
  351. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  352. return 0U;
  353. }
  354. #endif
  355. KernelBlock();
  356. osRtxInfo.kernel.state = osRtxKernelSuspended;
  357. delay = GetKernelSleepTime();
  358. EvrRtxKernelSuspended(delay);
  359. return delay;
  360. }
  361. /// Resume the RTOS Kernel scheduler.
  362. /// \note API identical to osKernelResume
  363. static void svcRtxKernelResume (uint32_t sleep_ticks) {
  364. os_thread_t *thread;
  365. os_timer_t *timer;
  366. uint32_t delay;
  367. uint32_t ticks, kernel_tick;
  368. if (osRtxInfo.kernel.state != osRtxKernelSuspended) {
  369. EvrRtxKernelResumed();
  370. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  371. return;
  372. }
  373. delay = GetKernelSleepTime();
  374. if (sleep_ticks >= delay) {
  375. ticks = delay - 1U;
  376. } else {
  377. ticks = sleep_ticks;
  378. }
  379. // Update Thread Delay sleep ticks
  380. thread = osRtxInfo.thread.delay_list;
  381. if (thread != NULL) {
  382. thread->delay -= ticks;
  383. }
  384. // Update Timer sleep ticks
  385. timer = osRtxInfo.timer.list;
  386. if (timer != NULL) {
  387. timer->tick -= ticks;
  388. }
  389. #ifdef RTX_THREAD_WATCHDOG
  390. // Update Thread Watchdog sleep ticks
  391. thread = osRtxInfo.thread.wdog_list;
  392. if (thread != NULL) {
  393. thread->wdog_tick -= ticks;
  394. }
  395. #endif
  396. kernel_tick = osRtxInfo.kernel.tick + sleep_ticks;
  397. osRtxInfo.kernel.tick += ticks;
  398. while (osRtxInfo.kernel.tick != kernel_tick) {
  399. osRtxInfo.kernel.tick++;
  400. // Process Thread Delays
  401. osRtxThreadDelayTick();
  402. // Process Timers
  403. if (osRtxInfo.timer.tick != NULL) {
  404. osRtxInfo.timer.tick();
  405. }
  406. #ifdef RTX_THREAD_WATCHDOG
  407. // Process Watchdog Timers
  408. osRtxThreadWatchdogTick();
  409. #endif
  410. }
  411. osRtxInfo.kernel.state = osRtxKernelRunning;
  412. osRtxThreadDispatch(NULL);
  413. KernelUnblock();
  414. EvrRtxKernelResumed();
  415. }
  416. #ifdef RTX_SAFETY_CLASS
  417. /// Protect the RTOS Kernel scheduler access.
  418. /// \note API identical to osKernelProtect
  419. static osStatus_t svcRtxKernelProtect (uint32_t safety_class) {
  420. uint32_t thread_class;
  421. osStatus_t status;
  422. // Check parameters
  423. if (safety_class > 0x0FU) {
  424. EvrRtxKernelError((int32_t)osErrorParameter);
  425. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  426. return osErrorParameter;
  427. }
  428. switch (osRtxInfo.kernel.state) {
  429. case osRtxKernelInactive:
  430. EvrRtxKernelError(osRtxErrorKernelNotReady);
  431. status = osError;
  432. break;
  433. case osRtxKernelReady:
  434. osRtxInfo.kernel.protect &= (uint8_t)~osRtxKernelProtectClass_Msk;
  435. osRtxInfo.kernel.protect |= (uint8_t)(safety_class << osRtxKernelProtectClass_Pos);
  436. EvrRtxKernelProtected();
  437. status = osOK;
  438. break;
  439. case osRtxKernelRunning:
  440. // Check the safety class
  441. thread_class = (uint32_t)osRtxThreadGetRunning()->attr >> osRtxAttrClass_Pos;
  442. if ((safety_class > thread_class) ||
  443. (thread_class < ((uint32_t)osRtxInfo.kernel.protect >> osRtxKernelProtectClass_Pos))) {
  444. EvrRtxKernelError((int32_t)osErrorSafetyClass);
  445. status = osErrorSafetyClass;
  446. break;
  447. }
  448. osRtxInfo.kernel.protect &= (uint8_t)~osRtxKernelProtectClass_Msk;
  449. osRtxInfo.kernel.protect |= (uint8_t)(safety_class << osRtxKernelProtectClass_Pos);
  450. EvrRtxKernelProtected();
  451. status = osOK;
  452. break;
  453. case osRtxKernelLocked:
  454. case osRtxKernelSuspended:
  455. EvrRtxKernelError(osRtxErrorKernelNotRunning);
  456. status = osError;
  457. break;
  458. default:
  459. // Should never come here
  460. status = osError;
  461. break;
  462. }
  463. return status;
  464. }
  465. /// Destroy objects for specified safety classes.
  466. /// \note API identical to osKernelDestroyClass
  467. static osStatus_t svcRtxKernelDestroyClass (uint32_t safety_class, uint32_t mode) {
  468. os_thread_t *thread;
  469. os_thread_t *thread_next;
  470. // Check parameters
  471. if (safety_class > 0x0FU) {
  472. EvrRtxKernelError((int32_t)osErrorParameter);
  473. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  474. return osErrorParameter;
  475. }
  476. // Check running thread safety class (when called from thread)
  477. thread = osRtxThreadGetRunning();
  478. if ((thread != NULL) && IsSVCallIrq()) {
  479. if ((((mode & osSafetyWithSameClass) != 0U) &&
  480. ((thread->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class)) ||
  481. (((mode & osSafetyWithLowerClass) != 0U) &&
  482. (((thread->attr >> osRtxAttrClass_Pos) + 1U) < (uint8_t)safety_class))) {
  483. EvrRtxKernelError((int32_t)osErrorSafetyClass);
  484. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  485. return osErrorSafetyClass;
  486. }
  487. }
  488. // Delete RTOS objects for safety class
  489. osRtxMutexDeleteClass(safety_class, mode);
  490. osRtxSemaphoreDeleteClass(safety_class, mode);
  491. osRtxMemoryPoolDeleteClass(safety_class, mode);
  492. osRtxMessageQueueDeleteClass(safety_class, mode);
  493. osRtxEventFlagsDeleteClass(safety_class, mode);
  494. osRtxTimerDeleteClass(safety_class, mode);
  495. // Threads in Wait List
  496. thread = osRtxInfo.thread.wait_list;
  497. while (thread != NULL) {
  498. thread_next = thread->delay_next;
  499. if ((((mode & osSafetyWithSameClass) != 0U) &&
  500. ((thread->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
  501. (((mode & osSafetyWithLowerClass) != 0U) &&
  502. ((thread->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class))) {
  503. osRtxThreadListRemove(thread);
  504. osRtxThreadDelayRemove(thread);
  505. #ifdef RTX_THREAD_WATCHDOG
  506. osRtxThreadWatchdogRemove(thread);
  507. #endif
  508. osRtxMutexOwnerRelease(thread->mutex_list);
  509. osRtxThreadJoinWakeup(thread);
  510. osRtxThreadDestroy(thread);
  511. }
  512. thread = thread_next;
  513. }
  514. // Threads in Delay List
  515. thread = osRtxInfo.thread.delay_list;
  516. while (thread != NULL) {
  517. thread_next = thread->delay_next;
  518. if ((((mode & osSafetyWithSameClass) != 0U) &&
  519. ((thread->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
  520. (((mode & osSafetyWithLowerClass) != 0U) &&
  521. ((thread->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class))) {
  522. osRtxThreadListRemove(thread);
  523. osRtxThreadDelayRemove(thread);
  524. #ifdef RTX_THREAD_WATCHDOG
  525. osRtxThreadWatchdogRemove(thread);
  526. #endif
  527. osRtxMutexOwnerRelease(thread->mutex_list);
  528. osRtxThreadJoinWakeup(thread);
  529. osRtxThreadDestroy(thread);
  530. }
  531. thread = thread_next;
  532. }
  533. // Threads in Ready List
  534. thread = osRtxInfo.thread.ready.thread_list;
  535. while (thread != NULL) {
  536. thread_next = thread->thread_next;
  537. if ((((mode & osSafetyWithSameClass) != 0U) &&
  538. ((thread->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
  539. (((mode & osSafetyWithLowerClass) != 0U) &&
  540. ((thread->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class))) {
  541. osRtxThreadListRemove(thread);
  542. #ifdef RTX_THREAD_WATCHDOG
  543. osRtxThreadWatchdogRemove(thread);
  544. #endif
  545. osRtxMutexOwnerRelease(thread->mutex_list);
  546. osRtxThreadJoinWakeup(thread);
  547. osRtxThreadDestroy(thread);
  548. }
  549. thread = thread_next;
  550. }
  551. // Running Thread
  552. thread = osRtxThreadGetRunning();
  553. if ((thread != NULL) &&
  554. ((((mode & osSafetyWithSameClass) != 0U) &&
  555. ((thread->attr >> osRtxAttrClass_Pos) == (uint8_t)safety_class)) ||
  556. (((mode & osSafetyWithLowerClass) != 0U) &&
  557. ((thread->attr >> osRtxAttrClass_Pos) < (uint8_t)safety_class)))) {
  558. if ((osRtxKernelGetState() != osRtxKernelRunning) ||
  559. (osRtxInfo.thread.ready.thread_list == NULL)) {
  560. osRtxThreadDispatch(NULL);
  561. EvrRtxKernelError((int32_t)osErrorResource);
  562. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  563. return osErrorResource;
  564. }
  565. #ifdef RTX_THREAD_WATCHDOG
  566. osRtxThreadWatchdogRemove(thread);
  567. #endif
  568. osRtxMutexOwnerRelease(thread->mutex_list);
  569. osRtxThreadJoinWakeup(thread);
  570. // Switch to next Ready Thread
  571. osRtxThreadSwitch(osRtxThreadListGet(&osRtxInfo.thread.ready));
  572. // Update Stack Pointer
  573. thread->sp = __get_PSP();
  574. #ifdef RTX_STACK_CHECK
  575. // Check Stack usage
  576. if (!osRtxThreadStackCheck(thread)) {
  577. osRtxThreadSetRunning(osRtxInfo.thread.run.next);
  578. (void)osRtxKernelErrorNotify(osRtxErrorStackOverflow, thread);
  579. }
  580. #endif
  581. // Mark running thread as deleted
  582. osRtxThreadSetRunning(NULL);
  583. // Destroy Thread
  584. osRtxThreadDestroy(thread);
  585. } else {
  586. osRtxThreadDispatch(NULL);
  587. }
  588. return osOK;
  589. }
  590. #endif
  591. /// Get the RTOS kernel tick count.
  592. /// \note API identical to osKernelGetTickCount
  593. static uint32_t svcRtxKernelGetTickCount (void) {
  594. EvrRtxKernelGetTickCount(osRtxInfo.kernel.tick);
  595. return osRtxInfo.kernel.tick;
  596. }
  597. /// Get the RTOS kernel tick frequency.
  598. /// \note API identical to osKernelGetTickFreq
  599. static uint32_t svcRtxKernelGetTickFreq (void) {
  600. EvrRtxKernelGetTickFreq(osRtxConfig.tick_freq);
  601. return osRtxConfig.tick_freq;
  602. }
  603. /// Get the RTOS kernel system timer count.
  604. /// \note API identical to osKernelGetSysTimerCount
  605. static uint32_t svcRtxKernelGetSysTimerCount (void) {
  606. uint32_t tick;
  607. uint32_t count;
  608. tick = (uint32_t)osRtxInfo.kernel.tick;
  609. count = OS_Tick_GetCount();
  610. if (OS_Tick_GetOverflow() != 0U) {
  611. count = OS_Tick_GetCount();
  612. tick++;
  613. }
  614. count += tick * OS_Tick_GetInterval();
  615. EvrRtxKernelGetSysTimerCount(count);
  616. return count;
  617. }
  618. /// Get the RTOS kernel system timer frequency.
  619. /// \note API identical to osKernelGetSysTimerFreq
  620. static uint32_t svcRtxKernelGetSysTimerFreq (void) {
  621. uint32_t freq = OS_Tick_GetClock();
  622. EvrRtxKernelGetSysTimerFreq(freq);
  623. return freq;
  624. }
  625. // Service Calls definitions
  626. //lint ++flb "Library Begin" [MISRA Note 11]
  627. SVC0_0 (KernelInitialize, osStatus_t)
  628. SVC0_3 (KernelGetInfo, osStatus_t, osVersion_t *, char *, uint32_t)
  629. SVC0_0 (KernelStart, osStatus_t)
  630. SVC0_0 (KernelLock, int32_t)
  631. SVC0_0 (KernelUnlock, int32_t)
  632. SVC0_1 (KernelRestoreLock, int32_t, int32_t)
  633. SVC0_0 (KernelSuspend, uint32_t)
  634. SVC0_1N(KernelResume, void, uint32_t)
  635. #ifdef RTX_SAFETY_CLASS
  636. SVC0_1 (KernelProtect, osStatus_t, uint32_t)
  637. SVC0_2 (KernelDestroyClass, osStatus_t, uint32_t, uint32_t)
  638. #endif
  639. SVC0_0 (KernelGetState, osKernelState_t)
  640. SVC0_0 (KernelGetTickCount, uint32_t)
  641. SVC0_0 (KernelGetTickFreq, uint32_t)
  642. SVC0_0 (KernelGetSysTimerCount, uint32_t)
  643. SVC0_0 (KernelGetSysTimerFreq, uint32_t)
  644. //lint --flb "Library End"
  645. // ==== Library functions ====
  646. /// RTOS Kernel Pre-Initialization Hook
  647. //lint -esym(759,osRtxKernelBeforeInit) "Prototype in header"
  648. //lint -esym(765,osRtxKernelBeforeInit) "Global scope (can be overridden)"
  649. //lint -esym(522,osRtxKernelBeforeInit) "Can be overridden (do not lack side-effects)"
  650. __WEAK void osRtxKernelBeforeInit (void) {
  651. }
  652. /// RTOS Kernel Error Notification Handler
  653. /// \note API identical to osRtxErrorNotify
  654. uint32_t osRtxKernelErrorNotify (uint32_t code, void *object_id) {
  655. EvrRtxKernelErrorNotify(code, object_id);
  656. return osRtxErrorNotify(code, object_id);
  657. }
  658. // ==== Public API ====
  659. /// Initialize the RTOS Kernel.
  660. osStatus_t osKernelInitialize (void) {
  661. osStatus_t status;
  662. osRtxKernelBeforeInit();
  663. EvrRtxKernelInitialize();
  664. if (IsException() || IsIrqMasked()) {
  665. EvrRtxKernelError((int32_t)osErrorISR);
  666. status = osErrorISR;
  667. } else {
  668. status = __svcKernelInitialize();
  669. }
  670. return status;
  671. }
  672. /// Get RTOS Kernel Information.
  673. osStatus_t osKernelGetInfo (osVersion_t *version, char *id_buf, uint32_t id_size) {
  674. osStatus_t status;
  675. EvrRtxKernelGetInfo(version, id_buf, id_size);
  676. if (IsException() || IsIrqMasked() || IsPrivileged()) {
  677. status = svcRtxKernelGetInfo(version, id_buf, id_size);
  678. } else {
  679. status = __svcKernelGetInfo(version, id_buf, id_size);
  680. }
  681. return status;
  682. }
  683. /// Get the current RTOS Kernel state.
  684. osKernelState_t osKernelGetState (void) {
  685. osKernelState_t state;
  686. if (IsException() || IsIrqMasked() || IsPrivileged()) {
  687. state = svcRtxKernelGetState();
  688. } else {
  689. state = __svcKernelGetState();
  690. }
  691. return state;
  692. }
  693. /// Start the RTOS Kernel scheduler.
  694. osStatus_t osKernelStart (void) {
  695. osStatus_t status;
  696. EvrRtxKernelStart();
  697. if (IsException() || IsIrqMasked()) {
  698. EvrRtxKernelError((int32_t)osErrorISR);
  699. status = osErrorISR;
  700. } else {
  701. status = __svcKernelStart();
  702. }
  703. return status;
  704. }
  705. /// Lock the RTOS Kernel scheduler.
  706. int32_t osKernelLock (void) {
  707. int32_t lock;
  708. EvrRtxKernelLock();
  709. if (IsException() || IsIrqMasked()) {
  710. EvrRtxKernelError((int32_t)osErrorISR);
  711. lock = (int32_t)osErrorISR;
  712. } else {
  713. lock = __svcKernelLock();
  714. }
  715. return lock;
  716. }
  717. /// Unlock the RTOS Kernel scheduler.
  718. int32_t osKernelUnlock (void) {
  719. int32_t lock;
  720. EvrRtxKernelUnlock();
  721. if (IsException() || IsIrqMasked()) {
  722. EvrRtxKernelError((int32_t)osErrorISR);
  723. lock = (int32_t)osErrorISR;
  724. } else {
  725. lock = __svcKernelUnlock();
  726. }
  727. return lock;
  728. }
  729. /// Restore the RTOS Kernel scheduler lock state.
  730. int32_t osKernelRestoreLock (int32_t lock) {
  731. int32_t lock_new;
  732. EvrRtxKernelRestoreLock(lock);
  733. if (IsException() || IsIrqMasked()) {
  734. if (IsFault() || IsSVCallIrq() || IsPendSvIrq() || IsTickIrq(osRtxInfo.tick_irqn)) {
  735. lock_new = svcRtxKernelRestoreLock(lock);
  736. } else {
  737. EvrRtxKernelError((int32_t)osErrorISR);
  738. lock_new = (int32_t)osErrorISR;
  739. }
  740. } else {
  741. lock_new = __svcKernelRestoreLock(lock);
  742. }
  743. return lock_new;
  744. }
  745. /// Suspend the RTOS Kernel scheduler.
  746. uint32_t osKernelSuspend (void) {
  747. uint32_t ticks;
  748. EvrRtxKernelSuspend();
  749. if (IsException() || IsIrqMasked()) {
  750. EvrRtxKernelError((int32_t)osErrorISR);
  751. ticks = 0U;
  752. } else {
  753. ticks = __svcKernelSuspend();
  754. }
  755. return ticks;
  756. }
  757. /// Resume the RTOS Kernel scheduler.
  758. void osKernelResume (uint32_t sleep_ticks) {
  759. EvrRtxKernelResume(sleep_ticks);
  760. if (IsException() || IsIrqMasked()) {
  761. EvrRtxKernelError((int32_t)osErrorISR);
  762. } else {
  763. __svcKernelResume(sleep_ticks);
  764. }
  765. }
  766. #ifdef RTX_SAFETY_CLASS
  767. /// Protect the RTOS Kernel scheduler access.
  768. osStatus_t osKernelProtect (uint32_t safety_class) {
  769. osStatus_t status;
  770. EvrRtxKernelProtect(safety_class);
  771. if (IsException() || IsIrqMasked()) {
  772. EvrRtxKernelError((int32_t)osErrorISR);
  773. status = osErrorISR;
  774. } else {
  775. status = __svcKernelProtect(safety_class);
  776. }
  777. return status;
  778. }
  779. /// Destroy RTOS objects for specified safety classes.
  780. osStatus_t osKernelDestroyClass (uint32_t safety_class, uint32_t mode) {
  781. osStatus_t status;
  782. EvrRtxKernelDestroyClass(safety_class, mode);
  783. if (IsException() || IsIrqMasked()) {
  784. if (IsTickIrq(osRtxInfo.tick_irqn)) {
  785. status = svcRtxKernelDestroyClass(safety_class, mode);
  786. } else {
  787. EvrRtxKernelError((int32_t)osErrorISR);
  788. status = osErrorISR;
  789. }
  790. } else {
  791. status = __svcKernelDestroyClass(safety_class, mode);
  792. }
  793. return status;
  794. }
  795. #endif
  796. /// Get the RTOS kernel tick count.
  797. uint32_t osKernelGetTickCount (void) {
  798. uint32_t count;
  799. if (IsException() || IsIrqMasked()) {
  800. count = svcRtxKernelGetTickCount();
  801. } else {
  802. count = __svcKernelGetTickCount();
  803. }
  804. return count;
  805. }
  806. /// Get the RTOS kernel tick frequency.
  807. uint32_t osKernelGetTickFreq (void) {
  808. uint32_t freq;
  809. if (IsException() || IsIrqMasked()) {
  810. freq = svcRtxKernelGetTickFreq();
  811. } else {
  812. freq = __svcKernelGetTickFreq();
  813. }
  814. return freq;
  815. }
  816. /// Get the RTOS kernel system timer count.
  817. uint32_t osKernelGetSysTimerCount (void) {
  818. uint32_t count;
  819. if (IsException() || IsIrqMasked()) {
  820. count = svcRtxKernelGetSysTimerCount();
  821. } else {
  822. count = __svcKernelGetSysTimerCount();
  823. }
  824. return count;
  825. }
  826. /// Get the RTOS kernel system timer frequency.
  827. uint32_t osKernelGetSysTimerFreq (void) {
  828. uint32_t freq;
  829. if (IsException() || IsIrqMasked()) {
  830. freq = svcRtxKernelGetSysTimerFreq();
  831. } else {
  832. freq = __svcKernelGetSysTimerFreq();
  833. }
  834. return freq;
  835. }