[feat] add tlsf
This commit is contained in:
parent
d4f8b101bd
commit
3e9132d402
@ -2,11 +2,21 @@ set(TARGET component)
|
|||||||
add_library(${TARGET} INTERFACE)
|
add_library(${TARGET} INTERFACE)
|
||||||
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/pio_instance pio_instance)
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/pio_instance pio_instance)
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/eth eth)
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/printf printf)
|
|
||||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/os os)
|
|
||||||
|
|
||||||
target_link_libraries(${TARGET} INTERFACE pio_instance)
|
target_link_libraries(${TARGET} INTERFACE pio_instance)
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/eth eth)
|
||||||
target_link_libraries(${TARGET} INTERFACE eth)
|
target_link_libraries(${TARGET} INTERFACE eth)
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/printf printf)
|
||||||
target_link_libraries(${TARGET} INTERFACE printf)
|
target_link_libraries(${TARGET} INTERFACE printf)
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/os os)
|
||||||
target_link_libraries(${TARGET} INTERFACE os)
|
target_link_libraries(${TARGET} INTERFACE os)
|
||||||
|
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/shell shell)
|
||||||
|
target_link_libraries(${TARGET} INTERFACE shell)
|
||||||
|
|
||||||
|
if (${CONFIG_TLSF})
|
||||||
|
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/mm mm)
|
||||||
|
target_link_libraries(${TARGET} INTERFACE mm)
|
||||||
|
endif()
|
||||||
|
|||||||
19
component/mm/CMakeLists.txt
Executable file
19
component/mm/CMakeLists.txt
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
file(GLOB FILELIST
|
||||||
|
mem.c
|
||||||
|
tlsf/tlsf.c
|
||||||
|
tlsf/port_tlsf.c
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TARGET mm)
|
||||||
|
add_library(${TARGET} STATIC ${FILELIST})
|
||||||
|
|
||||||
|
target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tlsf)
|
||||||
|
target_include_directories(${TARGET} PUBLIC ${SDK_BASE_DIR}/driver/inc)
|
||||||
|
target_include_directories(${TARGET} PUBLIC ${SDK_BASE_DIR}/driver/inc/reg)
|
||||||
|
target_compile_definitions(${TARGET} PUBLIC -DCONFIG_TLSF)
|
||||||
|
|
||||||
|
if(CONFIG_FREERTOS)
|
||||||
|
target_compile_definitions(-DconfigSTACK_ALLOCATION_FROM_SEPARATE_HEAP=1)
|
||||||
|
endif()
|
||||||
306
component/mm/mem.c
Executable file
306
component/mm/mem.c
Executable file
@ -0,0 +1,306 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct mem_heap_s g_kmemheap;
|
||||||
|
struct mem_heap_s g_pmemheap;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: kmem_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate memory from the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void kmem_init(void *heapstart, size_t heapsize)
|
||||||
|
{
|
||||||
|
MEM_LOG("Heap: start=%p size=%u\r\n", heapstart, heapsize);
|
||||||
|
|
||||||
|
port_mem_init(KMEM_HEAP, heapstart, heapsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: malloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate memory from the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - Size (in bytes) of the memory region to be allocated.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address of the allocated memory (NULL on failure to allocate)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void *kmalloc(size_t size)
|
||||||
|
{
|
||||||
|
MEM_LOG("kmalloc %d\r\n", size);
|
||||||
|
|
||||||
|
return port_malloc(KMEM_HEAP, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pvPortMallocStack(size_t xSize)
|
||||||
|
{
|
||||||
|
return kmalloc(xSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Returns a chunk of user memory to the list of free nodes, merging with
|
||||||
|
* adjacent free chunks if possible.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void kfree(void *addr)
|
||||||
|
{
|
||||||
|
MEM_LOG("kfree %p\r\n", addr);
|
||||||
|
|
||||||
|
port_free(KMEM_HEAP, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vPortFreeStack(void *pv)
|
||||||
|
{
|
||||||
|
return kfree(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: kcalloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate and zero memory from the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - Size (in bytes) of the memory region to be allocated.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address of the allocated memory (NULL on failure to allocate)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void *kcalloc(size_t size, size_t len)
|
||||||
|
{
|
||||||
|
return port_calloc(KMEM_HEAP, size, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pmem_init
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate memory from the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void pmem_init(void *heapstart, size_t heapsize)
|
||||||
|
{
|
||||||
|
MEM_LOG("Heap: start=%p size=%u\r\n", heapstart, heapsize);
|
||||||
|
|
||||||
|
port_mem_init(PMEM_HEAP, heapstart, heapsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: malloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate memory from the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - Size (in bytes) of the memory region to be allocated.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address of the allocated memory (NULL on failure to allocate)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void *malloc(size_t size)
|
||||||
|
{
|
||||||
|
MEM_LOG("malloc %d\r\n", size);
|
||||||
|
|
||||||
|
return port_malloc(PMEM_HEAP, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: realloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Re-allocate memory in the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* oldmem - The old memory allocated
|
||||||
|
* newsize - Size (in bytes) of the new memory region to be re-allocated.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address of the re-allocated memory (NULL on failure to re-allocate)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void *realloc(void *old, size_t newlen)
|
||||||
|
{
|
||||||
|
return port_realloc(PMEM_HEAP, old, newlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: calloc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Allocate and zero memory from the user heap.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* size - Size (in bytes) of the memory region to be allocated.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The address of the allocated memory (NULL on failure to allocate)
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void *calloc(size_t size, size_t len)
|
||||||
|
{
|
||||||
|
return port_calloc(PMEM_HEAP, size, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: memalign
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* memalign requests more than enough space from malloc, finds a region
|
||||||
|
* within that chunk that meets the alignment request and then frees any
|
||||||
|
* leading or trailing space.
|
||||||
|
*
|
||||||
|
* The alignment argument must be a power of two (not checked). 8-byte
|
||||||
|
* alignment is guaranteed by normal malloc calls.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void *memalign(size_t align, size_t size)
|
||||||
|
{
|
||||||
|
return port_malloc_align(PMEM_HEAP, align, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: free
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Returns a chunk of user memory to the list of free nodes, merging with
|
||||||
|
* adjacent free chunks if possible.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void free(void *addr)
|
||||||
|
{
|
||||||
|
MEM_LOG("free %p\r\n", addr);
|
||||||
|
|
||||||
|
port_free(PMEM_HEAP, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: kfree_size
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Returns the free heap size
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
uint32_t kfree_size(void)
|
||||||
|
{
|
||||||
|
struct meminfo info;
|
||||||
|
|
||||||
|
port_mem_usage(KMEM_HEAP, &info);
|
||||||
|
|
||||||
|
return info.free_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t pfree_size(void)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_PSRAM) && defined(BL616) // only for bl618
|
||||||
|
struct meminfo info;
|
||||||
|
|
||||||
|
port_mem_usage(PMEM_HEAP, &info);
|
||||||
|
|
||||||
|
return info.free_size;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SHELL
|
||||||
|
#include <shell.h>
|
||||||
|
|
||||||
|
int cmd_free(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *Header = "total free alloc mxblk frnode alnode \r\n";
|
||||||
|
struct meminfo info;
|
||||||
|
char *mem;
|
||||||
|
|
||||||
|
mem = malloc(64);
|
||||||
|
port_mem_usage(KMEM_HEAP, &info);
|
||||||
|
|
||||||
|
snprintf(mem, 64, "%-8d%-8d%-8d%-8d%-8d%-8d\r\n", info.total_size, info.free_size, info.used_size, info.max_free_size,
|
||||||
|
info.free_node, info.used_node);
|
||||||
|
|
||||||
|
printf(Header);
|
||||||
|
printf(mem);
|
||||||
|
|
||||||
|
free(mem);
|
||||||
|
|
||||||
|
#if defined(CONFIG_PSRAM) && defined(BL616) // only for bl618
|
||||||
|
mem = malloc(64);
|
||||||
|
port_mem_usage(PMEM_HEAP, &info);
|
||||||
|
|
||||||
|
snprintf(mem, 64, "%-8d%-8d%-8d%-8d%-8d%-8d\r\n", info.total_size, info.free_size, info.used_size, info.max_free_size,
|
||||||
|
info.free_node, info.used_node);
|
||||||
|
|
||||||
|
printf(Header);
|
||||||
|
printf(mem);
|
||||||
|
|
||||||
|
free(mem);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SHELL_CMD_EXPORT_ALIAS(cmd_free, free, show memory usage);
|
||||||
|
#endif
|
||||||
122
component/mm/mem.h
Executable file
122
component/mm/mem.h
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* 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 __PORT_MM_MEM_H
|
||||||
|
#define __PORT_MM_MEM_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define MEM_ASSERT(x) \
|
||||||
|
{ \
|
||||||
|
if (!(x)) { \
|
||||||
|
printf(#x " assert failed at function %s\r\n", __FUNCTION__); \
|
||||||
|
save_and_disable_interrupt(); \
|
||||||
|
while (1) \
|
||||||
|
; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MEM_LOG(fmt, ...) //printf(fmt, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define MEM_IS_VALID(heap) ((heap) != NULL && (heap)->mem_impl != NULL)
|
||||||
|
|
||||||
|
#define KMEM_HEAP &g_kmemheap
|
||||||
|
#if defined(CONFIG_PSRAM) && (!defined(CONFIG_HEAP_ALWAYS_ON_KMEM))
|
||||||
|
#define PMEM_HEAP &g_pmemheap
|
||||||
|
#else
|
||||||
|
#define PMEM_HEAP &g_kmemheap
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct mem_heap_s {
|
||||||
|
void *priv;
|
||||||
|
void *heapstart;
|
||||||
|
size_t heapsize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct meminfo {
|
||||||
|
int total_size; /* This is the total size of memory allocated
|
||||||
|
* for use by malloc in bytes. */
|
||||||
|
int free_node; /* This is the number of free (not in use) chunks */
|
||||||
|
int used_node; /* This is the number of allocated (in use) chunks */
|
||||||
|
int max_free_size; /* Size of the largest free (not in use) chunk */
|
||||||
|
int used_size; /* This is the total size of memory occupied by
|
||||||
|
* chunks handed out by malloc. */
|
||||||
|
int free_size; /* This is the total size of memory occupied
|
||||||
|
* by free (not in use) chunks. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#undef EXTERN
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#define EXTERN extern "C"
|
||||||
|
extern "C" {
|
||||||
|
#else
|
||||||
|
#define EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXTERN struct mem_heap_s g_kmemheap;
|
||||||
|
EXTERN struct mem_heap_s g_pmemheap;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void kmem_init(void *heapstart, size_t heapsize);
|
||||||
|
void *kmalloc(size_t size);
|
||||||
|
void *kcalloc(size_t size, size_t len);
|
||||||
|
void kfree(void *addr);
|
||||||
|
uint32_t kfree_size(void);
|
||||||
|
|
||||||
|
void pmem_init(void *heapstart, size_t heapsize);
|
||||||
|
uint32_t pfree_size(void);
|
||||||
|
|
||||||
|
/* private api for mm*/
|
||||||
|
|
||||||
|
void port_mem_init(struct mem_heap_s *heap, void *heapstart, size_t heapsize);
|
||||||
|
void *port_malloc(struct mem_heap_s *heap, size_t nbytes);
|
||||||
|
void port_free(struct mem_heap_s *heap, void *ptr);
|
||||||
|
void *port_realloc(struct mem_heap_s *heap, void *ptr, size_t nbytes);
|
||||||
|
void *port_calloc(struct mem_heap_s *heap, size_t count, size_t size);
|
||||||
|
void *port_malloc_align(struct mem_heap_s *heap, size_t align, size_t size);
|
||||||
|
void port_mem_usage(struct mem_heap_s *heap, struct meminfo *info);
|
||||||
|
|
||||||
|
#undef EXTERN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __PORT_MM_MEM_H */
|
||||||
164
component/mm/tlsf/port_tlsf.c
Executable file
164
component/mm/tlsf/port_tlsf.c
Executable file
@ -0,0 +1,164 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
#include "tlsf.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
#if 0
|
||||||
|
#define TLSF_MALLOC_ASSERT(heap, x, size) \
|
||||||
|
{ \
|
||||||
|
if (!(x)) { \
|
||||||
|
printf("tlsf malloc %d bytes failed at function %s using heap base:%p\r\n", size, __FUNCTION__, heap->heapstart); \
|
||||||
|
port_irq_save(); \
|
||||||
|
while (1) \
|
||||||
|
; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define TLSF_MALLOC_ASSERT(heap, x, size) \
|
||||||
|
{ \
|
||||||
|
if (!(x)) { \
|
||||||
|
printf("tlsf malloc %d bytes failed at function %s using heap base:%p\r\n", size, __FUNCTION__, heap->heapstart); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: mem_tlfsinfo_walker
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void mem_tlfsinfo_walker(void *ptr, size_t size, int used,
|
||||||
|
void *user)
|
||||||
|
{
|
||||||
|
struct meminfo *info = user;
|
||||||
|
|
||||||
|
if (!used) {
|
||||||
|
info->free_node++;
|
||||||
|
info->free_size += size;
|
||||||
|
if (size > info->max_free_size) {
|
||||||
|
info->max_free_size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void port_mem_init(struct mem_heap_s *heap, void *heapstart, size_t heapsize)
|
||||||
|
{
|
||||||
|
heap->heapstart = (uint8_t *)heapstart + tlsf_size();
|
||||||
|
heap->heapsize = heapsize - tlsf_size();
|
||||||
|
heap->priv = tlsf_create_with_pool(heapstart, heapsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *port_malloc(struct mem_heap_s *heap, size_t nbytes)
|
||||||
|
{
|
||||||
|
void *ret = NULL;
|
||||||
|
uint32_t flag;
|
||||||
|
|
||||||
|
flag = save_and_disable_interrupt();
|
||||||
|
ret = tlsf_memalign(heap->priv, 32, nbytes);
|
||||||
|
TLSF_MALLOC_ASSERT(heap, ret != NULL, nbytes);
|
||||||
|
restore_interrupt(flag);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_free(struct mem_heap_s *heap, void *ptr)
|
||||||
|
{
|
||||||
|
uint32_t flag;
|
||||||
|
|
||||||
|
flag = save_and_disable_interrupt();
|
||||||
|
tlsf_free(heap->priv, ptr);
|
||||||
|
restore_interrupt(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *port_realloc(struct mem_heap_s *heap, void *ptr, size_t nbytes)
|
||||||
|
{
|
||||||
|
void *ret = NULL;
|
||||||
|
uint32_t flag;
|
||||||
|
|
||||||
|
flag = save_and_disable_interrupt();
|
||||||
|
ret = tlsf_realloc(heap->priv, ptr, nbytes);
|
||||||
|
TLSF_MALLOC_ASSERT(heap, ((nbytes != 0 && ret != NULL) || (nbytes == 0 && ret == NULL)), nbytes);
|
||||||
|
restore_interrupt(flag);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *port_calloc(struct mem_heap_s *heap, size_t count, size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = NULL;
|
||||||
|
size_t total = count * size;
|
||||||
|
uint32_t flag;
|
||||||
|
|
||||||
|
flag = save_and_disable_interrupt();
|
||||||
|
if (count > 0 && size > 0) {
|
||||||
|
if (count <= (SIZE_MAX / size)) {
|
||||||
|
ptr = tlsf_malloc(heap->priv, total);
|
||||||
|
if (ptr) {
|
||||||
|
memset(ptr, 0, total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
restore_interrupt(flag);
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *port_malloc_align(struct mem_heap_s *heap, size_t align, size_t size)
|
||||||
|
{
|
||||||
|
void *ret = NULL;
|
||||||
|
uint32_t flag;
|
||||||
|
|
||||||
|
flag = save_and_disable_interrupt();
|
||||||
|
ret = tlsf_memalign(heap->priv, align, size);
|
||||||
|
TLSF_MALLOC_ASSERT(heap, ret != NULL, size);
|
||||||
|
restore_interrupt(flag);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_mem_usage(struct mem_heap_s *heap, struct meminfo *info)
|
||||||
|
{
|
||||||
|
uint32_t flag;
|
||||||
|
|
||||||
|
memset(info, 0, sizeof(struct meminfo));
|
||||||
|
flag = save_and_disable_interrupt();
|
||||||
|
tlsf_walk_pool(heap->heapstart, mem_tlfsinfo_walker, info);
|
||||||
|
restore_interrupt(flag);
|
||||||
|
info->total_size = heap->heapsize;
|
||||||
|
info->used_size = info->total_size - info->free_size;
|
||||||
|
}
|
||||||
1301
component/mm/tlsf/tlsf.c
Executable file
1301
component/mm/tlsf/tlsf.c
Executable file
File diff suppressed because it is too large
Load Diff
90
component/mm/tlsf/tlsf.h
Executable file
90
component/mm/tlsf/tlsf.h
Executable file
@ -0,0 +1,90 @@
|
|||||||
|
#ifndef INCLUDED_tlsf
|
||||||
|
#define INCLUDED_tlsf
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Two Level Segregated Fit memory allocator, version 3.1.
|
||||||
|
** Written by Matthew Conte
|
||||||
|
** http://tlsf.baisoku.org
|
||||||
|
**
|
||||||
|
** Based on the original documentation by Miguel Masmano:
|
||||||
|
** http://www.gii.upv.es/tlsf/main/docs
|
||||||
|
**
|
||||||
|
** This implementation was written to the specification
|
||||||
|
** of the document, therefore no GPL restrictions apply.
|
||||||
|
**
|
||||||
|
** Copyright (c) 2006-2016, Matthew Conte
|
||||||
|
** All rights reserved.
|
||||||
|
**
|
||||||
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
** modification, are permitted provided that the following conditions are met:
|
||||||
|
** * Redistributions of source code must retain the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer.
|
||||||
|
** * Redistributions in binary form must reproduce the above copyright
|
||||||
|
** notice, this list of conditions and the following disclaimer in the
|
||||||
|
** documentation and/or other materials provided with the distribution.
|
||||||
|
** * Neither the name of the copyright holder nor the
|
||||||
|
** names of its contributors may be used to endorse or promote products
|
||||||
|
** derived from this software without specific prior written permission.
|
||||||
|
**
|
||||||
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
|
||||||
|
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */
|
||||||
|
/* pool_t: a block of memory that TLSF can manage. */
|
||||||
|
typedef void *tlsf_t;
|
||||||
|
typedef void *pool_t;
|
||||||
|
|
||||||
|
/* Create/destroy a memory pool. */
|
||||||
|
tlsf_t tlsf_create(void *mem);
|
||||||
|
tlsf_t tlsf_create_with_pool(void *mem, size_t bytes);
|
||||||
|
void tlsf_destroy(tlsf_t tlsf);
|
||||||
|
pool_t tlsf_get_pool(tlsf_t tlsf);
|
||||||
|
|
||||||
|
/* Add/remove memory pools. */
|
||||||
|
pool_t tlsf_add_pool(tlsf_t tlsf, void *mem, size_t bytes);
|
||||||
|
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
|
||||||
|
|
||||||
|
/* malloc/memalign/realloc/free replacements. */
|
||||||
|
void *tlsf_malloc(tlsf_t tlsf, size_t bytes);
|
||||||
|
void *tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes);
|
||||||
|
void *tlsf_realloc(tlsf_t tlsf, void *ptr, size_t size);
|
||||||
|
void tlsf_free(tlsf_t tlsf, void *ptr);
|
||||||
|
|
||||||
|
/* Returns internal block size, not original request size */
|
||||||
|
size_t tlsf_block_size(void *ptr);
|
||||||
|
|
||||||
|
/* Overheads/limits of internal structures. */
|
||||||
|
size_t tlsf_size(void);
|
||||||
|
size_t tlsf_align_size(void);
|
||||||
|
size_t tlsf_block_size_min(void);
|
||||||
|
size_t tlsf_block_size_max(void);
|
||||||
|
size_t tlsf_pool_overhead(void);
|
||||||
|
size_t tlsf_alloc_overhead(void);
|
||||||
|
|
||||||
|
/* Debugging. */
|
||||||
|
typedef void (*tlsf_walker)(void *ptr, size_t size, int used, void *user);
|
||||||
|
void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void *user);
|
||||||
|
/* Returns nonzero if any internal consistency check fails. */
|
||||||
|
int tlsf_check(tlsf_t tlsf);
|
||||||
|
int tlsf_check_pool(pool_t pool);
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -22,6 +22,7 @@ void timer_start(void);
|
|||||||
void timer_stop(void);
|
void timer_stop(void);
|
||||||
int timer_is_stopped(void);
|
int timer_is_stopped(void);
|
||||||
void timer_delay_us(uint32_t us);
|
void timer_delay_us(uint32_t us);
|
||||||
|
void timer_delay_ms(uint32_t ms);
|
||||||
|
|
||||||
void timer_alarm_set(uint8_t alarm_id, uint32_t alarm_count);
|
void timer_alarm_set(uint8_t alarm_id, uint32_t alarm_count);
|
||||||
uint32_t timer_alarm_get(uint8_t alarm_id);
|
uint32_t timer_alarm_get(uint8_t alarm_id);
|
||||||
|
|||||||
@ -72,6 +72,8 @@ uint32_t uart_get_flags(uart_hw_t *uart);
|
|||||||
void uart_write_block(uart_hw_t *uart, uint8_t *data, uint32_t length);
|
void uart_write_block(uart_hw_t *uart, uint8_t *data, uint32_t length);
|
||||||
int uart_put_char(uart_hw_t *uart, uint8_t c);
|
int uart_put_char(uart_hw_t *uart, uint8_t c);
|
||||||
int uart_get_char(uart_hw_t *uart);
|
int uart_get_char(uart_hw_t *uart);
|
||||||
|
uint32_t uart_write(uart_hw_t *uart, uint8_t *data, uint32_t length);
|
||||||
|
uint32_t uart_read(uart_hw_t *uart, uint8_t *data, uint32_t length);
|
||||||
|
|
||||||
uint32_t uart_int_get_raw_status(uart_hw_t *uart);
|
uint32_t uart_int_get_raw_status(uart_hw_t *uart);
|
||||||
uint32_t uart_int_get_status(uart_hw_t *uart);
|
uint32_t uart_int_get_status(uart_hw_t *uart);
|
||||||
|
|||||||
@ -51,6 +51,13 @@ void timer_delay_us(uint32_t us)
|
|||||||
while (timer_count_read() < time);
|
while (timer_count_read() < time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void timer_delay_ms(uint32_t ms)
|
||||||
|
{
|
||||||
|
uint64_t time = timer_count_read();
|
||||||
|
time += ms * 1000;
|
||||||
|
while (timer_count_read() < time);
|
||||||
|
}
|
||||||
|
|
||||||
void timer_alarm_set(uint8_t alarm_id, uint32_t alarm_count)
|
void timer_alarm_set(uint8_t alarm_id, uint32_t alarm_count)
|
||||||
{
|
{
|
||||||
if (alarm_id >= TIMER_ALARM_MAX) {
|
if (alarm_id >= TIMER_ALARM_MAX) {
|
||||||
|
|||||||
@ -65,6 +65,38 @@ int uart_get_char(uart_hw_t *uart)
|
|||||||
return (int)(uart->dr & 0xFF);
|
return (int)(uart->dr & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t uart_write(uart_hw_t *uart, uint8_t *data, uint32_t length)
|
||||||
|
{
|
||||||
|
uint32_t flag, idx;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
while (idx < length) {
|
||||||
|
flag = uart_get_flags(uart);
|
||||||
|
if (!(flag & UART_FLAG_TXFF)) {
|
||||||
|
uart->dr = data[idx++];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uart_read(uart_hw_t *uart, uint8_t *data, uint32_t length)
|
||||||
|
{
|
||||||
|
uint32_t flag, idx;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
while (idx < length) {
|
||||||
|
flag = uart_get_flags(uart);
|
||||||
|
if (!(flag & UART_FLAG_RXFE)) {
|
||||||
|
data[idx++] = uart->dr;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t uart_int_get_raw_status(uart_hw_t *uart)
|
uint32_t uart_int_get_raw_status(uart_hw_t *uart)
|
||||||
{
|
{
|
||||||
return (uart->ris & UART_INT_ALL);
|
return (uart->ris & UART_INT_ALL);
|
||||||
|
|||||||
11
example/memheap/CMakeLists.txt
Normal file
11
example/memheap/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
include(proj.conf)
|
||||||
|
|
||||||
|
project(${EXAMPLE_NAME} VERSION 0.1)
|
||||||
|
add_executable(${EXAMPLE_NAME}.elf main.c)
|
||||||
|
|
||||||
|
include_directories(.)
|
||||||
|
|
||||||
|
add_subdirectory(${SDK_BASE_DIR} sdk)
|
||||||
|
target_link_libraries(${EXAMPLE_NAME}.elf sdk)
|
||||||
18
example/memheap/Makefile
Normal file
18
example/memheap/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
EXAMPLE_BASE_DIR ?= $(shell realpath .)
|
||||||
|
EXAMPLE_NAME := $(notdir $(patsubst %/,%,$(CURDIR)))
|
||||||
|
SDK_BASE_DIR ?= $(shell realpath ./../..)
|
||||||
|
|
||||||
|
export SDK_BASE_DIR
|
||||||
|
export EXAMPLE_NAME
|
||||||
|
export EXAMPLE_BASE_DIR
|
||||||
|
|
||||||
|
GCC_PATH := $(shell which arm-none-eabi-gcc)
|
||||||
|
CROSS_COMPILE := $(patsubst %gcc,%,$(GCC_PATH))
|
||||||
|
ifeq ($(GCC_PATH),)
|
||||||
|
$(error arm-none-eabi-gcc not found in PATH. Please install the ARM toolchain.)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# add custom cmake definition
|
||||||
|
#cmake_definition+=-Dxxx=sss
|
||||||
|
|
||||||
|
include $(SDK_BASE_DIR)/project.build
|
||||||
50
example/memheap/main.c
Normal file
50
example/memheap/main.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "resets.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
int memheap_test(void)
|
||||||
|
{
|
||||||
|
char *ptr = NULL;
|
||||||
|
|
||||||
|
for (int i = 1;; i++) {
|
||||||
|
ptr = malloc(i * 128);
|
||||||
|
printf("remain %lu byte\r\n", kfree_size());
|
||||||
|
|
||||||
|
if (ptr != NULL) {
|
||||||
|
memcpy(ptr, "hello123456789123456789123456789", 33);
|
||||||
|
printf("ptr :%s\r\n", ptr);
|
||||||
|
printf("get memory :%d byte\r\n", i * 128);
|
||||||
|
free(ptr);
|
||||||
|
printf("free memory :%d byte\r\n", i * 128);
|
||||||
|
ptr = NULL;
|
||||||
|
timer_delay_ms(100);
|
||||||
|
} else {
|
||||||
|
printf("try to get %d byte memory failed!\r\n", i * 128);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
reset_unreset_blocks_wait(RESETS_BLOCK_IO_BANK0 | RESETS_BLOCK_UART0 | RESETS_BLOCK_TIMER);
|
||||||
|
gpio_init(0, GPIO_FUNC_UART | GPIO_PULL_UP | GPIO_DRIVE_4MA); /* UART_TX pin */
|
||||||
|
gpio_init(1, GPIO_FUNC_UART | GPIO_PULL_UP | GPIO_SCHMITT | GPIO_PAD_IE | GPIO_PAD_OD); /* UART_RX pin */
|
||||||
|
uart_init(uart0_hw, 6 * 1000 * 1000, UART_DATABITS_8 | UART_PARITY_NONE | UART_STOPBITS_1);
|
||||||
|
printf("memory heap example\r\n");
|
||||||
|
|
||||||
|
kmem_init((void *)0x20030000, 64 * 1024);
|
||||||
|
if (memheap_test() == -1) {
|
||||||
|
printf("memheap test fail\r\n");
|
||||||
|
while (1) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("memheap test success\r\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
example/memheap/proj.conf
Normal file
1
example/memheap/proj.conf
Normal file
@ -0,0 +1 @@
|
|||||||
|
set(CONFIG_TLSF 1)
|
||||||
@ -56,6 +56,7 @@ cmake_definition+= -DEXAMPLE_NAME=$(EXAMPLE_NAME)
|
|||||||
cmake_definition+= -DEXAMPLE_BASE_DIR=$(EXAMPLE_BASE_DIR)
|
cmake_definition+= -DEXAMPLE_BASE_DIR=$(EXAMPLE_BASE_DIR)
|
||||||
|
|
||||||
cmake_definition+= -DCONFIG_FREERTOS=$(CONFIG_FREERTOS)
|
cmake_definition+= -DCONFIG_FREERTOS=$(CONFIG_FREERTOS)
|
||||||
|
cmake_definition+= -DCONFIG_TLSF=$(CONFIG_TLSF)
|
||||||
|
|
||||||
FINAL_NAME_PRE := $(EXAMPLE_BASE_DIR)/build/$(EXAMPLE_NAME)
|
FINAL_NAME_PRE := $(EXAMPLE_BASE_DIR)/build/$(EXAMPLE_NAME)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user