rtx_evflags.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. * Copyright (c) 2013-2017 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: Event Flags functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // ==== Helper functions ====
  27. /// Set Event Flags.
  28. /// \param[in] ef event flags object.
  29. /// \param[in] flags specifies the flags to set.
  30. /// \return event flags after setting.
  31. static uint32_t EventFlagsSet (os_event_flags_t *ef, uint32_t flags) {
  32. #if (__EXCLUSIVE_ACCESS == 0U)
  33. uint32_t primask = __get_PRIMASK();
  34. #endif
  35. uint32_t event_flags;
  36. #if (__EXCLUSIVE_ACCESS == 0U)
  37. __disable_irq();
  38. ef->event_flags |= flags;
  39. event_flags = ef->event_flags;
  40. if (primask == 0U) {
  41. __enable_irq();
  42. }
  43. #else
  44. event_flags = atomic_set32(&ef->event_flags, flags);
  45. #endif
  46. return event_flags;
  47. }
  48. /// Clear Event Flags.
  49. /// \param[in] ef event flags object.
  50. /// \param[in] flags specifies the flags to clear.
  51. /// \return event flags before clearing.
  52. static uint32_t EventFlagsClear (os_event_flags_t *ef, uint32_t flags) {
  53. #if (__EXCLUSIVE_ACCESS == 0U)
  54. uint32_t primask = __get_PRIMASK();
  55. #endif
  56. uint32_t event_flags;
  57. #if (__EXCLUSIVE_ACCESS == 0U)
  58. __disable_irq();
  59. event_flags = ef->event_flags;
  60. ef->event_flags &= ~flags;
  61. if (primask == 0U) {
  62. __enable_irq();
  63. }
  64. #else
  65. event_flags = atomic_clr32(&ef->event_flags, flags);
  66. #endif
  67. return event_flags;
  68. }
  69. /// Check Event Flags.
  70. /// \param[in] ef event flags object.
  71. /// \param[in] flags specifies the flags to check.
  72. /// \param[in] options specifies flags options (osFlagsXxxx).
  73. /// \return event flags before clearing or 0 if specified flags have not been set.
  74. static uint32_t EventFlagsCheck (os_event_flags_t *ef, uint32_t flags, uint32_t options) {
  75. #if (__EXCLUSIVE_ACCESS == 0U)
  76. uint32_t primask;
  77. #endif
  78. uint32_t event_flags;
  79. if ((options & osFlagsNoClear) == 0U) {
  80. #if (__EXCLUSIVE_ACCESS == 0U)
  81. primask = __get_PRIMASK();
  82. __disable_irq();
  83. event_flags = ef->event_flags;
  84. if ((((options & osFlagsWaitAll) != 0U) && ((event_flags & flags) != flags)) ||
  85. (((options & osFlagsWaitAll) == 0U) && ((event_flags & flags) == 0U))) {
  86. event_flags = 0U;
  87. } else {
  88. ef->event_flags &= ~flags;
  89. }
  90. if (primask == 0U) {
  91. __enable_irq();
  92. }
  93. #else
  94. if ((options & osFlagsWaitAll) != 0U) {
  95. event_flags = atomic_chk32_all(&ef->event_flags, flags);
  96. } else {
  97. event_flags = atomic_chk32_any(&ef->event_flags, flags);
  98. }
  99. #endif
  100. } else {
  101. event_flags = ef->event_flags;
  102. if ((((options & osFlagsWaitAll) != 0U) && ((event_flags & flags) != flags)) ||
  103. (((options & osFlagsWaitAll) == 0U) && ((event_flags & flags) == 0U))) {
  104. event_flags = 0U;
  105. }
  106. }
  107. return event_flags;
  108. }
  109. // ==== Library functions ====
  110. /// Event Flags post ISR processing.
  111. /// \param[in] ef event flags object.
  112. void osRtxEventFlagsPostProcess (os_event_flags_t *ef) {
  113. os_thread_t *thread;
  114. os_thread_t *thread_next;
  115. uint32_t event_flags;
  116. if (ef->state == osRtxObjectInactive) {
  117. return;
  118. }
  119. // Check if Threads are waiting for Event Flags
  120. thread = ef->thread_list;
  121. while (thread != NULL) {
  122. thread_next = thread->thread_next;
  123. event_flags = EventFlagsCheck(ef, thread->wait_flags, thread->flags_options);
  124. if (event_flags != 0U) {
  125. osRtxThreadListRemove(thread);
  126. osRtxThreadWaitExit(thread, event_flags, false);
  127. EvrRtxEventFlagsWaitCompleted(ef, thread->wait_flags, thread->flags_options, event_flags);
  128. }
  129. thread = thread_next;
  130. }
  131. }
  132. // ==== Service Calls ====
  133. // Service Calls definitions
  134. SVC0_1M(EventFlagsNew, osEventFlagsId_t, const osEventFlagsAttr_t *)
  135. SVC0_1 (EventFlagsGetName, const char *, osEventFlagsId_t)
  136. SVC0_2 (EventFlagsSet, uint32_t, osEventFlagsId_t, uint32_t)
  137. SVC0_2 (EventFlagsClear, uint32_t, osEventFlagsId_t, uint32_t)
  138. SVC0_1 (EventFlagsGet, uint32_t, osEventFlagsId_t)
  139. SVC0_4 (EventFlagsWait, uint32_t, osEventFlagsId_t, uint32_t, uint32_t, uint32_t)
  140. SVC0_1 (EventFlagsDelete, osStatus_t, osEventFlagsId_t)
  141. /// Create and Initialize an Event Flags object.
  142. /// \note API identical to osEventFlagsNew
  143. osEventFlagsId_t svcRtxEventFlagsNew (const osEventFlagsAttr_t *attr) {
  144. os_event_flags_t *ef;
  145. uint8_t flags;
  146. const char *name;
  147. // Process attributes
  148. if (attr != NULL) {
  149. name = attr->name;
  150. ef = attr->cb_mem;
  151. if (ef != NULL) {
  152. if (((uint32_t)ef & 3U) || (attr->cb_size < sizeof(os_event_flags_t))) {
  153. EvrRtxEventFlagsError(NULL, osRtxErrorInvalidControlBlock);
  154. return NULL;
  155. }
  156. } else {
  157. if (attr->cb_size != 0U) {
  158. EvrRtxEventFlagsError(NULL, osRtxErrorInvalidControlBlock);
  159. return NULL;
  160. }
  161. }
  162. } else {
  163. name = NULL;
  164. ef = NULL;
  165. }
  166. // Allocate object memory if not provided
  167. if (ef == NULL) {
  168. if (osRtxInfo.mpi.event_flags != NULL) {
  169. ef = osRtxMemoryPoolAlloc(osRtxInfo.mpi.event_flags);
  170. } else {
  171. ef = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_event_flags_t), 1U);
  172. }
  173. if (ef == NULL) {
  174. EvrRtxEventFlagsError(NULL, osErrorNoMemory);
  175. return NULL;
  176. }
  177. flags = osRtxFlagSystemObject;
  178. } else {
  179. flags = 0U;
  180. }
  181. // Initialize control block
  182. ef->id = osRtxIdEventFlags;
  183. ef->state = osRtxObjectActive;
  184. ef->flags = flags;
  185. ef->name = name;
  186. ef->thread_list = NULL;
  187. ef->event_flags = 0U;
  188. // Register post ISR processing function
  189. osRtxInfo.post_process.event_flags = osRtxEventFlagsPostProcess;
  190. EvrRtxEventFlagsCreated(ef);
  191. return ef;
  192. }
  193. /// Get name of an Event Flags object.
  194. /// \note API identical to osEventFlagsGetName
  195. const char *svcRtxEventFlagsGetName (osEventFlagsId_t ef_id) {
  196. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  197. // Check parameters
  198. if ((ef == NULL) || (ef->id != osRtxIdEventFlags)) {
  199. EvrRtxEventFlagsGetName(ef, NULL);
  200. return NULL;
  201. }
  202. // Check object state
  203. if (ef->state == osRtxObjectInactive) {
  204. EvrRtxEventFlagsGetName(ef, NULL);
  205. return NULL;
  206. }
  207. EvrRtxEventFlagsGetName(ef, ef->name);
  208. return ef->name;
  209. }
  210. /// Set the specified Event Flags.
  211. /// \note API identical to osEventFlagsSet
  212. uint32_t svcRtxEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
  213. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  214. os_thread_t *thread;
  215. os_thread_t *thread_next;
  216. uint32_t event_flags;
  217. uint32_t event_flags0;
  218. // Check parameters
  219. if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
  220. (flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
  221. EvrRtxEventFlagsError(ef, osErrorParameter);
  222. return ((uint32_t)osErrorParameter);
  223. }
  224. // Check object state
  225. if (ef->state == osRtxObjectInactive) {
  226. EvrRtxEventFlagsError(ef, osErrorResource);
  227. return ((uint32_t)osErrorResource);
  228. }
  229. // Set Event Flags
  230. event_flags = EventFlagsSet(ef, flags);
  231. // Check if Threads are waiting for Event Flags
  232. thread = ef->thread_list;
  233. while (thread != NULL) {
  234. thread_next = thread->thread_next;
  235. event_flags0 = EventFlagsCheck(ef, thread->wait_flags, thread->flags_options);
  236. if (event_flags0 != 0U) {
  237. if ((thread->flags_options & osFlagsNoClear) == 0U) {
  238. event_flags = event_flags0 & ~thread->wait_flags;
  239. } else {
  240. event_flags = event_flags0;
  241. }
  242. osRtxThreadListRemove(thread);
  243. osRtxThreadWaitExit(thread, event_flags0, false);
  244. EvrRtxEventFlagsWaitCompleted(ef, thread->wait_flags, thread->flags_options, event_flags0);
  245. }
  246. thread = thread_next;
  247. }
  248. osRtxThreadDispatch(NULL);
  249. EvrRtxEventFlagsSetDone(ef, event_flags);
  250. return event_flags;
  251. }
  252. /// Clear the specified Event Flags.
  253. /// \note API identical to osEventFlagsClear
  254. uint32_t svcRtxEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
  255. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  256. uint32_t event_flags;
  257. // Check parameters
  258. if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
  259. (flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
  260. EvrRtxEventFlagsError(ef, osErrorParameter);
  261. return ((uint32_t)osErrorParameter);
  262. }
  263. // Check object state
  264. if (ef->state == osRtxObjectInactive) {
  265. EvrRtxEventFlagsError(ef, osErrorResource);
  266. return ((uint32_t)osErrorResource);
  267. }
  268. // Clear Event Flags
  269. event_flags = EventFlagsClear(ef, flags);
  270. EvrRtxEventFlagsClearDone(ef, event_flags);
  271. return event_flags;
  272. }
  273. /// Get the current Event Flags.
  274. /// \note API identical to osEventFlagsGet
  275. uint32_t svcRtxEventFlagsGet (osEventFlagsId_t ef_id) {
  276. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  277. // Check parameters
  278. if ((ef == NULL) || (ef->id != osRtxIdEventFlags)) {
  279. EvrRtxEventFlagsGet(ef, 0U);
  280. return 0U;
  281. }
  282. // Check object state
  283. if (ef->state == osRtxObjectInactive) {
  284. EvrRtxEventFlagsGet(ef, 0U);
  285. return 0U;
  286. }
  287. EvrRtxEventFlagsGet(ef, ef->event_flags);
  288. return ef->event_flags;
  289. }
  290. /// Wait for one or more Event Flags to become signaled.
  291. /// \note API identical to osEventFlagsWait
  292. uint32_t svcRtxEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
  293. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  294. os_thread_t *running_thread;
  295. uint32_t event_flags;
  296. running_thread = osRtxThreadGetRunning();
  297. if (running_thread == NULL) {
  298. EvrRtxEventFlagsError(ef, osRtxErrorKernelNotRunning);
  299. return ((uint32_t)osError);
  300. }
  301. // Check parameters
  302. if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
  303. (flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
  304. EvrRtxEventFlagsError(ef, osErrorParameter);
  305. return ((uint32_t)osErrorParameter);
  306. }
  307. // Check object state
  308. if (ef->state == osRtxObjectInactive) {
  309. EvrRtxEventFlagsError(ef, osErrorResource);
  310. return ((uint32_t)osErrorResource);
  311. }
  312. // Check Event Flags
  313. event_flags = EventFlagsCheck(ef, flags, options);
  314. if (event_flags != 0U) {
  315. EvrRtxEventFlagsWaitCompleted(ef, flags, options, event_flags);
  316. return event_flags;
  317. }
  318. // Check if timeout is specified
  319. if (timeout != 0U) {
  320. EvrRtxEventFlagsWaitPending(ef, flags, options, timeout);
  321. // Store waiting flags and options
  322. running_thread->wait_flags = flags;
  323. running_thread->flags_options = (uint8_t)options;
  324. // Suspend current Thread
  325. osRtxThreadListPut((os_object_t*)ef, running_thread);
  326. osRtxThreadWaitEnter(osRtxThreadWaitingEventFlags, timeout);
  327. return ((uint32_t)osErrorTimeout);
  328. }
  329. EvrRtxEventFlagsWaitNotCompleted(ef, flags, options);
  330. return ((uint32_t)osErrorResource);
  331. }
  332. /// Delete an Event Flags object.
  333. /// \note API identical to osEventFlagsDelete
  334. osStatus_t svcRtxEventFlagsDelete (osEventFlagsId_t ef_id) {
  335. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  336. os_thread_t *thread;
  337. // Check parameters
  338. if ((ef == NULL) || (ef->id != osRtxIdEventFlags)) {
  339. EvrRtxEventFlagsError(ef, osErrorParameter);
  340. return osErrorParameter;
  341. }
  342. // Check object state
  343. if (ef->state == osRtxObjectInactive) {
  344. EvrRtxEventFlagsError(ef, osErrorResource);
  345. return osErrorResource;
  346. }
  347. // Mark object as inactive
  348. ef->state = osRtxObjectInactive;
  349. // Unblock waiting threads
  350. if (ef->thread_list != NULL) {
  351. do {
  352. thread = osRtxThreadListGet((os_object_t*)ef);
  353. osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, false);
  354. } while (ef->thread_list != NULL);
  355. osRtxThreadDispatch(NULL);
  356. }
  357. // Free object memory
  358. if (ef->flags & osRtxFlagSystemObject) {
  359. if (osRtxInfo.mpi.event_flags != NULL) {
  360. osRtxMemoryPoolFree(osRtxInfo.mpi.event_flags, ef);
  361. } else {
  362. osRtxMemoryFree(osRtxInfo.mem.common, ef);
  363. }
  364. }
  365. EvrRtxEventFlagsDestroyed(ef);
  366. return osOK;
  367. }
  368. // ==== ISR Calls ====
  369. /// Set the specified Event Flags.
  370. /// \note API identical to osEventFlagsSet
  371. __STATIC_INLINE
  372. uint32_t isrRtxEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
  373. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  374. uint32_t event_flags;
  375. // Check parameters
  376. if ((ef == NULL) || (ef->id != osRtxIdEventFlags) ||
  377. (flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
  378. EvrRtxEventFlagsError(ef, osErrorParameter);
  379. return ((uint32_t)osErrorParameter);
  380. }
  381. // Check object state
  382. if (ef->state == osRtxObjectInactive) {
  383. EvrRtxEventFlagsError(ef, osErrorResource);
  384. return ((uint32_t)osErrorResource);
  385. }
  386. // Set Event Flags
  387. event_flags = EventFlagsSet(ef, flags);
  388. // Register post ISR processing
  389. osRtxPostProcess((os_object_t *)ef);
  390. EvrRtxEventFlagsSetDone(ef, event_flags);
  391. return event_flags;
  392. }
  393. /// Wait for one or more Event Flags to become signaled.
  394. /// \note API identical to osEventFlagsWait
  395. __STATIC_INLINE
  396. uint32_t isrRtxEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
  397. os_event_flags_t *ef = (os_event_flags_t *)ef_id;
  398. uint32_t event_flags;
  399. // Check parameters
  400. if ((ef == NULL) || (ef->id != osRtxIdEventFlags) || (timeout != 0U) ||
  401. (flags & ~((1U << osRtxEventFlagsLimit) - 1U))) {
  402. EvrRtxEventFlagsError(ef, osErrorParameter);
  403. return ((uint32_t)osErrorParameter);
  404. }
  405. // Check object state
  406. if (ef->state == osRtxObjectInactive) {
  407. EvrRtxEventFlagsError(ef, osErrorResource);
  408. return ((uint32_t)osErrorResource);
  409. }
  410. // Check Event Flags
  411. event_flags = EventFlagsCheck(ef, flags, options);
  412. if (event_flags != 0U) {
  413. EvrRtxEventFlagsWaitCompleted(ef, flags, options, event_flags);
  414. return ((uint32_t)event_flags);
  415. }
  416. EvrRtxEventFlagsWaitNotCompleted(ef, flags, options);
  417. return ((uint32_t)osErrorResource);
  418. }
  419. // ==== Public API ====
  420. /// Create and Initialize an Event Flags object.
  421. osEventFlagsId_t osEventFlagsNew (const osEventFlagsAttr_t *attr) {
  422. EvrRtxEventFlagsNew(attr);
  423. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  424. EvrRtxEventFlagsError(NULL, osErrorISR);
  425. return NULL;
  426. }
  427. return __svcEventFlagsNew(attr);
  428. }
  429. /// Get name of an Event Flags object.
  430. const char *osEventFlagsGetName (osEventFlagsId_t ef_id) {
  431. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  432. EvrRtxEventFlagsGetName(ef_id, NULL);
  433. return NULL;
  434. }
  435. return __svcEventFlagsGetName(ef_id);
  436. }
  437. /// Set the specified Event Flags.
  438. uint32_t osEventFlagsSet (osEventFlagsId_t ef_id, uint32_t flags) {
  439. EvrRtxEventFlagsSet(ef_id, flags);
  440. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  441. return isrRtxEventFlagsSet(ef_id, flags);
  442. } else {
  443. return __svcEventFlagsSet(ef_id, flags);
  444. }
  445. }
  446. /// Clear the specified Event Flags.
  447. uint32_t osEventFlagsClear (osEventFlagsId_t ef_id, uint32_t flags) {
  448. EvrRtxEventFlagsClear(ef_id, flags);
  449. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  450. return svcRtxEventFlagsClear(ef_id, flags);
  451. } else {
  452. return __svcEventFlagsClear(ef_id, flags);
  453. }
  454. }
  455. /// Get the current Event Flags.
  456. uint32_t osEventFlagsGet (osEventFlagsId_t ef_id) {
  457. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  458. return svcRtxEventFlagsGet(ef_id);
  459. } else {
  460. return __svcEventFlagsGet(ef_id);
  461. }
  462. }
  463. /// Wait for one or more Event Flags to become signaled.
  464. uint32_t osEventFlagsWait (osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) {
  465. EvrRtxEventFlagsWait(ef_id, flags, options, timeout);
  466. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  467. return isrRtxEventFlagsWait(ef_id, flags, options, timeout);
  468. } else {
  469. return __svcEventFlagsWait(ef_id, flags, options, timeout);
  470. }
  471. }
  472. /// Delete an Event Flags object.
  473. osStatus_t osEventFlagsDelete (osEventFlagsId_t ef_id) {
  474. EvrRtxEventFlagsDelete(ef_id);
  475. if (IS_IRQ_MODE() || IS_IRQ_MASKED()) {
  476. EvrRtxEventFlagsError(ef_id, osErrorISR);
  477. return osErrorISR;
  478. }
  479. return __svcEventFlagsDelete(ef_id);
  480. }