mcu_hi3321_watch/tjd/system/sys_memory.c
2025-05-26 20:15:20 +08:00

435 lines
14 KiB
C

/*----------------------------------------------------------------------------
* 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);
}