diff --git a/source/Core/BSP/Pinecilv2/FreeRTOSConfig.h b/source/Core/BSP/Pinecilv2/FreeRTOSConfig.h index 4877b936..718036a6 100644 --- a/source/Core/BSP/Pinecilv2/FreeRTOSConfig.h +++ b/source/Core/BSP/Pinecilv2/FreeRTOSConfig.h @@ -14,7 +14,7 @@ #define configTICK_RATE_HZ ((TickType_t)1000) #define configMAX_PRIORITIES (7) #define configMINIMAL_STACK_SIZE ((unsigned short)160) /* Only needs to be this high as some demo tasks also use this constant. In production only the idle task would use this. */ -#define configTOTAL_HEAP_SIZE ((size_t)1024 * 4) +#define configTOTAL_HEAP_SIZE ((size_t)1024 * 8) #define configMAX_TASK_NAME_LEN (24) #define configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 diff --git a/source/Core/BSP/Pinecilv2/MemMang/heap_4.c b/source/Core/BSP/Pinecilv2/MemMang/heap_5.c similarity index 69% rename from source/Core/BSP/Pinecilv2/MemMang/heap_4.c rename to source/Core/BSP/Pinecilv2/MemMang/heap_5.c index 8008f270..aab4f8f4 100644 --- a/source/Core/BSP/Pinecilv2/MemMang/heap_4.c +++ b/source/Core/BSP/Pinecilv2/MemMang/heap_5.c @@ -22,15 +22,50 @@ * https://www.FreeRTOS.org * https://github.com/FreeRTOS * + * 1 tab == 4 spaces! */ /* - * A sample implementation of pvPortMalloc() and vPortFree() that combines - * (coalescences) adjacent memory blocks as they are freed, and in so doing - * limits memory fragmentation. + * A sample implementation of pvPortMalloc() that allows the heap to be defined + * across multiple non-contigous blocks and combines (coalescences) adjacent + * memory blocks as they are freed. + * + * See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative + * implementations, and the memory management pages of https://www.FreeRTOS.org + * for more information. + * + * Usage notes: + * + * vPortDefineHeapRegions() ***must*** be called before pvPortMalloc(). + * pvPortMalloc() will be called if any task objects (tasks, queues, event + * groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be + * called before any other objects are defined. + * + * vPortDefineHeapRegions() takes a single parameter. The parameter is an array + * of HeapRegion_t structures. HeapRegion_t is defined in portable.h as + * + * typedef struct HeapRegion + * { + * uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap. + * size_t xSizeInBytes; << Size of the block of memory. + * } HeapRegion_t; + * + * The array is terminated using a NULL zero sized region definition, and the + * memory regions defined in the array ***must*** appear in address order from + * low address to high address. So the following is a valid example of how + * to use the function. + * + * HeapRegion_t xHeapRegions[] = + * { + * { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000 + * { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000 + * { NULL, 0 } << Terminates the array. + * }; + * + * vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions(). + * + * Note 0x80000000 is the lower address so appears in the array first. * - * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the - * memory management pages of https://www.FreeRTOS.org for more information. */ #include @@ -54,16 +89,6 @@ /* Assumes 8bit bytes! */ #define heapBITS_PER_BYTE ( ( size_t ) 8 ) -/* Allocate the memory for the heap. */ -#if ( configAPPLICATION_ALLOCATED_HEAP == 1 ) - -/* The application writer has already defined the array used for the RTOS -* heap - probably so it can be placed in a special segment or address. */ - extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -#else - PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -#endif /* configAPPLICATION_ALLOCATED_HEAP */ - /* Define the linked list structure. This is used to link free blocks in order * of their memory address. */ typedef struct A_BLOCK_LINK @@ -80,13 +105,7 @@ typedef struct A_BLOCK_LINK * the block in front it and/or the block behind it if the memory blocks are * adjacent to each other. */ -static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) PRIVILEGED_FUNCTION; - -/* - * Called automatically to setup the required heap structures the first time - * pvPortMalloc() is called. - */ -static void prvHeapInit( void ) PRIVILEGED_FUNCTION; +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ); /*-----------------------------------------------------------*/ @@ -95,20 +114,20 @@ static void prvHeapInit( void ) PRIVILEGED_FUNCTION; static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); /* Create a couple of list links to mark the start and end of the list. */ -PRIVILEGED_DATA static BlockLink_t xStart, * pxEnd = NULL; +static BlockLink_t xStart, * pxEnd = NULL; /* 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. */ -PRIVILEGED_DATA static size_t xFreeBytesRemaining = 0U; -PRIVILEGED_DATA static size_t xMinimumEverFreeBytesRemaining = 0U; -PRIVILEGED_DATA static size_t xNumberOfSuccessfulAllocations = 0; -PRIVILEGED_DATA static size_t xNumberOfSuccessfulFrees = 0; +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 * application. When the bit is free the block is still part of the free heap * space. */ -PRIVILEGED_DATA static size_t xBlockAllocatedBit = 0; +static size_t xBlockAllocatedBit = 0; /*-----------------------------------------------------------*/ @@ -117,19 +136,12 @@ void * pvPortMalloc( size_t xWantedSize ) BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink; void * pvReturn = NULL; + /* The heap must be initialised before the first call to + * prvPortMalloc(). */ + configASSERT( pxEnd ); + vTaskSuspendAll(); { - /* If this is the first call to malloc then the heap will require - * initialisation to setup the list of free blocks. */ - if( pxEnd == NULL ) - { - prvHeapInit(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - /* 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 @@ -148,7 +160,6 @@ void * pvPortMalloc( size_t xWantedSize ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); - configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); } else { @@ -194,7 +205,6 @@ void * pvPortMalloc( size_t xWantedSize ) * cast is used to prevent byte alignment warnings from the * compiler. */ pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize ); - configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_ALIGNMENT_MASK ) == 0 ); /* Calculate the sizes of two blocks split from the * single block. */ @@ -202,7 +212,7 @@ void * pvPortMalloc( size_t xWantedSize ) pxBlock->xBlockSize = xWantedSize; /* Insert the new block into the list of free blocks. */ - prvInsertBlockIntoFreeList( pxNewBlockLink ); + prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); } else { @@ -259,7 +269,6 @@ void * pvPortMalloc( size_t xWantedSize ) } #endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */ - configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_ALIGNMENT_MASK ) == 0 ); return pvReturn; } /*-----------------------------------------------------------*/ @@ -325,61 +334,7 @@ size_t xPortGetMinimumEverFreeHeapSize( void ) } /*-----------------------------------------------------------*/ -void vPortInitialiseBlocks( void ) -{ - /* This just exists to keep the linker quiet. */ -} -/*-----------------------------------------------------------*/ - -static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */ -{ - BlockLink_t * pxFirstFreeBlock; - uint8_t * pucAlignedHeap; - size_t uxAddress; - size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; - - /* Ensure the heap starts on a correctly aligned boundary. */ - uxAddress = ( size_t ) ucHeap; - - if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) - { - uxAddress += ( portBYTE_ALIGNMENT - 1 ); - uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); - xTotalHeapSize -= uxAddress - ( size_t ) ucHeap; - } - - pucAlignedHeap = ( uint8_t * ) uxAddress; - - /* xStart is used to hold a pointer to the first item in the list of free - * blocks. The void cast is used to prevent compiler warnings. */ - xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; - xStart.xBlockSize = ( size_t ) 0; - - /* pxEnd is used to mark the end of the list of free blocks and is inserted - * at the end of the heap space. */ - uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize; - uxAddress -= xHeapStructSize; - uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); - pxEnd = ( void * ) uxAddress; - pxEnd->xBlockSize = 0; - pxEnd->pxNextFreeBlock = NULL; - - /* To start with there is a single free block that is sized to take up the - * entire heap space, minus the space taken by pxEnd. */ - pxFirstFreeBlock = ( void * ) pucAlignedHeap; - pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock; - pxFirstFreeBlock->pxNextFreeBlock = pxEnd; - - /* Only one block exists - and it covers the entire usable heap space. */ - xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; - - /* Work out the position of the top bit in a size_t variable. */ - xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); -} -/*-----------------------------------------------------------*/ - -static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */ +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) { BlockLink_t * pxIterator; uint8_t * puc; @@ -442,6 +397,101 @@ static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVI } /*-----------------------------------------------------------*/ +void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) +{ + BlockLink_t * pxFirstFreeBlockInRegion = NULL, * pxPreviousFreeBlock; + size_t xAlignedHeap; + size_t xTotalRegionSize, xTotalHeapSize = 0; + BaseType_t xDefinedRegions = 0; + size_t xAddress; + const HeapRegion_t * pxHeapRegion; + + /* Can only call once! */ + configASSERT( pxEnd == NULL ); + + pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); + + while( pxHeapRegion->xSizeInBytes > 0 ) + { + xTotalRegionSize = pxHeapRegion->xSizeInBytes; + + /* Ensure the heap region starts on a correctly aligned boundary. */ + xAddress = ( size_t ) pxHeapRegion->pucStartAddress; + + if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) + { + xAddress += ( portBYTE_ALIGNMENT - 1 ); + xAddress &= ~portBYTE_ALIGNMENT_MASK; + + /* Adjust the size for the bytes lost to alignment. */ + xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress; + } + + xAlignedHeap = xAddress; + + /* Set xStart if it has not already been set. */ + if( xDefinedRegions == 0 ) + { + /* xStart is used to hold a pointer to the first item in the list of + * free blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = ( BlockLink_t * ) xAlignedHeap; + xStart.xBlockSize = ( size_t ) 0; + } + else + { + /* Should only get here if one region has already been added to the + * heap. */ + configASSERT( pxEnd != NULL ); + + /* Check blocks are passed in with increasing start addresses. */ + configASSERT( xAddress > ( size_t ) pxEnd ); + } + + /* Remember the location of the end marker in the previous region, if + * any. */ + pxPreviousFreeBlock = pxEnd; + + /* pxEnd is used to mark the end of the list of free blocks and is + * inserted at the end of the region space. */ + xAddress = xAlignedHeap + xTotalRegionSize; + xAddress -= xHeapStructSize; + xAddress &= ~portBYTE_ALIGNMENT_MASK; + pxEnd = ( BlockLink_t * ) xAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block in this region that is + * sized to take up the entire heap region minus the space taken by the + * free block structure. */ + pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap; + pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion; + pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd; + + /* If this is not the first region that makes up the entire heap space + * then link the previous region to this region. */ + if( pxPreviousFreeBlock != NULL ) + { + pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion; + } + + xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; + + /* Move onto the next HeapRegion_t structure. */ + xDefinedRegions++; + pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); + } + + xMinimumEverFreeBytesRemaining = xTotalHeapSize; + xFreeBytesRemaining = xTotalHeapSize; + + /* Check something was actually defined before it is accessed. */ + configASSERT( xTotalHeapSize ); + + /* 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; @@ -466,9 +516,15 @@ void vPortGetHeapStats( HeapStats_t * pxHeapStats ) xMaxSize = pxBlock->xBlockSize; } - if( pxBlock->xBlockSize < xMinSize ) + /* Heap five will have a zero sized block at the end of each + * each region - the block is only used to link to the next + * heap region so it not a real block. */ + if( pxBlock->xBlockSize != 0 ) { - xMinSize = pxBlock->xBlockSize; + if( pxBlock->xBlockSize < xMinSize ) + { + xMinSize = pxBlock->xBlockSize; + } } /* Move to the next block in the chain until the last block is diff --git a/source/Core/BSP/Pinecilv2/Setup.cpp b/source/Core/BSP/Pinecilv2/Setup.cpp index adfbc1c9..26f7872c 100644 --- a/source/Core/BSP/Pinecilv2/Setup.cpp +++ b/source/Core/BSP/Pinecilv2/Setup.cpp @@ -17,12 +17,25 @@ #define ADC_FILTER_LEN 4 uint16_t ADCReadings[ADC_NORM_SAMPLES]; // room for 32 lots of the pair of readings +// Heap + +extern uint8_t _heap_start; +extern uint8_t _heap_size; // @suppress("Type cannot be resolved") +static HeapRegion_t xHeapRegions[] = { + {&_heap_start, (unsigned int)&_heap_size}, + {NULL, 0}, /* Terminates the array. */ + {NULL, 0} /* Terminates the array. */ +}; + // Functions void setup_timer_scheduler(void); void setup_pwm(void); void setup_adc(void); void hardware_init() { + + vPortDefineHeapRegions(xHeapRegions); + gpio_set_mode(OLED_RESET_Pin, GPIO_OUTPUT_MODE); gpio_set_mode(KEY_A_Pin, GPIO_INPUT_PD_MODE); gpio_set_mode(KEY_B_Pin, GPIO_INPUT_PD_MODE); diff --git a/source/Core/BSP/Pinecilv2/ble.c b/source/Core/BSP/Pinecilv2/ble.c index 9a174255..ae32c231 100644 --- a/source/Core/BSP/Pinecilv2/ble.c +++ b/source/Core/BSP/Pinecilv2/ble.c @@ -55,18 +55,23 @@ void bt_enable_cb(int err) } + void ble_stack_start(void) { - MSG("[OS] ble_controller_init...\r\n"); + MSG("[OS] ble_stack_start...\r\n"); GLB_Set_EM_Sel(GLB_EM_8KB); + MSG("[OS] ble_controller_init...\r\n"); ble_controller_init(configMAX_PRIORITIES - 1); + MSG("[OS] ble_controller_init...Done\r\n"); // // Initialize BLE Host stack - // MSG("[OS] hci_driver_init...\r\n"); - // hci_driver_init(); + MSG("[OS] hci_driver_init...\r\n"); + hci_driver_init(); + MSG("[OS] hci_driver_init...Done\r\n"); - // MSG("[OS] bt_enable...\r\n"); - // bt_enable(bt_enable_cb); + MSG("[OS] bt_enable...\r\n"); + bt_enable(bt_enable_cb); + MSG("[OS] bt_enable...Done\r\n"); }