/** * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd * * SPDX-License-Identifier: Apache-2.0 ****************************************************************************** * @file drv_heap.c * @version V0.2 * @brief heap interface * * Change Logs: * Date Author Notes * 2019-03-26 Cliff.Chen first implementation * 2019-05-15 Cliff.Chen Add large heap * ****************************************************************************** */ #include <rtthread.h> #include "drv_heap.h" #ifdef RT_USING_UNCACHE_HEAP static struct rt_memheap _uncache_heap; rt_err_t rt_uncache_heap_init(void *begin_addr, void *end_addr) { /* initialize a default heap in the system */ return rt_memheap_init(&_uncache_heap, "ucheap", begin_addr, (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr); } void *rt_malloc_uncache(rt_size_t size) { return rt_memheap_alloc(&_uncache_heap, size); } void rt_free_uncache(void *ptr) { rt_memheap_free(ptr); } #endif #ifdef RT_USING_LARGE_HEAP #include "hal_base.h" static struct rt_memheap _large_heap; rt_err_t rt_large_heap_init(void *begin_addr, void *end_addr) { /* initialize a default heap in the system */ return rt_memheap_init(&_large_heap, "large", begin_addr, (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr); } void *rt_malloc_large(rt_size_t size) { if (size < RT_LARGE_MALLOC_THRRESH) return NULL; return rt_memheap_alloc(&_large_heap, size); } RTM_EXPORT(rt_malloc_large); void rt_free_large(void *ptr) { rt_memheap_free(ptr); } RTM_EXPORT(rt_free_large); void *rt_dma_malloc_large(rt_size_t size) { void *align_ptr; void *ptr; rt_size_t align, align_size; if (size < RT_LARGE_MALLOC_THRRESH) return NULL; align = 4; align_size = 0; #ifdef CACHE_LINE_SIZE align = CACHE_LINE_SIZE; #endif #ifdef DMA_ALIGN_SIZE align = align > DMA_ALIGN_SIZE ? align : DMA_ALIGN_SIZE; #endif align_size = RT_ALIGN(size, align) + align; ptr = rt_memheap_alloc(&_large_heap, align_size); if (ptr != RT_NULL) { /* the allocated memory block is aligned */ if (((rt_uint32_t)ptr & (align - 1)) == 0) { align_ptr = (void *)((rt_uint32_t)ptr + align); } else { align_ptr = (void *)(((rt_uint32_t)ptr + (align - 1)) & ~(align - 1)); } /* set the pointer before alignment pointer to the real pointer */ *((rt_uint32_t *)((rt_uint32_t)align_ptr - sizeof(void *))) = (rt_uint32_t)ptr; ptr = align_ptr; } return ptr; } RTM_EXPORT(rt_dma_malloc_large); void rt_dma_free_large(void *ptr) { void *real_ptr; real_ptr = (void *) * (rt_uint32_t *)((rt_uint32_t)ptr - sizeof(void *)); rt_memheap_free(real_ptr); } RTM_EXPORT(rt_dma_free_large); #endif #ifdef RT_USING_DTCM_HEAP #include "hal_base.h" static struct rt_memheap _dtcm_heap; extern int __dtcm_start__, __dtcm_end__; #define RK_DTCM_BEGIN (&__dtcm_start__) #define RK_DTCM_END (&__dtcm_end__) int rt_dtcm_heap_init(void) { rt_err_t ret; rt_device_t dsp; dsp = rt_device_find("dsp0"); RT_ASSERT(dsp != RT_NULL); ret = rt_device_open(dsp, RT_DEVICE_FLAG_RDWR); RT_ASSERT(ret == RT_EOK); return rt_memheap_init(&_dtcm_heap, "dtcmheap", RK_DTCM_BEGIN, (rt_uint32_t)RK_DTCM_END - (rt_uint32_t)RK_DTCM_BEGIN); return RT_EOK; } INIT_COMPONENT_EXPORT(rt_dtcm_heap_init); void *rt_malloc_dtcm(rt_size_t size) { //rt_kprintf("rt_malloc_dtcm: size = %d\n", size); if (size < RT_DTCM_MALLOC_THRRESH) return NULL; return rt_memheap_alloc(&_dtcm_heap, size); } RTM_EXPORT(rt_malloc_dtcm); void rt_free_dtcm(void *ptr) { rt_memheap_free(ptr); } RTM_EXPORT(rt_free_dtcm); void *rt_dma_malloc_dtcm(rt_size_t size) { void *align_ptr; void *ptr; rt_size_t align, align_size; //rt_kprintf("rt_dma_malloc_dtcm: size = %d\n", size); if (size < RT_DTCM_MALLOC_THRRESH) return NULL; align = 4; align_size = 0; #ifdef CACHE_LINE_SIZE align = CACHE_LINE_SIZE; #endif #ifdef DMA_ALIGN_SIZE align = align > DMA_ALIGN_SIZE ? align : DMA_ALIGN_SIZE; #endif align_size = RT_ALIGN(size, align) + align; ptr = rt_memheap_alloc(&_dtcm_heap, align_size); if (ptr != RT_NULL) { /* the allocated memory block is aligned */ if (((rt_uint32_t)ptr & (align - 1)) == 0) { align_ptr = (void *)((rt_uint32_t)ptr + align); } else { align_ptr = (void *)(((rt_uint32_t)ptr + (align - 1)) & ~(align - 1)); } /* set the pointer before alignment pointer to the real pointer */ *((rt_uint32_t *)((rt_uint32_t)align_ptr - sizeof(void *))) = (rt_uint32_t)ptr; ptr = align_ptr; } return ptr; } RTM_EXPORT(rt_dma_malloc_dtcm); void rt_dma_free_dtcm(void *ptr) { void *real_ptr; real_ptr = (void *) * (rt_uint32_t *)((rt_uint32_t)ptr - sizeof(void *)); rt_memheap_free(real_ptr); } RTM_EXPORT(rt_dma_free_dtcm); #endif #ifdef RT_USING_PSRAM_HEAP #include "hal_base.h" static struct rt_memheap _psram_heap; extern int __psramheap_start__, __psramheap_end__; #define RK_PSRAMHEAP_BEGIN (&__psramheap_start__) #define RK_PSRAMHEAP_END (&__psramheap_end__) int rt_psram_heap_init(void) { return rt_memheap_init(&_psram_heap, "psramheap", RK_PSRAMHEAP_BEGIN, (rt_uint32_t)RK_PSRAMHEAP_END - (rt_uint32_t)RK_PSRAMHEAP_BEGIN); } INIT_COMPONENT_EXPORT(rt_psram_heap_init); void *rt_malloc_psram(rt_size_t size) { //rt_kprintf("rt_malloc_dtcm: size = %d\n", size); if (size < RT_PSRAM_MALLOC_THRRESH) return NULL; return rt_memheap_alloc(&_psram_heap, size); } RTM_EXPORT(rt_malloc_psram); void rt_free_psram(void *ptr) { rt_memheap_free(ptr); } RTM_EXPORT(rt_free_psram); void *rt_dma_malloc_psram(rt_size_t size) { void *align_ptr; void *ptr; rt_size_t align, align_size; //rt_kprintf("rt_dma_malloc_dtcm: size = %d\n", size); if (size < RT_PSRAM_MALLOC_THRRESH) return NULL; align = 4; align_size = 0; #ifdef CACHE_LINE_SIZE align = CACHE_LINE_SIZE; #endif #ifdef DMA_ALIGN_SIZE align = align > DMA_ALIGN_SIZE ? align : DMA_ALIGN_SIZE; #endif align_size = RT_ALIGN(size, align) + align; ptr = rt_memheap_alloc(&_psram_heap, align_size); if (ptr != RT_NULL) { /* the allocated memory block is aligned */ if (((rt_uint32_t)ptr & (align - 1)) == 0) { align_ptr = (void *)((rt_uint32_t)ptr + align); } else { align_ptr = (void *)(((rt_uint32_t)ptr + (align - 1)) & ~(align - 1)); } /* set the pointer before alignment pointer to the real pointer */ *((rt_uint32_t *)((rt_uint32_t)align_ptr - sizeof(void *))) = (rt_uint32_t)ptr; ptr = align_ptr; } return ptr; } RTM_EXPORT(rt_dma_malloc_psram); void rt_dma_free_psram(void *ptr) { void *real_ptr; real_ptr = (void *) * (rt_uint32_t *)((rt_uint32_t)ptr - sizeof(void *)); rt_memheap_free(real_ptr); } RTM_EXPORT(rt_dma_free_psram); #endif