1 /******************************************************************************
2 * Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************/
18 #include "ev_buffer.h"
19 #include "common/assert.h"
20 #include "common/utility.h"
21 #include "drivers/B91/ext_driver/ext_misc.h"
22 #include "mempool.h"
23 #include "user_config.h"
24 #include <string.h>
25
26 #ifdef WIN32
27 #include <malloc.h>
28 #endif
29
30 #if 1
31
32 #define DEFAULT_BUFFER_GROUP_NUM 3
33
34 /**************************** Private Variable Definitions *******************/
35
36 typedef struct {
37 mem_pool_t *qHead;
38 u16 size;
39 u8 availBufNum;
40 u8 reserved;
41 } ev_buf_groups_t;
42
43 typedef struct bufm_vars {
44 ev_buf_groups_t bufGroups[DEFAULT_BUFFER_GROUP_NUM];
45 } ev_buf_vars_t;
46
47 ev_buf_vars_t ev_buf_vs;
48 ev_buf_vars_t *ev_buf_v = &ev_buf_vs;
49
50 MEMPOOL_DECLARE(size_0_pool, size_0_mem, BUFFER_GROUP_0, BUFFER_NUM_IN_GROUP0);
51 MEMPOOL_DECLARE(size_1_pool, size_1_mem, BUFFER_GROUP_1, BUFFER_NUM_IN_GROUP1);
52 MEMPOOL_DECLARE(size_2_pool, size_2_mem, BUFFER_GROUP_2, BUFFER_NUM_IN_GROUP2);
53
54 /*********************************************************************
55 * @fn ev_buf_isExisted
56 *
57 * @brief Return whether the buffer is in the available buffer
58 *
59 * @param index
60 * @param block
61 *
62 * @return TRUE or FALSE
63 */
ev_buf_isExisted(u8 index,mem_block_t * block)64 u8 ev_buf_isExisted(u8 index, mem_block_t *block)
65 {
66 mem_pool_t *pool = (mem_pool_t *)ev_buf_v->bufGroups[index].qHead;
67 mem_block_t *curBlock = pool->free_list;
68
69 while (curBlock) {
70 if (block == curBlock) {
71 return TRUE;
72 }
73 curBlock = curBlock->next_block;
74 }
75
76 return FALSE;
77 }
78
ev_buf_retriveMempoolHeader(u8 * pd)79 u8 *ev_buf_retriveMempoolHeader(u8 *pd)
80 {
81 return pd - (OFFSETOF(ev_bufItem_t, data) - OFFSETOF(mem_block_t, data));
82 }
83
84 /*********************************************************************
85 * @fn ev_buf_reset
86 *
87 * @brief Reset the EV Buffer module
88 *
89 * @param None
90 *
91 * @return None
92 */
ev_buf_reset(void)93 void ev_buf_reset(void)
94 {
95 u16 size[DEFAULT_BUFFER_GROUP_NUM] = {BUFFER_GROUP_0, BUFFER_GROUP_1, BUFFER_GROUP_2};
96 mem_pool_t *memPool[DEFAULT_BUFFER_GROUP_NUM] = {&size_0_pool, &size_1_pool, &size_2_pool};
97 u8 *mem[DEFAULT_BUFFER_GROUP_NUM] = {size_0_mem, size_1_mem, size_2_mem};
98 u8 buffCnt[DEFAULT_BUFFER_GROUP_NUM] = {BUFFER_NUM_IN_GROUP0, BUFFER_NUM_IN_GROUP1, BUFFER_NUM_IN_GROUP2};
99
100 memset((u8 *)ev_buf_v, 0, sizeof(ev_buf_vars_t));
101
102 /* reinitialize available buffer */
103 for (u8 i = 0; i < DEFAULT_BUFFER_GROUP_NUM; i++) {
104 ev_buf_v->bufGroups[i].availBufNum = buffCnt[i];
105 ev_buf_v->bufGroups[i].qHead = mempool_init(memPool[i], mem[i], size[i], buffCnt[i]);
106 ev_buf_v->bufGroups[i].size = size[i];
107 }
108 }
109
110 /*********************************************************************
111 * @fn ev_buf_init
112 *
113 * @brief Initialize the EV Buffer module
114 *
115 * @param None
116 *
117 * @return None
118 */
ev_buf_init(void)119 void ev_buf_init(void)
120 {
121 ev_buf_reset();
122 }
123
124 /*********************************************************************
125 * @fn ev_buf_allocate
126 *
127 * @brief Allocate an available buffer according to the requested size
128 * The allocated buffer will have only three kind of size, defined
129 * in @ref EV_BUFFER_CONSTANT
130 *
131 * @param size - requested size
132 *
133 * @return Pointer to an allocated buffer.
134 * NULL means the there is no available buffer.
135 */
136
137 #if EV_BUFFER_DEBUG
my_ev_buf_allocate(u16 size,u16 line)138 u8 *my_ev_buf_allocate(u16 size, u16 line)
139 #else
140 u8 *ev_buf_allocate(u16 size)
141 #endif
142 {
143 if ((size == 0) || (size > MAX_BUFFER_SIZE)) {
144 /* the size parameter is wrong */
145 return NULL;
146 }
147 u32 r = irq_disable();
148 u8 index = U8_MAX;
149
150 /* find related the buffer blocks */
151 for (u8 i = 0; i < DEFAULT_BUFFER_GROUP_NUM; i++) {
152 if ((size <= ev_buf_v->bufGroups[i].size - OFFSETOF(ev_bufItem_t, data)) &&
153 ev_buf_v->bufGroups[i].availBufNum) {
154 index = i;
155 break;
156 }
157 }
158 if ((index == U8_MAX) || (!ev_buf_v->bufGroups[index].availBufNum)) {
159 /* no available buffer */
160 irq_restore(r);
161 return NULL;
162 }
163 u8 *temp = (u8 *)mempool_alloc(ev_buf_v->bufGroups[index].qHead);
164 if (!temp) {
165 irq_restore(r);
166 return NULL;
167 }
168 ev_buf_v->bufGroups[index].availBufNum--;
169
170 ev_bufItem_t *pNewBuf = (ev_bufItem_t *)(temp - 4);
171 pNewBuf->groupIndex = index;
172 #if EV_BUFFER_DEBUG
173 pNewBuf->line = line;
174 pNewBuf->flag = 0xfe;
175 #endif
176 irq_restore(r);
177 return pNewBuf->data;
178 }
179
180 /*********************************************************************
181 * @fn ev_buf_free
182 *
183 * @brief Free the specified buffer
184 *
185 * @param pBuf - the pointer to the specified buffer to free.
186 *
187 * @return status
188 */
189 #if EV_BUFFER_DEBUG
190 volatile u32 T_DBG_evFreeBuf = 0;
191 volatile u16 T_DBG_evFreeBufLine = 0;
my_ev_buf_free(u8 * pBuf,u16 line)192 buf_sts_t my_ev_buf_free(u8 *pBuf, u16 line)
193 #else
194 buf_sts_t ev_buf_free(u8 *pBuf)
195 #endif
196 {
197 u32 r = irq_disable();
198
199 if (!is_ev_buf(pBuf)) {
200 #if EV_BUFFER_DEBUG
201 T_DBG_evFreeBuf = (u32)pBuf;
202 T_DBG_evFreeBufLine = line;
203 #endif
204 }
205
206 ev_bufItem_t *pDelBuf = ev_buf_getHead(pBuf);
207
208 /* check whether the buffer is duplicated release */
209 if (ev_buf_isExisted(pDelBuf->groupIndex, (mem_block_t *)pDelBuf)) {
210 #if EV_BUFFER_DEBUG
211 T_DBG_evFreeBuf = (u32)pBuf;
212 T_DBG_evFreeBufLine = line;
213 #endif
214 irq_restore(r);
215 return BUFFER_DUPLICATE_FREE;
216 }
217
218 mempool_free(ev_buf_v->bufGroups[pDelBuf->groupIndex].qHead, ev_buf_retriveMempoolHeader(pBuf));
219 ev_buf_v->bufGroups[pDelBuf->groupIndex].availBufNum++;
220
221 #if EV_BUFFER_DEBUG
222 pDelBuf->line = line;
223 pDelBuf->flag = 0xff;
224 #endif
225
226 irq_restore(r);
227 return BUFFER_SUCC;
228 }
229
230 /*********************************************************************
231 * @fn ev_buf_getHead
232 *
233 * @brief Get the header pointer of a buffer item
234 *
235 * @param pd - the pointer of a data, which is previously allocated
236 *
237 * @return Pointer of bufferItem
238 */
ev_buf_getHead(u8 * pd)239 ev_bufItem_t *ev_buf_getHead(u8 *pd)
240 {
241 return (ev_bufItem_t *)(pd - OFFSETOF(ev_bufItem_t, data));
242 }
243
244 /*********************************************************************
245 * @fn ev_buf_getTail
246 *
247 * @brief Get the pointer from a EV BUFFER tail.
248 *
249 * @param pd - the pointer of a data, which is previously allocated
250 * @param offsetToTail - The offset to Tail
251 *
252 * @return Pointer of the specified memory
253 */
ev_buf_getTail(u8 * pd,int offsetToTail)254 u8 *ev_buf_getTail(u8 *pd, int offsetToTail)
255 {
256 u32 index;
257 u16 size[DEFAULT_BUFFER_GROUP_NUM] = {BUFFER_GROUP_0, BUFFER_GROUP_1, BUFFER_GROUP_2};
258
259 memcpy((u8 *)&index, pd - 4, 4);
260 assert((index < 3) && (index >= 0));
261 return (u8 *)(pd - 8 + size[index] - offsetToTail);
262 }
263
is_ev_buf(void * arg)264 u8 is_ev_buf(void *arg)
265 {
266 if (((u32)arg >= (u32)(size_0_mem) && (u32)arg <= ((u32)(size_0_mem) + sizeof(size_0_mem))) ||
267 ((u32)arg >= (u32)(size_1_mem) && (u32)arg <= ((u32)(size_1_mem) + sizeof(size_1_mem))) ||
268 ((u32)arg >= (u32)(size_2_mem) && (u32)arg <= ((u32)(size_2_mem) + sizeof(size_2_mem)))) {
269 return 1;
270 }
271 return 0;
272 }
273
ev_buf_getFreeMaxSize(void)274 u16 ev_buf_getFreeMaxSize(void)
275 {
276 u16 size = 0;
277
278 for (u8 i = 0; i < DEFAULT_BUFFER_GROUP_NUM; i++) {
279 if (ev_buf_v->bufGroups[i].availBufNum) {
280 if ((ev_buf_v->bufGroups[i].size - OFFSETOF(ev_bufItem_t, data)) > size) {
281 size = ev_buf_v->bufGroups[i].size - OFFSETOF(ev_bufItem_t, data);
282 }
283 }
284 }
285
286 return size;
287 }
288
289 #endif /* MODULE_BUFM_ENABLE */
290