Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-rtos by
rt_Task.c
00001 /*---------------------------------------------------------------------------- 00002 * RL-ARM - RTX 00003 *---------------------------------------------------------------------------- 00004 * Name: RT_TASK.C 00005 * Purpose: Task functions and system start up. 00006 * Rev.: V4.60 00007 *---------------------------------------------------------------------------- 00008 * 00009 * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH 00010 * All rights reserved. 00011 * Redistribution and use in source and binary forms, with or without 00012 * modification, are permitted provided that the following conditions are met: 00013 * - Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * - Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * - Neither the name of ARM nor the names of its contributors may be used 00019 * to endorse or promote products derived from this software without 00020 * specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 00026 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00027 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00028 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00031 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *---------------------------------------------------------------------------*/ 00034 00035 #include "rt_TypeDef.h" 00036 #include "RTX_Conf.h" 00037 #include "rt_System.h" 00038 #include "rt_Task.h" 00039 #include "rt_List.h" 00040 #include "rt_MemBox.h" 00041 #include "rt_Robin.h" 00042 #include "rt_HAL_CM.h" 00043 00044 /*---------------------------------------------------------------------------- 00045 * Global Variables 00046 *---------------------------------------------------------------------------*/ 00047 00048 /* Running and next task info. */ 00049 struct OS_TSK os_tsk; 00050 00051 /* Task Control Blocks of idle demon */ 00052 struct OS_TCB os_idle_TCB; 00053 00054 00055 /*---------------------------------------------------------------------------- 00056 * Local Functions 00057 *---------------------------------------------------------------------------*/ 00058 00059 OS_TID rt_get_TID (void) { 00060 U32 tid; 00061 00062 for (tid = 1; tid <= os_maxtaskrun; tid++) { 00063 if (os_active_TCB[tid-1] == NULL) { 00064 return ((OS_TID)tid); 00065 } 00066 } 00067 return (0); 00068 } 00069 00070 #if defined (__CC_ARM) && !defined (__MICROLIB) 00071 /*--------------------------- __user_perthread_libspace ---------------------*/ 00072 extern void *__libspace_start; 00073 00074 void *__user_perthread_libspace (void) { 00075 /* Provide a separate libspace for each task. */ 00076 if (os_tsk.run == NULL) { 00077 /* RTX not running yet. */ 00078 return (&__libspace_start); 00079 } 00080 return (void *)(os_tsk.run->std_libspace); 00081 } 00082 #endif 00083 00084 /*--------------------------- rt_init_context -------------------------------*/ 00085 00086 void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) { 00087 /* Initialize general part of the Task Control Block. */ 00088 p_TCB->cb_type = TCB; 00089 p_TCB->state = READY; 00090 p_TCB->prio = priority; 00091 p_TCB->p_lnk = NULL; 00092 p_TCB->p_rlnk = NULL; 00093 p_TCB->p_dlnk = NULL; 00094 p_TCB->p_blnk = NULL; 00095 p_TCB->delta_time = 0; 00096 p_TCB->interval_time = 0; 00097 p_TCB->events = 0; 00098 p_TCB->waits = 0; 00099 p_TCB->stack_frame = 0; 00100 00101 rt_init_stack (p_TCB, task_body); 00102 } 00103 00104 00105 /*--------------------------- rt_switch_req ---------------------------------*/ 00106 00107 void rt_switch_req (P_TCB p_new) { 00108 /* Switch to next task (identified by "p_new"). */ 00109 os_tsk.new_tsk = p_new; 00110 p_new->state = RUNNING; 00111 DBG_TASK_SWITCH(p_new->task_id); 00112 } 00113 00114 00115 /*--------------------------- rt_dispatch -----------------------------------*/ 00116 00117 void rt_dispatch (P_TCB next_TCB) { 00118 /* Dispatch next task if any identified or dispatch highest ready task */ 00119 /* "next_TCB" identifies a task to run or has value NULL (=no next task) */ 00120 if (next_TCB == NULL) { 00121 /* Running task was blocked: continue with highest ready task */ 00122 next_TCB = rt_get_first (&os_rdy); 00123 rt_switch_req (next_TCB); 00124 } 00125 else { 00126 /* Check which task continues */ 00127 if (next_TCB->prio > os_tsk.run->prio) { 00128 /* preempt running task */ 00129 rt_put_rdy_first (os_tsk.run); 00130 os_tsk.run->state = READY; 00131 rt_switch_req (next_TCB); 00132 } 00133 else { 00134 /* put next task into ready list, no task switch takes place */ 00135 next_TCB->state = READY; 00136 rt_put_prio (&os_rdy, next_TCB); 00137 } 00138 } 00139 } 00140 00141 00142 /*--------------------------- rt_block --------------------------------------*/ 00143 00144 void rt_block (U16 timeout, U8 block_state) { 00145 /* Block running task and choose next ready task. */ 00146 /* "timeout" sets a time-out value or is 0xffff (=no time-out). */ 00147 /* "block_state" defines the appropriate task state */ 00148 P_TCB next_TCB; 00149 00150 if (timeout) { 00151 if (timeout < 0xffff) { 00152 rt_put_dly (os_tsk.run, timeout); 00153 } 00154 os_tsk.run->state = block_state; 00155 next_TCB = rt_get_first (&os_rdy); 00156 rt_switch_req (next_TCB); 00157 } 00158 } 00159 00160 00161 /*--------------------------- rt_tsk_pass -----------------------------------*/ 00162 00163 void rt_tsk_pass (void) { 00164 /* Allow tasks of same priority level to run cooperatively.*/ 00165 P_TCB p_new; 00166 00167 p_new = rt_get_same_rdy_prio(); 00168 if (p_new != NULL) { 00169 rt_put_prio ((P_XCB)&os_rdy, os_tsk.run); 00170 os_tsk.run->state = READY; 00171 rt_switch_req (p_new); 00172 } 00173 } 00174 00175 00176 /*--------------------------- rt_tsk_self -----------------------------------*/ 00177 00178 OS_TID rt_tsk_self (void) { 00179 /* Return own task identifier value. */ 00180 if (os_tsk.run == NULL) { 00181 return (0); 00182 } 00183 return (os_tsk.run->task_id); 00184 } 00185 00186 00187 /*--------------------------- rt_tsk_prio -----------------------------------*/ 00188 00189 OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) { 00190 /* Change execution priority of a task to "new_prio". */ 00191 P_TCB p_task; 00192 00193 if (task_id == 0) { 00194 /* Change execution priority of calling task. */ 00195 os_tsk.run->prio = new_prio; 00196 run:if (rt_rdy_prio() > new_prio) { 00197 rt_put_prio (&os_rdy, os_tsk.run); 00198 os_tsk.run->state = READY; 00199 rt_dispatch (NULL); 00200 } 00201 return (OS_R_OK); 00202 } 00203 00204 /* Find the task in the "os_active_TCB" array. */ 00205 if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) { 00206 /* Task with "task_id" not found or not started. */ 00207 return (OS_R_NOK); 00208 } 00209 p_task = os_active_TCB[task_id-1]; 00210 p_task->prio = new_prio; 00211 if (p_task == os_tsk.run) { 00212 goto run; 00213 } 00214 rt_resort_prio (p_task); 00215 if (p_task->state == READY) { 00216 /* Task enqueued in a ready list. */ 00217 p_task = rt_get_first (&os_rdy); 00218 rt_dispatch (p_task); 00219 } 00220 return (OS_R_OK); 00221 } 00222 00223 /*--------------------------- rt_tsk_delete ---------------------------------*/ 00224 00225 OS_RESULT rt_tsk_delete (OS_TID task_id) { 00226 /* Terminate the task identified with "task_id". */ 00227 P_TCB task_context; 00228 00229 if (task_id == 0 || task_id == os_tsk.run->task_id) { 00230 /* Terminate itself. */ 00231 os_tsk.run->state = INACTIVE; 00232 os_tsk.run->tsk_stack = rt_get_PSP (); 00233 rt_stk_check (); 00234 os_active_TCB[os_tsk.run->task_id-1] = NULL; 00235 00236 os_tsk.run->stack = NULL; 00237 DBG_TASK_NOTIFY(os_tsk.run, __FALSE); 00238 os_tsk.run = NULL; 00239 rt_dispatch (NULL); 00240 /* The program should never come to this point. */ 00241 } 00242 else { 00243 /* Find the task in the "os_active_TCB" array. */ 00244 if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) { 00245 /* Task with "task_id" not found or not started. */ 00246 return (OS_R_NOK); 00247 } 00248 task_context = os_active_TCB[task_id-1]; 00249 rt_rmv_list (task_context); 00250 rt_rmv_dly (task_context); 00251 os_active_TCB[task_id-1] = NULL; 00252 00253 task_context->stack = NULL; 00254 DBG_TASK_NOTIFY(task_context, __FALSE); 00255 } 00256 return (OS_R_OK); 00257 } 00258 00259 00260 /*--------------------------- rt_sys_init -----------------------------------*/ 00261 00262 #ifdef __CMSIS_RTOS 00263 void rt_sys_init (void) { 00264 #else 00265 void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk) { 00266 #endif 00267 /* Initialize system and start up task declared with "first_task". */ 00268 U32 i; 00269 00270 DBG_INIT(); 00271 00272 /* Initialize dynamic memory and task TCB pointers to NULL. */ 00273 for (i = 0; i < os_maxtaskrun; i++) { 00274 os_active_TCB[i] = NULL; 00275 } 00276 00277 /* Set up TCB of idle demon */ 00278 os_idle_TCB.task_id = 255; 00279 os_idle_TCB.priv_stack = idle_task_stack_size; 00280 os_idle_TCB.stack = idle_task_stack; 00281 rt_init_context (&os_idle_TCB, 0, os_idle_demon); 00282 00283 /* Set up ready list: initially empty */ 00284 os_rdy.cb_type = HCB; 00285 os_rdy.p_lnk = NULL; 00286 /* Set up delay list: initially empty */ 00287 os_dly.cb_type = HCB; 00288 os_dly.p_dlnk = NULL; 00289 os_dly.p_blnk = NULL; 00290 os_dly.delta_time = 0; 00291 00292 /* Fix SP and systemvariables to assume idle task is running */ 00293 /* Transform main program into idle task by assuming idle TCB */ 00294 #ifndef __CMSIS_RTOS 00295 rt_set_PSP (os_idle_TCB.tsk_stack+32); 00296 #endif 00297 os_tsk.run = &os_idle_TCB; 00298 os_tsk.run->state = RUNNING; 00299 00300 /* Initialize ps queue */ 00301 os_psq->first = 0; 00302 os_psq->last = 0; 00303 os_psq->size = os_fifo_size; 00304 00305 rt_init_robin (); 00306 00307 /* Intitialize SVC and PendSV */ 00308 rt_svc_init (); 00309 00310 #ifndef __CMSIS_RTOS 00311 /* Intitialize and start system clock timer */ 00312 os_tick_irqn = os_tick_init (); 00313 if (os_tick_irqn >= 0) { 00314 OS_X_INIT(os_tick_irqn); 00315 } 00316 00317 /* Start up first user task before entering the endless loop */ 00318 rt_tsk_create (first_task, prio_stksz, stk, NULL); 00319 #endif 00320 } 00321 00322 00323 /*--------------------------- rt_sys_start ----------------------------------*/ 00324 00325 #ifdef __CMSIS_RTOS 00326 void rt_sys_start (void) { 00327 /* Start system */ 00328 00329 /* Intitialize and start system clock timer */ 00330 os_tick_irqn = os_tick_init (); 00331 if (os_tick_irqn >= 0) { 00332 OS_X_INIT(os_tick_irqn); 00333 } 00334 } 00335 #endif 00336 00337 /*---------------------------------------------------------------------------- 00338 * end of file 00339 *---------------------------------------------------------------------------*/
Generated on Wed Jul 13 2022 18:32:39 by
