/* * 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 is provided as an example of how to create a FreeRTOS project * that does not need a heap. configSUPPORT_STATIC_ALLOCATION is set to 1 to * allow RTOS objects to be created using statically allocated RAM, and * configSUPPORT_DYNAMIC_ALLOCATION is set to 0 to remove any build dependency * on the FreeRTOS heap. When configSUPPORT_DYNAMIC_ALLOCATION is set to 0 * pvPortMalloc() just equates to NULL, and calls to vPortFree() have no * effect. See: * * https://www.FreeRTOS.org/a00111.html and * https://www.FreeRTOS.org/Static_Vs_Dynamic_Memory_Allocation.html * ******************************************************************************* */ /* Standard includes. */ #include #include #include /* FreeRTOS kernel includes. */ #include "FreeRTOS.h" #include "task.h" /* Standard demo includes. */ #include "StaticAllocation.h" /*-----------------------------------------------------------*/ /* * Prototypes for the standard FreeRTOS stack overflow hook (callback) * function. http://www.freertos.org/Stacks-and-stack-overflow-checking.html */ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char * pcTaskName ); /* * This demo has configSUPPORT_STATIC_ALLOCATION set to 1 so the following * application callback function must be provided to supply the RAM that will * get used for the Idle task data structures and stack. */ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t * pulIdleTaskStackSize ); /* * This demo has configSUPPORT_STATIC_ALLOCATION set to 1 and configUSE_TIMERS * set to 1 so the following application callback function must be provided to * supply the RAM that will get used for the Timer task data structures and * stack. */ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t * pulTimerTaskStackSize ); /* This demo only uses the standard demo tasks that use statically allocated * RAM. A 'check' task is also created to periodically inspect the demo tasks to * ensure they are still running, and that no errors have been detected. */ static void prvStartCheckTask( void ); static void prvCheckTask( void * pvParameters ); /*-----------------------------------------------------------*/ int main( void ) { /* This demo has configSUPPORT_STATIC_ALLOCATION set to 1 and * configSUPPORT_DYNAMIC_ALLOCATION set to 0, so the only standard temo tasks * created are the ones that only use static allocation. This allow the * application to be built without including a FreeRTOS heap file (without one * of the heap files described on http://www.freertos.org/a00111.html */ vStartStaticallyAllocatedTasks(); /* Start a task that periodically inspects the tasks created by * vStartStaticallyAllocatedTasks() to ensure they are still running, and not * reporting any errors. */ prvStartCheckTask(); /* Start the scheduler so the demo tasks start to execute. */ vTaskStartScheduler(); /* vTaskStartScheduler() would only return if RAM required by the Idle and * Timer tasks could not be allocated. As this demo uses statically allocated * RAM only, there are no allocations that could fail, and * vTaskStartScheduler() cannot return - so there is no need to put the normal * infinite loop after the call to vTaskStartScheduler(). */ return 0; } /*-----------------------------------------------------------*/ static void prvStartCheckTask( void ) { /* Allocate the data structure that will hold the task's TCB. NOTE: This is * declared static so it still exists after this function has returned. */ static StaticTask_t xCheckTask; /* Allocate the stack that will be used by the task. NOTE: This is declared * static so it still exists after this function has returned. */ static StackType_t ucTaskStack[ configMINIMAL_STACK_SIZE * sizeof( StackType_t ) ]; /* Create the task, which will use the RAM allocated by the linker to the * variables declared in this function. */ xTaskCreateStatic( prvCheckTask, "Check", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, ucTaskStack, &xCheckTask ); } /*-----------------------------------------------------------*/ static void prvCheckTask( void * pvParameters ) { const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL ); static char * pcStatusMessage = "No errors"; /* Just to remove compiler warning. */ ( void ) pvParameters; for( ; ; ) { /* Place this task in the blocked state until it is time to run again. */ vTaskDelay( xCycleFrequency ); /* Check the tasks that use static allocation are still executing. */ if( xAreStaticAllocationTasksStillRunning() != pdPASS ) { pcStatusMessage = "Error: Static allocation"; } /* This is the only task that uses stdout so its ok to call printf() * directly. */ printf( "%s - tick count %d - number of tasks executing %d\r\n", pcStatusMessage, xTaskGetTickCount(), uxTaskGetNumberOfTasks() ); } } /*-----------------------------------------------------------*/ void vApplicationStackOverflowHook( TaskHandle_t pxTask, char * pcTaskName ) { ( void ) pcTaskName; ( void ) pxTask; /* Run time stack overflow checking is performed if * configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook * function is called if a stack overflow is detected. This function is * provided as an example only as stack overflow checking does not function * when running the FreeRTOS Windows port. */ vAssertCalled( __LINE__, __FILE__ ); } /*-----------------------------------------------------------*/ void vAssertCalled( unsigned long ulLine, const char * const pcFileName ) { volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0; /* Called if an assertion passed to configASSERT() fails. See * http://www.freertos.org/a00110.html#configASSERT for more information. */ /* Parameters are not used. */ ( void ) ulLine; ( void ) pcFileName; printf( "ASSERT! Line %d, file %s\r\n", ulLine, pcFileName ); taskENTER_CRITICAL(); { /* You can step out of this function to debug the assertion by using * the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero * value. */ while( ulSetToNonZeroInDebuggerToContinue == 0 ) { __asm { NOP }; __asm { NOP }; } } taskEXIT_CRITICAL(); } /*-----------------------------------------------------------*/ /* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is * used by the Idle task. */ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t * pulIdleTaskStackSize ) { /* If the buffers to be provided to the Idle task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ static StaticTask_t xIdleTaskTCB; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; /* Pass out a pointer to the StaticTask_t structure in which the Idle task's * state will be stored. */ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; /* Pass out the array that will be used as the Idle task's stack. */ *ppxIdleTaskStackBuffer = uxIdleTaskStack; /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. * Note that, as the array is necessarily of type StackType_t, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } /*-----------------------------------------------------------*/ /* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the * application must provide an implementation of vApplicationGetTimerTaskMemory() * to provide the memory that is used by the Timer service task. */ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t * pulTimerTaskStackSize ) { /* If the buffers to be provided to the Timer task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ static StaticTask_t xTimerTaskTCB; static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; /* Pass out a pointer to the StaticTask_t structure in which the Timer * task's state will be stored. */ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; /* Pass out the array that will be used as the Timer task's stack. */ *ppxTimerTaskStackBuffer = uxTimerTaskStack; /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. * Note that, as the array is necessarily of type StackType_t, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; }