2 * FreeRTOS Kernel V10.2.1
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://www.FreeRTOS.org
\r
23 * http://aws.amazon.com/freertos
\r
25 * 1 tab == 4 spaces!
\r
28 /* Kernel includes. */
\r
29 #include "FreeRTOS.h"
\r
32 /* IoT SDK includes. */
\r
33 #include "iot_taskpool.h"
\r
36 * Prototypes for the functions that demonstrate the task pool API.
\r
38 static void prvExample_BasicSingleJob( void );
\r
39 static void prvExample_BasicRecyclableJob( void );
\r
41 /* Prototypes of the callback functions used in the examples. */
\r
42 static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext );
\r
45 * Prototypes for the standard FreeRTOS application hook (callback) functions
\r
46 * implemented within this file. See http://www.freertos.org/a00016.html .
\r
48 void vApplicationMallocFailedHook( void );
\r
49 void vApplicationIdleHook( void );
\r
50 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
\r
51 void vApplicationTickHook( void );
\r
52 void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );
\r
53 void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );
\r
56 * The task used to demonstrate the task pool API.
\r
58 static void prvTaskPoolDemoTask( void *pvParameters );
\r
60 static const IotTaskPoolInfo_t xTaskPoolParameters = {
\r
61 /* Minimum number of threads in a task pool. */
\r
63 /* Maximum number of threads in a task pool. */
\r
65 /* Stack size for every task pool thread - in words, not bytes. */
\r
66 configMINIMAL_STACK_SIZE,
\r
67 /* Priority for every task pool thread. */
\r
71 /*-----------------------------------------------------------*/
\r
75 /* This example uses a single application task, which in turn is used to
\r
76 create and send jobs to task pool tasks. */
\r
77 xTaskCreate( prvTaskPoolDemoTask,
\r
79 configMINIMAL_STACK_SIZE,
\r
84 vTaskStartScheduler();
\r
86 /* Should not reach here as vTaskStartScheduler() will only return if there
\r
87 was insufficient FreeRTOS heap memory to create the Idle or Timer
\r
91 /*-----------------------------------------------------------*/
\r
93 static void prvTaskPoolDemoTask( void *pvParameters )
\r
95 IotTaskPoolError_t xResult;
\r
97 /* Remove compiler warnings about unused parameters. */
\r
98 ( void ) pvParameters;
\r
100 /* The task pool must be created before it can be used. */
\r
101 // xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );
\r
102 // configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
104 /* Attempting to create the task pool again should then appear to succeed
\r
105 (in case it is initialised by more than one library), but have no effect. */
\r
106 // xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );
\r
107 // configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
111 /* Run through each task pool example in turn. See the comments in the
\r
112 below functions for details of their behaviour. */
\r
113 prvExample_BasicSingleJob();
\r
114 prvExample_BasicRecyclableJob();
\r
116 vTaskDelete( NULL );
\r
119 /*-----------------------------------------------------------*/
\r
121 static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )
\r
123 TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;
\r
125 /* Remove warnings about unused parameters. */
\r
126 ( void ) pTaskPool;
\r
129 /* Notify the task that created this job. */
\r
130 xTaskNotifyGive( xTaskToNotify );
\r
132 /*-----------------------------------------------------------*/
\r
134 static void prvExample_BasicSingleJob( void )
\r
136 IotTaskPoolJobStorage_t xJobStorage;
\r
137 IotTaskPoolJob_t xJob;
\r
138 IotTaskPoolError_t xResult;
\r
140 const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );
\r
142 /* Ensure the notification count is 0 before scheduling the job. */
\r
143 while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );
\r
145 /* Create and schedule a job using the handle of this task as the job's
\r
146 context and the function that sends a notification to the task handle as
\r
147 the jobs callback function. The job is created using storage allocated on
\r
148 the stack of this function - so no memory is allocated. */
\r
149 xResult = IotTaskPool_CreateJob( prvSimpleTaskNotifyCallback, /* Callback function. */
\r
150 ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */
\r
153 configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
155 xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );
\r
156 configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
158 /* Wait for the notification coming from the job's callback function. */
\r
159 ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );
\r
160 configASSERT( ulReturn );
\r
162 /*-----------------------------------------------------------*/
\r
164 static void prvExample_BasicRecyclableJob( void )
\r
166 IotTaskPoolJob_t xJob;
\r
167 IotTaskPoolError_t xResult;
\r
169 const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );
\r
171 /* Ensure the notification count is 0 before scheduling the job. */
\r
172 while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );
\r
174 /* Create and schedule a job using the handle of this task as the job's
\r
175 context and the function that sends a notification to the task handle as
\r
176 the jobs callback function. The job is created as a recyclable job - so it
\r
177 is allocated inside the create function, but can then be used again and
\r
179 xResult = IotTaskPool_CreateRecyclableSystemJob( prvSimpleTaskNotifyCallback,
\r
180 ( void * ) xTaskGetCurrentTaskHandle(),
\r
182 configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
184 xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );
\r
185 configASSERT( xResult == IOT_TASKPOOL_SUCCESS );
\r
187 /* Wait for the notification coming from the job's callback function. */
\r
188 ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );
\r
189 configASSERT( ulReturn );
\r
191 /*-----------------------------------------------------------*/
\r
193 void vApplicationMallocFailedHook( void )
\r
195 /* vApplicationMallocFailedHook() will only be called if
\r
196 configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
\r
197 function that will get called if a call to pvPortMalloc() fails.
\r
198 pvPortMalloc() is called internally by the kernel whenever a task, queue,
\r
199 timer or semaphore is created. It is also called by various parts of the
\r
200 demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the
\r
201 size of the heap available to pvPortMalloc() is defined by
\r
202 configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize()
\r
203 API function can be used to query the size of free heap space that remains
\r
204 (although it does not provide information on how the remaining heap might be
\r
205 fragmented). See http://www.freertos.org/a00111.html for more
\r
207 vAssertCalled( __LINE__, __FILE__ );
\r
209 /*-----------------------------------------------------------*/
\r
211 void vApplicationIdleHook( void )
\r
213 /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
\r
214 to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
\r
215 task. It is essential that code added to this hook function never attempts
\r
216 to block in any way (for example, call xQueueReceive() with a block time
\r
217 specified, or call vTaskDelay()). If application tasks make use of the
\r
218 vTaskDelete() API function to delete themselves then it is also important
\r
219 that vApplicationIdleHook() is permitted to return to its calling function,
\r
220 because it is the responsibility of the idle task to clean up memory
\r
221 allocated by the kernel to any task that has since deleted itself. */
\r
223 /*-----------------------------------------------------------*/
\r
225 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
\r
227 ( void ) pcTaskName;
\r
230 /* Run time stack overflow checking is performed if
\r
231 configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
\r
232 function is called if a stack overflow is detected. This function is
\r
233 provided as an example only as stack overflow checking does not function
\r
234 when running the FreeRTOS Windows port. */
\r
235 vAssertCalled( __LINE__, __FILE__ );
\r
237 /*-----------------------------------------------------------*/
\r
239 void vApplicationTickHook( void )
\r
241 /* This function will be called by each tick interrupt if
\r
242 configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be
\r
243 added here, but the tick hook is called from an interrupt context, so
\r
244 code must not attempt to block, and only the interrupt safe FreeRTOS API
\r
245 functions can be used (those that end in FromISR()). */
\r
247 /*-----------------------------------------------------------*/
\r
249 void vApplicationDaemonTaskStartupHook( void )
\r
251 /* This function will be called once only, when the daemon task starts to
\r
252 execute (sometimes called the timer task). This is useful if the
\r
253 application includes initialisation code that would benefit from executing
\r
254 after the scheduler has been started. */
\r
256 /*-----------------------------------------------------------*/
\r
258 void vAssertCalled( unsigned long ulLine, const char * const pcFileName )
\r
260 volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;
\r
262 /* Called if an assertion passed to configASSERT() fails. See
\r
263 http://www.freertos.org/a00110.html#configASSERT for more information. */
\r
265 /* Parameters are not used. */
\r
267 ( void ) pcFileName;
\r
270 taskENTER_CRITICAL();
\r
272 /* You can step out of this function to debug the assertion by using
\r
273 the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero
\r
275 while( ulSetToNonZeroInDebuggerToContinue == 0 )
\r
277 __asm volatile( "NOP" );
\r
278 __asm volatile( "NOP" );
\r
281 taskEXIT_CRITICAL();
\r
283 /*-----------------------------------------------------------*/
\r
285 /* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an
\r
286 implementation of vApplicationGetIdleTaskMemory() to provide the memory that is
\r
287 used by the Idle task. */
\r
288 void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )
\r
290 /* If the buffers to be provided to the Idle task are declared inside this
\r
291 function then they must be declared static - otherwise they will be allocated on
\r
292 the stack and so not exists after this function exits. */
\r
293 static StaticTask_t xIdleTaskTCB;
\r
294 static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];
\r
296 /* Pass out a pointer to the StaticTask_t structure in which the Idle task's
\r
297 state will be stored. */
\r
298 *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
\r
300 /* Pass out the array that will be used as the Idle task's stack. */
\r
301 *ppxIdleTaskStackBuffer = uxIdleTaskStack;
\r
303 /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.
\r
304 Note that, as the array is necessarily of type StackType_t,
\r
305 configMINIMAL_STACK_SIZE is specified in words, not bytes. */
\r
306 *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
\r
308 /*-----------------------------------------------------------*/
\r
310 /* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the
\r
311 application must provide an implementation of vApplicationGetTimerTaskMemory()
\r
312 to provide the memory that is used by the Timer service task. */
\r
313 void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )
\r
315 /* If the buffers to be provided to the Timer task are declared inside this
\r
316 function then they must be declared static - otherwise they will be allocated on
\r
317 the stack and so not exists after this function exits. */
\r
318 static StaticTask_t xTimerTaskTCB;
\r
319 static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];
\r
321 /* Pass out a pointer to the StaticTask_t structure in which the Timer
\r
322 task's state will be stored. */
\r
323 *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;
\r
325 /* Pass out the array that will be used as the Timer task's stack. */
\r
326 *ppxTimerTaskStackBuffer = uxTimerTaskStack;
\r
328 /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.
\r
329 Note that, as the array is necessarily of type StackType_t,
\r
330 configMINIMAL_STACK_SIZE is specified in words, not bytes. */
\r
331 *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
\r