]>
git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/rtos/rtx/TARGET_CORTEX_A/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"
36 #include "RTX_Config.h"
37 #include "rt_System.h"
40 #include "rt_MemBox.h"
43 #include "rt_HAL_CA.h"
45 #include "rt_HAL_CM.h"
48 /*----------------------------------------------------------------------------
50 *---------------------------------------------------------------------------*/
52 /* Running and next task info. */
55 /* Task Control Blocks of idle demon */
56 struct OS_TCB os_idle_TCB
;
59 /*----------------------------------------------------------------------------
61 *---------------------------------------------------------------------------*/
63 static OS_TID
rt_get_TID (void) {
66 for (tid
= 1; tid
<= os_maxtaskrun
; tid
++) {
67 if (os_active_TCB
[tid
-1] == NULL
) {
75 /*--------------------------- rt_init_context -------------------------------*/
77 static void rt_init_context (P_TCB p_TCB
, U8 priority
, FUNCP task_body
) {
78 /* Initialize general part of the Task Control Block. */
81 p_TCB
->prio
= priority
;
86 p_TCB
->delta_time
= 0;
87 p_TCB
->interval_time
= 0;
90 p_TCB
->stack_frame
= 0;
92 if (p_TCB
->priv_stack
== 0) {
93 /* Allocate the memory space for the stack. */
94 p_TCB
->stack
= rt_alloc_box (mp_stk
);
96 rt_init_stack (p_TCB
, task_body
);
100 /*--------------------------- rt_switch_req ---------------------------------*/
102 void rt_switch_req (P_TCB p_new
) {
103 /* Switch to next task (identified by "p_new"). */
105 p_new
->state
= RUNNING
;
106 DBG_TASK_SWITCH(p_new
->task_id
);
110 /*--------------------------- rt_dispatch -----------------------------------*/
112 void rt_dispatch (P_TCB next_TCB
) {
113 /* Dispatch next task if any identified or dispatch highest ready task */
114 /* "next_TCB" identifies a task to run or has value NULL (=no next task) */
115 if (next_TCB
== NULL
) {
116 /* Running task was blocked: continue with highest ready task */
117 next_TCB
= rt_get_first (&os_rdy
);
118 rt_switch_req (next_TCB
);
121 /* Check which task continues */
122 if (next_TCB
->prio
> os_tsk
.run
->prio
) {
123 /* preempt running task */
124 rt_put_rdy_first (os_tsk
.run
);
125 os_tsk
.run
->state
= READY
;
126 rt_switch_req (next_TCB
);
129 /* put next task into ready list, no task switch takes place */
130 next_TCB
->state
= READY
;
131 rt_put_prio (&os_rdy
, next_TCB
);
137 /*--------------------------- rt_block --------------------------------------*/
139 void rt_block (U16 timeout
, U8 block_state
) {
140 /* Block running task and choose next ready task. */
141 /* "timeout" sets a time-out value or is 0xffff (=no time-out). */
142 /* "block_state" defines the appropriate task state */
146 if (timeout
< 0xffff) {
147 rt_put_dly (os_tsk
.run
, timeout
);
149 os_tsk
.run
->state
= block_state
;
150 next_TCB
= rt_get_first (&os_rdy
);
151 rt_switch_req (next_TCB
);
156 /*--------------------------- rt_tsk_pass -----------------------------------*/
158 void rt_tsk_pass (void) {
159 /* Allow tasks of same priority level to run cooperatively.*/
162 p_new
= rt_get_same_rdy_prio();
164 rt_put_prio ((P_XCB
)&os_rdy
, os_tsk
.run
);
165 os_tsk
.run
->state
= READY
;
166 rt_switch_req (p_new
);
171 /*--------------------------- rt_tsk_self -----------------------------------*/
173 OS_TID
rt_tsk_self (void) {
174 /* Return own task identifier value. */
175 if (os_tsk
.run
== NULL
) {
178 return (os_tsk
.run
->task_id
);
182 /*--------------------------- rt_tsk_prio -----------------------------------*/
184 OS_RESULT
rt_tsk_prio (OS_TID task_id
, U8 new_prio
) {
185 /* Change execution priority of a task to "new_prio". */
189 /* Change execution priority of calling task. */
190 os_tsk
.run
->prio
= new_prio
;
191 run
:if (rt_rdy_prio() > new_prio
) {
192 rt_put_prio (&os_rdy
, os_tsk
.run
);
193 os_tsk
.run
->state
= READY
;
199 /* Find the task in the "os_active_TCB" array. */
200 if (task_id
> os_maxtaskrun
|| os_active_TCB
[task_id
-1] == NULL
) {
201 /* Task with "task_id" not found or not started. */
204 p_task
= os_active_TCB
[task_id
-1];
205 p_task
->prio
= new_prio
;
206 if (p_task
== os_tsk
.run
) {
209 rt_resort_prio (p_task
);
210 if (p_task
->state
== READY
) {
211 /* Task enqueued in a ready list. */
212 p_task
= rt_get_first (&os_rdy
);
213 rt_dispatch (p_task
);
219 /*--------------------------- rt_tsk_create ---------------------------------*/
221 OS_TID
rt_tsk_create (FUNCP task
, U32 prio_stksz
, void *stk
, void *argv
) {
222 /* Start a new task declared with "task". */
226 /* Priority 0 is reserved for idle task! */
227 if ((prio_stksz
& 0xFF) == 0) {
230 task_context
= rt_alloc_box (mp_tcb
);
231 if (task_context
== NULL
) {
234 /* If "size != 0" use a private user provided stack. */
235 task_context
->stack
= stk
;
236 task_context
->priv_stack
= prio_stksz
>> 8;
237 /* Pass parameter 'argv' to 'rt_init_context' */
238 task_context
->msg
= argv
;
239 /* For 'size == 0' system allocates the user stack from the memory pool. */
240 rt_init_context (task_context
, prio_stksz
& 0xFF, task
);
242 /* Find a free entry in 'os_active_TCB' table. */
244 os_active_TCB
[i
-1] = task_context
;
245 task_context
->task_id
= i
;
246 DBG_TASK_NOTIFY(task_context
, __TRUE
);
247 rt_dispatch (task_context
);
252 /*--------------------------- rt_tsk_delete ---------------------------------*/
254 OS_RESULT
rt_tsk_delete (OS_TID task_id
) {
255 /* Terminate the task identified with "task_id". */
258 if (task_id
== 0 || task_id
== os_tsk
.run
->task_id
) {
259 /* Terminate itself. */
260 os_tsk
.run
->state
= INACTIVE
;
261 os_tsk
.run
->tsk_stack
= rt_get_PSP ();
263 os_active_TCB
[os_tsk
.run
->task_id
-1] = NULL
;
264 rt_free_box (mp_stk
, os_tsk
.run
->stack
);
265 os_tsk
.run
->stack
= NULL
;
266 DBG_TASK_NOTIFY(os_tsk
.run
, __FALSE
);
267 rt_free_box (mp_tcb
, os_tsk
.run
);
270 /* The program should never come to this point. */
273 /* Find the task in the "os_active_TCB" array. */
274 if (task_id
> os_maxtaskrun
|| os_active_TCB
[task_id
-1] == NULL
) {
275 /* Task with "task_id" not found or not started. */
278 task_context
= os_active_TCB
[task_id
-1];
279 rt_rmv_list (task_context
);
280 rt_rmv_dly (task_context
);
281 os_active_TCB
[task_id
-1] = NULL
;
282 rt_free_box (mp_stk
, task_context
->stack
);
283 task_context
->stack
= NULL
;
284 DBG_TASK_NOTIFY(task_context
, __FALSE
);
285 rt_free_box (mp_tcb
, task_context
);
291 /*--------------------------- rt_sys_init -----------------------------------*/
294 void rt_sys_init (void) {
296 void rt_sys_init (FUNCP first_task
, U32 prio_stksz
, void *stk
) {
298 /* Initialize system and start up task declared with "first_task". */
303 /* Initialize dynamic memory and task TCB pointers to NULL. */
304 for (i
= 0; i
< os_maxtaskrun
; i
++) {
305 os_active_TCB
[i
] = NULL
;
307 rt_init_box (&mp_tcb
, mp_tcb_size
, sizeof(struct OS_TCB
));
308 rt_init_box (&mp_stk
, mp_stk_size
, BOX_ALIGN_8
| (U16
)(os_stackinfo
));
309 rt_init_box ((U32
*)m_tmr
, mp_tmr_size
, sizeof(struct OS_TMR
));
311 /* Set up TCB of idle demon */
312 os_idle_TCB
.task_id
= 255;
313 os_idle_TCB
.priv_stack
= 0;
314 rt_init_context (&os_idle_TCB
, 0, os_idle_demon
);
316 /* Set up ready list: initially empty */
317 os_rdy
.cb_type
= HCB
;
319 /* Set up delay list: initially empty */
320 os_dly
.cb_type
= HCB
;
321 os_dly
.p_dlnk
= NULL
;
322 os_dly
.p_blnk
= NULL
;
323 os_dly
.delta_time
= 0;
325 /* Fix SP and system variables to assume idle task is running */
326 /* Transform main program into idle task by assuming idle TCB */
328 rt_set_PSP (os_idle_TCB
.tsk_stack
+32);
330 os_tsk
.run
= &os_idle_TCB
;
331 os_tsk
.run
->state
= RUNNING
;
333 /* Initialize ps queue */
336 os_psq
->size
= os_fifo_size
;
340 /* Initialize SVC and PendSV */
344 /* Initialize and start system clock timer */
345 os_tick_irqn
= os_tick_init ();
346 if (os_tick_irqn
>= 0) {
347 OS_X_INIT(os_tick_irqn
);
350 /* Start up first user task before entering the endless loop */
351 rt_tsk_create (first_task
, prio_stksz
, stk
, NULL
);
356 /*--------------------------- rt_sys_start ----------------------------------*/
359 void rt_sys_start (void) {
362 /* Initialize and start system clock timer */
363 os_tick_irqn
= os_tick_init ();
364 if (os_tick_irqn
>= 0) {
365 OS_X_INIT(os_tick_irqn
);
370 /*----------------------------------------------------------------------------
372 *---------------------------------------------------------------------------*/