rt_System.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*----------------------------------------------------------------------------
  2. * CMSIS-RTOS - RTX
  3. *----------------------------------------------------------------------------
  4. * Name: RT_SYSTEM.C
  5. * Purpose: System Task Manager
  6. * Rev.: V4.78
  7. *----------------------------------------------------------------------------
  8. *
  9. * Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
  10. * All rights reserved.
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. * - Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * - Neither the name of ARM nor the names of its contributors may be used
  19. * to endorse or promote products derived from this software without
  20. * specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *---------------------------------------------------------------------------*/
  34. #include "rt_TypeDef.h"
  35. #include "RTX_Config.h"
  36. #include "rt_Task.h"
  37. #include "rt_System.h"
  38. #include "rt_Event.h"
  39. #include "rt_List.h"
  40. #include "rt_Mailbox.h"
  41. #include "rt_Semaphore.h"
  42. #include "rt_Time.h"
  43. #include "rt_Timer.h"
  44. #include "rt_Robin.h"
  45. #include "rt_HAL_CM.h"
  46. /*----------------------------------------------------------------------------
  47. * Global Variables
  48. *---------------------------------------------------------------------------*/
  49. int os_tick_irqn;
  50. /*----------------------------------------------------------------------------
  51. * Local Variables
  52. *---------------------------------------------------------------------------*/
  53. static volatile BIT os_lock;
  54. static volatile BIT os_psh_flag;
  55. static U8 pend_flags;
  56. /*----------------------------------------------------------------------------
  57. * Global Functions
  58. *---------------------------------------------------------------------------*/
  59. #define RL_RTX_VER 0x478
  60. #if defined (__CC_ARM)
  61. __asm void $$RTX$$version (void) {
  62. /* Export a version number symbol for a version control. */
  63. EXPORT __RL_RTX_VER
  64. __RL_RTX_VER EQU RL_RTX_VER
  65. }
  66. #endif
  67. /*--------------------------- rt_suspend ------------------------------------*/
  68. extern U32 sysUserTimerWakeupTime(void);
  69. U32 rt_suspend (void) {
  70. /* Suspend OS scheduler */
  71. U32 delta = 0xFFFF;
  72. #ifdef __CMSIS_RTOS
  73. U32 sleep;
  74. #endif
  75. rt_tsk_lock();
  76. if (os_dly.p_dlnk) {
  77. delta = os_dly.delta_time;
  78. }
  79. #ifdef __CMSIS_RTOS
  80. sleep = sysUserTimerWakeupTime();
  81. if (sleep < delta) delta = sleep;
  82. #else
  83. if (os_tmr.next) {
  84. if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
  85. }
  86. #endif
  87. return (delta);
  88. }
  89. /*--------------------------- rt_resume -------------------------------------*/
  90. extern void sysUserTimerUpdate (U32 sleep_time);
  91. void rt_resume (U32 sleep_time) {
  92. /* Resume OS scheduler after suspend */
  93. P_TCB next;
  94. U32 delta;
  95. os_tsk.run->state = READY;
  96. rt_put_rdy_first (os_tsk.run);
  97. os_robin.task = NULL;
  98. /* Update delays. */
  99. if (os_dly.p_dlnk) {
  100. delta = sleep_time;
  101. if (delta >= os_dly.delta_time) {
  102. delta -= os_dly.delta_time;
  103. os_time += os_dly.delta_time;
  104. os_dly.delta_time = 1;
  105. while (os_dly.p_dlnk) {
  106. rt_dec_dly();
  107. if (delta == 0) break;
  108. delta--;
  109. os_time++;
  110. }
  111. } else {
  112. os_time += delta;
  113. os_dly.delta_time -= delta;
  114. }
  115. } else {
  116. os_time += sleep_time;
  117. }
  118. /* Check the user timers. */
  119. #ifdef __CMSIS_RTOS
  120. sysUserTimerUpdate(sleep_time);
  121. #else
  122. if (os_tmr.next) {
  123. delta = sleep_time;
  124. if (delta >= os_tmr.tcnt) {
  125. delta -= os_tmr.tcnt;
  126. os_tmr.tcnt = 1;
  127. while (os_tmr.next) {
  128. rt_tmr_tick();
  129. if (delta == 0) break;
  130. delta--;
  131. }
  132. } else {
  133. os_tmr.tcnt -= delta;
  134. }
  135. }
  136. #endif
  137. /* Switch back to highest ready task */
  138. next = rt_get_first (&os_rdy);
  139. rt_switch_req (next);
  140. rt_tsk_unlock();
  141. }
  142. /*--------------------------- rt_tsk_lock -----------------------------------*/
  143. void rt_tsk_lock (void) {
  144. /* Prevent task switching by locking out scheduler */
  145. if (os_tick_irqn < 0) {
  146. OS_LOCK();
  147. os_lock = __TRUE;
  148. OS_UNPEND (&pend_flags);
  149. } else {
  150. OS_X_LOCK(os_tick_irqn);
  151. os_lock = __TRUE;
  152. OS_X_UNPEND (&pend_flags);
  153. }
  154. }
  155. /*--------------------------- rt_tsk_unlock ---------------------------------*/
  156. void rt_tsk_unlock (void) {
  157. /* Unlock scheduler and re-enable task switching */
  158. if (os_tick_irqn < 0) {
  159. OS_UNLOCK();
  160. os_lock = __FALSE;
  161. OS_PEND (pend_flags, os_psh_flag);
  162. os_psh_flag = __FALSE;
  163. } else {
  164. OS_X_UNLOCK(os_tick_irqn);
  165. os_lock = __FALSE;
  166. OS_X_PEND (pend_flags, os_psh_flag);
  167. os_psh_flag = __FALSE;
  168. }
  169. }
  170. /*--------------------------- rt_psh_req ------------------------------------*/
  171. void rt_psh_req (void) {
  172. /* Initiate a post service handling request if required. */
  173. if (os_lock == __FALSE) {
  174. OS_PEND_IRQ ();
  175. }
  176. else {
  177. os_psh_flag = __TRUE;
  178. }
  179. }
  180. /*--------------------------- rt_pop_req ------------------------------------*/
  181. void rt_pop_req (void) {
  182. /* Process an ISR post service requests. */
  183. struct OS_XCB *p_CB;
  184. P_TCB next;
  185. U32 idx;
  186. os_tsk.run->state = READY;
  187. rt_put_rdy_first (os_tsk.run);
  188. idx = os_psq->last;
  189. while (os_psq->count) {
  190. p_CB = os_psq->q[idx].id;
  191. if (p_CB->cb_type == TCB) {
  192. /* Is of TCB type */
  193. rt_evt_psh ((P_TCB)p_CB, (U16)os_psq->q[idx].arg);
  194. }
  195. else if (p_CB->cb_type == MCB) {
  196. /* Is of MCB type */
  197. rt_mbx_psh ((P_MCB)p_CB, (void *)os_psq->q[idx].arg);
  198. }
  199. else {
  200. /* Must be of SCB type */
  201. rt_sem_psh ((P_SCB)p_CB);
  202. }
  203. if (++idx == os_psq->size) idx = 0;
  204. rt_dec (&os_psq->count);
  205. }
  206. os_psq->last = idx;
  207. next = rt_get_first (&os_rdy);
  208. rt_switch_req (next);
  209. }
  210. /*--------------------------- os_tick_init ----------------------------------*/
  211. __weak int os_tick_init (void) {
  212. /* Initialize SysTick timer as system tick timer. */
  213. rt_systick_init();
  214. return (-1); /* Return IRQ number of SysTick timer */
  215. }
  216. /*--------------------------- os_tick_val -----------------------------------*/
  217. __weak U32 os_tick_val (void) {
  218. /* Get SysTick timer current value (0 .. OS_TRV). */
  219. return rt_systick_val();
  220. }
  221. /*--------------------------- os_tick_ovf -----------------------------------*/
  222. __weak U32 os_tick_ovf (void) {
  223. /* Get SysTick timer overflow flag */
  224. return rt_systick_ovf();
  225. }
  226. /*--------------------------- os_tick_irqack --------------------------------*/
  227. __weak void os_tick_irqack (void) {
  228. /* Acknowledge timer interrupt. */
  229. }
  230. /*--------------------------- rt_systick ------------------------------------*/
  231. extern void sysTimerTick(void);
  232. void rt_systick (void) {
  233. /* Check for system clock update, suspend running task. */
  234. P_TCB next;
  235. os_tsk.run->state = READY;
  236. rt_put_rdy_first (os_tsk.run);
  237. /* Check Round Robin timeout. */
  238. rt_chk_robin ();
  239. /* Update delays. */
  240. os_time++;
  241. rt_dec_dly ();
  242. /* Check the user timers. */
  243. #ifdef __CMSIS_RTOS
  244. sysTimerTick();
  245. #else
  246. rt_tmr_tick ();
  247. #endif
  248. /* Switch back to highest ready task */
  249. next = rt_get_first (&os_rdy);
  250. rt_switch_req (next);
  251. }
  252. /*--------------------------- rt_stk_check ----------------------------------*/
  253. __weak void rt_stk_check (void) {
  254. /* Check for stack overflow. */
  255. if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
  256. (os_tsk.run->stack[0] != MAGIC_WORD)) {
  257. os_error (OS_ERR_STK_OVF);
  258. }
  259. }
  260. /*----------------------------------------------------------------------------
  261. * end of file
  262. *---------------------------------------------------------------------------*/