]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Demo/FreeRTOS_Plus_IoT_SDK/TaskPool/main.c
In small FreeRTOS applications it is unlikely there will be any task pools other...
[freertos] / FreeRTOS-Plus / Demo / FreeRTOS_Plus_IoT_SDK / TaskPool / main.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\r
3  * Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\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
11  *\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
14  *\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
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /* Kernel includes. */\r
29 #include "FreeRTOS.h"\r
30 #include "task.h"\r
31 \r
32 /* IoT SDK includes. */\r
33 #include "iot_taskpool.h"\r
34 \r
35 /*\r
36  * Prototypes for the functions that demonstrate the task pool API.\r
37  */\r
38 static void prvExample_BasicSingleJob( void );\r
39 static void prvExample_BasicRecyclableJob( void );\r
40 \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
43 \r
44 /*\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
47  */\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
54 \r
55 /*\r
56  * The task used to demonstrate the task pool API.\r
57  */\r
58 static void prvTaskPoolDemoTask( void *pvParameters );\r
59 \r
60 static const IotTaskPoolInfo_t xTaskPoolParameters = {\r
61                                                                                                                 /* Minimum number of threads in a task pool. */\r
62                                                                                                                 2,\r
63                                                                                                                 /* Maximum number of threads in a task pool. */\r
64                                                                                                                 2,\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
68                                                                                                                 tskIDLE_PRIORITY,\r
69                                                                                                          };\r
70 \r
71 /*-----------------------------------------------------------*/\r
72 \r
73 int main( void )\r
74 {\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
78                                  "PoolDemo",\r
79                                  configMINIMAL_STACK_SIZE,\r
80                                  NULL,\r
81                                  tskIDLE_PRIORITY,\r
82                                  NULL );\r
83 \r
84         vTaskStartScheduler();\r
85 \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
88         Daemon task. */\r
89         return 0;\r
90 }\r
91 /*-----------------------------------------------------------*/\r
92 \r
93 static void prvTaskPoolDemoTask( void *pvParameters )\r
94 {\r
95 IotTaskPoolError_t xResult;\r
96 \r
97         /* Remove compiler warnings about unused parameters. */\r
98         ( void ) pvParameters;\r
99 \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
103 \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
108 \r
109         for( ;; )\r
110         {\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
115 \r
116                 vTaskDelete( NULL );\r
117         }\r
118 }\r
119 /*-----------------------------------------------------------*/\r
120 \r
121 static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )\r
122 {\r
123 TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;\r
124 \r
125         /* Remove warnings about unused parameters. */\r
126         ( void ) pTaskPool;\r
127         ( void ) pJob;\r
128 \r
129         /* Notify the task that created this job. */\r
130         xTaskNotifyGive( xTaskToNotify );\r
131 }\r
132 /*-----------------------------------------------------------*/\r
133 \r
134 static void prvExample_BasicSingleJob( void )\r
135 {\r
136 IotTaskPoolJobStorage_t xJobStorage;\r
137 IotTaskPoolJob_t xJob;\r
138 IotTaskPoolError_t xResult;\r
139 uint32_t ulReturn;\r
140 const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );\r
141 \r
142         /* Ensure the notification count is 0 before scheduling the job. */\r
143         while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );\r
144 \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
151                                                                           &xJobStorage,\r
152                                                                           &xJob );\r
153         configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
154 \r
155         xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );\r
156         configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
157 \r
158         /* Wait for the notification coming from the job's callback function. */\r
159         ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );\r
160         configASSERT( ulReturn );\r
161 }\r
162 /*-----------------------------------------------------------*/\r
163 \r
164 static void prvExample_BasicRecyclableJob( void )\r
165 {\r
166 IotTaskPoolJob_t xJob;\r
167 IotTaskPoolError_t xResult;\r
168 uint32_t ulReturn;\r
169 const TickType_t xShortDelay = pdMS_TO_TICKS( 200 );\r
170 \r
171         /* Ensure the notification count is 0 before scheduling the job. */\r
172         while( ulTaskNotifyTake( pdTRUE, 0 ) != 0 );\r
173 \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
178         again. */\r
179         xResult = IotTaskPool_CreateRecyclableSystemJob(  prvSimpleTaskNotifyCallback,\r
180                                                                                                          ( void * ) xTaskGetCurrentTaskHandle(),\r
181                                                                                                          &xJob );\r
182         configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
183 \r
184         xResult = IotTaskPool_ScheduleSystemJob( xJob, 0 );\r
185         configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
186 \r
187         /* Wait for the notification coming from the job's callback function. */\r
188         ulReturn = ulTaskNotifyTake( pdTRUE, xShortDelay );\r
189         configASSERT( ulReturn );\r
190 }\r
191 /*-----------------------------------------------------------*/\r
192 \r
193 void vApplicationMallocFailedHook( void )\r
194 {\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
206         information. */\r
207         vAssertCalled( __LINE__, __FILE__ );\r
208 }\r
209 /*-----------------------------------------------------------*/\r
210 \r
211 void vApplicationIdleHook( void )\r
212 {\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
222 }\r
223 /*-----------------------------------------------------------*/\r
224 \r
225 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
226 {\r
227         ( void ) pcTaskName;\r
228         ( void ) pxTask;\r
229 \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
236 }\r
237 /*-----------------------------------------------------------*/\r
238 \r
239 void vApplicationTickHook( void )\r
240 {\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
246 }\r
247 /*-----------------------------------------------------------*/\r
248 \r
249 void vApplicationDaemonTaskStartupHook( void )\r
250 {\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
255 }\r
256 /*-----------------------------------------------------------*/\r
257 \r
258 void vAssertCalled( unsigned long ulLine, const char * const pcFileName )\r
259 {\r
260 volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;\r
261 \r
262         /* Called if an assertion passed to configASSERT() fails.  See\r
263         http://www.freertos.org/a00110.html#configASSERT for more information. */\r
264 \r
265         /* Parameters are not used. */\r
266         ( void ) ulLine;\r
267         ( void ) pcFileName;\r
268 \r
269 \r
270         taskENTER_CRITICAL();\r
271         {\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
274                 value. */\r
275                 while( ulSetToNonZeroInDebuggerToContinue == 0 )\r
276                 {\r
277                         __asm volatile( "NOP" );\r
278                         __asm volatile( "NOP" );\r
279                 }\r
280         }\r
281         taskEXIT_CRITICAL();\r
282 }\r
283 /*-----------------------------------------------------------*/\r
284 \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
289 {\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
295 \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
299 \r
300         /* Pass out the array that will be used as the Idle task's stack. */\r
301         *ppxIdleTaskStackBuffer = uxIdleTaskStack;\r
302 \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
307 }\r
308 /*-----------------------------------------------------------*/\r
309 \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
314 {\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
320 \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
324 \r
325         /* Pass out the array that will be used as the Timer task's stack. */\r
326         *ppxTimerTaskStackBuffer = uxTimerTaskStack;\r
327 \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
332 }\r
333 \r