[feat] add tlsf
This commit is contained in:
parent
d4f8b101bd
commit
3e9132d402
@ -2,11 +2,21 @@ set(TARGET component)
|
||||
add_library(${TARGET} INTERFACE)
|
||||
|
||||
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)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/eth eth)
|
||||
target_link_libraries(${TARGET} INTERFACE eth)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/printf printf)
|
||||
target_link_libraries(${TARGET} INTERFACE printf)
|
||||
|
||||
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/os 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);
|
||||
int timer_is_stopped(void);
|
||||
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);
|
||||
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);
|
||||
int uart_put_char(uart_hw_t *uart, uint8_t c);
|
||||
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_status(uart_hw_t *uart);
|
||||
|
||||
@ -51,6 +51,13 @@ void timer_delay_us(uint32_t us)
|
||||
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)
|
||||
{
|
||||
if (alarm_id >= TIMER_ALARM_MAX) {
|
||||
|
||||
@ -65,6 +65,38 @@ int uart_get_char(uart_hw_t *uart)
|
||||
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)
|
||||
{
|
||||
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+= -DCONFIG_FREERTOS=$(CONFIG_FREERTOS)
|
||||
cmake_definition+= -DCONFIG_TLSF=$(CONFIG_TLSF)
|
||||
|
||||
FINAL_NAME_PRE := $(EXAMPLE_BASE_DIR)/build/$(EXAMPLE_NAME)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user