00001 /* 00002 FreeRTOS V6.0.0 - Copyright (C) 2009 Real Time Engineers Ltd. 00003 00004 *************************************************************************** 00005 * * 00006 * If you are: * 00007 * * 00008 * + New to FreeRTOS, * 00009 * + Wanting to learn FreeRTOS or multitasking in general quickly * 00010 * + Looking for basic training, * 00011 * + Wanting to improve your FreeRTOS skills and productivity * 00012 * * 00013 * then take a look at the FreeRTOS eBook * 00014 * * 00015 * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * 00016 * http://www.FreeRTOS.org/Documentation * 00017 * * 00018 * A pdf reference manual is also available. Both are usually delivered * 00019 * to your inbox within 20 minutes to two hours when purchased between 8am * 00020 * and 8pm GMT (although please allow up to 24 hours in case of * 00021 * exceptional circumstances). Thank you for your support! * 00022 * * 00023 *************************************************************************** 00024 00025 This file is part of the FreeRTOS distribution. 00026 00027 FreeRTOS is free software; you can redistribute it and/or modify it under 00028 the terms of the GNU General Public License (version 2) as published by the 00029 Free Software Foundation AND MODIFIED BY the FreeRTOS exception. 00030 ***NOTE*** The exception to the GPL is included to allow you to distribute 00031 a combined work that includes FreeRTOS without being obliged to provide the 00032 source code for proprietary components outside of the FreeRTOS kernel. 00033 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT 00034 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00035 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 00036 more details. You should have received a copy of the GNU General Public 00037 License and the FreeRTOS license exception along with FreeRTOS; if not it 00038 can be viewed here: http://www.freertos.org/a00114.html and also obtained 00039 by writing to Richard Barry, contact details for whom are available on the 00040 FreeRTOS WEB site. 00041 00042 1 tab == 4 spaces! 00043 00044 http://www.FreeRTOS.org - Documentation, latest information, license and 00045 contact details. 00046 00047 http://www.SafeRTOS.com - A version that is certified for use in safety 00048 critical systems. 00049 00050 http://www.OpenRTOS.com - Commercial support, development, porting, 00051 licensing and training services. 00052 */ 00053 00073 /* 00074 Changes from V3.0.0 00075 + CreationCount sizes changed from unsigned portBASE_TYPE to 00076 unsigned short to minimize the risk of overflowing. 00077 00078 + Reset of usLastCreationCount added 00079 00080 Changes from V3.1.0 00081 + Changed the dummy calculation to use variables of type long, rather than 00082 float. This allows the file to be used with ports that do not support 00083 floating point. 00084 00085 */ 00086 00087 #include <stdlib.h> 00088 00089 /* Scheduler include files. */ 00090 #include "FreeRTOS.h" 00091 #include "task.h" 00092 00093 /* Demo program include files. */ 00094 #include "death.h" 00095 00096 #define deathSTACK_SIZE ( configMINIMAL_STACK_SIZE + 60 ) 00097 00098 /* The task originally created which is responsible for periodically dynamically 00099 creating another four tasks. */ 00100 static portTASK_FUNCTION_PROTO( vCreateTasks, pvParameters ); 00101 00102 /* The task function of the dynamically created tasks. */ 00103 static portTASK_FUNCTION_PROTO( vSuicidalTask, pvParameters ); 00104 00105 /* A variable which is incremented every time the dynamic tasks are created. This 00106 is used to check that the task is still running. */ 00107 static volatile unsigned short usCreationCount = 0; 00108 00109 /* Used to store the number of tasks that were originally running so the creator 00110 task can tell if any of the suicidal tasks have failed to die. 00111 */ 00112 static volatile unsigned portBASE_TYPE uxTasksRunningAtStart = 0; 00113 00114 /* Tasks are deleted by the idle task. Under heavy load the idle task might 00115 not get much processing time, so it would be legitimate for several tasks to 00116 remain undeleted for a short period. */ 00117 static const unsigned portBASE_TYPE uxMaxNumberOfExtraTasksRunning = 2; 00118 00119 /* Used to store a handle to the task that should be killed by a suicidal task, 00120 before it kills itself. */ 00121 xTaskHandle xCreatedTask; 00122 00123 /*-----------------------------------------------------------*/ 00124 00125 void vCreateSuicidalTasks( unsigned portBASE_TYPE uxPriority ) 00126 { 00127 unsigned portBASE_TYPE *puxPriority; 00128 00129 /* Create the Creator tasks - passing in as a parameter the priority at which 00130 the suicidal tasks should be created. */ 00131 puxPriority = ( unsigned portBASE_TYPE * ) pvPortMalloc( sizeof( unsigned portBASE_TYPE ) ); 00132 *puxPriority = uxPriority; 00133 00134 xTaskCreate( vCreateTasks, ( signed char * ) "CREATOR", deathSTACK_SIZE, ( void * ) puxPriority, uxPriority, NULL ); 00135 00136 /* Record the number of tasks that are running now so we know if any of the 00137 suicidal tasks have failed to be killed. */ 00138 uxTasksRunningAtStart = ( unsigned portBASE_TYPE ) uxTaskGetNumberOfTasks(); 00139 00140 /* FreeRTOS.org versions before V3.0 started the idle-task as the very 00141 first task. The idle task was then already included in uxTasksRunningAtStart. 00142 From FreeRTOS V3.0 on, the idle task is started when the scheduler is 00143 started. Therefore the idle task is not yet accounted for. We correct 00144 this by increasing uxTasksRunningAtStart by 1. */ 00145 uxTasksRunningAtStart++; 00146 } 00147 /*-----------------------------------------------------------*/ 00148 00149 static portTASK_FUNCTION( vSuicidalTask, pvParameters ) 00150 { 00151 volatile long l1, l2; 00152 xTaskHandle xTaskToKill; 00153 const portTickType xDelay = ( portTickType ) 200 / portTICK_RATE_MS; 00154 00155 if( pvParameters != NULL ) 00156 { 00157 /* This task is periodically created four times. Two created tasks are 00158 passed a handle to the other task so it can kill it before killing itself. 00159 The other task is passed in null. */ 00160 xTaskToKill = *( xTaskHandle* )pvParameters; 00161 } 00162 else 00163 { 00164 xTaskToKill = NULL; 00165 } 00166 00167 for( ;; ) 00168 { 00169 /* Do something random just to use some stack and registers. */ 00170 l1 = 2; 00171 l2 = 89; 00172 l2 *= l1; 00173 vTaskDelay( xDelay ); 00174 00175 if( xTaskToKill != NULL ) 00176 { 00177 /* Make sure the other task has a go before we delete it. */ 00178 vTaskDelay( ( portTickType ) 0 ); 00179 00180 /* Kill the other task that was created by vCreateTasks(). */ 00181 vTaskDelete( xTaskToKill ); 00182 00183 /* Kill ourselves. */ 00184 vTaskDelete( NULL ); 00185 } 00186 } 00187 }/*lint !e818 !e550 Function prototype must be as per standard for task functions. */ 00188 /*-----------------------------------------------------------*/ 00189 00190 static portTASK_FUNCTION( vCreateTasks, pvParameters ) 00191 { 00192 const portTickType xDelay = ( portTickType ) 1000 / portTICK_RATE_MS; 00193 unsigned portBASE_TYPE uxPriority; 00194 00195 uxPriority = *( unsigned portBASE_TYPE * ) pvParameters; 00196 vPortFree( pvParameters ); 00197 00198 for( ;; ) 00199 { 00200 /* Just loop round, delaying then creating the four suicidal tasks. */ 00201 vTaskDelay( xDelay ); 00202 00203 xCreatedTask = NULL; 00204 00205 xTaskCreate( vSuicidalTask, ( signed char * ) "SUICID1", configMINIMAL_STACK_SIZE, NULL, uxPriority, &xCreatedTask ); 00206 xTaskCreate( vSuicidalTask, ( signed char * ) "SUICID2", configMINIMAL_STACK_SIZE, &xCreatedTask, uxPriority, NULL ); 00207 00208 ++usCreationCount; 00209 } 00210 } 00211 /*-----------------------------------------------------------*/ 00212 00213 /* This is called to check that the creator task is still running and that there 00214 are not any more than four extra tasks. */ 00215 portBASE_TYPE xIsCreateTaskStillRunning( void ) 00216 { 00217 static unsigned short usLastCreationCount = 0xfff; 00218 portBASE_TYPE xReturn = pdTRUE; 00219 static unsigned portBASE_TYPE uxTasksRunningNow; 00220 00221 if( usLastCreationCount == usCreationCount ) 00222 { 00223 xReturn = pdFALSE; 00224 } 00225 else 00226 { 00227 usLastCreationCount = usCreationCount; 00228 } 00229 00230 uxTasksRunningNow = ( unsigned portBASE_TYPE ) uxTaskGetNumberOfTasks(); 00231 00232 if( uxTasksRunningNow < uxTasksRunningAtStart ) 00233 { 00234 xReturn = pdFALSE; 00235 } 00236 else if( ( uxTasksRunningNow - uxTasksRunningAtStart ) > uxMaxNumberOfExtraTasksRunning ) 00237 { 00238 xReturn = pdFALSE; 00239 } 00240 else 00241 { 00242 /* Everything is okay. */ 00243 } 00244 00245 return xReturn; 00246 } 00247 00248