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