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 /***************************************************************************
19 * *
20 * INSERT COPYRIGHT HERE! *
21 * *
22 ****************************************************************************
23 PURPOSE: Zigbee packet buffers pool
24 */
25 #include "zb_buffer.h"
26 #include "common/compiler.h"
27
28 /*! \addtogroup buf */
29 /*! @{ */
30
31 /*
32 * the buffer for zigbee stack initilization
33 *
34 * */
tl_zbBufferInit(void)35 void tl_zbBufferInit(void)
36 {
37 memset((u8 *)&g_mPool, 0, sizeof(zb_buf_pool_t));
38
39 zb_buf_t *p = g_mPool.head = &g_mPool.pool[0];
40
41 for (s32 i = 0; i < ZB_BUF_POOL_SIZE - 1; i++) {
42 p->next = (p + 1);
43 p++;
44 }
45 p->next = NULL;
46 }
47
48 /*
49 * allocate a buffer directly
50 * return success, if the pool has a empty buffer,
51 * if not, return failure
52 *
53 * */
54 #if ZB_BUFFER_DEBUG
my_zb_buf_get(u16 line)55 static _attribute_ram_code_ zb_buf_t *my_zb_buf_get(u16 line)
56 #else
57 static _attribute_ram_code_ zb_buf_t *zb_buf_get(void)
58 #endif
59 {
60 zb_buf_t *buf = NULL;
61
62 u8 r = irq_disable();
63 if (g_mPool.usedNum < ZB_BUF_POOL_SIZE) {
64 if ((((u32)(g_mPool.head) < (u32)(&g_mPool.pool[0])) && (g_mPool.head != NULL)) ||
65 ((u32)(g_mPool.head) > (u32)(&g_mPool.pool[ZB_BUF_POOL_SIZE - 1]))) {
66 }
67
68 buf = g_mPool.head;
69 if (buf) {
70 g_mPool.head = buf->next;
71 buf->next = NULL;
72 memset(&buf->hdr, 0, sizeof(buf->hdr));
73 memset(buf->buf, 0, ZB_BUF_SIZE);
74 g_mPool.usedNum++;
75 buf->hdr.used = 1;
76 #if ZB_BUFFER_DEBUG
77 u32 idx = buf->allocCnt % ZB_BUFF_DBG_NUM;
78 buf->allocInfo[idx].allocLine = line;
79 #endif
80 buf->allocCnt++;
81 } else {
82 if (g_mPool.usedNum < ZB_BUF_POOL_SIZE) {
83 }
84 }
85 }
86 irq_restore(r);
87
88 if (!buf) {
89 }
90
91 return buf;
92 }
93
tl_phyRxBufTozbBuf(u8 * p)94 inline u8 *tl_phyRxBufTozbBuf(u8 *p)
95 {
96 return (p - RX_ZBBUF_OFFSET);
97 }
98
tl_zbBufToPhyRxBuf(u8 * p)99 inline u8 *tl_zbBufToPhyRxBuf(u8 *p)
100 {
101 return (p + RX_ZBBUF_OFFSET);
102 }
103
104 /*
105 * allocate a buffer directly for ZB stack
106 * return success, if the pool has a empty buffer,
107 * if not, return failure
108 *
109 * */
110 #if ZB_BUFFER_DEBUG
my_zb_buf_allocate(u16 line)111 zb_buf_t *my_zb_buf_allocate(u16 line)
112 {
113 return my_zb_buf_get(line);
114 }
tl_getRxBuf(void)115 _attribute_ram_code_ u8 *tl_getRxBuf(void)
116 {
117 u8 *buf = (u8 *)my_zb_buf_get(90);
118 if (buf) {
119 return TL_INBUF_TO_RXBUF(buf);
120 }
121 return NULL;
122 }
123 #else
zb_buf_allocate(void)124 _attribute_ram_code_ zb_buf_t *zb_buf_allocate(void)
125 {
126 return zb_buf_get();
127 }
128
tl_getRxBuf(void)129 _attribute_ram_code_ u8 *tl_getRxBuf(void)
130 {
131 u8 *buf = (u8 *)zb_buf_get();
132 if (buf) {
133 return TL_INBUF_TO_RXBUF(buf);
134 }
135 return NULL;
136 }
137
138 #endif
139
140 /*
141 * free the buffer
142 * */
143 volatile u32 T_zbBufDbg = 0;
144 volatile u32 T_zbBufFreeDbg = 0;
145 #if ZB_BUFFER_DEBUG
146 volatile u32 T_zbBufFreeDbgLine = 0;
147 volatile u32 T_zbBufFreeDbgIdx = 0;
148 volatile u32 T_zbBufFreeDbgIdx1 = 0;
my_zb_buf_free(zb_buf_t * buf,u16 line)149 u8 my_zb_buf_free(zb_buf_t *buf, u16 line)
150 #else
151 u8 zb_buf_free(zb_buf_t *buf)
152 #endif
153 {
154 u8 r = irq_disable();
155
156 if (!is_zb_buf((void *)buf)) {
157 }
158
159 #if ZB_BUFFER_DEBUG
160 u32 idx = buf->freeCnt % ZB_BUFF_DBG_NUM;
161 T_zbBufFreeDbgLine = buf->allocInfo[idx].freeLine;
162 T_zbBufFreeDbgIdx1 = buf->allocCnt;
163 T_zbBufFreeDbgIdx = idx;
164 buf->allocInfo[idx].freeLine = line;
165 buf->allocInfo[idx].handler = buf->hdr.handle;
166 buf->allocInfo[idx].id = buf->hdr.id;
167 buf->allocInfo[idx].nlmeStatus = buf->hdr.resvHdr;
168 T_zbBufDbg = (u32)buf;
169 #endif
170
171 buf->freeCnt++;
172 if (buf->hdr.macTxFifo == 1 || buf->freeCnt > buf->allocCnt || buf->hdr.used == 0) {
173 T_zbBufFreeDbg = (buf->hdr.macTxFifo << 24) | ((buf->freeCnt > buf->allocCnt) << 16) | buf->hdr.used;
174 T_zbBufDbg = (u32)buf;
175 }
176
177 if ((((u32)(g_mPool.head) < (u32)(&g_mPool.pool[0])) && (g_mPool.head != NULL)) ||
178 ((u32)(g_mPool.head) > (u32)(&g_mPool.pool[ZB_BUF_POOL_SIZE - 1]))) {
179 }
180
181 g_mPool.usedNum--;
182 buf->next = g_mPool.head;
183 g_mPool.head = buf;
184
185 if ((((u32)(g_mPool.head) < (u32)(&g_mPool.pool[0])) && (g_mPool.head != NULL)) ||
186 ((u32)(g_mPool.head) > (u32)(&g_mPool.pool[ZB_BUF_POOL_SIZE - 1]))) {
187 }
188 buf->hdr.used = 0;
189 buf->hdr.handle = 0xff;
190
191 irq_restore(r);
192 return SUCCESS;
193 }
194
tl_bufInitalloc(zb_buf_t * p,u8 size)195 void *tl_bufInitalloc(zb_buf_t *p, u8 size)
196 {
197 #ifdef ZB_SECURITY
198 size += 8; // Extra 4 bytes for APS MIC and 4 bytes for NWK MIC
199 #endif
200 return (void *)((u8 *)p + ((ZB_BUF_SIZE - size) & (~0x03)));
201 }
202
203 /* clear the buffer, some info set as 0 */
zb_buf_clear(zb_buf_t * p)204 void zb_buf_clear(zb_buf_t *p)
205 {
206 u8 used = p->hdr.used;
207
208 u8 r = irq_disable();
209 memset(&p->hdr, 0, sizeof(p->hdr));
210 p->hdr.used = used;
211 irq_restore(r);
212 }
213
is_zb_buf(void * p)214 bool is_zb_buf(void *p)
215 {
216 if (((u32)p >= (u32)(&g_mPool.pool[0])) && ((u32)p < (u32)((&g_mPool.pool[ZB_BUF_POOL_SIZE - 1])) + ZB_BUF_SIZE)) {
217 return 1;
218 }
219 return 0;
220 }
221
222 #if ZB_BUFFER_DEBUG
223 volatile u8 T_zbbud_debug_start = 0;
224 typedef struct {
225 u8 id;
226 u8 handle;
227 u16 allocateLine;
228 } zb_bufDbg_t;
229 zb_bufDbg_t g_zbBufDBG[ZB_BUF_POOL_NUM];
230
zb_buf_debug_start(void)231 void zb_buf_debug_start(void)
232 {
233 if (T_zbbud_debug_start) {
234 u8 cnt = 0;
235 T_zbbud_debug_start = 0;
236 for (s32 i = 0; i < ZB_BUF_POOL_SIZE - 1; i++) {
237 if (g_mPool.pool[i].hdr.used) {
238 g_zbBufDBG[cnt].handle = g_mPool.pool[i].hdr.handle;
239 g_zbBufDBG[cnt].id = g_mPool.pool[i].hdr.id;
240 cnt++;
241 }
242 }
243 }
244 }
245 #endif
246
247 /*! @} */
248