[feat] add tlsf

This commit is contained in:
zhji 2025-06-29 17:14:59 +08:00
parent d4f8b101bd
commit 3e9132d402
16 changed files with 2139 additions and 4 deletions

View File

@ -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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

90
component/mm/tlsf/tlsf.h Executable file
View 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

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View 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
View 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
View 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;
}

View File

@ -0,0 +1 @@
set(CONFIG_TLSF 1)

View File

@ -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)