]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/utilities/task_pool/DemoTasks/SimpleTaskPoolExamples.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_IoT_Libraries / utilities / task_pool / DemoTasks / SimpleTaskPoolExamples.c
diff --git a/FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/utilities/task_pool/DemoTasks/SimpleTaskPoolExamples.c b/FreeRTOS-Labs/Demo/FreeRTOS_IoT_Libraries/utilities/task_pool/DemoTasks/SimpleTaskPoolExamples.c
new file mode 100644 (file)
index 0000000..3c8fa06
--- /dev/null
@@ -0,0 +1,306 @@
+/*\r
+ * FreeRTOS Kernel V10.2.1\r
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
+ * this software and associated documentation files (the "Software"), to deal in\r
+ * the Software without restriction, including without limitation the rights to\r
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
+ * the Software, and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ *\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
+ *\r
+ * 1 tab == 4 spaces!\r
+ */\r
+\r
+\r
+/* Kernel includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* Standard includes. */\r
+#include <stdio.h>\r
+\r
+/* IoT SDK includes. */\r
+#include "iot_taskpool_freertos.h"\r
+\r
+/* Demo includes. */\r
+#include "demo_config.h"\r
+\r
+/* The priority at which that tasks in the task pool (the worker tasks) get\r
+created. */\r
+#define tpTASK_POOL_WORKER_PRIORITY            1\r
+\r
+/*\r
+ * Prototypes for the functions that demonstrate the task pool API.\r
+ * See the implementation of the prvTaskPoolDemoTask() function within this file\r
+ * for a description of the individual functions.  A configASSERT() is hit if\r
+ * any of the demos encounter any unexpected behavior.\r
+ */\r
+static void prvExample_BasicSingleJob( void );\r
+static void prvExample_DeferredJobAndCancellingJobs( void );\r
+\r
+/*\r
+ * Prototypes of the callback functions used in the examples.  The callback\r
+ * simply sends a signal (in the form of a direct task notification) to the\r
+ * prvTaskPoolDemoTask() task to let the task know that the callback execute.\r
+ * The handle of the prvTaskPoolDemoTask() task is not accessed directly, but\r
+ * instead passed into the task pool job as the job's context.\r
+ */\r
+static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext );\r
+\r
+/*\r
+ * The task used to demonstrate the task pool API.  This task just loops through\r
+ * each demo in turn.\r
+ */\r
+static void prvTaskPoolDemoTask( void *pvParameters );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Parameters used to create the system task pool - see TBD for more information\r
+ * as the task pool used in this example is a slimmed down version of the full\r
+ * library - the slimmed down version being intended specifically for FreeRTOS\r
+ * kernel use cases. */\r
+static const IotTaskPoolInfo_t xTaskPoolParameters = {\r
+                                                                                                               /* minThreads:\r
+                                                                                                                * Minimum number of threads in a task pool.\r
+                                                                                                                * Note the slimmed down version of the task\r
+                                                                                                                * pool used by this library does not auto-scale\r
+                                                                                                                * the number of tasks in the pool so in this\r
+                                                                                                                * case this sets the number of tasks in the\r
+                                                                                                                * pool. */\r
+                                                                                                               IOT_TASKPOOL_NUMBER_OF_WORKERS,\r
+                                                                                                               /* maxThreads:\r
+                                                                                                                * Maximum number of threads in a task pool.\r
+                                                                                                                * Note the slimmed down version of the task\r
+                                                                                                                * pool used by this library does not auto-scale\r
+                                                                                                                * the number of tasks in the pool so in this\r
+                                                                                                                * case this parameter must match minThreads. */\r
+                                                                                                               IOT_TASKPOOL_NUMBER_OF_WORKERS,\r
+                                                                                                               /* Stack size for every task pool thread - in\r
+                                                                                                                * bytes, hence multiplying by the number of bytes\r
+                                                                                                                * in a word as configMINIMAL_STACK_SIZE is\r
+                                                                                                                * specified in words. */\r
+                                                                                                               configMINIMAL_STACK_SIZE * sizeof( portSTACK_TYPE ),\r
+                                                                                                               /* Priority for every task pool thread. */\r
+                                                                                                               tpTASK_POOL_WORKER_PRIORITY,\r
+                                                                                                        };\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+void vStartSimpleTaskPoolDemo( void )\r
+{\r
+       /* This example uses a single application task, which in turn is used to\r
+        * create and send jobs to task pool tasks. */\r
+       xTaskCreate( prvTaskPoolDemoTask,               /* Function that implements the task. */\r
+                                "PoolDemo",                            /* Text name for the task - only used for debugging. */\r
+                                democonfigDEMO_STACKSIZE,      /* Size of stack (in words, not bytes) to allocate for the task. */\r
+                                NULL,                                          /* Task parameter - not used in this case. */\r
+                                tskIDLE_PRIORITY,                      /* Task priority, must be between 0 and configMAX_PRIORITIES - 1. */\r
+                                NULL );                                        /* Used to pass out a handle to the created task - not used in this case. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvTaskPoolDemoTask( void *pvParameters )\r
+{\r
+IotTaskPoolError_t xResult;\r
+uint32_t ulLoops = 0;\r
+\r
+       /* Remove compiler warnings about unused parameters. */\r
+       ( void ) pvParameters;\r
+\r
+       configPRINTF( ( "---------STARTING DEMO---------\r\n" ) );\r
+\r
+       /* The task pool must be created before it can be used.  The system task\r
+        * pool is the task pool managed by the task pool library itself - the storage\r
+        * used by the task pool is provided by the library. */\r
+       xResult = IotTaskPool_CreateSystemTaskPool( &xTaskPoolParameters );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       for( ;; )\r
+       {\r
+               /* Demonstrate the most basic use case where a non persistent job is\r
+                * created and scheduled to run immediately.  The task pool worker tasks\r
+                * (in which the job callback function executes) have a priority above the\r
+                * priority of this task so the job's callback executes as soon as it is\r
+                * scheduled. */\r
+               prvExample_BasicSingleJob();\r
+\r
+               /* Demonstrate a job being scheduled to run at some time in the\r
+                * future, and how a job scheduled to run in the future can be canceled\r
+                * if it has not yet started executing.  */\r
+               prvExample_DeferredJobAndCancellingJobs();\r
+\r
+               ulLoops++;\r
+               if( ( ulLoops % 10UL ) == 0 )\r
+               {\r
+                       configPRINTF( ( "prvTaskPoolDemoTask() performed %u iterations successfully.\r\n", ulLoops ) );\r
+                       configPRINTF( ( "Demo completed successfully.\r\n" ) );\r
+                       fflush( stdout );\r
+               }\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSimpleTaskNotifyCallback( IotTaskPool_t pTaskPool, IotTaskPoolJob_t pJob, void *pUserContext )\r
+{\r
+/* The jobs context is the handle of the task to which a notification should\r
+ * be sent. */\r
+TaskHandle_t xTaskToNotify = ( TaskHandle_t ) pUserContext;\r
+\r
+       /* Remove warnings about unused parameters. */\r
+       ( void ) pTaskPool;\r
+       ( void ) pJob;\r
+\r
+       /* Notify the task that created this job. */\r
+       xTaskNotifyGive( xTaskToNotify );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_BasicSingleJob( void )\r
+{\r
+IotTaskPoolJobStorage_t xJobStorage;\r
+IotTaskPoolJob_t xJob;\r
+IotTaskPoolError_t xResult;\r
+uint32_t ulReturn;\r
+const uint32_t ulNoFlags = 0UL;\r
+const TickType_t xNoDelay = ( TickType_t ) 0;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+IotTaskPoolJobStatus_t xJobStatus;\r
+\r
+       /* Direct to task notifications are used to communicate between worker tasks\r
+       and this task.  Don't expect any notifications to be pending before commencing. */\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+       /* Create and schedule a job using the handle of this task as the job's\r
+        * context and the function that sends a notification to the task handle as\r
+        * the job's callback function.  This is not a recyclable job so the storage\r
+        * required to hold information about the job is provided by this task - in\r
+        * this case the storage is on the stack of this task so no memory is allocated\r
+        * dynamically but the stack frame must remain in scope for the lifetime of\r
+        * the job. */\r
+       xResult = IotTaskPool_CreateJob(  prvSimpleTaskNotifyCallback, /* Callback function. */\r
+                                                                         ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
+                                                                         &xJobStorage,\r
+                                                                         &xJob );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The job has been created but not scheduled so is now ready. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+\r
+       /* This is not a persistent (recyclable) job and its storage is on the\r
+        * stack of this function, so the amount of heap space available should not\r
+        * have changed since entering this function. */\r
+       configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
+\r
+       /* In the full task pool implementation the first parameter is used to\r
+        * pass the handle of the task pool to schedule.  The lean task pool\r
+        * implementation used in this demo only supports a single task pool, which\r
+        * is created internally within the library, so the first parameter is NULL. */\r
+       xResult = IotTaskPool_Schedule( NULL, xJob, ulNoFlags );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* Look for the notification coming from the job's callback function.  The\r
+        * priority of the task pool worker task that executes the callback is higher\r
+        * than the priority of this task so a block time is not needed - the task pool\r
+        * worker task preempts this task and sends the notification (from the job's\r
+        * callback) as soon as the job is scheduled. */\r
+       ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
+       configASSERT( ulReturn );\r
+\r
+       /* The job's callback has executed so the job has now completed. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_COMPLETED );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvExample_DeferredJobAndCancellingJobs( void )\r
+{\r
+IotTaskPoolJobStorage_t xJobStorage;\r
+IotTaskPoolJob_t xJob;\r
+IotTaskPoolError_t xResult;\r
+uint32_t ulReturn;\r
+const uint32_t ulShortDelay_ms = 100UL;\r
+const TickType_t xNoDelay = ( TickType_t ) 0, xAllowableMargin = ( TickType_t ) 5; /* Large margin for Windows port, which is not real time. */\r
+TickType_t xTimeBefore, xElapsedTime, xShortDelay_ticks;\r
+size_t xFreeHeapBeforeCreatingJob = xPortGetFreeHeapSize();\r
+IotTaskPoolJobStatus_t xJobStatus;\r
+\r
+       /* Don't expect any notifications to be pending yet. */\r
+       configASSERT( ulTaskNotifyTake( pdTRUE, xNoDelay ) == 0 );\r
+\r
+       /* Create a job using the handle of this task as the job's context and the\r
+        * function that sends a notification to the task handle as the job's callback\r
+        * function.  The job is created using storage allocated on the stack of this\r
+        * function - so no memory is allocated. */\r
+       xResult = IotTaskPool_CreateJob(  prvSimpleTaskNotifyCallback, /* Callback function. */\r
+                                                                         ( void * ) xTaskGetCurrentTaskHandle(), /* Job context. */\r
+                                                                         &xJobStorage,\r
+                                                                         &xJob );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The job has been created but not scheduled so is now ready. */\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_READY );\r
+\r
+       /* This is not a persistent (recyclable) job and its storage is on the\r
+        * stack of this function, so the amount of heap space available should not\r
+        * have changed since entering this function. */\r
+       configASSERT( xFreeHeapBeforeCreatingJob == xPortGetFreeHeapSize() );\r
+\r
+       /* Schedule the job to run its callback in ulShortDelay_ms milliseconds time.\r
+        * In the full task pool implementation the first parameter is used to  pass the\r
+        * handle of the task pool to schedule.  The lean task pool implementation used\r
+        * in this demo only supports a single task pool, which is created internally\r
+        * within the library, so the first parameter is NULL. */\r
+       xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* The scheduled job should not have executed yet, so don't expect any\r
+        * notifications and expect the job's status to be 'deferred'. */\r
+       ulReturn = ulTaskNotifyTake( pdTRUE, xNoDelay );\r
+       configASSERT( ulReturn == 0 );\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_DEFERRED );\r
+\r
+       /* As the job has not yet been executed it can be canceled. */\r
+       xResult = IotTaskPool_TryCancel( NULL, xJob, &xJobStatus );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+       IotTaskPool_GetStatus( NULL, xJob, &xJobStatus );\r
+       configASSERT( xJobStatus == IOT_TASKPOOL_STATUS_CANCELED );\r
+\r
+       /* Schedule the job again, and this time wait until its callback is\r
+        * executed (the callback function sends a notification to this task) to see\r
+        * that it executes at the right time. */\r
+       xTimeBefore = xTaskGetTickCount();\r
+       xResult = IotTaskPool_ScheduleDeferred( NULL, xJob, ulShortDelay_ms );\r
+       configASSERT( xResult == IOT_TASKPOOL_SUCCESS );\r
+\r
+       /* Wait twice the deferred execution time to ensure the callback is executed\r
+        * before the call below times out. */\r
+       ulReturn = ulTaskNotifyTake( pdTRUE, pdMS_TO_TICKS( ulShortDelay_ms * 2UL ) );\r
+       xElapsedTime = xTaskGetTickCount() - xTimeBefore;\r
+\r
+       /* A single notification should have been received... */\r
+       configASSERT( ulReturn == 1 );\r
+\r
+       /* ...and the time since scheduling the job should be greater than or\r
+        * equal to the deferred execution time - which is converted to ticks for\r
+        * comparison. */\r
+       xShortDelay_ticks = pdMS_TO_TICKS( ulShortDelay_ms );\r
+       configASSERT( ( xElapsedTime >= xShortDelay_ticks ) && ( xElapsedTime  < ( xShortDelay_ticks + xAllowableMargin ) ) );\r
+}\r
+/*-----------------------------------------------------------*/\r