int main(void) { vPortDefineHeapRegions(xHeapRegions); SystemCoreClockUpdate(); SystemSetupStuff(); xQueue = xQueueCreate(mainQUEUE_LENGTH, sizeof(unsigned long)); if (xQueue != NULL) { //xTaskCreate(task_DigitalTest, "Digital", configMINIMAL_STACK_SIZE, NULL, 5, NULL); xTaskCreate(task_Keypad, "Keypad", configMINIMAL_STACK_SIZE, NULL, 6, NULL); #if DEBUGCONSOLE xTaskCreate(task_Console, "Console", configMINIMAL_STACK_SIZE, NULL, 5, NULL); #else xTaskCreate(task_LCD, "LCD", 1024, NULL, 8, NULL); #endif xTaskCreate(task_Sensor, "Sensor", 256, NULL, 5, NULL); xTaskCreate(task_PowerMgmt, "PowerMgmt", 160, NULL, 5, NULL); xTaskCreate(task_MotorCtrl, "MotorCtrl", configMINIMAL_STACK_SIZE, NULL, 5, NULL); vTaskStartScheduler(); } }
static void prvInitialiseHeap( void ) { /* This demo uses heap_5.c, so start by defining some heap regions. This is only done to provide an example as this demo could easily create one large heap region instead of multiple smaller heap regions - in which case heap_4.c would be the more appropriate choice. No initialisation is required when heap_4.c is used. The xHeapRegions structure requires the regions to be defined in order, so this just creates one big array, then populates the structure with 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(). */ const HeapRegion_t xHeapRegions[] = { /* Start address with dummy offsets Size */ { ucHeap + 1, mainREGION_1_SIZE }, { ucHeap + 15 + mainREGION_1_SIZE, mainREGION_2_SIZE }, { ucHeap + 19 + mainREGION_1_SIZE + mainREGION_2_SIZE, mainREGION_3_SIZE }, { NULL, 0 } }; /* Sanity check that the sizes and offsets defined actually fit into the array. */ configASSERT( ( ulAdditionalOffset + mainREGION_1_SIZE + mainREGION_2_SIZE + mainREGION_3_SIZE ) < configTOTAL_HEAP_SIZE ); vPortDefineHeapRegions( xHeapRegions ); }
static void prvInitHeapMemory(void) { extern char _ebss[]; extern char __top_RAM[]; extern char __base_RAM2[]; extern char __top_RAM2[]; /* Allocate two blocks of RAM for use by the heap. */ const char* base_RAM = _ebss + REDLIB_HEAP; const HeapRegion_t xHeapRegions[] = { { ( uint8_t * ) base_RAM, __top_RAM - base_RAM }, // Remainder of first 32KB { ( uint8_t * ) __base_RAM2, __top_RAM2 - __base_RAM2}, // 40KB { NULL, 0 } /* Terminates the array. */ }; vPortDefineHeapRegions(xHeapRegions); }
void *pvPortMalloc( size_t xWantedSize ) { BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; void *pvReturn = NULL; /* Realtek test code start */ if(pxEnd == NULL) { // lower StartAddress must put in lower index of array, must sort by address xHeapRegions[0].pucStartAddress = (uint8_t*)0x10002300; // released image1 text xHeapRegions[0].xSizeInBytes = 0x3D00; xHeapRegions[1].pucStartAddress = ucHeap; xHeapRegions[1].xSizeInBytes = sizeof(ucHeap); vPortDefineHeapRegions( xHeapRegions ); } /* Realtek test code end */ /* The heap must be initialised before the first call to prvPortMalloc(). */ configASSERT( pxEnd ); vTaskSuspendAll(); { /* Check the requested block size is not so large that the top bit is set. The top bit of the block size member of the BlockLink_t structure is used to determine who owns the block - the application or the kernel, so it must be free. */ if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) { /* The wanted size is increased so it can contain a BlockLink_t structure in addition to the requested amount of bytes. */ if( xWantedSize > 0 ) { xWantedSize += uxHeapStructSize; /* Ensure that blocks are always aligned to the required number of bytes. */ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until one of adequate size is found. */ pxPreviousBlock = &xStart; pxBlock = xStart.pxNextFreeBlock; while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) { pxPreviousBlock = pxBlock; pxBlock = pxBlock->pxNextFreeBlock; } /* If the end marker was reached then a block of adequate size was not found. */ if( pxBlock != pxEnd ) { /* Return the memory space pointed to - jumping over the BlockLink_t structure at its start. */ pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize ); /* This block is being returned for use so must be taken out of the list of free blocks. */ pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; /* If the block is larger than required it can be split into two. */ if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) { /* This block is to be split into two. Create a new block following the number of bytes requested. The void cast is used to prevent byte alignment warnings from the compiler. */ pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); /* Calculate the sizes of two blocks split from the single block. */ pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); } else { mtCOVERAGE_TEST_MARKER(); } xFreeBytesRemaining -= pxBlock->xBlockSize; if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) { xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; } else { mtCOVERAGE_TEST_MARKER(); } /* The block is being returned - it is allocated and owned by the application and has no "next" block. */ pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->pxNextFreeBlock = NULL; } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } traceMALLOC( pvReturn, xWantedSize ); } ( void ) xTaskResumeAll(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif return pvReturn; }
void *pvPortMalloc( size_t xWantedSize, const char * file, unsigned line, bool use_iram) #endif { BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; void *pvReturn = NULL; static bool is_inited = false; if (!is_inited) { void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); xHeapRegions[0].pucStartAddress = ( uint8_t * )&_heap_start; xHeapRegions[0].xSizeInBytes = (( size_t)( 0x40000000 - (uint32)&_heap_start)); xHeapRegions[1].pucStartAddress = ( uint8_t * )&_lit4_end; xHeapRegions[1].xSizeInBytes = (( size_t)( 0x4010C000 - (uint32)&_lit4_end)); is_inited = true; vPortDefineHeapRegions(xHeapRegions); } /* The heap must be initialised before the first call to prvPortMalloc(). */ configASSERT( pxEnd ); // vTaskSuspendAll(); ETS_INTR_LOCK(); { /* Check the requested block size is not so large that the top bit is set. The top bit of the block size member of the BlockLink_t structure is used to determine who owns the block - the application or the kernel, so it must be free. */ if( ( xWantedSize & xBlockAllocatedBit ) == 0 ) { /* The wanted size is increased so it can contain a BlockLink_t structure in addition to the requested amount of bytes. */ if( xWantedSize > 0 ) { xWantedSize += uxHeapStructSize; /* Ensure that blocks are always aligned to the required number of bytes. */ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) { /* Traverse the list from the start (lowest address) block until one of adequate size is found. */ pxPreviousBlock = &xStart; pxBlock = xStart.pxNextFreeBlock; BlockLink_t *pxIterator; /* Iterate through the list until a block is found that has a higher address than the block being inserted. */ for( pxIterator = &xStart; pxIterator->pxNextFreeBlock != 0; pxIterator = pxIterator->pxNextFreeBlock ) { if ((line == 0 || use_iram == true) && (uint32)pxIterator->pxNextFreeBlock > 0x40000000 && pxIterator->pxNextFreeBlock->xBlockSize > xWantedSize) { pxPreviousBlock = pxIterator; pxBlock = pxIterator->pxNextFreeBlock; break; } } while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) { pxPreviousBlock = pxBlock; pxBlock = pxBlock->pxNextFreeBlock; } /* If the end marker was reached then a block of adequate size was not found. */ if( pxBlock != pxEnd ) { /* Return the memory space pointed to - jumping over the BlockLink_t structure at its start. */ pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + uxHeapStructSize ); /* This block is being returned for use so must be taken out of the list of free blocks. */ pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; /* If the block is larger than required it can be split into two. */ if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ) { /* This block is to be split into two. Create a new block following the number of bytes requested. The void cast is used to prevent byte alignment warnings from the compiler. */ pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); /* Calculate the sizes of two blocks split from the single block. */ pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); } else { mtCOVERAGE_TEST_MARKER(); } xFreeBytesRemaining -= pxBlock->xBlockSize; if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) { xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; } else { mtCOVERAGE_TEST_MARKER(); } /* The block is being returned - it is allocated and owned by the application and has no "next" block. */ pxBlock->xBlockSize |= xBlockAllocatedBit; pxBlock->pxNextFreeBlock = NULL; #ifdef MEMLEAK_DEBUG if(uxHeapStructSize >= sizeof( BlockLink_t )){ pxBlock->file = file; pxBlock->line = line; } //link the use block prvInsertBlockIntoUsedList(pxBlock); #endif } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } } else { mtCOVERAGE_TEST_MARKER(); } traceMALLOC( pvReturn, xWantedSize ); } // ( void ) xTaskResumeAll(); ETS_INTR_UNLOCK(); #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } else { mtCOVERAGE_TEST_MARKER(); } } #endif return pvReturn; }