/*---------------------------------------------------------------------------- * Copyright (c) Fenda Technologies Co., Ltd. 2021. All rights reserved. * * Description:sys_memory.c * * Author: saimen * * Create: 2021-08-25 *--------------------------------------------------------------------------*/ //lib //os //sdk //drv #include "sys_typedef.h" #include "sys_config.h" #include "sys_memory.h" #include "sys_adapter.h" //user #define ENABLE_STATIC_PRINT false extern uint32_t am_util_stdio_printf(const char *pcFmt, ...); #define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__) #if ENABLE_STATIC_PRINT #define static_print_info(...) am_util_stdio_printf(__VA_ARGS__) #else #define static_print_info(...) #endif #define EXTERNAL_MEMORY_XIPMM_MODE //unsigned short int g_ext_memory_map_list[EXT_MEMORY_MALLOC_BLOCK_NUMBER]; //unsigned char g_ext_memory_malloc_buffer[EXTERNAL_MEMORY_MALLOC_BUFFER_SIZE]; //unsigned short int g_ui_memory_map_list[UI_MEMORY_MALLOC_BLOCK_NUMBER]; //unsigned char g_ui_memory_malloc_buffer[UI_MEMORY_MALLOC_BUFFER_SIZE]; static uint8_t g_mem_flag = false; #ifndef EXTERNAL_MEMORY_XIPMM_MODE //PSRAM内存管理LIST在片内。 //typedef struct A_BLOCK_NODE //{ // struct A_BLOCK_NODE *next_free_block; /*<< The next free block in the list. */ // size_t block_size; /*<< The size of the free block. */ // size_t *data; /*<< data block. */ //} block_node_t; void sys_ui_memory_init(void) { g_mem_flag = true; memset((unsigned char *)g_ui_memory_map_list, 0, sizeof(g_ui_memory_map_list)); // memset((unsigned char *)g_ui_memory_malloc_buffer, 0, UI_MEMORY_MALLOC_BUFFER_SIZE); } void *sys_ui_malloc(unsigned int malloc_size) { unsigned int block_number = 0, free_block_find = 0; int i= 0; unsigned int j = 0; static_print_info("ui_malloc:%d,%d\r\n", g_ui_mem_flag, malloc_size); if((malloc_size == 0) || (malloc_size > UI_MEMORY_MALLOC_BUFFER_SIZE) || (g_mem_flag == false)) return NULL; block_number = malloc_size / UI_MEMORY_MALLOC_BLOCK_SIZE; if(malloc_size % UI_MEMORY_MALLOC_BLOCK_SIZE) block_number++; for ( i = ( UI_MEMORY_MALLOC_BLOCK_NUMBER - 1 ); i >= 0; i-- ) { if ( g_ui_memory_map_list[i] == 0 ) free_block_find++; else free_block_find = 0; if ( free_block_find == block_number ) break; } if(free_block_find == block_number) { for(j = 0; j < block_number; j++) { g_ui_memory_map_list[i + j] = block_number; } static_print_info("malloc_addr:0x%x len:%d \r\n", (i * UI_MEMORY_MALLOC_BLOCK_SIZE + UI_MEMORY_MALLOC_BASE_ADDR), malloc_size); return (void *) (i * UI_MEMORY_MALLOC_BLOCK_SIZE + UI_MEMORY_MALLOC_BASE_ADDR); } return NULL; } void sys_ui_free(void *addr) { unsigned int index = 0; unsigned int wait_free_block = 0; unsigned int i = 0; static_print_info("ui_free=0x%x\r\n", addr); if((g_mem_flag == false)) return; if(addr == NULL) return; //am_util_stdio_printf("ui_free=0x%x,0x%x\r\n", ui_memory_malloc_buffer, UI_MEMORY_MALLOC_BUFFER_SIZE); if(((unsigned int) addr < ((unsigned int)UI_MEMORY_MALLOC_END_ADDR)) && ((unsigned int) addr >= (unsigned int)UI_MEMORY_MALLOC_BASE_ADDR)) { index = ((unsigned int) addr - (unsigned int)UI_MEMORY_MALLOC_BASE_ADDR) / UI_MEMORY_MALLOC_BLOCK_SIZE; wait_free_block = g_ui_memory_map_list[index]; for(i = 0; i < wait_free_block; i++) { g_ui_memory_map_list[index + i] = 0; } } } unsigned char sys_ui_memory_used(void) { unsigned int used = 0; unsigned int i = 0; for(i = 0; i < UI_MEMORY_MALLOC_BLOCK_NUMBER; i++) { if(g_ui_memory_map_list[i]) used++; } return (used * 100) / (UI_MEMORY_MALLOC_BLOCK_NUMBER); } #else /*-----------------------------------------------------------*/ #define UI_BYTE_ALIGNMENT ( ( size_t ) 16 ) #define UI_BYTE_ALIGNMENT_MASK ( ( size_t ) (UI_BYTE_ALIGNMENT-1) ) /* Work out the position of the top bit in a size_t variable. */ #define BLOCK_ALLOCATED_BIT ( ( size_t ) 0x80000000 ) /* saimen:Block sizes must not get too small.Double node_struct_size space */ #define UI_MINIMUM_BLOCK_SIZE ( ( size_t ) ( node_struct_size << 1 ) ) typedef struct A_BLOCK_NODE { struct A_BLOCK_NODE *next_free_block; /*<< The next free block in the list. */ size_t block_size; /*<< The size of the free block. */ } block_node_t; /*-----------------------------------------------------------*/ static const size_t node_struct_size = (sizeof(block_node_t) + ((size_t)(UI_BYTE_ALIGNMENT - 1))) & ~((size_t) UI_BYTE_ALIGNMENT_MASK); static block_node_t g_start_node ={0}, *g_end_node = NULL; static size_t ui_current_free_bytes = 0U; static size_t ui_minimum_free_bytes = 0U; /*-----------------------------------------------------------*/ //static void ui_memory_init( void ); static void sys_ui_insert_node(block_node_t *insert_block); /*-----------------------------------------------------------*/ void sys_debug_marker(uint8_t marker_type) { if(marker_type == 0) { static_print_info("%d ui_heep error.\r\n", xTaskGetTickCount()); while(1) { sys_smart_delay_ms(10); } } //static_print_info("%d ui_heep warning:%d.\r\n",xTaskGetTickCount(),marker_type); } void *sys_ui_malloc(size_t wanted_size) { block_node_t *block_temp, *previous_block, *new_block; void *return_p = NULL; if(g_end_node == NULL) { sys_ui_memory_init(); } else { sys_debug_marker(8); } //static_print_remind("%d ui_malloc:0x%x\r\n",xTaskGetTickCount(),wanted_size); if((wanted_size & BLOCK_ALLOCATED_BIT) == 0) { if(wanted_size > 0) { wanted_size += node_struct_size; if((wanted_size & UI_BYTE_ALIGNMENT_MASK) != 0x00) { /* Byte alignment required. */ wanted_size += (UI_BYTE_ALIGNMENT - (wanted_size & UI_BYTE_ALIGNMENT_MASK)); sys_debug_marker((wanted_size & UI_BYTE_ALIGNMENT_MASK) == 0); } } if((wanted_size > 0) && (wanted_size <= ui_current_free_bytes)) { previous_block = &g_start_node; block_temp = g_start_node.next_free_block; while((block_temp->block_size < wanted_size) && (block_temp->next_free_block != NULL)) { previous_block = block_temp; block_temp = block_temp->next_free_block; } if(block_temp != g_end_node) { return_p = (void *)(((uint8_t *) previous_block->next_free_block) + node_struct_size); previous_block->next_free_block = block_temp->next_free_block; if((block_temp->block_size - wanted_size) > UI_MINIMUM_BLOCK_SIZE) { new_block = (void *)(((uint8_t *) block_temp) + wanted_size); sys_debug_marker((((size_t) new_block) & UI_BYTE_ALIGNMENT_MASK) == 0); new_block->block_size = block_temp->block_size - wanted_size; block_temp->block_size = wanted_size; sys_ui_insert_node(new_block); } // else // { // sys_debug_marker(8); // } ui_current_free_bytes -= block_temp->block_size; if(ui_current_free_bytes < ui_minimum_free_bytes) { ui_minimum_free_bytes = ui_current_free_bytes; } block_temp->block_size |= BLOCK_ALLOCATED_BIT; block_temp->next_free_block = NULL; } } } sys_debug_marker((((size_t) return_p) & (size_t) UI_BYTE_ALIGNMENT_MASK) == 0); static_print_info("%d ok:0x%x,b_temp:0x%x,b_size:0x%x,c_free:0x%x,min_free:0x%x\r\n",xTaskGetTickCount(),return_p,block_temp,block_temp->block_size,ui_current_free_bytes,ui_minimum_free_bytes); if(return_p == NULL) { static_print_remind("error: sys_ui_malloc() return_p==NULL,%d-%d-%d\r\n",wanted_size,ui_current_free_bytes,ui_minimum_free_bytes); } return return_p; } /*-----------------------------------------------------------*/ void sys_ui_free(void *pv) { uint8_t *puc = (uint8_t *) pv; block_node_t *block_temp; static_print_info("%d ui_free:0x%x\r\n",xTaskGetTickCount(),pv); if(pv >= (void *)UI_MEMORY_MALLOC_BASE_ADDR) { puc -= node_struct_size; block_temp = (void *) puc; /* Check the block is actually allocated. */ //sys_debug_marker( ( block_temp->block_size & BLOCK_ALLOCATED_BIT ) != 0 ); //sys_debug_marker( block_temp->next_free_block == NULL ); if((block_temp->block_size & BLOCK_ALLOCATED_BIT) != 0) { if(block_temp->next_free_block == NULL) { block_temp->block_size &= ~BLOCK_ALLOCATED_BIT; ui_current_free_bytes += block_temp->block_size; sys_ui_insert_node(((block_node_t *) block_temp)); } else { sys_debug_marker(9); } } else { sys_debug_marker(9); } } } /*-----------------------------------------------------------*/ size_t sys_ui_get_free_size(void) { return ui_current_free_bytes; } /*-----------------------------------------------------------*/ size_t sys_ui_get_minimum_ever_free_size(void) { return ui_minimum_free_bytes; } /*-----------------------------------------------------------*/ void sys_ui_init_blocks(void) { } /*-----------------------------------------------------------*/ void sys_ui_memory_init(void) { block_node_t *first_free_block; uint8_t *aligned_heap; size_t ux_address; size_t total_heap_size = UI_MEMORY_MALLOC_BUFFER_SIZE; ux_address = (size_t) UI_MEMORY_MALLOC_BASE_ADDR; if((ux_address & UI_BYTE_ALIGNMENT_MASK) != 0) { ux_address += (UI_BYTE_ALIGNMENT - 1); ux_address &= ~((size_t) UI_BYTE_ALIGNMENT_MASK); total_heap_size -= ux_address - (size_t) UI_MEMORY_MALLOC_BASE_ADDR; } aligned_heap = (uint8_t *) ux_address; g_start_node.next_free_block = (void *) aligned_heap; g_start_node.block_size = (size_t) 0; ux_address = ((size_t) aligned_heap) + total_heap_size; ux_address -= node_struct_size; ux_address &= ~((size_t) UI_BYTE_ALIGNMENT_MASK); g_end_node = (void *) ux_address; g_end_node->block_size = 0; g_end_node->next_free_block = NULL; first_free_block = (void *) aligned_heap; first_free_block->block_size = ux_address - (size_t) first_free_block; first_free_block->next_free_block = g_end_node; ui_minimum_free_bytes = first_free_block->block_size; ui_current_free_bytes = first_free_block->block_size; } /*-----------------------------------------------------------*/ static void sys_ui_insert_node(block_node_t *insert_block) { block_node_t *iterator_node; uint8_t *puc; for(iterator_node = &g_start_node; iterator_node->next_free_block < insert_block; iterator_node = iterator_node->next_free_block) { //static_print_remind("%d ui_insert_node 1:0x%x,0x%x\r\n",xTaskGetTickCount(),iterator_node,iterator_node->next_free_block); } /* Do the block being inserted, and the block it is being inserted after make a contiguous block of memory? */ puc = (uint8_t *) iterator_node; if((puc + iterator_node->block_size) == (uint8_t *) insert_block) { iterator_node->block_size += insert_block->block_size; insert_block = iterator_node; } else { //sys_debug_marker(10); } /* Do the block being inserted, and the block it is being inserted before make a contiguous block of memory? */ puc = (uint8_t *) insert_block; if((puc + insert_block->block_size) == (uint8_t *) iterator_node->next_free_block) { if(iterator_node->next_free_block != g_end_node) { /* Form one big block from the two blocks. */ insert_block->block_size += iterator_node->next_free_block->block_size; insert_block->next_free_block = iterator_node->next_free_block->next_free_block; } else { insert_block->next_free_block = g_end_node; } } else { insert_block->next_free_block = iterator_node->next_free_block; } /* If the block being inserted plugged a gab, so was merged with the block before and the block after, then it's next_free_block pointer will have already been set, and should not be set here as that would make it point to itself. */ if(iterator_node != insert_block) { iterator_node->next_free_block = insert_block; } else { //sys_debug_marker(10); } } #endif // void sys_ext_memory_init ( void ) { sys_ui_memory_init(); } void *sys_ext_malloc ( unsigned int malloc_size ) { return sys_ui_malloc(malloc_size); } void sys_ext_free ( void *addr ) { sys_ui_free(addr); }