rt_System.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*----------------------------------------------------------------------------
  2. * CMSIS-RTOS - RTX
  3. *----------------------------------------------------------------------------
  4. * Name: RT_SYSTEM.C
  5. * Purpose: System Task Manager
  6. * Rev.: V4.82
  7. *----------------------------------------------------------------------------
  8. *
  9. * Copyright (c) 1999-2009 KEIL, 2009-2017 ARM Germany GmbH. All rights reserved.
  10. *
  11. * SPDX-License-Identifier: Apache-2.0
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the License); you may
  14. * not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  21. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. *---------------------------------------------------------------------------*/
  25. #include "rt_TypeDef.h"
  26. #include "RTX_Config.h"
  27. #include "rt_Task.h"
  28. #include "rt_System.h"
  29. #include "rt_Event.h"
  30. #include "rt_List.h"
  31. #include "rt_Mailbox.h"
  32. #include "rt_Semaphore.h"
  33. #include "rt_Time.h"
  34. #include "rt_Timer.h"
  35. #include "rt_Robin.h"
  36. #include "rt_HAL_CM.h"
  37. /*----------------------------------------------------------------------------
  38. * Global Variables
  39. *---------------------------------------------------------------------------*/
  40. S32 os_tick_irqn;
  41. /*----------------------------------------------------------------------------
  42. * Local Variables
  43. *---------------------------------------------------------------------------*/
  44. static volatile BIT os_lock;
  45. static volatile BIT os_psh_flag;
  46. static U8 pend_flags;
  47. /*----------------------------------------------------------------------------
  48. * Global Functions
  49. *---------------------------------------------------------------------------*/
  50. #define RL_RTX_VER 0x482
  51. #if defined (__CC_ARM)
  52. __asm void $$RTX$$version (void) {
  53. /* Export a version number symbol for a version control. */
  54. EXPORT __RL_RTX_VER
  55. __RL_RTX_VER EQU RL_RTX_VER
  56. }
  57. #endif
  58. /*--------------------------- rt_suspend ------------------------------------*/
  59. extern U32 sysUserTimerWakeupTime(void);
  60. U32 rt_suspend (void) {
  61. /* Suspend OS scheduler */
  62. U32 delta = 0xFFFFU;
  63. #ifdef __CMSIS_RTOS
  64. U32 sleep;
  65. #endif
  66. rt_tsk_lock();
  67. if (os_dly.p_dlnk) {
  68. delta = os_dly.delta_time;
  69. }
  70. #ifdef __CMSIS_RTOS
  71. sleep = sysUserTimerWakeupTime();
  72. if (sleep < delta) { delta = sleep; }
  73. #else
  74. if (os_tmr.next) {
  75. if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
  76. }
  77. #endif
  78. return (delta);
  79. }
  80. /*--------------------------- rt_resume -------------------------------------*/
  81. extern void sysUserTimerUpdate (U32 sleep_time);
  82. void rt_resume (U32 sleep_time) {
  83. /* Resume OS scheduler after suspend */
  84. P_TCB next;
  85. U32 delta;
  86. os_tsk.run->state = READY;
  87. rt_put_rdy_first (os_tsk.run);
  88. os_robin.task = NULL;
  89. /* Update delays. */
  90. if (os_dly.p_dlnk) {
  91. delta = sleep_time;
  92. if (delta >= os_dly.delta_time) {
  93. delta -= os_dly.delta_time;
  94. os_time += os_dly.delta_time;
  95. os_dly.delta_time = 1U;
  96. while (os_dly.p_dlnk) {
  97. rt_dec_dly();
  98. if (delta == 0U) { break; }
  99. delta--;
  100. os_time++;
  101. }
  102. } else {
  103. os_time += delta;
  104. os_dly.delta_time -= (U16)delta;
  105. }
  106. } else {
  107. os_time += sleep_time;
  108. }
  109. /* Check the user timers. */
  110. #ifdef __CMSIS_RTOS
  111. sysUserTimerUpdate(sleep_time);
  112. #else
  113. if (os_tmr.next) {
  114. delta = sleep_time;
  115. if (delta >= os_tmr.tcnt) {
  116. delta -= os_tmr.tcnt;
  117. os_tmr.tcnt = 1U;
  118. while (os_tmr.next) {
  119. rt_tmr_tick();
  120. if (delta == 0U) { break; }
  121. delta--;
  122. }
  123. } else {
  124. os_tmr.tcnt -= delta;
  125. }
  126. }
  127. #endif
  128. /* Switch back to highest ready task */
  129. next = rt_get_first (&os_rdy);
  130. rt_switch_req (next);
  131. rt_tsk_unlock();
  132. }
  133. /*--------------------------- rt_tsk_lock -----------------------------------*/
  134. void rt_tsk_lock (void) {
  135. /* Prevent task switching by locking out scheduler */
  136. if (os_tick_irqn < 0) {
  137. OS_LOCK();
  138. os_lock = __TRUE;
  139. OS_UNPEND(pend_flags);
  140. } else {
  141. OS_X_LOCK((U32)os_tick_irqn);
  142. os_lock = __TRUE;
  143. OS_X_UNPEND(pend_flags);
  144. }
  145. }
  146. /*--------------------------- rt_tsk_unlock ---------------------------------*/
  147. void rt_tsk_unlock (void) {
  148. /* Unlock scheduler and re-enable task switching */
  149. if (os_tick_irqn < 0) {
  150. OS_UNLOCK();
  151. os_lock = __FALSE;
  152. OS_PEND(pend_flags, os_psh_flag);
  153. os_psh_flag = __FALSE;
  154. } else {
  155. OS_X_UNLOCK((U32)os_tick_irqn);
  156. os_lock = __FALSE;
  157. OS_X_PEND(pend_flags, os_psh_flag);
  158. os_psh_flag = __FALSE;
  159. }
  160. }
  161. /*--------------------------- rt_psh_req ------------------------------------*/
  162. void rt_psh_req (void) {
  163. /* Initiate a post service handling request if required. */
  164. if (os_lock == __FALSE) {
  165. OS_PEND_IRQ();
  166. }
  167. else {
  168. os_psh_flag = __TRUE;
  169. }
  170. }
  171. /*--------------------------- rt_pop_req ------------------------------------*/
  172. void rt_pop_req (void) {
  173. /* Process an ISR post service requests. */
  174. struct OS_XCB *p_CB;
  175. P_TCB next;
  176. U32 idx;
  177. os_tsk.run->state = READY;
  178. rt_put_rdy_first (os_tsk.run);
  179. idx = os_psq->last;
  180. while (os_psq->count) {
  181. p_CB = os_psq->q[idx].id;
  182. if (p_CB->cb_type == TCB) {
  183. /* Is of TCB type */
  184. rt_evt_psh ((P_TCB)p_CB, (U16)os_psq->q[idx].arg);
  185. }
  186. else if (p_CB->cb_type == MCB) {
  187. /* Is of MCB type */
  188. rt_mbx_psh ((P_MCB)p_CB, (void *)os_psq->q[idx].arg);
  189. }
  190. else {
  191. /* Must be of SCB type */
  192. rt_sem_psh ((P_SCB)p_CB);
  193. }
  194. if (++idx == os_psq->size) { idx = 0U; }
  195. rt_dec (&os_psq->count);
  196. }
  197. os_psq->last = (U8)idx;
  198. next = rt_get_first (&os_rdy);
  199. rt_switch_req (next);
  200. }
  201. /*--------------------------- os_tick_init ----------------------------------*/
  202. __weak S32 os_tick_init (void) {
  203. /* Initialize SysTick timer as system tick timer. */
  204. rt_systick_init();
  205. return (-1); /* Return IRQ number of SysTick timer */
  206. }
  207. /*--------------------------- os_tick_val -----------------------------------*/
  208. __weak U32 os_tick_val (void) {
  209. /* Get SysTick timer current value (0 .. OS_TRV). */
  210. return rt_systick_val();
  211. }
  212. /*--------------------------- os_tick_ovf -----------------------------------*/
  213. __weak U32 os_tick_ovf (void) {
  214. /* Get SysTick timer overflow flag */
  215. return rt_systick_ovf();
  216. }
  217. /*--------------------------- os_tick_irqack --------------------------------*/
  218. __weak void os_tick_irqack (void) {
  219. /* Acknowledge timer interrupt. */
  220. }
  221. /*--------------------------- rt_systick ------------------------------------*/
  222. extern void sysTimerTick(void);
  223. void rt_systick (void) {
  224. /* Check for system clock update, suspend running task. */
  225. P_TCB next;
  226. os_tsk.run->state = READY;
  227. rt_put_rdy_first (os_tsk.run);
  228. /* Check Round Robin timeout. */
  229. rt_chk_robin ();
  230. /* Update delays. */
  231. os_time++;
  232. rt_dec_dly ();
  233. /* Check the user timers. */
  234. #ifdef __CMSIS_RTOS
  235. sysTimerTick();
  236. #else
  237. rt_tmr_tick ();
  238. #endif
  239. /* Switch back to highest ready task */
  240. next = rt_get_first (&os_rdy);
  241. rt_switch_req (next);
  242. }
  243. /*--------------------------- rt_stk_check ----------------------------------*/
  244. __weak void rt_stk_check (void) {
  245. /* Check for stack overflow. */
  246. if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
  247. (os_tsk.run->stack[0] != MAGIC_WORD)) {
  248. os_error (OS_ERR_STK_OVF);
  249. }
  250. }
  251. /*----------------------------------------------------------------------------
  252. * end of file
  253. *---------------------------------------------------------------------------*/