diff --git a/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo b/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo
index 7f5848df53..324972876a 100644
Binary files a/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo and b/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo differ
diff --git a/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h b/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h
index cc08b5f3f5..6b98922ee5 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h
+++ b/FreeRTOS/Demo/WIN32-MSVC/FreeRTOSConfig.h
@@ -62,7 +62,8 @@
#define configUSE_ALTERNATIVE_API 0
#define configUSE_QUEUE_SETS 1
#define configUSE_TASK_NOTIFICATIONS 1
-#define configSUPPORT_STATIC_ALLOCATION 1
+#define configSUPPORT_STATIC_ALLOCATION 0
+#define configSUPPORT_DYNAMIC_ALLOCATION 1
/* Software timer related configuration options. */
#define configUSE_TIMERS 1
diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj
index 87c034b6e4..d3531b4667 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj
+++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj
@@ -81,6 +81,7 @@
+
diff --git a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters
index ae43ea7508..0fcb7b7404 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters
+++ b/FreeRTOS/Demo/WIN32-MSVC/WIN32.vcxproj.filters
@@ -160,6 +160,9 @@
Demo App Source\Full_Demo\Common Demo Tasks
+
+ FreeRTOS Source\Source
+
diff --git a/FreeRTOS/Demo/WIN32-MSVC/main_full.c b/FreeRTOS/Demo/WIN32-MSVC/main_full.c
index 3f19db32e8..81d84750c5 100644
--- a/FreeRTOS/Demo/WIN32-MSVC/main_full.c
+++ b/FreeRTOS/Demo/WIN32-MSVC/main_full.c
@@ -245,6 +245,7 @@ static void prvCheckTask( void *pvParameters )
{
TickType_t xNextWakeTime;
const TickType_t xCycleFrequency = pdMS_TO_TICKS( 4000UL );
+HeapStats_t xHeapStats;
/* Just to remove compiler warning. */
( void ) pvParameters;
@@ -370,10 +371,17 @@ const TickType_t xCycleFrequency = pdMS_TO_TICKS( 4000UL );
/* This is the only task that uses stdout so its ok to call printf()
directly. */
- printf( "%s - tick count %zu - free heap %zu - min free heap %zu\r\n", pcStatusMessage,
- xTaskGetTickCount(),
- xPortGetFreeHeapSize(),
- xPortGetMinimumEverFreeHeapSize() );
+ vPortGetHeapStats( &xHeapStats );
+
+ configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == xPortGetFreeHeapSize() );
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xPortGetMinimumEverFreeHeapSize() );
+
+ printf( "%s - tick count %zu - free heap %zu - min free heap %zu - largest free block %zu \r\n",
+ pcStatusMessage,
+ xTaskGetTickCount(),
+ xHeapStats.xAvailableHeapSpaceInBytes,
+ xHeapStats.xMinimumEverFreeBytesRemaining,
+ xHeapStats.xSizeOfLargestFreeBlockInBytes );
}
}
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Demo/WIN32-MingW/main.c b/FreeRTOS/Demo/WIN32-MingW/main.c
index 2f3b36bfdc..2ccf29ac71 100644
--- a/FreeRTOS/Demo/WIN32-MingW/main.c
+++ b/FreeRTOS/Demo/WIN32-MingW/main.c
@@ -103,6 +103,12 @@ void vFullDemoIdleFunction( void );
*/
static void prvInitialiseHeap( void );
+/*
+ * Performs a few sanity checks on the behaviour of the vPortGetHeapStats()
+ * function.
+ */
+static void prvExerciseHeapStats( void );
+
/*
* Prototypes for the standard FreeRTOS application hook (callback) functions
* implemented within this file. See http://www.freertos.org/a00016.html .
@@ -344,6 +350,8 @@ offsets into the array - with gaps in between and messy alignment just for test
purposes. */
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
volatile uint32_t ulAdditionalOffset = 19; /* Just to prevent 'condition is always true' warnings in configASSERT(). */
+HeapStats_t xHeapStats;
+const HeapStats_t xZeroHeapStats = { 0 };
const HeapRegion_t xHeapRegions[] =
{
/* Start address with dummy offsets Size */
@@ -360,7 +368,80 @@ const HeapRegion_t xHeapRegions[] =
/* Prevent compiler warnings when configASSERT() is not defined. */
( void ) ulAdditionalOffset;
+ /* The heap has not been initialised yet so expect stats to all be zero. */
+ vPortGetHeapStats( &xHeapStats );
+ configASSERT( memcmp( &xHeapStats, &xZeroHeapStats, sizeof( HeapStats_t ) ) == 0 );
+
vPortDefineHeapRegions( xHeapRegions );
+
+ /* Sanity check vTaskGetHeapStats(). */
+ prvExerciseHeapStats();
+}
+/*-----------------------------------------------------------*/
+
+static void prvExerciseHeapStats( void )
+{
+HeapStats_t xHeapStats;
+size_t xInitialFreeSpace = xPortGetFreeHeapSize(), xMinimumFreeBytes;
+size_t xMetaDataOverhead, i;
+void *pvAllocatedBlock;
+const size_t xArraySize = 5, xBlockSize = 1000UL;
+void *pvAllocatedBlocks[ xArraySize ];
+
+ /* Check heap stats are as expected after initialisation but before any
+ allocations. */
+ vPortGetHeapStats( &xHeapStats );
+
+ /* Minimum ever free bytes remaining should be the same as the total number
+ of bytes as nothing has been allocated yet. */
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xHeapStats.xAvailableHeapSpaceInBytes );
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xInitialFreeSpace );
+
+ /* Nothing has been allocated or freed yet. */
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == 0 );
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == 0 );
+
+ /* Allocate a 1000 byte block then measure what the overhead of the
+ allocation in regards to how many bytes more than 1000 were actually
+ removed from the heap in order to store metadata about the allocation. */
+ pvAllocatedBlock = pvPortMalloc( xBlockSize );
+ configASSERT( pvAllocatedBlock );
+ xMetaDataOverhead = ( xInitialFreeSpace - xPortGetFreeHeapSize() ) - xBlockSize;
+
+ /* Free the block again to get back to where we started. */
+ vPortFree( pvAllocatedBlock );
+ vPortGetHeapStats( &xHeapStats );
+ configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == xInitialFreeSpace );
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == 1 );
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == 1 );
+
+ /* Allocate blocks checking some stats value on each allocation. */
+ for( i = 0; i < xArraySize; i++ )
+ {
+ pvAllocatedBlocks[ i ] = pvPortMalloc( xBlockSize );
+ configASSERT( pvAllocatedBlocks[ i ] );
+ vPortGetHeapStats( &xHeapStats );
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == ( xInitialFreeSpace - ( ( i + 1 ) * ( xBlockSize + xMetaDataOverhead ) ) ) );
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xHeapStats.xAvailableHeapSpaceInBytes );
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == ( 2Ul + i ) );
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == 1 ); /* Does not increase during allocations. */
+ }
+
+ configASSERT( xPortGetFreeHeapSize() == xPortGetMinimumEverFreeHeapSize() );
+ xMinimumFreeBytes = xPortGetFreeHeapSize();
+
+ /* Free the blocks again. */
+ for( i = 0; i < xArraySize; i++ )
+ {
+ vPortFree( pvAllocatedBlocks[ i ] );
+ vPortGetHeapStats( &xHeapStats );
+ configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == ( xInitialFreeSpace - ( ( ( xArraySize - i - 1 ) * ( xBlockSize + xMetaDataOverhead ) ) ) ) );
+ configASSERT( xHeapStats.xNumberOfSuccessfulAllocations == ( xArraySize + 1 ) ); /* Does not increase during frees. */
+ configASSERT( xHeapStats.xNumberOfSuccessfulFrees == ( 2UL + i ) );
+ }
+
+ /* The minimum ever free heap size should not change as blocks are freed. */
+ configASSERT( xMinimumFreeBytes == xPortGetMinimumEverFreeHeapSize() );
}
/*-----------------------------------------------------------*/
diff --git a/FreeRTOS/Demo/WIN32-MingW/main_full.c b/FreeRTOS/Demo/WIN32-MingW/main_full.c
index 13a66910a3..84ae4074e3 100644
--- a/FreeRTOS/Demo/WIN32-MingW/main_full.c
+++ b/FreeRTOS/Demo/WIN32-MingW/main_full.c
@@ -260,6 +260,7 @@ static void prvCheckTask( void *pvParameters )
{
TickType_t xNextWakeTime;
const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL );
+HeapStats_t xHeapStats;
/* Just to remove compiler warning. */
( void ) pvParameters;
@@ -385,10 +386,19 @@ const TickType_t xCycleFrequency = pdMS_TO_TICKS( 2500UL );
/* This is the only task that uses stdout so its ok to call printf()
directly. */
- printf( "%s - tick count %u - free heap %u - min free heap %u\r\n", pcStatusMessage,
- xTaskGetTickCount(),
- xPortGetFreeHeapSize(),
- xPortGetMinimumEverFreeHeapSize() );
+ vPortGetHeapStats( &xHeapStats );
+
+ configASSERT( xHeapStats.xAvailableHeapSpaceInBytes == xPortGetFreeHeapSize() );
+ configASSERT( xHeapStats.xMinimumEverFreeBytesRemaining == xPortGetMinimumEverFreeHeapSize() );
+
+ printf( "%s - tick count %u - free heap %u - min free heap %u - largest free block %u - number of free blocks %u\r\n",
+ pcStatusMessage,
+ xTaskGetTickCount(),
+ xHeapStats.xAvailableHeapSpaceInBytes,
+ xHeapStats.xMinimumEverFreeBytesRemaining,
+ xHeapStats.xSizeOfLargestFreeBlockInBytes,
+ xHeapStats.xNumberOfFreeBlocks );
+
fflush( stdout );
}
}