/*\r
- FreeRTOS V7.5.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
-\r
- VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
-\r
- ***************************************************************************\r
- * *\r
- * FreeRTOS provides completely free yet professionally developed, *\r
- * robust, strictly quality controlled, supported, and cross *\r
- * platform software that has become a de facto standard. *\r
- * *\r
- * Help yourself get started quickly and support the FreeRTOS *\r
- * project by purchasing a FreeRTOS tutorial book, reference *\r
- * manual, or both from: http://www.FreeRTOS.org/Documentation *\r
- * *\r
- * Thank you! *\r
- * *\r
- ***************************************************************************\r
-\r
- This file is part of the FreeRTOS distribution.\r
-\r
- FreeRTOS is free software; you can redistribute it and/or modify it under\r
- the terms of the GNU General Public License (version 2) as published by the\r
- Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
-\r
- >>! NOTE: The modification to the GPL is included to allow you to distribute\r
- >>! a combined work that includes FreeRTOS without being obliged to provide\r
- >>! the source code for proprietary components outside of the FreeRTOS\r
- >>! kernel.\r
-\r
- FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
- FOR A PARTICULAR PURPOSE. Full license text is available from the following\r
- link: http://www.freertos.org/a00114.html\r
-\r
- 1 tab == 4 spaces!\r
-\r
- ***************************************************************************\r
- * *\r
- * Having a problem? Start by reading the FAQ "My application does *\r
- * not run, what could be wrong?" *\r
- * *\r
- * http://www.FreeRTOS.org/FAQHelp.html *\r
- * *\r
- ***************************************************************************\r
-\r
- http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
- license and Real Time Engineers Ltd. contact details.\r
-\r
- http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
- including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
- compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
-\r
- http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
- Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS\r
- licenses offer ticketed support, indemnification and middleware.\r
-\r
- http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
- engineered and independently SIL3 certified version for use in safety and\r
- mission critical applications that require provable dependability.\r
-\r
- 1 tab == 4 spaces!\r
-*/\r
-\r
-/*\r
- *******************************************************************************\r
- * -NOTE- The Win32 port is a simulation (or is that emulation?) only! Do not\r
- * expect to get real time behaviour from the Win32 port or this demo\r
- * application. It is provided as a convenient development and demonstration\r
- * test bed only. This was tested using Windows XP on a dual core laptop.\r
+ * FreeRTOS Kernel V10.3.0\r
+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
*\r
- * - READ THE WEB DOCUMENTATION FOR THIS PORT FOR MORE INFORMATION ON USING IT -\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
- * main() creates all the demo application tasks, then starts the scheduler. \r
- * The web documentation provides more details of the standard demo application \r
- * tasks, which provide no particular functionality but do provide a good \r
- * example of how to use the FreeRTOS API.\r
+ * The above copyright notice and this permission notice shall be included in all\r
+ * copies or substantial portions of the Software.\r
*\r
- * In addition to the standard demo tasks, the following tasks and tests are\r
- * defined and/or created within this file:\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
- * "Check" task - This only executes every five seconds but has a high priority\r
- * to ensure it gets processor time. Its main function is to check that all the\r
- * standard demo tasks are still operational. While no errors have been\r
- * discovered the check task will print out "OK" and the current simulated tick\r
- * time. If an error is discovered in the execution of a task then the check\r
- * task will print out an appropriate error message.\r
+ * http://www.FreeRTOS.org\r
+ * http://aws.amazon.com/freertos\r
*\r
+ * 1 tab == 4 spaces!\r
*/\r
\r
+/******************************************************************************\r
+ * This project provides two demo applications. A simple blinky style project,\r
+ * and a more comprehensive test and demo application. The\r
+ * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two.\r
+ * The simply blinky demo is implemented and described in main_blinky.c. The\r
+ * more comprehensive test and demo application is implemented and described in\r
+ * main_full.c.\r
+ *\r
+ * This file implements the code that is not demo specific, including the\r
+ * hardware setup and FreeRTOS hook functions.\r
+ *\r
+ *******************************************************************************\r
+ * NOTE: Windows will not be running the FreeRTOS demo threads continuously, so\r
+ * do not expect to get real time behaviour from the FreeRTOS Windows port, or\r
+ * this demo application. Also, the timing information in the FreeRTOS+Trace\r
+ * logs have no meaningful units. See the documentation page for the Windows\r
+ * port for further information:\r
+ * http://www.freertos.org/FreeRTOS-Windows-Simulator-Emulator-for-Visual-Studio-and-Eclipse-MingW.html\r
+ *\r
+\r
+ *\r
+ *******************************************************************************\r
+ */\r
\r
/* Standard includes. */\r
#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <conio.h>\r
\r
-/* Kernel includes. */\r
-#include <FreeRTOS.h>\r
+/* FreeRTOS kernel includes. */\r
+#include "FreeRTOS.h"\r
#include "task.h"\r
-#include "queue.h"\r
-\r
-/* Standard demo includes. */\r
-#include "BlockQ.h"\r
-#include "integer.h"\r
-#include "semtest.h"\r
-#include "PollQ.h"\r
-#include "GenQTest.h"\r
-#include "QPeek.h"\r
-#include "recmutex.h"\r
-#include "flop.h"\r
-\r
-/* Priorities at which the tasks are created. */\r
-#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 )\r
-#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
-#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
-#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
-#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )\r
-#define mainFLASH_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )\r
-#define mainuIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )\r
-#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
-#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
-#define mainFLOP_TASK_PRIORITY ( tskIDLE_PRIORITY )\r
-\r
-/* Task function prototypes. */\r
-static void prvCheckTask( void *pvParameters );\r
+\r
+/* This project provides two demo applications. A simple blinky style demo\r
+application, and a more comprehensive test and demo application. The\r
+mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is used to select between the two.\r
+\r
+If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is 1 then the blinky demo will be built.\r
+The blinky demo is implemented and described in main_blinky.c.\r
+\r
+If mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is not 1 then the comprehensive test and\r
+demo application will be built. The comprehensive test and demo application is\r
+implemented and described in main_full.c. */\r
+#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0\r
+\r
+/* This demo uses heap_5.c, and these constants define the sizes of the regions\r
+that make up the total heap. heap_5 is only used for test and example purposes\r
+as this demo could easily create one large heap region instead of multiple\r
+smaller heap regions - in which case heap_4.c would be the more appropriate\r
+choice. See http://www.freertos.org/a00111.html for an explanation. */\r
+#define mainREGION_1_SIZE 10801\r
+#define mainREGION_2_SIZE 29905\r
+#define mainREGION_3_SIZE 6007\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1.\r
+ * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0.\r
+ */\r
+extern void main_blinky( void );\r
+extern void main_full( void );\r
+\r
+/*\r
+ * Only the comprehensive demo uses application hook (callback) functions. See\r
+ * http://www.freertos.org/a00016.html for more information.\r
+ */\r
+void vFullDemoTickHookFunction( void );\r
+void vFullDemoIdleFunction( void );\r
+\r
+/*\r
+ * This demo uses heap_5.c, so start by defining some heap regions. It is not\r
+ * necessary for this demo to use heap_5, as it could define one large heap\r
+ * region. Heap_5 is only used for test and example purposes. See\r
+ * http://www.freertos.org/a00111.html for an explanation.\r
+ */\r
+static void prvInitialiseHeap( void );\r
+\r
+/*\r
+ * Performs a few sanity checks on the behaviour of the vPortGetHeapStats()\r
+ * function.\r
+ */\r
+static void prvExerciseHeapStats( void );\r
+\r
+/*\r
+ * Prototypes for the standard FreeRTOS application hook (callback) functions\r
+ * implemented within this file. See http://www.freertos.org/a00016.html .\r
+ */\r
+void vApplicationMallocFailedHook( void );\r
+void vApplicationIdleHook( void );\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );\r
+void vApplicationTickHook( void );\r
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize );\r
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize );\r
+\r
+/*\r
+ * Writes trace data to a disk file when the trace recording is stopped.\r
+ * This function will simply overwrite any trace files that already exist.\r
+ */\r
+static void prvSaveTraceFile( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* When configSUPPORT_STATIC_ALLOCATION is set to 1 the application writer can\r
+use a callback function to optionally provide the memory required by the idle\r
+and timer tasks. This is the stack that will be used by the timer task. It is\r
+declared here, as a global, so it can be checked by a test that is implemented\r
+in a different file. */\r
+StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ];\r
+\r
+/* Notes if the trace is running or not. */\r
+static BaseType_t xTraceRunning = pdTRUE;\r
\r
/*-----------------------------------------------------------*/\r
\r
int main( void )\r
{\r
- /* Start the check task as described at the top of this file. */\r
- xTaskCreate( prvCheckTask, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL );\r
-\r
- /* Create the standard demo tasks. */\r
- vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );\r
- vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );\r
- vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );\r
- vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );\r
- vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );\r
- vStartQueuePeekTasks();\r
- vStartMathTasks( mainFLOP_TASK_PRIORITY );\r
- vStartRecursiveMutexTasks();\r
-\r
- /* Start the scheduler itself. */\r
- vTaskStartScheduler();\r
-\r
- /* Should never get here unless there was not enough heap space to create \r
- the idle and other system tasks. */\r
- return 0;\r
+ /* This demo uses heap_5.c, so start by defining some heap regions. heap_5\r
+ is only used for test and example reasons. Heap_4 is more appropriate. See\r
+ http://www.freertos.org/a00111.html for an explanation. */\r
+ prvInitialiseHeap();\r
+\r
+ /* Do not include trace code when performing a code coverage analysis. */\r
+ #if( projCOVERAGE_TEST != 1 )\r
+ {\r
+ /* Initialise the trace recorder. Use of the trace recorder is optional.\r
+ See http://www.FreeRTOS.org/trace for more information. */\r
+ vTraceEnable( TRC_START );\r
+\r
+ /* Start the trace recording - the recording is written to a file if\r
+ configASSERT() is called. */\r
+ printf( "\r\nTrace started.\r\nThe trace will be dumped to disk if a call to configASSERT() fails.\r\n" );\r
+ printf( "Uncomment the call to kbhit() in this file to also dump trace with a key press.\r\n" );\r
+ uiTraceStart();\r
+ }\r
+ #endif\r
+\r
+ /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top\r
+ of this file. */\r
+ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 )\r
+ {\r
+ main_blinky();\r
+ }\r
+ #else\r
+ {\r
+ main_full();\r
+ }\r
+ #endif\r
+\r
+ return 0;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-static void prvCheckTask( void *pvParameters )\r
+void vApplicationMallocFailedHook( void )\r
{\r
-portTickType xNextWakeTime;\r
-const portTickType xCycleFrequency = 5000 / portTICK_RATE_MS;\r
-char *pcStatusMessage = "OK";\r
+ /* vApplicationMallocFailedHook() will only be called if\r
+ configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook\r
+ function that will get called if a call to pvPortMalloc() fails.\r
+ pvPortMalloc() is called internally by the kernel whenever a task, queue,\r
+ timer or semaphore is created. It is also called by various parts of the\r
+ demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the\r
+ size of the heap available to pvPortMalloc() is defined by\r
+ configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize()\r
+ API function can be used to query the size of free heap space that remains\r
+ (although it does not provide information on how the remaining heap might be\r
+ fragmented). See http://www.freertos.org/a00111.html for more\r
+ information. */\r
+ vAssertCalled( __LINE__, __FILE__ );\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
- /* Just to remove compiler warning. */\r
- ( void ) pvParameters;\r
+void vApplicationIdleHook( void )\r
+{\r
+ /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set\r
+ to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle\r
+ task. It is essential that code added to this hook function never attempts\r
+ to block in any way (for example, call xQueueReceive() with a block time\r
+ specified, or call vTaskDelay()). If application tasks make use of the\r
+ vTaskDelete() API function to delete themselves then it is also important\r
+ that vApplicationIdleHook() is permitted to return to its calling function,\r
+ because it is the responsibility of the idle task to clean up memory\r
+ allocated by the kernel to any task that has since deleted itself. */\r
+\r
+ /* Uncomment the following code to allow the trace to be stopped with any\r
+ key press. The code is commented out by default as the kbhit() function\r
+ interferes with the run time behaviour. */\r
+ /*\r
+ if( _kbhit() != pdFALSE )\r
+ {\r
+ if( xTraceRunning == pdTRUE )\r
+ {\r
+ vTraceStop();\r
+ prvSaveTraceFile();\r
+ xTraceRunning = pdFALSE;\r
+ }\r
+ }\r
+ */\r
\r
- /* Initialise xNextWakeTime - this only needs to be done once. */\r
- xNextWakeTime = xTaskGetTickCount();\r
+ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )\r
+ {\r
+ /* Call the idle task processing used by the full demo. The simple\r
+ blinky demo does not use the idle task hook. */\r
+ vFullDemoIdleFunction();\r
+ }\r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )\r
+{\r
+ ( void ) pcTaskName;\r
+ ( void ) pxTask;\r
+\r
+ /* Run time stack overflow checking is performed if\r
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook\r
+ function is called if a stack overflow is detected. This function is\r
+ provided as an example only as stack overflow checking does not function\r
+ when running the FreeRTOS Windows port. */\r
+ vAssertCalled( __LINE__, __FILE__ );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationTickHook( void )\r
+{\r
+ /* This function will be called by each tick interrupt if\r
+ configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be\r
+ added here, but the tick hook is called from an interrupt context, so\r
+ code must not attempt to block, and only the interrupt safe FreeRTOS API\r
+ functions can be used (those that end in FromISR()). */\r
\r
- for( ;; )\r
+ #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 )\r
{\r
- /* Place this task in the blocked state until it is time to run again. */\r
- vTaskDelayUntil( &xNextWakeTime, xCycleFrequency );\r
-\r
- /* Check the standard demo tasks are running without error. */\r
- if( xAreIntegerMathsTaskStillRunning() != pdTRUE )\r
- {\r
- pcStatusMessage = "Error: IntMath";\r
- } \r
- else if( xAreGenericQueueTasksStillRunning() != pdTRUE )\r
- { \r
- pcStatusMessage = "Error: GenQueue";\r
- }\r
- else if( xAreQueuePeekTasksStillRunning() != pdTRUE )\r
+ vFullDemoTickHookFunction();\r
+ }\r
+ #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vApplicationDaemonTaskStartupHook( void )\r
+{\r
+ /* This function will be called once only, when the daemon task starts to\r
+ execute (sometimes called the timer task). This is useful if the\r
+ application includes initialisation code that would benefit from executing\r
+ after the scheduler has been started. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vAssertCalled( unsigned long ulLine, const char * const pcFileName )\r
+{\r
+static BaseType_t xPrinted = pdFALSE;\r
+volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0;\r
+\r
+ /* Called if an assertion passed to configASSERT() fails. See\r
+ http://www.freertos.org/a00110.html#configASSERT for more information. */\r
+\r
+ /* Parameters are not used. */\r
+ ( void ) ulLine;\r
+ ( void ) pcFileName;\r
+\r
+\r
+ taskENTER_CRITICAL();\r
+ {\r
+ /* Stop the trace recording. */\r
+ if( xPrinted == pdFALSE )\r
{\r
- pcStatusMessage = "Error: QueuePeek";\r
+ xPrinted = pdTRUE;\r
+ if( xTraceRunning == pdTRUE )\r
+ {\r
+ prvSaveTraceFile();\r
+ }\r
}\r
- else if( xAreBlockingQueuesStillRunning() != pdTRUE )\r
+\r
+ /* You can step out of this function to debug the assertion by using\r
+ the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero\r
+ value. */\r
+ while( ulSetToNonZeroInDebuggerToContinue == 0 )\r
{\r
- pcStatusMessage = "Error: BlockQueue";\r
+ __asm volatile( "NOP" );\r
+ __asm volatile( "NOP" );\r
}\r
- else if( xAreSemaphoreTasksStillRunning() != pdTRUE )\r
- {\r
- pcStatusMessage = "Error: SemTest";\r
- }\r
- else if( xArePollingQueuesStillRunning() != pdTRUE )\r
- {\r
- pcStatusMessage = "Error: PollQueue";\r
- }\r
- else if( xAreMathsTaskStillRunning() != pdPASS )\r
+ }\r
+ taskEXIT_CRITICAL();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSaveTraceFile( void )\r
+{\r
+ /* Tracing is not used when code coverage analysis is being performed. */\r
+ #if( projCOVERAGE_TEST != 1 )\r
+ {\r
+ FILE* pxOutputFile;\r
+\r
+ vTraceStop();\r
+\r
+ pxOutputFile = fopen( "Trace.dump", "wb");\r
+\r
+ if( pxOutputFile != NULL )\r
{\r
- pcStatusMessage = "Error: Flop";\r
+ fwrite( RecorderDataPtr, sizeof( RecorderDataType ), 1, pxOutputFile );\r
+ fclose( pxOutputFile );\r
+ printf( "\r\nTrace output saved to Trace.dump\r\n" );\r
}\r
- else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )\r
- {\r
- pcStatusMessage = "Error: RecMutex";\r
+ else\r
+ {\r
+ printf( "\r\nFailed to create trace dump file\r\n" );\r
}\r
-\r
- /* This is the only task that uses stdout so its ok to call printf() \r
- directly. */\r
- printf( "%s - %d\r\n", pcStatusMessage, ( int ) xTaskGetTickCount() );\r
- fflush( stdout ); /* Required by Eclipse console. */\r
}\r
+ #endif\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vApplicationIdleHook( void )\r
+static void prvInitialiseHeap( void )\r
+{\r
+/* The Windows demo could create one large heap region, in which case it would\r
+be appropriate to use heap_4. However, purely for demonstration purposes,\r
+heap_5 is used instead, so start by defining some heap regions. No\r
+initialisation is required when any other heap implementation is used. See\r
+http://www.freertos.org/a00111.html for more information.\r
+\r
+The xHeapRegions structure requires the regions to be defined in start address\r
+order, so this just creates one big array, then populates the structure with\r
+offsets into the array - with gaps in between and messy alignment just for test\r
+purposes. */\r
+static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];\r
+volatile uint32_t ulAdditionalOffset = 19; /* Just to prevent 'condition is always true' warnings in configASSERT(). */\r
+HeapStats_t xHeapStats;\r
+const HeapStats_t xZeroHeapStats = { 0 };\r
+const HeapRegion_t xHeapRegions[] =\r
{\r
-const unsigned long ulMSToSleep = 5;\r
+ /* Start address with dummy offsets Size */\r
+ { ucHeap + 1, mainREGION_1_SIZE },\r
+ { ucHeap + 15 + mainREGION_1_SIZE, mainREGION_2_SIZE },\r
+ { ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE, mainREGION_3_SIZE },\r
+ { NULL, 0 }\r
+};\r
+\r
+ /* Sanity check that the sizes and offsets defined actually fit into the\r
+ array. */\r
+ configASSERT( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE );\r
+\r
+ /* Prevent compiler warnings when configASSERT() is not defined. */\r
+ ( void ) ulAdditionalOffset;\r
+\r
+ /* The heap has not been initialised yet so expect stats to all be zero. */\r
+ vPortGetHeapStats( &xHeapStats );\r
+ configASSERT( memcmp( &xHeapStats, &xZeroHeapStats, sizeof( HeapStats_t ) ) == 0 );\r
\r
- /* Sleep to reduce CPU load, but don't sleep indefinitely in case there are\r
- tasks waiting to be terminated by the idle task. */\r
- Sleep( ulMSToSleep );\r
+ vPortDefineHeapRegions( xHeapRegions );\r
+\r
+ /* Sanity check vTaskGetHeapStats(). */\r
+ prvExerciseHeapStats();\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vApplicationMallocFailedHook( void )\r
+static void prvExerciseHeapStats( void )\r
+{\r
+HeapStats_t xHeapStats;\r
+size_t xInitialFreeSpace = xPortGetFreeHeapSize(), xMinimumFreeBytes;\r
+size_t xMetaDataOverhead, i;\r
+void *pvAllocatedBlock;\r
+const size_t xArraySize = 5, xBlockSize = 1000UL;\r
+void *pvAllocatedBlocks[ xArraySize ];\r
+\r
+ /* Check heap stats are as expected after initialisation but before any\r
+ allocations. */\r
+ vPortGetHeapStats( &xHeapStats );\r
+\r
+ /* Minimum ever free bytes remaining should be the same as the total number\r
+ of bytes as nothing has been allocated yet. */\r
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xHeapStats.xAvailableHeapSpaceInBytes );\r
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xInitialFreeSpace );\r
+\r
+ /* Nothing has been allocated or freed yet. */\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == 0 );\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == 0 );\r
+\r
+ /* Allocate a 1000 byte block then measure what the overhead of the\r
+ allocation in regards to how many bytes more than 1000 were actually\r
+ removed from the heap in order to store metadata about the allocation. */\r
+ pvAllocatedBlock = pvPortMalloc( xBlockSize );\r
+ configASSERT( pvAllocatedBlock );\r
+ xMetaDataOverhead = ( xInitialFreeSpace - xPortGetFreeHeapSize() ) - xBlockSize;\r
+\r
+ /* Free the block again to get back to where we started. */\r
+ vPortFree( pvAllocatedBlock );\r
+ vPortGetHeapStats( &xHeapStats );\r
+ configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == xInitialFreeSpace );\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == 1 );\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == 1 );\r
+\r
+ /* Allocate blocks checking some stats value on each allocation. */\r
+ for( i = 0; i < xArraySize; i++ )\r
+ {\r
+ pvAllocatedBlocks[ i ] = pvPortMalloc( xBlockSize );\r
+ configASSERT( pvAllocatedBlocks[ i ] );\r
+ vPortGetHeapStats( &xHeapStats );\r
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == ( xInitialFreeSpace - ( ( i + 1 ) * ( xBlockSize + xMetaDataOverhead ) ) ) );\r
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xHeapStats.xAvailableHeapSpaceInBytes );\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == ( 2Ul + i ) );\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == 1 ); /* Does not increase during allocations. */\r
+ }\r
+\r
+ configASSERT( xPortGetFreeHeapSize() == xPortGetMinimumEverFreeHeapSize() );\r
+ xMinimumFreeBytes = xPortGetFreeHeapSize();\r
+\r
+ /* Free the blocks again. */\r
+ for( i = 0; i < xArraySize; i++ )\r
+ {\r
+ vPortFree( pvAllocatedBlocks[ i ] );\r
+ vPortGetHeapStats( &xHeapStats );\r
+ configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == ( xInitialFreeSpace - ( ( ( xArraySize - i - 1 ) * ( xBlockSize + xMetaDataOverhead ) ) ) ) );\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == ( xArraySize + 1 ) ); /* Does not increase during frees. */\r
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == ( 2UL + i ) );\r
+ }\r
+\r
+ /* The minimum ever free heap size should not change as blocks are freed. */\r
+ configASSERT( xMinimumFreeBytes == xPortGetMinimumEverFreeHeapSize() );\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an\r
+implementation of vApplicationGetIdleTaskMemory() to provide the memory that is\r
+used by the Idle task. */\r
+void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize )\r
{\r
- /* Can be implemented if required, but probably not required in this \r
- environment and running this demo. */\r
+/* If the buffers to be provided to the Idle task are declared inside this\r
+function then they must be declared static - otherwise they will be allocated on\r
+the stack and so not exists after this function exits. */\r
+static StaticTask_t xIdleTaskTCB;\r
+static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ];\r
+\r
+ /* Pass out a pointer to the StaticTask_t structure in which the Idle task's\r
+ state will be stored. */\r
+ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB;\r
+\r
+ /* Pass out the array that will be used as the Idle task's stack. */\r
+ *ppxIdleTaskStackBuffer = uxIdleTaskStack;\r
+\r
+ /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.\r
+ Note that, as the array is necessarily of type StackType_t,\r
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */\r
+ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vApplicationStackOverflowHook( void )\r
+/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the\r
+application must provide an implementation of vApplicationGetTimerTaskMemory()\r
+to provide the memory that is used by the Timer service task. */\r
+void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize )\r
{\r
- /* Can be implemented if required, but not required in this \r
- environment and running this demo. */\r
+/* If the buffers to be provided to the Timer task are declared inside this\r
+function then they must be declared static - otherwise they will be allocated on\r
+the stack and so not exists after this function exits. */\r
+static StaticTask_t xTimerTaskTCB;\r
+\r
+ /* Pass out a pointer to the StaticTask_t structure in which the Timer\r
+ task's state will be stored. */\r
+ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB;\r
+\r
+ /* Pass out the array that will be used as the Timer task's stack. */\r
+ *ppxTimerTaskStackBuffer = uxTimerTaskStack;\r
+\r
+ /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer.\r
+ Note that, as the array is necessarily of type StackType_t,\r
+ configMINIMAL_STACK_SIZE is specified in words, not bytes. */\r
+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;\r
}\r
\r