/* * FreeRTOS V202212.00 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * https://www.FreeRTOS.org * https://github.com/FreeRTOS * */ /* ******************************************************************************* * This project provides two demo applications. A simple blinky style project, * and a more comprehensive test and demo application. The * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY * in main.c. This file implements the comprehensive test and demo version. * * This file only contains the source code that is specific to the full demo. * Generic functions, such FreeRTOS hook functions, are defined in main.c. ******************************************************************************* * * main() creates all the demo application tasks, then starts the scheduler. * The web documentation provides more details of the standard demo application * tasks, which provide no particular functionality but do provide a good * example of how to use the FreeRTOS API. * * In addition to the standard demo tasks, the following tasks and tests are * defined and/or created within this file: * * "Check" task - This only executes every five (simulated) seconds. Its main * function is to check the tests running in the standard demo tasks have never * failed and that all the tasks are still running. If that is the case the * check task prints "PASS : nnnn (x)", where nnnn is the current tick count and * x is the number of times the interrupt nesting test executed while interrupts * were nested. If the check task discovers a failed test or a stalled task * it prints a message that indicates which task reported the error or stalled. * Normally the check task would have the highest priority to keep its timing * jitter to a minimum. In this case the check task is run at the idle priority * to ensure other tasks are not stalled by it writing to a slow UART using a * polling driver. * */ /* Standard includes. */ #include #include /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" /* Demo app includes. */ #include "death.h" #include "blocktim.h" #include "semtest.h" #include "PollQ.h" #include "GenQTest.h" #include "QPeek.h" #include "recmutex.h" #include "QueueSet.h" #include "EventGroupsDemo.h" #include "MessageBufferDemo.h" #include "StreamBufferDemo.h" #include "AbortDelay.h" #include "countsem.h" #include "dynamic.h" #include "MessageBufferAMP.h" #include "QueueOverwrite.h" #include "QueueSetPolling.h" #include "StaticAllocation.h" #include "TaskNotify.h" #include "TaskNotifyArray.h" #include "TimerDemo.h" #include "StreamBufferInterrupt.h" #include "IntSemTest.h" /*-----------------------------------------------------------*/ /* Task priorities. */ #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) /* Stack sizes are defined relative to configMINIMAL_STACK_SIZE so they scale * across projects that have that constant set differently - in this case the * constant is different depending on the compiler in use. */ #define mainMESSAGE_BUFFER_STACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) ) #define mainCHECK_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE + ( configMINIMAL_STACK_SIZE >> 1 ) ) #define mainREG_TEST_STACK_SIZE_WORDS 90 /* Parameters that are passed into the register check tasks solely for the * purpose of ensuring parameters are passed into tasks correctly. */ #define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 ) #define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 ) /*-----------------------------------------------------------*/ /* * Register check tasks as described at the top of this file. The nature of * these files necessitates that they are written in an assembly file, but the * entry points are kept in the C file for the convenience of checking the task * parameter. */ static void prvRegTestTaskEntry1( void * pvParameters ); extern void vRegTest1Implementation( void ); static void prvRegTestTaskEntry2( void * pvParameters ); extern void vRegTest2Implementation( void ); /* The task that checks the operation of all the other standard demo tasks, as * described at the top of this file. */ static void prvCheckTask( void * pvParameters ); /*-----------------------------------------------------------*/ /* The following two variables are used to communicate the status of the * register check tasks to the check task. If the variables keep incrementing, * then the register check tasks have not discovered any errors. If a variable * stops incrementing, then an error has been found. */ uint32_t ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL; volatile uint32_t * pulRegTest1LoopCounter = &ulRegTest1LoopCounter; volatile uint32_t * pulRegTest2LoopCounter = &ulRegTest2LoopCounter; /*-----------------------------------------------------------*/ void main_full( void ) { /* Start the standard demo tasks. */ vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY ); vStartRecursiveMutexTasks(); vCreateBlockTimeTasks(); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); vStartQueuePeekTasks(); vStartQueueSetTasks(); vStartEventGroupTasks(); vStartMessageBufferTasks( mainMESSAGE_BUFFER_STACK_SIZE ); vStartStreamBufferTasks(); vCreateAbortDelayTasks(); vStartCountingSemaphoreTasks(); vStartDynamicPriorityTasks(); vStartMessageBufferAMPTasks( configMINIMAL_STACK_SIZE ); vStartQueueOverwriteTask( tskIDLE_PRIORITY ); vStartQueueSetPollingTask(); vStartStaticallyAllocatedTasks(); vStartTaskNotifyTask(); vStartTaskNotifyArrayTask(); vStartTimerDemoTask( 50 ); vStartStreamBufferInterruptDemo(); vStartInterruptSemaphoreTasks(); /* Create the register check tasks, as described at the top of this file. * Use xTaskCreateStatic() to create a task using only statically allocated * memory. */ xTaskCreate( prvRegTestTaskEntry1, /* The function that implements the task. */ "Reg1", /* The name of the task. */ mainREG_TEST_STACK_SIZE_WORDS, /* Size of stack to allocate for the task - in words not bytes!. */ mainREG_TEST_TASK_1_PARAMETER, /* Parameter passed into the task. */ tskIDLE_PRIORITY, /* Priority of the task. */ NULL ); /* Can be used to pass out a handle to the created task. */ xTaskCreate( prvRegTestTaskEntry2, "Reg2", mainREG_TEST_STACK_SIZE_WORDS, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL ); /* The suicide tasks must be created last as they need to know how many * tasks were running prior to their creation in order to ascertain whether * or not the correct/expected number of tasks are running at any given time. */ vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); xTaskCreate( prvCheckTask, "Check", mainCHECK_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); /* Start the scheduler. */ vTaskStartScheduler(); /* If configSUPPORT_STATIC_ALLOCATION was false then execution would only * get here if there was insufficient heap memory to create either the idle or * timer tasks. As static allocation is used execution should never be able * to reach here. */ for( ; ; ) { } } /*-----------------------------------------------------------*/ static void prvRegTestTaskEntry1( void * pvParameters ) { /* Although the regtest task is written in assembler, its entry point is * written in C for convenience of checking the task parameter is being passed * in correctly. */ if( pvParameters == mainREG_TEST_TASK_1_PARAMETER ) { /* Start the part of the test that is written in assembler. */ vRegTest1Implementation(); } /* The following line will only execute if the task parameter is found to * be incorrect. The check task will detect that the regtest loop counter is * not being incremented and flag an error. */ vTaskDelete( NULL ); } /*-----------------------------------------------------------*/ static void prvRegTestTaskEntry2( void * pvParameters ) { /* Although the regtest task is written in assembler, its entry point is * written in C for convenience of checking the task parameter is being passed * in correctly. */ if( pvParameters == mainREG_TEST_TASK_2_PARAMETER ) { /* Start the part of the test that is written in assembler. */ vRegTest2Implementation(); } /* The following line will only execute if the task parameter is found to * be incorrect. The check task will detect that the regtest loop counter is * not being incremented and flag an error. */ vTaskDelete( NULL ); } /*-----------------------------------------------------------*/ /* See the comments at the top of this file. */ static void prvCheckTask( void * pvParameters ) { static const char * pcMessage = "FreeRTOS Demo SUCCESS:"; const TickType_t xTaskPeriod = pdMS_TO_TICKS( 5000UL ); TickType_t xPreviousWakeTime; uint32_t ulLastRegTest1Value = 0, ulLastRegTest2Value = 0; /* Avoid warning about unused parameter. */ ( void ) pvParameters; /* Demo start marker. */ printf( "FreeRTOS Demo Start\r\n" ); xPreviousWakeTime = xTaskGetTickCount(); for( ; ; ) { vTaskDelayUntil( &xPreviousWakeTime, xTaskPeriod ); /* Has an error been found in any task? */ if( xAreStreamBufferTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreStreamBufferTasksStillRunning() returned false"; } else if( xAreMessageBufferTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreMessageBufferTasksStillRunning() returned false"; } if( xAreGenericQueueTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreGenericQueueTasksStillRunning() returned false"; } else if( xIsCreateTaskStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xIsCreateTaskStillRunning() returned false"; } else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreBlockTimeTestTasksStillRunning() returned false"; } else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreSemaphoreTasksStillRunning() returned false"; } else if( xArePollingQueuesStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xArePollingQueuesStillRunning() returned false"; } else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreQueuePeekTasksStillRunning() returned false"; } else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreRecursiveMutexTasksStillRunning() returned false"; } else if( xAreQueueSetTasksStillRunning() != pdPASS ) { pcMessage = "FreeRTOS Demo ERROR: xAreQueueSetTasksStillRunning() returned false"; } else if( xAreEventGroupTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreEventGroupTasksStillRunning() returned false"; } else if( xAreAbortDelayTestTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreAbortDelayTestTasksStillRunning() returned false"; } else if( xAreCountingSemaphoreTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreCountingSemaphoreTasksStillRunning() returned false"; } else if( xAreDynamicPriorityTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreDynamicPriorityTasksStillRunning() returned false"; } else if( xAreMessageBufferAMPTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreMessageBufferAMPTasksStillRunning() returned false"; } else if( xIsQueueOverwriteTaskStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xIsQueueOverwriteTaskStillRunning() returned false"; } else if( xAreQueueSetPollTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreQueueSetPollTasksStillRunning() returned false"; } else if( xAreStaticAllocationTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreStaticAllocationTasksStillRunning() returned false"; } else if( xAreTaskNotificationTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreTaskNotificationTasksStillRunning() returned false"; } else if( xAreTaskNotificationArrayTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreTaskNotificationArrayTasksStillRunning() returned false"; } else if( xAreTimerDemoTasksStillRunning( xTaskPeriod ) != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreTimerDemoTasksStillRunning() returned false"; } else if( xIsInterruptStreamBufferDemoStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xIsInterruptStreamBufferDemoStillRunning() returned false"; } else if( xAreInterruptSemaphoreTasksStillRunning() != pdTRUE ) { pcMessage = "FreeRTOS Demo ERROR: xAreInterruptSemaphoreTasksStillRunning() returned false"; } else if( ulLastRegTest1Value == ulRegTest1LoopCounter ) /* Check that the register test 1 task is still running. */ { pcMessage = "FreeRTOS Demo ERROR: Register test 1.\r\n"; } else if( ulLastRegTest2Value == ulRegTest2LoopCounter ) /* Check that the register test 2 task is still running. */ { pcMessage = "FreeRTOS Demo ERROR: Register test 2.\r\n"; } ulLastRegTest1Value = ulRegTest1LoopCounter; ulLastRegTest2Value = ulRegTest2LoopCounter; /* It is normally not good to call printf() from an embedded system, * although it is ok in this simulated case. */ printf( "%s : %d\r\n", pcMessage, ( int ) xTaskGetTickCount() ); } } /*-----------------------------------------------------------*/ void vFullDemoTickHookFunction( void ) { /* Write to a queue that is in use as part of the queue set demo to * demonstrate using queue sets from an ISR. */ vQueueSetAccessQueueSetFromISR(); /* Call the event group ISR tests. */ vPeriodicEventGroupsProcessing(); /* Exercise stream buffers from interrupts. */ vPeriodicStreamBufferProcessing(); /* Exercise using queue overwrites from interrupts. */ vQueueOverwritePeriodicISRDemo(); /* Exercise using Queue Sets from interrupts. */ vQueueSetPollingInterruptAccess(); /* Exercise using task notifications from interrupts. */ xNotifyTaskFromISR(); xNotifyArrayTaskFromISR(); /* Exercise software timers from interrupts. */ vTimerPeriodicISRTests(); /* Exercise stream buffers from interrupts. */ vBasicStreamBufferSendFromISR(); /* Exercise semaphores from interrupts. */ vInterruptSemaphorePeriodicTest(); } /*-----------------------------------------------------------*/