1 /**
2   * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
3   *
4   * SPDX-License-Identifier: Apache-2.0
5   ******************************************************************************
6   * @file    drv_heap.c
7   * @version V0.2
8   * @brief   heap interface
9   *
10   * Change Logs:
11   * Date           Author          Notes
12   * 2019-03-26     Cliff.Chen      first implementation
13   * 2019-05-15     Cliff.Chen      Add large heap
14   *
15   ******************************************************************************
16   */
17 #include <rtthread.h>
18 #include "drv_heap.h"
19 
20 #ifdef RT_USING_UNCACHE_HEAP
21 static struct rt_memheap _uncache_heap;
22 
rt_uncache_heap_init(void * begin_addr,void * end_addr)23 rt_err_t rt_uncache_heap_init(void *begin_addr, void *end_addr)
24 {
25     /* initialize a default heap in the system */
26     return rt_memheap_init(&_uncache_heap,
27                            "ucheap",
28                            begin_addr,
29                            (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr);
30 }
31 
rt_malloc_uncache(rt_size_t size)32 void *rt_malloc_uncache(rt_size_t size)
33 {
34     return rt_memheap_alloc(&_uncache_heap, size);
35 }
36 
rt_free_uncache(void * ptr)37 void rt_free_uncache(void *ptr)
38 {
39     rt_memheap_free(ptr);
40 }
41 #endif
42 
43 #ifdef RT_USING_LARGE_HEAP
44 #include "hal_base.h"
45 
46 static struct rt_memheap _large_heap;
47 
rt_large_heap_init(void * begin_addr,void * end_addr)48 rt_err_t rt_large_heap_init(void *begin_addr, void *end_addr)
49 {
50     /* initialize a default heap in the system */
51     return rt_memheap_init(&_large_heap,
52                            "large",
53                            begin_addr,
54                            (rt_uint32_t)end_addr - (rt_uint32_t)begin_addr);
55 }
56 
rt_malloc_large(rt_size_t size)57 void *rt_malloc_large(rt_size_t size)
58 {
59     if (size < RT_LARGE_MALLOC_THRRESH)
60         return NULL;
61 
62     return rt_memheap_alloc(&_large_heap, size);
63 }
64 RTM_EXPORT(rt_malloc_large);
65 
rt_free_large(void * ptr)66 void rt_free_large(void *ptr)
67 {
68     rt_memheap_free(ptr);
69 }
70 RTM_EXPORT(rt_free_large);
71 
rt_dma_malloc_large(rt_size_t size)72 void *rt_dma_malloc_large(rt_size_t size)
73 {
74     void *align_ptr;
75     void *ptr;
76     rt_size_t align, align_size;
77 
78     if (size < RT_LARGE_MALLOC_THRRESH)
79         return NULL;
80 
81     align = 4;
82     align_size = 0;
83 
84 #ifdef CACHE_LINE_SIZE
85     align = CACHE_LINE_SIZE;
86 #endif
87 
88 #ifdef DMA_ALIGN_SIZE
89     align = align > DMA_ALIGN_SIZE ? align : DMA_ALIGN_SIZE;
90 #endif
91 
92     align_size = RT_ALIGN(size, align) + align;
93     ptr = rt_memheap_alloc(&_large_heap, align_size);
94     if (ptr != RT_NULL)
95     {
96         /* the allocated memory block is aligned */
97         if (((rt_uint32_t)ptr & (align - 1)) == 0)
98         {
99             align_ptr = (void *)((rt_uint32_t)ptr + align);
100         }
101         else
102         {
103             align_ptr = (void *)(((rt_uint32_t)ptr + (align - 1)) & ~(align - 1));
104         }
105 
106         /* set the pointer before alignment pointer to the real pointer */
107         *((rt_uint32_t *)((rt_uint32_t)align_ptr - sizeof(void *))) = (rt_uint32_t)ptr;
108 
109         ptr = align_ptr;
110     }
111 
112     return ptr;
113 }
114 RTM_EXPORT(rt_dma_malloc_large);
115 
rt_dma_free_large(void * ptr)116 void rt_dma_free_large(void *ptr)
117 {
118     void *real_ptr;
119 
120     real_ptr = (void *) * (rt_uint32_t *)((rt_uint32_t)ptr - sizeof(void *));
121     rt_memheap_free(real_ptr);
122 }
123 RTM_EXPORT(rt_dma_free_large);
124 
125 #endif
126 
127 
128 #ifdef RT_USING_DTCM_HEAP
129 #include "hal_base.h"
130 
131 static struct rt_memheap _dtcm_heap;
132 extern int __dtcm_start__, __dtcm_end__;
133 
134 #define RK_DTCM_BEGIN   (&__dtcm_start__)
135 #define RK_DTCM_END     (&__dtcm_end__)
136 
rt_dtcm_heap_init(void)137 int rt_dtcm_heap_init(void)
138 {
139     rt_err_t ret;
140     rt_device_t dsp;
141 
142     dsp = rt_device_find("dsp0");
143     RT_ASSERT(dsp != RT_NULL);
144 
145     ret = rt_device_open(dsp, RT_DEVICE_FLAG_RDWR);
146     RT_ASSERT(ret == RT_EOK);
147 
148     return rt_memheap_init(&_dtcm_heap,
149                            "dtcmheap",
150                            RK_DTCM_BEGIN,
151                            (rt_uint32_t)RK_DTCM_END - (rt_uint32_t)RK_DTCM_BEGIN);
152 
153     return RT_EOK;
154 }
155 INIT_COMPONENT_EXPORT(rt_dtcm_heap_init);
156 
rt_malloc_dtcm(rt_size_t size)157 void *rt_malloc_dtcm(rt_size_t size)
158 {
159     //rt_kprintf("rt_malloc_dtcm: size = %d\n", size);
160     if (size < RT_DTCM_MALLOC_THRRESH)
161         return NULL;
162 
163     return rt_memheap_alloc(&_dtcm_heap, size);
164 }
165 RTM_EXPORT(rt_malloc_dtcm);
166 
rt_free_dtcm(void * ptr)167 void rt_free_dtcm(void *ptr)
168 {
169     rt_memheap_free(ptr);
170 }
171 RTM_EXPORT(rt_free_dtcm);
172 
rt_dma_malloc_dtcm(rt_size_t size)173 void *rt_dma_malloc_dtcm(rt_size_t size)
174 {
175     void *align_ptr;
176     void *ptr;
177     rt_size_t align, align_size;
178 
179     //rt_kprintf("rt_dma_malloc_dtcm: size = %d\n", size);
180     if (size < RT_DTCM_MALLOC_THRRESH)
181         return NULL;
182 
183     align = 4;
184     align_size = 0;
185 
186 #ifdef CACHE_LINE_SIZE
187     align = CACHE_LINE_SIZE;
188 #endif
189 
190 #ifdef DMA_ALIGN_SIZE
191     align = align > DMA_ALIGN_SIZE ? align : DMA_ALIGN_SIZE;
192 #endif
193 
194     align_size = RT_ALIGN(size, align) + align;
195     ptr = rt_memheap_alloc(&_dtcm_heap, align_size);
196     if (ptr != RT_NULL)
197     {
198         /* the allocated memory block is aligned */
199         if (((rt_uint32_t)ptr & (align - 1)) == 0)
200         {
201             align_ptr = (void *)((rt_uint32_t)ptr + align);
202         }
203         else
204         {
205             align_ptr = (void *)(((rt_uint32_t)ptr + (align - 1)) & ~(align - 1));
206         }
207 
208         /* set the pointer before alignment pointer to the real pointer */
209         *((rt_uint32_t *)((rt_uint32_t)align_ptr - sizeof(void *))) = (rt_uint32_t)ptr;
210 
211         ptr = align_ptr;
212     }
213 
214     return ptr;
215 }
216 RTM_EXPORT(rt_dma_malloc_dtcm);
217 
rt_dma_free_dtcm(void * ptr)218 void rt_dma_free_dtcm(void *ptr)
219 {
220     void *real_ptr;
221 
222     real_ptr = (void *) * (rt_uint32_t *)((rt_uint32_t)ptr - sizeof(void *));
223     rt_memheap_free(real_ptr);
224 }
225 RTM_EXPORT(rt_dma_free_dtcm);
226 
227 #endif
228 
229 
230 #ifdef RT_USING_PSRAM_HEAP
231 #include "hal_base.h"
232 
233 static struct rt_memheap _psram_heap;
234 extern int __psramheap_start__, __psramheap_end__;
235 
236 #define RK_PSRAMHEAP_BEGIN   (&__psramheap_start__)
237 #define RK_PSRAMHEAP_END     (&__psramheap_end__)
238 
rt_psram_heap_init(void)239 int rt_psram_heap_init(void)
240 {
241     return rt_memheap_init(&_psram_heap,
242                            "psramheap",
243                            RK_PSRAMHEAP_BEGIN,
244                            (rt_uint32_t)RK_PSRAMHEAP_END - (rt_uint32_t)RK_PSRAMHEAP_BEGIN);
245 }
246 INIT_COMPONENT_EXPORT(rt_psram_heap_init);
247 
rt_malloc_psram(rt_size_t size)248 void *rt_malloc_psram(rt_size_t size)
249 {
250     //rt_kprintf("rt_malloc_dtcm: size = %d\n", size);
251     if (size < RT_PSRAM_MALLOC_THRRESH)
252         return NULL;
253 
254     return rt_memheap_alloc(&_psram_heap, size);
255 }
256 RTM_EXPORT(rt_malloc_psram);
257 
rt_free_psram(void * ptr)258 void rt_free_psram(void *ptr)
259 {
260     rt_memheap_free(ptr);
261 }
262 RTM_EXPORT(rt_free_psram);
263 
rt_dma_malloc_psram(rt_size_t size)264 void *rt_dma_malloc_psram(rt_size_t size)
265 {
266     void *align_ptr;
267     void *ptr;
268     rt_size_t align, align_size;
269 
270     //rt_kprintf("rt_dma_malloc_dtcm: size = %d\n", size);
271     if (size < RT_PSRAM_MALLOC_THRRESH)
272         return NULL;
273 
274     align = 4;
275     align_size = 0;
276 
277 #ifdef CACHE_LINE_SIZE
278     align = CACHE_LINE_SIZE;
279 #endif
280 
281 #ifdef DMA_ALIGN_SIZE
282     align = align > DMA_ALIGN_SIZE ? align : DMA_ALIGN_SIZE;
283 #endif
284 
285     align_size = RT_ALIGN(size, align) + align;
286     ptr = rt_memheap_alloc(&_psram_heap, align_size);
287     if (ptr != RT_NULL)
288     {
289         /* the allocated memory block is aligned */
290         if (((rt_uint32_t)ptr & (align - 1)) == 0)
291         {
292             align_ptr = (void *)((rt_uint32_t)ptr + align);
293         }
294         else
295         {
296             align_ptr = (void *)(((rt_uint32_t)ptr + (align - 1)) & ~(align - 1));
297         }
298 
299         /* set the pointer before alignment pointer to the real pointer */
300         *((rt_uint32_t *)((rt_uint32_t)align_ptr - sizeof(void *))) = (rt_uint32_t)ptr;
301 
302         ptr = align_ptr;
303     }
304 
305     return ptr;
306 }
307 RTM_EXPORT(rt_dma_malloc_psram);
308 
rt_dma_free_psram(void * ptr)309 void rt_dma_free_psram(void *ptr)
310 {
311     void *real_ptr;
312 
313     real_ptr = (void *) * (rt_uint32_t *)((rt_uint32_t)ptr - sizeof(void *));
314     rt_memheap_free(real_ptr);
315 }
316 RTM_EXPORT(rt_dma_free_psram);
317 
318 #endif
319