1 /*
2 * Copyright (c) 2021 Chipsea Technologies (Shenzhen) Corp., Ltd. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef _WB_CO_UTILS_H
16 #define _WB_CO_UTILS_H
17
18 #include "compiler.h"
19 #include <limits.h>
20 #include "wb_co_math.h"
21
22 /**
23 ****************************************************************************************
24 * @brief Converts a STA index in an Association Index.
25 * @param[in] sta_idx The station index.
26 * @return The association index
27 ****************************************************************************************
28 */
29 #define CO_STAIDX_TO_AID(sta_idx) ((sta_idx) + 1)
30
31 /**
32 ****************************************************************************************
33 * @brief Get the index of an element in an array.
34 * @param[in] __element_ptr Pointer to the element
35 * @param[in] __array_ptr Pointer to the array
36 * @return The index of the element
37 ****************************************************************************************
38 */
39 #define CO_GET_INDEX(__element_ptr, __array_ptr) ((__element_ptr) - (__array_ptr))
40
41 /**
42 ****************************************************************************************
43 * @brief Get the number of element in an array.
44 * @param[in] a Pointer to the array
45 * @return The number of the element
46 ****************************************************************************************
47 */
48 #define CO_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
49
50 /// Length of a char in bytes
51 #define CHAR_LEN (CHAR_BIT/8)
52
53 /// Pack a structure field
54 #define __PACKED16 __attribute__ ((__packed__))
55 #ifndef __PACKED
56 #define __PACKED __attribute__ ((__packed__))
57 #endif
58
59 /**
60 ****************************************************************************************
61 * @brief Converts a CPU pointer into a HW address
62 * This macro is used to convert a SW pointer into the corresponding HW address. With CPUs
63 * having native byte support, the value returned will be the same as the pointer passed.
64 * With TL4, the value returned is the pointer multiplied by 2.
65 * @param[in] ptr Pointer to be converted
66 * @return The corresponding HW address
67 ****************************************************************************************
68 */
69 #define CPU2HW(ptr) (((uint32_t)(ptr)) * CHAR_LEN)
70
71 /**
72 ****************************************************************************************
73 * @brief Converts a HW address into a CPU pointer
74 * This macro is doing the reverse operation as @ref CPU2HW.
75 * @param[in] ptr Address to be converted
76 * @return The corresponding CPU pointer
77 ****************************************************************************************
78 */
79 #define HW2CPU(ptr) ((void *)(((uint32_t)(ptr)) / CHAR_LEN))
80
81 /**
82 ****************************************************************************************
83 * @brief Return the size of a variable or type in bytes
84 * @param[in] a Variable for which the size is computed
85 * @return The size of the variable in bytes
86 ****************************************************************************************
87 */
88 #define sizeof_b(a) (sizeof(a) * CHAR_LEN)
89
90 /**
91 ****************************************************************************************
92 * @brief Return the offset (in bytes) of a structure element
93 * @param[in] a Structure type
94 * @param[in] b Field name
95 * @return The of the field in bytes
96 ****************************************************************************************
97 */
98 #define offsetof_b(a, b) (offsetof(a, b) * CHAR_LEN)
99
100 /*
101 * FUNCTION DECLARATIONS
102 ****************************************************************************************
103 */
104 /**
105 ****************************************************************************************
106 * @brief Read an aligned 16 bits word.
107 * @param[in] ptr16 The address of the first byte of the 16 bits word.
108 * @return The 16 bits value.
109 ****************************************************************************************
110 */
co_read16(void const * ptr16)111 __STATIC_INLINE uint16_t co_read16(void const *ptr16)
112 {
113 return *((uint16_t*)ptr16);
114 }
115
116 /**
117 ****************************************************************************************
118 * @brief Write an aligned 16 bits word.
119 * @param[in] ptr16 The address of the first byte of the 16 bits word.
120 * @param[in] value The value to write.
121 ****************************************************************************************
122 */
co_write16(void const * ptr16,uint32_t value)123 __STATIC_INLINE void co_write16(void const *ptr16, uint32_t value)
124 {
125 *(uint16_t*)ptr16 = value;
126 }
127
128 /**
129 ****************************************************************************************
130 * @brief Read an aligned 32 bit word.
131 * @param[in] ptr32 The address of the first byte of the 32 bit word.
132 * @return The 32 bit value.
133 ****************************************************************************************
134 */
co_read32(void const * ptr32)135 __STATIC_INLINE uint32_t co_read32(void const *ptr32)
136 {
137 return *((uint32_t*)ptr32);
138 }
139
140 /**
141 ****************************************************************************************
142 * @brief Write an aligned 32 bits word.
143 * @param[in] ptr32 The address of the first byte of the 32 bits word.
144 * @param[in] value The value to write.
145 ****************************************************************************************
146 */
co_write32(void const * ptr32,uint32_t value)147 __STATIC_INLINE void co_write32(void const *ptr32, uint32_t value)
148 {
149 *(uint32_t*)ptr32 = value;
150 }
151
152 /**
153 ****************************************************************************************
154 * @brief Copy a 32-bit aligned buffer into another one
155 * The length in bytes is converted to the corresponding number of 32-bit words. If the
156 * byte length is not a multiple of 4, then additional bytes will be copied at the end
157 * of the buffer. It is the responsibility of the caller to ensure that these extra-byte
158 * copy won't corrupt the memory at the end of the destination buffer.
159 *
160 * @param[in] dst Pointer to the destination buffer
161 * @param[in] src Pointer to the source buffer
162 * @param[in] len Length to be copied (in bytes)
163 ****************************************************************************************
164 */
co_copy32(uint32_t * dst,uint32_t * src,uint32_t len)165 __STATIC_INLINE void co_copy32(uint32_t *dst, uint32_t *src, uint32_t len)
166 {
167 len = CO_ALIGN4_HI(len)/4;
168 while (len--)
169 {
170 *dst++ = *src++;
171 }
172 }
173
174 /**
175 ****************************************************************************************
176 * @brief Read a 8 bits word.
177 * @param[in] addr The address of the first byte of the 8 bits word.
178 * @return The read value
179 ****************************************************************************************
180 */
co_read8p(uint32_t addr)181 __STATIC_INLINE uint8_t co_read8p(uint32_t addr)
182 {
183 #ifdef CFG_RWTL
184 int shift = (addr & 0x1) * 8;
185 uint16_t *ptr = (uint16_t *)(addr / 2);
186 return ((uint8_t)((*ptr >> shift) & 0xFF));
187 #else
188 return (*(uint8_t *)addr);
189 #endif
190 }
191
192 /**
193 ****************************************************************************************
194 * @brief Write a 8 bits word.
195 * @param[in] addr The address of the first byte of the 8 bits word.
196 * @param[in] value The value to write.
197 ****************************************************************************************
198 */
co_write8p(uint32_t addr,uint8_t value)199 __STATIC_INLINE void co_write8p(uint32_t addr, uint8_t value)
200 {
201 #ifdef CFG_RWTL
202 int shift = (addr & 0x1) * 8;
203 uint16_t *ptr = (uint16_t *)(addr / 2);
204 *ptr = (*ptr & ~(0xFF << shift)) | ((value & 0xFF) << shift);
205 #else
206 *(uint8_t *)addr = value;
207 #endif
208 }
209
210
211 /**
212 ****************************************************************************************
213 * @brief Read a packed 16 bits word.
214 * @param[in] addr The address of the first byte of the 16 bits word.
215 * @return The 16 bits value.
216 ****************************************************************************************
217 */
co_read16p(uint32_t addr)218 __STATIC_INLINE uint16_t co_read16p(uint32_t addr)
219 {
220 #ifdef CFG_RWTL
221 return ((((uint16_t)co_read8p(addr + 1)) << 8) | co_read8p(addr));
222 #else
223 struct co_read16_struct
224 {
225 uint16_t val __PACKED16;
226 } *ptr = (struct co_read16_struct*)addr;
227 return ptr->val;
228 #endif
229 }
230
231 /**
232 ****************************************************************************************
233 * @brief Write a packed 16 bits word.
234 * @param[in] addr The address of the first byte of the 16 bits word.
235 * @param[in] value The value to write.
236 ****************************************************************************************
237 */
co_write16p(uint32_t addr,uint32_t value)238 __STATIC_INLINE void co_write16p(uint32_t addr, uint32_t value)
239 {
240 #ifdef CFG_RWTL
241 co_write8p(addr, value & 0xFF);
242 co_write8p(addr + 1, ((value >> 8) & 0xFF));
243 #else
244 struct co_read16_struct
245 {
246 uint16_t val __PACKED16;
247 } *ptr = (struct co_read16_struct*) addr;
248
249 ptr->val = value;
250 #endif
251 }
252
253 /**
254 ****************************************************************************************
255 * @brief Read a packed 24 bits word.
256 * @param[in] addr The address of the first byte of the 24 bits word.
257 * @return The 24 bits value, on a 32-bit variable.
258 ****************************************************************************************
259 */
co_read24p(uint32_t addr)260 __STATIC_INLINE uint32_t co_read24p(uint32_t addr)
261 {
262 return ((((uint32_t)co_read16p(addr + 1)) << 8) | co_read8p(addr));
263 }
264
265 /**
266 ****************************************************************************************
267 * @brief Write a packed 24 bits word.
268 * @param[in] addr The address of the first byte of the 24 bits word.
269 * @param[in] value The value to write.
270 ****************************************************************************************
271 */
co_write24p(uint32_t addr,uint32_t value)272 __STATIC_INLINE void co_write24p(uint32_t addr, uint32_t value)
273 {
274 co_write8p(addr, value & 0xFF);
275 co_write16p(addr + 1, ((value >> 8) & 0xFFFF));
276 }
277
278 /**
279 ****************************************************************************************
280 * @brief Read a packed 32 bits word.
281 * @param[in] addr The address of the first byte of the 32 bits word.
282 * @return The 32 bits value.
283 ****************************************************************************************
284 */
co_read32p(uint32_t addr)285 __STATIC_INLINE uint32_t co_read32p(uint32_t addr)
286 {
287 #ifdef CFG_RWTL
288 return ((((uint32_t)co_read16p(addr + 2)) << 16) | co_read16p(addr));
289 #else
290 struct co_read32_struct
291 {
292 uint32_t val __PACKED;
293 } *ptr = (struct co_read32_struct*) addr;
294 return ptr->val;
295 #endif
296 }
297
298 /**
299 ****************************************************************************************
300 * @brief Write a packed 32 bits word.
301 * @param[in] addr The address of the first byte of the 32 bits word.
302 * @param[in] value The value to write.
303 ****************************************************************************************
304 */
co_write32p(uint32_t addr,uint32_t value)305 __STATIC_INLINE void co_write32p(uint32_t addr, uint32_t value)
306 {
307 #ifdef CFG_RWTL
308 co_write16p(addr, value & 0xFFFF);
309 co_write16p(addr + 2, ((value >> 16) & 0xFFFF));
310 #else
311 struct co_read32_struct
312 {
313 uint32_t val __PACKED;
314 } *ptr = (struct co_read32_struct*) addr;
315 ptr->val = value;
316 #endif
317 }
318
319 /**
320 ****************************************************************************************
321 * @brief Read a packed 64 bits word.
322 * @param[in] addr The address of the first byte of the 64 bits word.
323 * @return The 64 bits value.
324 ****************************************************************************************
325 */
co_read64p(uint32_t addr)326 __STATIC_INLINE uint64_t co_read64p(uint32_t addr)
327 {
328 #ifdef CFG_RWTL
329 return ((((uint64_t)co_read32p(addr + 4)) << 32) | co_read32p(addr));
330 #else
331 struct co_read64_struct
332 {
333 uint64_t val __PACKED;
334 } *ptr = (struct co_read64_struct*) addr;
335 return ptr->val;
336 #endif
337 }
338
339 /**
340 ****************************************************************************************
341 * @brief Compare a packed byte buffer with a CPU byte array
342 * @param[in] pkd The address of the packed buffer.
343 * @param[in] ptr Pointer to the CPU byte array
344 * @param[in] len Length to be compared
345 *
346 * @return true if the buffers are equal, false otherwise
347 ****************************************************************************************
348 */
co_cmp8p(uint32_t pkd,uint8_t const * ptr,uint32_t len)349 __STATIC_INLINE bool co_cmp8p(uint32_t pkd, uint8_t const *ptr, uint32_t len)
350 {
351 while (len--)
352 {
353 if (co_read8p(pkd++) != (*ptr++ & 0xFF))
354 return false;
355 }
356 return true;
357 }
358
359 /**
360 ****************************************************************************************
361 * @brief Copy and pack a byte array to another one
362 * @param[in] dst The address of the first byte of the packed buffer in which the data has
363 * to be copied.
364 * @param[in] src Pointer to the source buffer
365 * @param[in] len Length to be copied
366 ****************************************************************************************
367 */
co_pack8p(uint32_t dst,uint8_t const * src,uint32_t len)368 __STATIC_INLINE void co_pack8p(uint32_t dst, uint8_t const *src, uint32_t len)
369 {
370 while (len--)
371 {
372 co_write8p(dst++, *src++);
373 }
374 }
375
376 /**
377 ****************************************************************************************
378 * @brief Copy and unpack a byte array to another one
379 * @param[in] dst Pointer to the first byte of the unpacked buffer in which the data has
380 * to be copied.
381 * @param[in] src Address of the packed source buffer
382 * @param[in] len Length to be copied
383 ****************************************************************************************
384 */
co_unpack8p(uint8_t * dst,uint32_t src,uint32_t len)385 __STATIC_INLINE void co_unpack8p(uint8_t *dst, uint32_t src, uint32_t len)
386 {
387 while (len--)
388 {
389 *dst++ = co_read8p(src++);
390 }
391 }
392
393 /**
394 ****************************************************************************************
395 * @brief Copy a packed byte array to another packed byte array
396 * @param[in] dst The address of the first byte of the packed buffer in which the data has
397 * to be copied.
398 * @param[in] src Address of the source buffer
399 * @param[in] len Length to be copied
400 ****************************************************************************************
401 */
co_copy8p(uint32_t dst,uint32_t src,uint32_t len)402 __STATIC_INLINE void co_copy8p(uint32_t dst, uint32_t src, uint32_t len)
403 {
404 while (len--)
405 {
406 co_write8p(dst++, co_read8p(src++));
407 }
408 }
409
410 /**
411 ****************************************************************************************
412 * @brief This function returns the value of bit field inside an array of bits,
413 * represented as an array of bytes.
414 * @param[in] array Array of bits
415 * @param[in] lsb Position of the LSB of the field inside the array of bits
416 * @param[in] width Width of the field
417 * @return true if the specified bit is set, false otherwise
418 ****************************************************************************************
419 */
co_val_get(uint8_t const array[],int lsb,int width)420 __STATIC_INLINE uint8_t co_val_get(uint8_t const array[], int lsb, int width)
421 {
422 int msb = lsb + width - 1;
423 int l_byte_idx = lsb/8;
424 int m_byte_idx = msb/8;
425 uint8_t val;
426
427 if (m_byte_idx == l_byte_idx)
428 {
429 uint8_t mask = CO_BIT(width) - 1;
430 int shift = lsb % 8;
431 val = (array[l_byte_idx] >> shift) & mask;
432 }
433 else
434 {
435 uint8_t l_bits_cnt = m_byte_idx * 8 - lsb;
436 uint8_t l_mask = CO_BIT(l_bits_cnt) - 1;
437 uint8_t m_mask = CO_BIT(width - l_bits_cnt) - 1;
438 int l_shift = lsb % 8;
439 val = (array[l_byte_idx] >> l_shift) & l_mask;
440 val |= (array[m_byte_idx] & m_mask) << l_bits_cnt;
441 }
442 return (val);
443 }
444
445 /**
446 ****************************************************************************************
447 * @brief This function sets a value of a bit field inside an array of bits,
448 * represented as an array of bytes.
449 * @param[in] array Array of bits
450 * @param[in] lsb Position of the LSB of the field inside the array of bits
451 * @param[in] width Width of the field
452 * @param[in] val Value to be set
453 ****************************************************************************************
454 */
co_val_set(uint8_t array[],int lsb,int width,uint8_t val)455 __STATIC_INLINE void co_val_set(uint8_t array[], int lsb, int width, uint8_t val)
456 {
457 int msb = lsb + width - 1;
458 int l_byte_idx = lsb/8;
459 int m_byte_idx = msb/8;
460
461 if (m_byte_idx == l_byte_idx)
462 {
463 uint8_t mask = CO_BIT(width) - 1;
464 int shift = lsb % 8;
465 array[l_byte_idx] &= ~(mask << shift);
466 array[l_byte_idx] |= (val & mask) << shift;
467 }
468 else
469 {
470 uint8_t l_bits_cnt = m_byte_idx * 8 - lsb;
471 uint8_t l_mask = CO_BIT(l_bits_cnt) - 1;
472 uint8_t m_mask = CO_BIT(width - l_bits_cnt) - 1;
473 int l_shift = lsb % 8;
474 array[l_byte_idx] &= ~(l_mask << l_shift);
475 array[m_byte_idx] &= ~m_mask;
476 array[l_byte_idx] |= (val & l_mask) << l_shift;
477 array[m_byte_idx] |= (val >> l_bits_cnt) & m_mask;
478 }
479 }
480
481 /**
482 ****************************************************************************************
483 * @brief This function returns the status of a specific bit position inside an array of
484 * bits, represented as an array of bytes.
485 * @param[in] array Array of bits to be checked
486 * @param[in] pos Bit position to be checked
487 * @return true if the specified bit is set, false otherwise
488 ****************************************************************************************
489 */
co_bit_is_set(uint8_t const array[],int pos)490 __STATIC_INLINE bool co_bit_is_set(uint8_t const array[], int pos)
491 {
492 return ((array[pos / 8] & CO_BIT(pos % 8)) != 0);
493 }
494
495 /**
496 ****************************************************************************************
497 * @brief This function sets a specific bit position inside an array of bits, represented
498 * as an array of bytes.
499 * @param[in] array Array of bits
500 * @param[in] pos Bit position to be set
501 ****************************************************************************************
502 */
co_bit_set(uint8_t array[],uint8_t pos)503 __STATIC_INLINE void co_bit_set(uint8_t array[], uint8_t pos)
504 {
505 array[pos / 8] |= CO_BIT(pos % 8);
506 }
507
508 /**
509 ****************************************************************************************
510 * @brief This function clears a specific bit position inside an array of bits,
511 * represented as an array of bytes.
512 * @param[in] array Array of bits
513 * @param[in] pos Bit position to be cleared
514 ****************************************************************************************
515 */
co_bit_clr(uint8_t array[],uint8_t pos)516 __STATIC_INLINE void co_bit_clr(uint8_t array[], uint8_t pos)
517 {
518 array[pos / 8] &= ~CO_BIT(pos % 8);
519 }
520
521 #endif // _WB_CO_UTILS_H
522