From 0be83598f1e61917b9ea6789f793a87c3a8e2907 Mon Sep 17 00:00:00 2001 From: "Ben V. Brown" <5425387+Ralim@users.noreply.github.com> Date: Thu, 6 Jul 2023 07:35:01 +1000 Subject: [PATCH] Try side-port of different linker and ram for PinecilV2 (#1730) Try side-port of different linker and ram --- source/Core/BSP/Pinecilv2/Setup.cpp | 8 +- .../bsp/bsp_common/platform/bflb_platform.c | 18 +- .../drivers/bl702_driver/bl702_flash.ld | 28 +- .../drivers/bl702_driver/startup/drv_mmheap.c | 421 ++++++++++++++++++ .../drivers/bl702_driver/startup/drv_mmheap.h | 159 +++++++ 5 files changed, 605 insertions(+), 29 deletions(-) create mode 100644 source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.c create mode 100644 source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.h diff --git a/source/Core/BSP/Pinecilv2/Setup.cpp b/source/Core/BSP/Pinecilv2/Setup.cpp index 2134e3286..96d9a5d0e 100644 --- a/source/Core/BSP/Pinecilv2/Setup.cpp +++ b/source/Core/BSP/Pinecilv2/Setup.cpp @@ -19,15 +19,13 @@ uint16_t ADCReadings[ADC_NORM_SAMPLES]; // room for 32 lots of the pair of readi // Heap -extern uint8_t __HeapBase; -extern uint8_t __HeapLimit; // @suppress("Type cannot be resolved") -const uint32_t _heap_size = ((&__HeapLimit) - (&__HeapBase)); +extern uint8_t _heap_start; +extern uint8_t _heap_size; // @suppress("Type cannot be resolved") static HeapRegion_t xHeapRegions[] = { - {&__HeapBase, (unsigned int)_heap_size}, + {&_heap_start, (unsigned int)&_heap_size}, {NULL, 0}, /* Terminates the array. */ {NULL, 0} /* Terminates the array. */ }; - // Functions void setup_timer_scheduler(void); diff --git a/source/Core/BSP/Pinecilv2/bl_mcu_sdk/bsp/bsp_common/platform/bflb_platform.c b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/bsp/bsp_common/platform/bflb_platform.c index 0923d8ef3..47aad724f 100644 --- a/source/Core/BSP/Pinecilv2/bl_mcu_sdk/bsp/bsp_common/platform/bflb_platform.c +++ b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/bsp/bsp_common/platform/bflb_platform.c @@ -21,6 +21,7 @@ * */ #include "bflb_platform.h" +#include "drv_mmheap.h" #include "hal_common.h" #include "hal_flash.h" #include "hal_mtimer.h" @@ -32,8 +33,11 @@ extern uint32_t __HeapLimit; static uint8_t uart_dbg_disable = 0; -// struct heap_info mmheap_root; +struct heap_info mmheap_root; +static struct heap_region system_mmheap[] = { + {NULL, 0}, {NULL, 0}, /* Terminates the array. */ +}; __WEAK__ void board_init(void) {} __WEAK__ enum uart_index_type board_get_debug_uart_index(void) { return 0; } @@ -88,14 +92,14 @@ void bflb_platform_init(uint32_t baudrate) { } static bool initialized = false; if (!initialized) { - // system_mmheap[0].addr = (uint8_t *)&__HeapBase; - // system_mmheap[0].mem_size = ((size_t)&__HeapLimit - (size_t)&__HeapBase); + system_mmheap[0].addr = (uint8_t *)&__HeapBase; + system_mmheap[0].mem_size = ((size_t)&__HeapLimit - (size_t)&__HeapBase); - // if (system_mmheap[0].mem_size > 0) { - // mmheap_init(&mmheap_root, system_mmheap); - // } + if (system_mmheap[0].mem_size > 0) { + mmheap_init(&mmheap_root, system_mmheap); + } - // MSG("dynamic memory init success,heap size = %d Kbyte \r\n", system_mmheap[0].mem_size / 1024); + MSG("dynamic memory init success,heap size = %d Kbyte \r\n", system_mmheap[0].mem_size / 1024); initialized = 1; if (ret != SUCCESS) { MSG("flash init fail!!!\r\n"); diff --git a/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/bl702_flash.ld b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/bl702_flash.ld index b36c21f6c..37165c60c 100644 --- a/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/bl702_flash.ld +++ b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/bl702_flash.ld @@ -17,17 +17,18 @@ OUTPUT_ARCH( "riscv" ) /* configure the entry point */ ENTRY(_enter) -StackSize = 0x800; /* 2KB */ - -__EM_SIZE = DEFINED(ble_controller_init) ? 8K : 0K; +StackSize = 0x1000; /* 4KB */ +__EM_SIZE =8K; MEMORY { xip_memory (rx) : ORIGIN = 0x23000000, LENGTH = 1022K itcm_memory (rx) : ORIGIN = 0x22014000, LENGTH = 12K - dtcm_memory (rx) : ORIGIN = 0x42017000, LENGTH = 4K - ram_memory (!rx) : ORIGIN = 0x42018000, LENGTH = 96K - hbn_memory (rx) : ORIGIN = 0x40010000, LENGTH = 0xE00 /* hbn ram 4K used 3.5K*/ + dtcm_memory (rx) : ORIGIN = 0x42014000, LENGTH = 8K + ram_memory (!rx) : ORIGIN = 0x42016000, LENGTH = 72K + rsvd_memory (!rx) : ORIGIN = 0x42028000, LENGTH = 1K + ram2_memory (!rx) : ORIGIN = 0x42028400, LENGTH = (31K - __EM_SIZE) + hbn_memory (rx) : ORIGIN = 0x40010000, LENGTH = 0xE00 /* hbn ram 4K used 3.5K*/ } SECTIONS @@ -91,13 +92,12 @@ SECTIONS . = ALIGN(4); __text_code_end__ = .; } > xip_memory - .preinit_array : + .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } >xip_memory AT>xip_memory - .init_array : { PROVIDE_HIDDEN (__init_array_start = .); @@ -105,7 +105,6 @@ SECTIONS KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) PROVIDE_HIDDEN (__init_array_end = .); } >xip_memory AT>xip_memory - .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); @@ -113,7 +112,6 @@ SECTIONS KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) PROVIDE_HIDDEN (__fini_array_end = .); } >xip_memory AT>xip_memory - .ctors : { /* gcc uses crtbegin.o to find the start of @@ -137,7 +135,6 @@ SECTIONS KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } >xip_memory AT>xip_memory - .dtors : { KEEP (*crtbegin.o(.dtors)) @@ -146,13 +143,11 @@ SECTIONS KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } >xip_memory AT>xip_memory - .lalign : { . = ALIGN(4); PROVIDE( _data_lma = . ); } >xip_memory AT>xip_memory - . = ALIGN(4); __itcm_load_addr = .; @@ -182,7 +177,7 @@ SECTIONS __tcm_code_end__ = .; } > itcm_memory - __hbn_load_addr = __itcm_load_addr + SIZEOF(.itcm_region); + __hbn_load_addr = __itcm_load_addr + SIZEOF(.itcm_region); .hbn_ram_region : AT (__hbn_load_addr) { @@ -208,8 +203,6 @@ SECTIONS . = ALIGN(4); __tcm_data_end__ = .; } > dtcm_memory - - /*************************************************************************/ /* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign @@ -226,7 +219,6 @@ SECTIONS __StackTop = ORIGIN(dtcm_memory) + LENGTH(dtcm_memory); PROVIDE( __freertos_irq_stack_top = __StackTop); __StackLimit = __StackTop - SIZEOF(.stack_dummy); - /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= __tcm_data_end__, "region RAM overflowed with stack") /*************************************************************************/ @@ -326,5 +318,7 @@ SECTIONS ASSERT((__HeapLimit - __HeapBase ) >= __heap_min_size, "heap size is too short.") + PROVIDE( _heap_start = ORIGIN(ram2_memory) ); + PROVIDE( _heap_size = LENGTH(ram2_memory) ); } diff --git a/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.c b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.c new file mode 100644 index 000000000..7369b7c50 --- /dev/null +++ b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.c @@ -0,0 +1,421 @@ +/** + * @file drv_mmheap.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ + +#include "drv_mmheap.h" + +#define MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT 8 +#define MEM_MANAGE_BITS_PER_BYTE 8 +#define MEM_MANAGE_MEM_STRUCT_SIZE mmheap_align_up(sizeof(struct heap_node), MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT) +#define MEM_MANAGE_MINUM_MEM_SIZE (MEM_MANAGE_MEM_STRUCT_SIZE << 1) +#define MEM_MANAGE_ALLOCA_LABAL ((size_t)((size_t)1 << (sizeof(size_t) * MEM_MANAGE_BITS_PER_BYTE - 1))) + +static inline size_t mmheap_align_down(size_t data, size_t align_byte) +{ + return data & ~(align_byte - 1); +} + +static inline size_t mmheap_align_up(size_t data, size_t align_byte) +{ + return (data + align_byte - 1) & ~(align_byte - 1); +} + +static inline struct heap_node *mmheap_addr_sub(const void *addr) +{ + return (struct heap_node *)((const uint8_t *)addr - MEM_MANAGE_MEM_STRUCT_SIZE); +} + +static inline void *mmheap_addr_add(const struct heap_node *mem_node) +{ + return (void *)((const uint8_t *)mem_node + MEM_MANAGE_MEM_STRUCT_SIZE); +} + +/** + * @brief mmheap_insert_node_to_freelist + * + * @param pRoot + * @param pNode + */ +static inline void mmheap_insert_node_to_freelist(struct heap_info *pRoot, struct heap_node *pNode) +{ + struct heap_node *pPriv_Node; + struct heap_node *pNext_Node; + /*Find the node with an address similar to pNode*/ + for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pNode; pPriv_Node = pPriv_Node->next_node) { + } + + pNext_Node = pPriv_Node->next_node; + /*Try to merge the pNode with the previous block*/ + if ((uint8_t *)mmheap_addr_add(pPriv_Node) + pPriv_Node->mem_size == (uint8_t *)pNode) { + if (pPriv_Node != pRoot->pStart) { /*can merge if not start block*/ + pPriv_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNode->mem_size; + pNode = pPriv_Node; + } else { + /*The latter is not merged if it is a Start block to avoid wasting memory*/ + pRoot->pStart->next_node = pNode; + } + } else { + /*Insert directly into the free single-chain table when merging is not possible*/ + pPriv_Node->next_node = pNode; + } + /*Try to merge the pNode with the next block*/ + if ((uint8_t *)mmheap_addr_add(pNode) + pNode->mem_size == (uint8_t *)pNext_Node) { + if (pNext_Node != pRoot->pEnd) { + pNode->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size; + pNode->next_node = pNext_Node->next_node; + } else { + pNode->next_node = pRoot->pEnd; + } + } else { + /*Insert directly into the free single-chain table when merging is not possible*/ + pNode->next_node = pNext_Node; + } +} + +/** + * @brief mmheap_get_state + * + * @param pRoot + * @param pState + */ +void mmheap_get_state(struct heap_info *pRoot, struct heap_state *pState) +{ + MMHEAP_ASSERT(pRoot->pStart != NULL); + MMHEAP_ASSERT(pRoot->pEnd != NULL); + pState->max_node_size = pRoot->pStart->next_node->mem_size; + pState->min_node_size = pRoot->pStart->next_node->mem_size; + pState->remain_size = 0; + pState->free_node_num = 0; + MMHEAP_LOCK(); + for (struct heap_node *pNode = pRoot->pStart->next_node; pNode->next_node != NULL; pNode = pNode->next_node) { + pState->remain_size += pNode->mem_size; + pState->free_node_num++; + if (pNode->mem_size > pState->max_node_size) + pState->max_node_size = pNode->mem_size; + if (pNode->mem_size < pState->min_node_size) + pState->min_node_size = pNode->mem_size; + } + MMHEAP_UNLOCK(); +} +/** + * @brief mmheap_align_alloc + * + * @param pRoot + * @param align_size + * @param want_size + * @return void* + */ +void *mmheap_align_alloc(struct heap_info *pRoot, size_t align_size, size_t want_size) +{ + void *pReturn = NULL; + struct heap_node *pPriv_Node, *pNow_Node; + + MMHEAP_ASSERT(pRoot->pStart != NULL); + MMHEAP_ASSERT(pRoot->pEnd != NULL); + + if (want_size == 0) { + return NULL; + } + + if ((want_size & MEM_MANAGE_ALLOCA_LABAL) != 0) { + MMHEAP_MALLOC_FAIL(); + return NULL; + } + + if (align_size & (align_size - 1)) { + MMHEAP_MALLOC_FAIL(); + return NULL; + } + + MMHEAP_LOCK(); + if (want_size < MEM_MANAGE_MINUM_MEM_SIZE) + want_size = MEM_MANAGE_MINUM_MEM_SIZE; + if (align_size < MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT) + align_size = MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT; + + want_size = mmheap_align_up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT); + + pPriv_Node = pRoot->pStart; + pNow_Node = pRoot->pStart->next_node; + + while (pNow_Node->next_node != NULL) { + if (pNow_Node->mem_size >= want_size + MEM_MANAGE_MEM_STRUCT_SIZE) { + size_t use_align_size; + size_t new_size; + pReturn = (void *)mmheap_align_up((size_t)mmheap_addr_add(pNow_Node), align_size); /*Calculate the aligned address*/ + use_align_size = (uint8_t *)pReturn - (uint8_t *)mmheap_addr_add(pNow_Node); /*Calculate the memory consumed by the alignment*/ + if (use_align_size != 0) { /*if Memory misalignment*/ + if (use_align_size < MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) { /*The unaligned value is too small*/ + pReturn = (void *)mmheap_align_up( + (size_t)mmheap_addr_add(pNow_Node) + MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE, align_size); + use_align_size = (uint8_t *)pReturn - (uint8_t *)mmheap_addr_add(pNow_Node); + } + if (use_align_size <= pNow_Node->mem_size) { + new_size = pNow_Node->mem_size - use_align_size; /*Calculate the remaining memory size by removing the memory consumed by alignment*/ + if (new_size >= want_size) { /*Meet the conditions for distribution*/ + struct heap_node *pNew_Node = mmheap_addr_sub(pReturn); + pNow_Node->mem_size -= new_size + MEM_MANAGE_MEM_STRUCT_SIZE; /*Split Node*/ + pNew_Node->mem_size = new_size; /*The new node is also not in the free chain and does not need to be discharged from the free chain*/ + pNew_Node->next_node = NULL; + pNow_Node = pNew_Node; + break; + } + } + } else { /*Memory is directly aligned*/ + pPriv_Node->next_node = pNow_Node->next_node; + pNow_Node->next_node = NULL; + break; + } + } + pPriv_Node = pNow_Node; + pNow_Node = pNow_Node->next_node; + } + + if (pNow_Node == pRoot->pEnd) { + MMHEAP_UNLOCK(); + MMHEAP_MALLOC_FAIL(); + return NULL; + } + + if (pNow_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE + want_size) { /*Node memory is still available*/ + struct heap_node *pNew_Node = (struct heap_node *)((uint8_t *)mmheap_addr_add(pNow_Node) + want_size); /*Calculate the address of the node that will be moved into the free chain table*/ + pNew_Node->mem_size = pNow_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE; + pNew_Node->next_node = NULL; + pNow_Node->mem_size = want_size; + mmheap_insert_node_to_freelist(pRoot, pNew_Node); + } + pNow_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL; + MMHEAP_UNLOCK(); + return pReturn; +} +/** + * @brief mmheap_alloc + * + * @param pRoot + * @param want_size + * @return void* + */ +void *mmheap_alloc(struct heap_info *pRoot, size_t want_size) +{ + return mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size); +} +/** + * @brief mmheap_realloc + * + * @param pRoot + * @param src_addr + * @param want_size + * @return void* + */ +void *mmheap_realloc(struct heap_info *pRoot, void *src_addr, size_t want_size) +{ + void *pReturn = NULL; + struct heap_node *pNext_Node, *pPriv_Node; + struct heap_node *pSrc_Node; + MMHEAP_ASSERT(pRoot->pStart != NULL); + MMHEAP_ASSERT(pRoot->pEnd != NULL); + if (src_addr == NULL) { + return mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size); + } + if (want_size == 0) { + mmheap_free(pRoot, src_addr); + return NULL; + } + + MMHEAP_LOCK(); + if ((want_size & MEM_MANAGE_ALLOCA_LABAL) != 0) { + MMHEAP_UNLOCK(); + MMHEAP_MALLOC_FAIL(); + return NULL; + } + + pSrc_Node = mmheap_addr_sub(src_addr); + + if ((pSrc_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) == 0) { + MMHEAP_UNLOCK(); + MMHEAP_ASSERT((pSrc_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) != 0); + MMHEAP_MALLOC_FAIL(); + return NULL; + } + + pSrc_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL; + if (pSrc_Node->mem_size >= want_size) { + pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL; + pReturn = src_addr; + MMHEAP_UNLOCK(); + return pReturn; + } + /*Start looking in the free list for blocks similar to this block*/ + for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pSrc_Node; pPriv_Node = pPriv_Node->next_node) { + } + pNext_Node = pPriv_Node->next_node; + + if (pNext_Node != pRoot->pEnd && + ((uint8_t *)src_addr + pSrc_Node->mem_size == (uint8_t *)pNext_Node) && + (pSrc_Node->mem_size + pNext_Node->mem_size + MEM_MANAGE_MEM_STRUCT_SIZE >= want_size)) { + /*Meet next node non-end, memory contiguous, enough memory left*/ + pReturn = src_addr; + pPriv_Node->next_node = pNext_Node->next_node; + pSrc_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size; + want_size = mmheap_align_up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT); + if (pSrc_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE + want_size) { /*Removing the remaining space allocated is enough to open new blocks*/ + struct heap_node *pNew_Node = (struct heap_node *)((uint8_t *)mmheap_addr_add(pSrc_Node) + want_size); + pNew_Node->next_node = NULL; + pNew_Node->mem_size = pSrc_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE; + pSrc_Node->mem_size = want_size; + mmheap_insert_node_to_freelist(pRoot, pNew_Node); + } + pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL; + MMHEAP_UNLOCK(); + } else { + MMHEAP_UNLOCK(); + pReturn = mmheap_align_alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size); + if (pReturn == NULL) { + pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL; + MMHEAP_MALLOC_FAIL(); + return NULL; + } + MMHEAP_LOCK(); + memcpy(pReturn, src_addr, pSrc_Node->mem_size); + pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL; + MMHEAP_UNLOCK(); + mmheap_free(pRoot, src_addr); + } + return pReturn; +} +/** + * @brief + * + * @param pRoot + * @param num + * @param size + * @return void* + */ +void *mmheap_calloc(struct heap_info *pRoot, size_t num, size_t size) +{ + void *pReturn = NULL; + + pReturn = (void *)mmheap_alloc(pRoot, size * num); + + if (pReturn) { + memset(pReturn, 0, num * size); + } + + return pReturn; +} +/** + * @brief mmheap_free + * + * @param pRoot + * @param addr + */ +void mmheap_free(struct heap_info *pRoot, void *addr) +{ + struct heap_node *pFree_Node; + MMHEAP_ASSERT(pRoot->pStart != NULL); + MMHEAP_ASSERT(pRoot->pEnd != NULL); + MMHEAP_LOCK(); + if (addr == NULL) { + MMHEAP_UNLOCK(); + return; + } + pFree_Node = mmheap_addr_sub(addr); + + if ((pFree_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) == 0) { + MMHEAP_UNLOCK(); + MMHEAP_ASSERT((pFree_Node->mem_size & MEM_MANAGE_ALLOCA_LABAL) != 0); + return; + } + + if (pFree_Node->next_node != NULL) { + MMHEAP_UNLOCK(); + MMHEAP_ASSERT(pFree_Node->next_node == NULL); + return; + } + pFree_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL; + mmheap_insert_node_to_freelist(pRoot, pFree_Node); + MMHEAP_UNLOCK(); +} +/** + * @brief mmheap_init + * + * @param pRoot + * @param pRegion + */ +void mmheap_init(struct heap_info *pRoot, const struct heap_region *pRegion) +{ + struct heap_node *align_addr; + size_t align_size; + struct heap_node *pPriv_node = NULL; + + pRoot->total_size = 0; + pRoot->pEnd = NULL; + pRoot->pStart = NULL; + + for (; pRegion->addr != NULL; pRegion++) { + align_addr = (struct heap_node *)mmheap_align_up((size_t)pRegion->addr, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT); /*Calculate the aligned address*/ + if ((uint8_t *)align_addr > pRegion->mem_size + (uint8_t *)pRegion->addr) /*Alignment consumes more memory than the memory area*/ + continue; + align_size = pRegion->mem_size - ((uint8_t *)align_addr - (uint8_t *)pRegion->addr); /*Calculate the size of memory left after alignment*/ + if (align_size < MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) /*if Aligning the remaining memory is too small*/ + continue; + align_size -= MEM_MANAGE_MEM_STRUCT_SIZE; /*Find the size of the memory block after removing the table header*/ + align_addr->mem_size = align_size; + align_addr->next_node = NULL; + if (pRoot->pStart == NULL) { + pRoot->pStart = align_addr; /*set current addr for start*/ + if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE + MEM_MANAGE_MEM_STRUCT_SIZE) { /*If the remaining blocks are large enough*/ + align_size -= MEM_MANAGE_MEM_STRUCT_SIZE; /*Remove the next block of table headers remaining memory size*/ + align_addr = (struct heap_node *)((uint8_t *)pRoot->pStart + MEM_MANAGE_MEM_STRUCT_SIZE); //the next block addr + align_addr->mem_size = align_size; + align_addr->next_node = NULL; + pRoot->pStart->mem_size = 0; + pRoot->pStart->next_node = align_addr; + pRoot->total_size = align_addr->mem_size; + } else { /*The memory is too small, and the address of the current memory block is recorded as start*/ + pRoot->total_size = 0; + pRoot->pStart->mem_size = 0; + } + } else { + pPriv_node->next_node = align_addr; + pRoot->total_size += align_size; + } + pPriv_node = align_addr; + } + //At this point, pPriv_node is the last block, then place the end of the table at the end of the block, find the address to place the end block, end block is only convenient for traversal, so as small as possible, assigned to MEM_MANAGE_MEM_STRUCT_SIZE + align_addr = (struct heap_node *)mmheap_align_down( + (size_t)mmheap_addr_add(pPriv_node) + pPriv_node->mem_size - MEM_MANAGE_MEM_STRUCT_SIZE, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT); + align_size = (uint8_t *)align_addr - (uint8_t *)mmheap_addr_add(pPriv_node); /*Find the remaining size of the previous block after the end block is allocated*/ + if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE) { + pRoot->total_size -= pPriv_node->mem_size - align_size; /*Removing memory consumed by allocating end blocks*/ + pRoot->pEnd = align_addr; /*Update the address at the end of the list*/ + pPriv_node->next_node = align_addr; + pPriv_node->mem_size = align_size; + align_addr->next_node = NULL; + align_addr->mem_size = 0; /*The end block is not involved in memory allocation, so a direct 0 is sufficient*/ + } else { /*The last block is too small, directly as the end block*/ + pRoot->pEnd = pPriv_node; + pRoot->total_size -= pPriv_node->mem_size; + } + MMHEAP_ASSERT(pRoot->pStart != NULL); + MMHEAP_ASSERT(pRoot->pEnd != NULL); +} diff --git a/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.h b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.h new file mode 100644 index 000000000..3509af184 --- /dev/null +++ b/source/Core/BSP/Pinecilv2/bl_mcu_sdk/drivers/bl702_driver/startup/drv_mmheap.h @@ -0,0 +1,159 @@ +/** + * @file drv_mmheap.h + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ +#ifndef __DRV_MMHEAP_H +#define __DRV_MMHEAP_H + +#include +#include +#include + +#ifndef MMHEAP_LOCK +#define MMHEAP_LOCK() +#endif + +#ifndef MMHEAP_UNLOCK +#define MMHEAP_UNLOCK() +#endif + +#ifndef MMHEAP_ASSERT +#define MMHEAP_ASSERT(A) \ + if (!(A)) \ + printf("mmheap malloc error:drv_mmheap,%d\r\n", __LINE__) + +#endif + +#ifndef MMHEAP_MALLOC_FAIL +#define MMHEAP_MALLOC_FAIL() printf("mmheap malloc fail:drv_mmheap,%d\r\n", __LINE__) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct heap_region { + void *addr; + size_t mem_size; +}; + +struct heap_node { + struct heap_node *next_node; + size_t mem_size; +}; + +struct heap_info { + struct heap_node *pStart; + struct heap_node *pEnd; + size_t total_size; +}; + +struct heap_state { + size_t remain_size; + size_t free_node_num; + size_t max_node_size; + size_t min_node_size; +}; + +void mmheap_init(struct heap_info *pRoot, const struct heap_region *pRigon); +/** + * @brief Alloc start address aligned memory from the heap. + * Alloc aligned address and specified size memory from the heap. + * + * @attention + * + * @param[in] pRoot heap info. + * @param[in] align_size address align mask of the memory. + * @param[in] want_size size of the memory. + * + * @return the pointer to the allocated memory. + */ +void *mmheap_align_alloc(struct heap_info *pRoot, size_t align_size, size_t want_size); +/** + * @brief Alloc memory. + * Allocate size bytes and returns a pointer to the allocated memory. + * + * @attention size should no bigger than MMHEAP_BLK_SIZE_MAX. + * + * @param[in] pRoot heap info. + * @param[in] want_size size of the memory. + * + * @return the pointer to the allocated memory. + */ +void *mmheap_alloc(struct heap_info *pRoot, size_t want_size); +/** + * @brief Realloc memory from the heap. + * Change the size of the memory block pointed to by ptr to size bytes. + * + * @attention + *
    + *
  • if ptr is NULL, then the call is equivalent to mmheap_alloc(size), for all values of size. + *
  • if ptr is if size is equal to zero, and ptr is not NULL, then the call is equivalent to mmheap_free(ptr). + *
+ * + * @param[in] pRoot heap info. + * @param[in] src_addr old pointer to the memory space. + * @param[in] want_size new size of the memory space. + * + * @return the new pointer to the allocated memory. + */ +void *mmheap_realloc(struct heap_info *pRoot, void *src_addr, size_t want_size); +/** + * @brief Cealloc memory from the heap. + * Change the size of the memory block pointed to by ptr to size bytes. + * + * @attention + *
    + *
  • if ptr is NULL, then the call is equivalent to mmheap_alloc(size), for all values of size. + *
  • if ptr is if size is equal to zero, and ptr is not NULL, then the call is equivalent to mmheap_free(ptr). + *
+ * + * @param[in] pRoot heap info. + * @param[in] num size number. + * @param[in] size new size of the memory space. + * + * @return the new pointer to the allocated memory. + */ +void *mmheap_calloc(struct heap_info *pRoot, size_t num, size_t size); +/** + * @brief Free the memory. + * Free the memory space pointed to by ptr, which must have been returned by a previous call to mmheap_alloc(), mmheap_aligned_alloc(), or mmheap_realloc(). + * + * @attention + * + * @param[in] pRoot heap info. + * @param[in] addr pointer to the memory. + * + * @return None. + */ +void mmheap_free(struct heap_info *pRoot, void *addr); +/** + * @brief get mmheap state + * + * @param pRoot heap info. + * @param pState heap state + */ +void mmheap_get_state(struct heap_info *pRoot, struct heap_state *pState); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file