diff --git a/FreeRTOS/Source/include/portable.h b/FreeRTOS/Source/include/portable.h
index a1bb449050..d2baf14a4c 100644
--- a/FreeRTOS/Source/include/portable.h
+++ b/FreeRTOS/Source/include/portable.h
@@ -118,13 +118,26 @@ extern "C" {
 	#endif
 #endif
 
-/* Used by heap_5.c. */
+/* Used by heap_5.c to define the start address and size of each memory region
+that together comprise the total FreeRTOS heap space. */
 typedef struct HeapRegion
 {
 	uint8_t *pucStartAddress;
 	size_t xSizeInBytes;
 } HeapRegion_t;
 
+/* Used to pass information about the heap out of vPortGetHeapStats(). */
+typedef struct xHeapStats
+{
+	size_t xAvailableHeapSpaceInBytes;		/* The total heap size currently available - this is the sum of all the free blocks, not the largest block that can be allocated. */
+	size_t xSizeOfLargestFreeBlockInBytes; 	/* The maximum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
+	size_t xSizeOfSmallestFreeBlockInBytes; /* The minimum size, in bytes, of all the free blocks within the heap at the time vPortGetHeapStats() is called. */
+	size_t xNumberOfFreeBlocks;				/* The number of free memory blocks within the heap at the time vPortGetHeapStats() is called. */
+	size_t xMinimumEverFreeBytesRemaining;	/* The minimum amount of total free memory (sum of all free blocks) there has been in the heap since the system booted. */
+	size_t xNumberOfSuccessfulAllocations;	/* The number of calls to pvPortMalloc() that have returned a valid memory block. */
+	size_t xNumberOfSuccessfulFrees;		/* The number of calls to vPortFree() that has successfully freed a block of memory. */
+} HeapStats_t;
+
 /*
  * Used to define multiple heap regions for use by heap_5.c.  This function
  * must be called before any calls to pvPortMalloc() - not creating a task,
@@ -138,6 +151,11 @@ typedef struct HeapRegion
  */
 void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) PRIVILEGED_FUNCTION;
 
+/*
+ * Returns a HeapStats_t structure filled with information about the current
+ * heap state.
+ */
+void vPortGetHeapStats( HeapStats_t *pxHeapStats );
 
 /*
  * Map to the memory management routines required for the port.
diff --git a/FreeRTOS/Source/portable/MemMang/heap_4.c b/FreeRTOS/Source/portable/MemMang/heap_4.c
index 23714eb240..9270646344 100644
--- a/FreeRTOS/Source/portable/MemMang/heap_4.c
+++ b/FreeRTOS/Source/portable/MemMang/heap_4.c
@@ -97,10 +97,12 @@ static const size_t xHeapStructSize	= ( sizeof( BlockLink_t ) + ( ( size_t ) ( p
 /* Create a couple of list links to mark the start and end of the list. */
 static BlockLink_t xStart, *pxEnd = NULL;
 
-/* Keeps track of the number of free bytes remaining, but says nothing about
-fragmentation. */
+/* Keeps track of the number of calls to allocate and free memory as well as the
+number of free bytes remaining, but says nothing about fragmentation. */
 static size_t xFreeBytesRemaining = 0U;
 static size_t xMinimumEverFreeBytesRemaining = 0U;
+static size_t xNumberOfSuccessfulAllocations = 0;
+static size_t xNumberOfSuccessfulFrees = 0;
 
 /* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize
 member of an BlockLink_t structure is set then the block belongs to the
@@ -221,6 +223,7 @@ void *pvReturn = NULL;
 					by the application and has no "next" block. */
 					pxBlock->xBlockSize |= xBlockAllocatedBit;
 					pxBlock->pxNextFreeBlock = NULL;
+					xNumberOfSuccessfulAllocations++;
 				}
 				else
 				{
@@ -292,6 +295,7 @@ BlockLink_t *pxLink;
 					xFreeBytesRemaining += pxLink->xBlockSize;
 					traceFREE( pv, pxLink->xBlockSize );
 					prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
+					xNumberOfSuccessfulFrees++;
 				}
 				( void ) xTaskResumeAll();
 			}
@@ -326,6 +330,58 @@ void vPortInitialiseBlocks( void )
 }
 /*-----------------------------------------------------------*/
 
+void vPortGetHeapStats( HeapStats_t *pxHeapStats )
+{
+BlockLink_t *pxBlock;
+size_t xBlocks = 0, xMaxSize = 0, xMinSize = 0;
+
+	vTaskSuspendAll();
+	{
+		pxBlock = xStart.pxNextFreeBlock;
+
+		/* pxBlock will be NULL if the heap has not been initialised.  The heap
+		is initialised automatically when the first allocation is made. */
+		if( pxBlock != NULL )
+		{
+			do
+			{
+				/* Increment the number of blocks and record the largest block seen
+				so far. */
+				xBlocks++;
+
+				if( pxBlock->xBlockSize > xMaxSize )
+				{
+					xMaxSize = pxBlock->xBlockSize;
+				}
+
+				if( pxBlock->xBlockSize < xMinSize )
+				{
+					xMinSize = pxBlock->xBlockSize;
+				}
+
+				/* Move to the next block in the chain until the last block is
+				reached. */
+				pxBlock = pxBlock->pxNextFreeBlock;
+			} while( pxBlock != pxEnd );
+		}
+	}
+	xTaskResumeAll();
+
+	pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
+	pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
+	pxHeapStats->xNumberOfFreeBlocks = xBlocks;
+
+	taskENTER_CRITICAL();
+	{
+		pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
+		pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
+		pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
+		pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
+	}
+	taskEXIT_CRITICAL();
+}
+/*-----------------------------------------------------------*/
+
 static void prvHeapInit( void )
 {
 BlockLink_t *pxFirstFreeBlock;
diff --git a/FreeRTOS/Source/portable/MemMang/heap_5.c b/FreeRTOS/Source/portable/MemMang/heap_5.c
index 8e50762360..614210edf3 100644
--- a/FreeRTOS/Source/portable/MemMang/heap_5.c
+++ b/FreeRTOS/Source/portable/MemMang/heap_5.c
@@ -116,10 +116,12 @@ static const size_t xHeapStructSize	= ( sizeof( BlockLink_t ) + ( ( size_t ) ( p
 /* Create a couple of list links to mark the start and end of the list. */
 static BlockLink_t xStart, *pxEnd = NULL;
 
-/* Keeps track of the number of free bytes remaining, but says nothing about
-fragmentation. */
+/* Keeps track of the number of calls to allocate and free memory as well as the
+number of free bytes remaining, but says nothing about fragmentation. */
 static size_t xFreeBytesRemaining = 0U;
 static size_t xMinimumEverFreeBytesRemaining = 0U;
+static size_t xNumberOfSuccessfulAllocations = 0;
+static size_t xNumberOfSuccessfulFrees = 0;
 
 /* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize
 member of an BlockLink_t structure is set then the block belongs to the
@@ -231,6 +233,7 @@ void *pvReturn = NULL;
 					by the application and has no "next" block. */
 					pxBlock->xBlockSize |= xBlockAllocatedBit;
 					pxBlock->pxNextFreeBlock = NULL;
+					xNumberOfSuccessfulAllocations++;
 				}
 				else
 				{
@@ -301,6 +304,7 @@ BlockLink_t *pxLink;
 					xFreeBytesRemaining += pxLink->xBlockSize;
 					traceFREE( pv, pxLink->xBlockSize );
 					prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
+					xNumberOfSuccessfulFrees++;
 				}
 				( void ) xTaskResumeAll();
 			}
@@ -482,4 +486,56 @@ const HeapRegion_t *pxHeapRegion;
 	/* Work out the position of the top bit in a size_t variable. */
 	xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );
 }
+/*-----------------------------------------------------------*/
+
+void vPortGetHeapStats( HeapStats_t *pxHeapStats )
+{
+	BlockLink_t *pxBlock;
+	size_t xBlocks = 0, xMaxSize = 0, xMinSize = 0;
+
+	vTaskSuspendAll();
+	{
+		pxBlock = xStart.pxNextFreeBlock;
+
+		/* pxBlock will be NULL if the heap has not been initialised.  The heap
+		is initialised automatically when the first allocation is made. */
+		if( pxBlock != NULL )
+		{
+			do
+			{
+				/* Increment the number of blocks and record the largest block seen
+				so far. */
+				xBlocks++;
+
+				if( pxBlock->xBlockSize > xMaxSize )
+				{
+					xMaxSize = pxBlock->xBlockSize;
+				}
+
+				if( pxBlock->xBlockSize < xMinSize )
+				{
+					xMinSize = pxBlock->xBlockSize;
+				}
+
+				/* Move to the next block in the chain until the last block is
+				reached. */
+				pxBlock = pxBlock->pxNextFreeBlock;
+			} while( pxBlock != pxEnd );
+		}
+	}
+	xTaskResumeAll();
+
+	pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize;
+	pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize;
+	pxHeapStats->xNumberOfFreeBlocks = xBlocks;
+
+	taskENTER_CRITICAL();
+	{
+		pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining;
+		pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations;
+		pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees;
+		pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining;
+	}
+	taskEXIT_CRITICAL();
+}