• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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