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.
rt_Task.c
00001 /** 00002 * @file rt_Task.c 00003 * @brief 00004 * 00005 * DAPLink Interface Firmware 00006 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved 00007 * SPDX-License-Identifier: Apache-2.0 00008 * 00009 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00010 * not use this file except in compliance with the License. 00011 * You may obtain a copy of the License at 00012 * 00013 * http://www.apache.org/licenses/LICENSE-2.0 00014 * 00015 * Unless required by applicable law or agreed to in writing, software 00016 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00017 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00018 * See the License for the specific language governing permissions and 00019 * limitations under the License. 00020 */ 00021 00022 #include "rt_TypeDef.h" 00023 #include "RTX_Config.h" 00024 #include "rt_System.h" 00025 #include "rt_Task.h" 00026 #include "rt_List.h" 00027 #include "rt_MemBox.h" 00028 #include "rt_Robin.h" 00029 #include "rt_HAL_CM.h" 00030 00031 /*---------------------------------------------------------------------------- 00032 * Global Variables 00033 *---------------------------------------------------------------------------*/ 00034 00035 /* Running and next task info. */ 00036 struct OS_TSK os_tsk; 00037 00038 /* Task Control Blocks of idle demon */ 00039 struct OS_TCB os_idle_TCB; 00040 00041 00042 /*---------------------------------------------------------------------------- 00043 * Local Functions 00044 *---------------------------------------------------------------------------*/ 00045 00046 static OS_TID rt_get_TID (void) { 00047 U32 tid; 00048 00049 for (tid = 1; tid <= os_maxtaskrun; tid++) { 00050 if (os_active_TCB[tid-1] == NULL) { 00051 return ((OS_TID)tid); 00052 } 00053 } 00054 return (0); 00055 } 00056 00057 00058 /*--------------------------- rt_init_context -------------------------------*/ 00059 00060 static void rt_init_context (P_TCB p_TCB, U8 priority, FUNCP task_body) { 00061 /* Initialize general part of the Task Control Block. */ 00062 p_TCB->cb_type = TCB; 00063 p_TCB->state = READY; 00064 p_TCB->prio = priority; 00065 p_TCB->p_lnk = NULL; 00066 p_TCB->p_rlnk = NULL; 00067 p_TCB->p_dlnk = NULL; 00068 p_TCB->p_blnk = NULL; 00069 p_TCB->delta_time = 0; 00070 p_TCB->interval_time = 0; 00071 p_TCB->events = 0; 00072 p_TCB->waits = 0; 00073 p_TCB->ret_val = OS_R_OK; 00074 p_TCB->ret_upd = 0; 00075 00076 if (p_TCB->priv_stack == 0) { 00077 /* Allocate the memory space for the stack. */ 00078 p_TCB->stack = rt_alloc_box (mp_stk); 00079 } 00080 rt_init_stack (p_TCB, task_body); 00081 } 00082 00083 00084 /*--------------------------- rt_switch_req ---------------------------------*/ 00085 00086 void rt_switch_req (P_TCB p_new) { 00087 /* Switch to next task (identified by "p_new"). */ 00088 os_tsk.new = p_new; 00089 p_new->state = RUNNING; 00090 DBG_TASK_SWITCH(p_new->task_id); 00091 } 00092 00093 00094 /*--------------------------- rt_dispatch -----------------------------------*/ 00095 00096 void rt_dispatch (P_TCB next_TCB) { 00097 /* Dispatch next task if any identified or dispatch highest ready task */ 00098 /* "next_TCB" identifies a task to run or has value NULL (=no next task) */ 00099 if (next_TCB == NULL) { 00100 /* Running task was blocked: continue with highest ready task */ 00101 next_TCB = rt_get_first (&os_rdy); 00102 rt_switch_req (next_TCB); 00103 } 00104 else { 00105 /* Check which task continues */ 00106 if (next_TCB->prio > os_tsk.run->prio) { 00107 /* preempt running task */ 00108 rt_put_rdy_first (os_tsk.run); 00109 os_tsk.run->state = READY; 00110 rt_switch_req (next_TCB); 00111 } 00112 else { 00113 /* put next task into ready list, no task switch takes place */ 00114 next_TCB->state = READY; 00115 rt_put_prio (&os_rdy, next_TCB); 00116 } 00117 } 00118 } 00119 00120 00121 /*--------------------------- rt_block --------------------------------------*/ 00122 00123 void rt_block (U16 timeout, U8 block_state) { 00124 /* Block running task and choose next ready task. */ 00125 /* "timeout" sets a time-out value or is 0xffff (=no time-out). */ 00126 /* "block_state" defines the appropriate task state */ 00127 P_TCB next_TCB; 00128 00129 if (timeout) { 00130 if (timeout < 0xffff) { 00131 rt_put_dly (os_tsk.run, timeout); 00132 } 00133 os_tsk.run->state = block_state; 00134 next_TCB = rt_get_first (&os_rdy); 00135 rt_switch_req (next_TCB); 00136 } 00137 } 00138 00139 00140 /*--------------------------- rt_tsk_pass -----------------------------------*/ 00141 00142 void rt_tsk_pass (void) { 00143 /* Allow tasks of same priority level to run cooperatively.*/ 00144 P_TCB p_new; 00145 00146 p_new = rt_get_same_rdy_prio(); 00147 if (p_new != NULL) { 00148 rt_put_prio ((P_XCB)&os_rdy, os_tsk.run); 00149 os_tsk.run->state = READY; 00150 rt_switch_req (p_new); 00151 } 00152 } 00153 00154 00155 /*--------------------------- rt_tsk_self -----------------------------------*/ 00156 00157 OS_TID rt_tsk_self (void) { 00158 /* Return own task identifier value. */ 00159 if (os_tsk.run == NULL) { 00160 return (0); 00161 } 00162 return (os_tsk.run->task_id); 00163 } 00164 00165 00166 /*--------------------------- rt_tsk_prio -----------------------------------*/ 00167 00168 OS_RESULT rt_tsk_prio (OS_TID task_id, U8 new_prio) { 00169 /* Change execution priority of a task to "new_prio". */ 00170 P_TCB p_task; 00171 00172 if (task_id == 0) { 00173 /* Change execution priority of calling task. */ 00174 os_tsk.run->prio = new_prio; 00175 run:if (rt_rdy_prio() > new_prio) { 00176 rt_put_prio (&os_rdy, os_tsk.run); 00177 os_tsk.run->state = READY; 00178 os_tsk.run->ret_val = OS_R_OK; 00179 rt_dispatch (NULL); 00180 } 00181 return (OS_R_OK); 00182 } 00183 00184 /* Find the task in the "os_active_TCB" array. */ 00185 if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) { 00186 /* Task with "task_id" not found or not started. */ 00187 return (OS_R_NOK); 00188 } 00189 p_task = os_active_TCB[task_id-1]; 00190 p_task->prio = new_prio; 00191 if (p_task == os_tsk.run) { 00192 goto run; 00193 } 00194 rt_resort_prio (p_task); 00195 if (p_task->state == READY) { 00196 /* Task enqueued in a ready list. */ 00197 p_task = rt_get_first (&os_rdy); 00198 os_tsk.run->ret_val = OS_R_OK; 00199 rt_dispatch (p_task); 00200 } 00201 return (OS_R_OK); 00202 } 00203 00204 00205 /*--------------------------- rt_tsk_create ---------------------------------*/ 00206 00207 OS_TID rt_tsk_create (FUNCP task, U32 prio_stksz, void *stk, void *argv) { 00208 /* Start a new task declared with "task". */ 00209 P_TCB task_context; 00210 U32 i; 00211 00212 /* Priority 0 is reserved for idle task! */ 00213 if ((prio_stksz & 0xFF) == 0) { 00214 prio_stksz += 1; 00215 } 00216 task_context = rt_alloc_box (mp_tcb); 00217 if (task_context == NULL) { 00218 return (0); 00219 } 00220 /* If "size != 0" use a private user provided stack. */ 00221 task_context->stack = stk; 00222 task_context->priv_stack = prio_stksz >> 8; 00223 /* Pass parameter 'argv' to 'rt_init_context' */ 00224 task_context->msg = argv; 00225 /* For 'size == 0' system allocates the user stack from the memory pool. */ 00226 rt_init_context (task_context, prio_stksz & 0xFF, task); 00227 00228 /* Find a free entry in 'os_active_TCB' table. */ 00229 i = rt_get_TID (); 00230 os_active_TCB[i-1] = task_context; 00231 task_context->task_id = i; 00232 DBG_TASK_NOTIFY(task_context, __TRUE); 00233 rt_dispatch (task_context); 00234 os_tsk.run->ret_val = i; 00235 return ((OS_TID)i); 00236 } 00237 00238 00239 /*--------------------------- rt_tsk_delete ---------------------------------*/ 00240 00241 OS_RESULT rt_tsk_delete (OS_TID task_id) { 00242 /* Terminate the task identified with "task_id". */ 00243 P_TCB task_context; 00244 00245 if (task_id == 0 || task_id == os_tsk.run->task_id) { 00246 /* Terminate itself. */ 00247 os_tsk.run->state = INACTIVE; 00248 os_tsk.run->tsk_stack = rt_get_PSP (); 00249 rt_stk_check (); 00250 os_active_TCB[os_tsk.run->task_id-1] = NULL; 00251 rt_free_box (mp_stk, os_tsk.run->stack); 00252 os_tsk.run->stack = NULL; 00253 DBG_TASK_NOTIFY(os_tsk.run, __FALSE); 00254 rt_free_box (mp_tcb, os_tsk.run); 00255 os_tsk.run = NULL; 00256 rt_dispatch (NULL); 00257 /* The program should never come to this point. */ 00258 } 00259 else { 00260 /* Find the task in the "os_active_TCB" array. */ 00261 if (task_id > os_maxtaskrun || os_active_TCB[task_id-1] == NULL) { 00262 /* Task with "task_id" not found or not started. */ 00263 return (OS_R_NOK); 00264 } 00265 task_context = os_active_TCB[task_id-1]; 00266 rt_rmv_list (task_context); 00267 rt_rmv_dly (task_context); 00268 os_active_TCB[task_id-1] = NULL; 00269 rt_free_box (mp_stk, task_context->stack); 00270 task_context->stack = NULL; 00271 DBG_TASK_NOTIFY(task_context, __FALSE); 00272 rt_free_box (mp_tcb, task_context); 00273 } 00274 return (OS_R_OK); 00275 } 00276 00277 00278 /*--------------------------- rt_sys_init -----------------------------------*/ 00279 00280 void rt_sys_init (FUNCP first_task, U32 prio_stksz, void *stk) { 00281 /* Initialize system and start up task declared with "first_task". */ 00282 U32 i; 00283 00284 DBG_INIT(); 00285 00286 /* Initialize dynamic memory and task TCB pointers to NULL. */ 00287 for (i = 0; i < os_maxtaskrun; i++) { 00288 os_active_TCB[i] = NULL; 00289 } 00290 rt_init_box (&mp_tcb, mp_tcb_size, sizeof(struct OS_TCB)); 00291 rt_init_box (&mp_stk, mp_stk_size, BOX_ALIGN_8 | (U16)(os_stackinfo)); 00292 rt_init_box ((U32 *)m_tmr, mp_tmr_size, sizeof(struct OS_TMR)); 00293 00294 /* Set up TCB of idle demon */ 00295 os_idle_TCB.task_id = 255; 00296 os_idle_TCB.priv_stack = 0; 00297 rt_init_context (&os_idle_TCB, 0, os_idle_demon); 00298 00299 /* Set up ready list: initially empty */ 00300 os_rdy.cb_type = HCB; 00301 os_rdy.p_lnk = NULL; 00302 /* Set up delay list: initially empty */ 00303 os_dly.cb_type = HCB; 00304 os_dly.p_dlnk = NULL; 00305 os_dly.p_blnk = NULL; 00306 os_dly.delta_time = 0; 00307 00308 /* Fix SP and systemvariables to assume idle task is running */ 00309 /* Transform main program into idle task by assuming idle TCB */ 00310 rt_set_PSP (os_idle_TCB.tsk_stack+32); 00311 os_tsk.run = &os_idle_TCB; 00312 os_tsk.run->state = RUNNING; 00313 00314 /* Initialize ps queue */ 00315 os_psq->first = 0; 00316 os_psq->last = 0; 00317 os_psq->size = os_fifo_size; 00318 00319 rt_init_robin (); 00320 00321 /* Intitialize SVC and PendSV */ 00322 rt_svc_init (); 00323 00324 /* Intitialize system clock timer */ 00325 os_tick_irqn = os_tick_init (); 00326 if (os_tick_irqn >= 0) { 00327 OS_X_INIT(os_tick_irqn); 00328 } 00329 00330 /* Start up first user task before entering the endless loop */ 00331 rt_tsk_create (first_task, prio_stksz, stk, NULL); 00332 } 00333 00334 /*---------------------------------------------------------------------------- 00335 * end of file 00336 *---------------------------------------------------------------------------*/
Generated on Tue Jul 12 2022 15:37:22 by
