]> git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/rtos/rtx/TARGET_CORTEX_M/rt_System.c
Merge commit '5a0132f1c1c9a14fd2941f0a5e29bbf5e31da20c' into master-core-pull
[tmk_keyboard.git] / tmk_core / tool / mbed / mbed-sdk / libraries / rtos / rtx / TARGET_CORTEX_M / rt_System.c
1 /*----------------------------------------------------------------------------
2 * RL-ARM - RTX
3 *----------------------------------------------------------------------------
4 * Name: RT_SYSTEM.C
5 * Purpose: System Task Manager
6 * Rev.: V4.60
7 *----------------------------------------------------------------------------
8 *
9 * Copyright (c) 1999-2009 KEIL, 2009-2012 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
35 #include "rt_TypeDef.h"
36 #include "RTX_Conf.h"
37 #include "rt_Task.h"
38 #include "rt_System.h"
39 #include "rt_Event.h"
40 #include "rt_List.h"
41 #include "rt_Mailbox.h"
42 #include "rt_Semaphore.h"
43 #include "rt_Time.h"
44 #include "rt_Robin.h"
45 #include "rt_HAL_CM.h"
46
47 /*----------------------------------------------------------------------------
48 * Global Variables
49 *---------------------------------------------------------------------------*/
50
51 int os_tick_irqn;
52
53 /*----------------------------------------------------------------------------
54 * Local Variables
55 *---------------------------------------------------------------------------*/
56
57 static volatile BIT os_lock;
58 static volatile BIT os_psh_flag;
59 static U8 pend_flags;
60
61 /*----------------------------------------------------------------------------
62 * Global Functions
63 *---------------------------------------------------------------------------*/
64
65 #if defined (__CC_ARM)
66 __asm void $$RTX$$version (void) {
67 /* Export a version number symbol for a version control. */
68
69 EXPORT __RL_RTX_VER
70
71 __RL_RTX_VER EQU 0x450
72 }
73 #endif
74
75
76 /*--------------------------- rt_suspend ------------------------------------*/
77 U32 rt_suspend (void) {
78 /* Suspend OS scheduler */
79 U32 delta = 0xFFFF;
80
81 rt_tsk_lock();
82
83 if (os_dly.p_dlnk) {
84 delta = os_dly.delta_time;
85 }
86 #ifndef __CMSIS_RTOS
87 if (os_tmr.next) {
88 if (os_tmr.tcnt < delta) delta = os_tmr.tcnt;
89 }
90 #endif
91
92 return (delta);
93 }
94
95
96 /*--------------------------- rt_resume -------------------------------------*/
97 void rt_resume (U32 sleep_time) {
98 /* Resume OS scheduler after suspend */
99 P_TCB next;
100 U32 delta;
101
102 os_tsk.run->state = READY;
103 rt_put_rdy_first (os_tsk.run);
104
105 os_robin.task = NULL;
106
107 /* Update delays. */
108 if (os_dly.p_dlnk) {
109 delta = sleep_time;
110 if (delta >= os_dly.delta_time) {
111 delta -= os_dly.delta_time;
112 os_time += os_dly.delta_time;
113 os_dly.delta_time = 1;
114 while (os_dly.p_dlnk) {
115 rt_dec_dly();
116 if (delta == 0) break;
117 delta--;
118 os_time++;
119 }
120 } else {
121 os_time += delta;
122 os_dly.delta_time -= delta;
123 }
124 } else {
125 os_time += sleep_time;
126 }
127
128 #ifndef __CMSIS_RTOS
129 /* Check the user timers. */
130 if (os_tmr.next) {
131 delta = sleep_time;
132 if (delta >= os_tmr.tcnt) {
133 delta -= os_tmr.tcnt;
134 os_tmr.tcnt = 1;
135 while (os_tmr.next) {
136 rt_tmr_tick();
137 if (delta == 0) break;
138 delta--;
139 }
140 } else {
141 os_tmr.tcnt -= delta;
142 }
143 }
144 #endif
145
146 /* Switch back to highest ready task */
147 next = rt_get_first (&os_rdy);
148 rt_switch_req (next);
149
150 rt_tsk_unlock();
151 }
152
153
154 /*--------------------------- rt_tsk_lock -----------------------------------*/
155
156 void rt_tsk_lock (void) {
157 /* Prevent task switching by locking out scheduler */
158 if (os_tick_irqn < 0) {
159 OS_LOCK();
160 os_lock = __TRUE;
161 OS_UNPEND (&pend_flags);
162 } else {
163 OS_X_LOCK(os_tick_irqn);
164 os_lock = __TRUE;
165 OS_X_UNPEND (&pend_flags);
166 }
167 }
168
169
170 /*--------------------------- rt_tsk_unlock ---------------------------------*/
171
172 void rt_tsk_unlock (void) {
173 /* Unlock scheduler and re-enable task switching */
174 if (os_tick_irqn < 0) {
175 OS_UNLOCK();
176 os_lock = __FALSE;
177 OS_PEND (pend_flags, os_psh_flag);
178 os_psh_flag = __FALSE;
179 } else {
180 OS_X_UNLOCK(os_tick_irqn);
181 os_lock = __FALSE;
182 OS_X_PEND (pend_flags, os_psh_flag);
183 os_psh_flag = __FALSE;
184 }
185 }
186
187
188 /*--------------------------- rt_psh_req ------------------------------------*/
189
190 void rt_psh_req (void) {
191 /* Initiate a post service handling request if required. */
192 if (os_lock == __FALSE) {
193 OS_PEND_IRQ ();
194 }
195 else {
196 os_psh_flag = __TRUE;
197 }
198 }
199
200
201 /*--------------------------- rt_pop_req ------------------------------------*/
202
203 void rt_pop_req (void) {
204 /* Process an ISR post service requests. */
205 struct OS_XCB *p_CB;
206 P_TCB next;
207 U32 idx;
208
209 os_tsk.run->state = READY;
210 rt_put_rdy_first (os_tsk.run);
211
212 idx = os_psq->last;
213 while (os_psq->count) {
214 p_CB = os_psq->q[idx].id;
215 if (p_CB->cb_type == TCB) {
216 /* Is of TCB type */
217 rt_evt_psh ((P_TCB)p_CB, (U16)os_psq->q[idx].arg);
218 }
219 else if (p_CB->cb_type == MCB) {
220 /* Is of MCB type */
221 rt_mbx_psh ((P_MCB)p_CB, (void *)os_psq->q[idx].arg);
222 }
223 else {
224 /* Must be of SCB type */
225 rt_sem_psh ((P_SCB)p_CB);
226 }
227 if (++idx == os_psq->size) idx = 0;
228 rt_dec (&os_psq->count);
229 }
230 os_psq->last = idx;
231
232 next = rt_get_first (&os_rdy);
233 rt_switch_req (next);
234 }
235
236
237 /*--------------------------- os_tick_init ----------------------------------*/
238
239 __weak int os_tick_init (void) {
240 /* Initialize SysTick timer as system tick timer. */
241 rt_systick_init ();
242 return (-1); /* Return IRQ number of SysTick timer */
243 }
244
245
246 /*--------------------------- os_tick_irqack --------------------------------*/
247
248 __weak void os_tick_irqack (void) {
249 /* Acknowledge timer interrupt. */
250 }
251
252
253 /*--------------------------- rt_systick ------------------------------------*/
254
255 extern void sysTimerTick(void);
256
257 void rt_systick (void) {
258 /* Check for system clock update, suspend running task. */
259 P_TCB next;
260
261 os_tsk.run->state = READY;
262 rt_put_rdy_first (os_tsk.run);
263
264 /* Check Round Robin timeout. */
265 rt_chk_robin ();
266
267 /* Update delays. */
268 os_time++;
269 rt_dec_dly ();
270
271 /* Check the user timers. */
272 #ifdef __CMSIS_RTOS
273 sysTimerTick();
274 #else
275 rt_tmr_tick ();
276 #endif
277
278 /* Switch back to highest ready task */
279 next = rt_get_first (&os_rdy);
280 rt_switch_req (next);
281 }
282
283 /*--------------------------- rt_stk_check ----------------------------------*/
284 __weak void rt_stk_check (void) {
285 /* Check for stack overflow. */
286 if (os_tsk.run->task_id == 0x01) {
287 // TODO: For the main thread the check should be done against the main heap pointer
288 } else {
289 if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
290 (os_tsk.run->stack[0] != MAGIC_WORD)) {
291 os_error (OS_ERR_STK_OVF);
292 }
293 }
294 }
295
296 /*----------------------------------------------------------------------------
297 * end of file
298 *---------------------------------------------------------------------------*/
299
Imprint / Impressum