]>
git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/rtos/rtx/TARGET_CORTEX_M/rt_Task.c
1 /*----------------------------------------------------------------------------
3 *----------------------------------------------------------------------------
5 * Purpose: Task functions and system start up.
7 *----------------------------------------------------------------------------
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.
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 *---------------------------------------------------------------------------*/
35 #include "rt_TypeDef.h"
37 #include "rt_System.h"
40 #include "rt_MemBox.h"
42 #include "rt_HAL_CM.h"
44 /*----------------------------------------------------------------------------
46 *---------------------------------------------------------------------------*/
48 /* Running and next task info. */
51 /* Task Control Blocks of idle demon */
52 struct OS_TCB os_idle_TCB
;
55 /*----------------------------------------------------------------------------
57 *---------------------------------------------------------------------------*/
59 OS_TID
rt_get_TID (void) {
62 for (tid
= 1; tid
<= os_maxtaskrun
; tid
++) {
63 if (os_active_TCB
[tid
-1] == NULL
) {
70 #if defined (__CC_ARM) && !defined (__MICROLIB)
71 /*--------------------------- __user_perthread_libspace ---------------------*/
72 extern void *__libspace_start
;
74 void *__user_perthread_libspace (void) {
75 /* Provide a separate libspace for each task. */
76 if (os_tsk
.run
== NULL
) {
77 /* RTX not running yet. */
78 return (&__libspace_start
);
80 return (void *)(os_tsk
.run
->std_libspace
);
84 /*--------------------------- rt_init_context -------------------------------*/
86 void rt_init_context (P_TCB p_TCB
, U8 priority
, FUNCP task_body
) {
87 /* Initialize general part of the Task Control Block. */
90 p_TCB
->prio
= priority
;
95 p_TCB
->delta_time
= 0;
96 p_TCB
->interval_time
= 0;
99 p_TCB
->stack_frame
= 0;
101 rt_init_stack (p_TCB
, task_body
);
105 /*--------------------------- rt_switch_req ---------------------------------*/
107 void rt_switch_req (P_TCB p_new
) {
108 /* Switch to next task (identified by "p_new"). */
109 os_tsk
.new_tsk
= p_new
;
110 p_new
->state
= RUNNING
;
111 DBG_TASK_SWITCH(p_new
->task_id
);
115 /*--------------------------- rt_dispatch -----------------------------------*/
117 void rt_dispatch (P_TCB next_TCB
) {
118 /* Dispatch next task if any identified or dispatch highest ready task */
119 /* "next_TCB" identifies a task to run or has value NULL (=no next task) */
120 if (next_TCB
== NULL
) {
121 /* Running task was blocked: continue with highest ready task */
122 next_TCB
= rt_get_first (&os_rdy
);
123 rt_switch_req (next_TCB
);
126 /* Check which task continues */
127 if (next_TCB
->prio
> os_tsk
.run
->prio
) {
128 /* preempt running task */
129 rt_put_rdy_first (os_tsk
.run
);
130 os_tsk
.run
->state
= READY
;
131 rt_switch_req (next_TCB
);
134 /* put next task into ready list, no task switch takes place */
135 next_TCB
->state
= READY
;
136 rt_put_prio (&os_rdy
, next_TCB
);
142 /*--------------------------- rt_block --------------------------------------*/
144 void rt_block (U16 timeout
, U8 block_state
) {
145 /* Block running task and choose next ready task. */
146 /* "timeout" sets a time-out value or is 0xffff (=no time-out). */
147 /* "block_state" defines the appropriate task state */
151 if (timeout
< 0xffff) {
152 rt_put_dly (os_tsk
.run
, timeout
);
154 os_tsk
.run
->state
= block_state
;
155 next_TCB
= rt_get_first (&os_rdy
);
156 rt_switch_req (next_TCB
);
161 /*--------------------------- rt_tsk_pass -----------------------------------*/
163 void rt_tsk_pass (void) {
164 /* Allow tasks of same priority level to run cooperatively.*/
167 p_new
= rt_get_same_rdy_prio();
169 rt_put_prio ((P_XCB
)&os_rdy
, os_tsk
.run
);
170 os_tsk
.run
->state
= READY
;
171 rt_switch_req (p_new
);
176 /*--------------------------- rt_tsk_self -----------------------------------*/
178 OS_TID
rt_tsk_self (void) {
179 /* Return own task identifier value. */
180 if (os_tsk
.run
== NULL
) {
183 return (os_tsk
.run
->task_id
);
187 /*--------------------------- rt_tsk_prio -----------------------------------*/
189 OS_RESULT
rt_tsk_prio (OS_TID task_id
, U8 new_prio
) {
190 /* Change execution priority of a task to "new_prio". */
194 /* Change execution priority of calling task. */
195 os_tsk
.run
->prio
= new_prio
;
196 run
:if (rt_rdy_prio() > new_prio
) {
197 rt_put_prio (&os_rdy
, os_tsk
.run
);
198 os_tsk
.run
->state
= READY
;
204 /* Find the task in the "os_active_TCB" array. */
205 if (task_id
> os_maxtaskrun
|| os_active_TCB
[task_id
-1] == NULL
) {
206 /* Task with "task_id" not found or not started. */
209 p_task
= os_active_TCB
[task_id
-1];
210 p_task
->prio
= new_prio
;
211 if (p_task
== os_tsk
.run
) {
214 rt_resort_prio (p_task
);
215 if (p_task
->state
== READY
) {
216 /* Task enqueued in a ready list. */
217 p_task
= rt_get_first (&os_rdy
);
218 rt_dispatch (p_task
);
223 /*--------------------------- rt_tsk_delete ---------------------------------*/
225 OS_RESULT
rt_tsk_delete (OS_TID task_id
) {
226 /* Terminate the task identified with "task_id". */
229 if (task_id
== 0 || task_id
== os_tsk
.run
->task_id
) {
230 /* Terminate itself. */
231 os_tsk
.run
->state
= INACTIVE
;
232 os_tsk
.run
->tsk_stack
= rt_get_PSP ();
234 os_active_TCB
[os_tsk
.run
->task_id
-1] = NULL
;
236 os_tsk
.run
->stack
= NULL
;
237 DBG_TASK_NOTIFY(os_tsk
.run
, __FALSE
);
240 /* The program should never come to this point. */
243 /* Find the task in the "os_active_TCB" array. */
244 if (task_id
> os_maxtaskrun
|| os_active_TCB
[task_id
-1] == NULL
) {
245 /* Task with "task_id" not found or not started. */
248 task_context
= os_active_TCB
[task_id
-1];
249 rt_rmv_list (task_context
);
250 rt_rmv_dly (task_context
);
251 os_active_TCB
[task_id
-1] = NULL
;
253 task_context
->stack
= NULL
;
254 DBG_TASK_NOTIFY(task_context
, __FALSE
);
260 /*--------------------------- rt_sys_init -----------------------------------*/
263 void rt_sys_init (void) {
265 void rt_sys_init (FUNCP first_task
, U32 prio_stksz
, void *stk
) {
267 /* Initialize system and start up task declared with "first_task". */
272 /* Initialize dynamic memory and task TCB pointers to NULL. */
273 for (i
= 0; i
< os_maxtaskrun
; i
++) {
274 os_active_TCB
[i
] = NULL
;
277 /* Set up TCB of idle demon */
278 os_idle_TCB
.task_id
= 255;
279 os_idle_TCB
.priv_stack
= idle_task_stack_size
;
280 os_idle_TCB
.stack
= idle_task_stack
;
281 rt_init_context (&os_idle_TCB
, 0, os_idle_demon
);
283 /* Set up ready list: initially empty */
284 os_rdy
.cb_type
= HCB
;
286 /* Set up delay list: initially empty */
287 os_dly
.cb_type
= HCB
;
288 os_dly
.p_dlnk
= NULL
;
289 os_dly
.p_blnk
= NULL
;
290 os_dly
.delta_time
= 0;
292 /* Fix SP and systemvariables to assume idle task is running */
293 /* Transform main program into idle task by assuming idle TCB */
295 rt_set_PSP (os_idle_TCB
.tsk_stack
+32);
297 os_tsk
.run
= &os_idle_TCB
;
298 os_tsk
.run
->state
= RUNNING
;
300 /* Initialize ps queue */
303 os_psq
->size
= os_fifo_size
;
307 /* Intitialize SVC and PendSV */
311 /* Intitialize and start system clock timer */
312 os_tick_irqn
= os_tick_init ();
313 if (os_tick_irqn
>= 0) {
314 OS_X_INIT(os_tick_irqn
);
317 /* Start up first user task before entering the endless loop */
318 rt_tsk_create (first_task
, prio_stksz
, stk
, NULL
);
323 /*--------------------------- rt_sys_start ----------------------------------*/
326 void rt_sys_start (void) {
329 /* Intitialize and start system clock timer */
330 os_tick_irqn
= os_tick_init ();
331 if (os_tick_irqn
>= 0) {
332 OS_X_INIT(os_tick_irqn
);
337 /*----------------------------------------------------------------------------
339 *---------------------------------------------------------------------------*/