GCC Code Coverage Report


Directory: main/
File: tools/util.h
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 11 11 100.0%
Functions: 1 1 100.0%
Branches: 6 6 100.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2011-2014, Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Misc utilities
10 *
11 * Misc utilities usable by the kernel and application code.
12 */
13
14 #ifndef _BLE_MESH_UTIL_H_
15 #define _BLE_MESH_UTIL_H_
16
17 #include <stdio.h>
18 #include <stddef.h>
19 #ifndef BLUERETRO
20 #include "mesh_types.h"
21 #include "mesh_trace.h"
22 #include "soc/soc.h"
23 #endif /* BLUERETRO */
24
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28
29 /* Helper to pass a int as a pointer or vice-versa.
30 * Those are available for 32 bits architectures:
31 */
32 #define POINTER_TO_UINT(x) ((u32_t) (x))
33 #define UINT_TO_POINTER(x) ((void *) (x))
34 #define POINTER_TO_INT(x) ((s32_t) (x))
35 #define INT_TO_POINTER(x) ((void *) (x))
36
37 /* Evaluates to 0 if cond is true-ish; compile error otherwise */
38 #define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1)
39
40 /* Evaluates to 0 if array is an array; compile error if not array (e.g.
41 * pointer)
42 */
43 #define IS_ARRAY(array) \
44 ZERO_OR_COMPILE_ERROR( \
45 !__builtin_types_compatible_p(__typeof__(array), \
46 __typeof__(&(array)[0])))
47
48 /* Evaluates to number of elements in an array; compile error if not
49 * an array (e.g. pointer)
50 */
51 #define ARRAY_SIZE(array) \
52 ((unsigned long) (IS_ARRAY(array) + \
53 (sizeof(array) / sizeof((array)[0]))))
54
55 /* Evaluates to 1 if ptr is part of array, 0 otherwise; compile error if
56 * "array" argument is not an array (e.g. "ptr" and "array" mixed up)
57 */
58 #define PART_OF_ARRAY(array, ptr) \
59 ((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)]))
60
61 #define CONTAINER_OF(ptr, type, field) \
62 ((type *)(((char *)(ptr)) - offsetof(type, field)))
63
64 /* round "x" up/down to next multiple of "align" (which must be a power of 2) */
65 #define ROUND_UP(x, align) \
66 (((unsigned long)(x) + ((unsigned long)align - 1)) & \
67 ~((unsigned long)align - 1))
68 #define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)align - 1))
69
70 #define ceiling_fraction(numerator, divider) \
71 (((numerator) + ((divider) - 1)) / (divider))
72
73 /* Internal helpers only used by the sys_* APIs further below */
74 #ifndef __bswap_16
75 #define __bswap_16(x) ((u16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
76 #endif
77
78 #ifndef __bswap_32
79 #define __bswap_32(x) ((u32_t) ((((x) >> 24) & 0xff) | \
80 (((x) >> 8) & 0xff00) | \
81 (((x) & 0xff00) << 8) | \
82 (((x) & 0xff) << 24)))
83 #endif
84
85 #ifndef __bswap_64
86 #define __bswap_64(x) ((u64_t) ((((x) >> 56) & 0xff) | \
87 (((x) >> 40) & 0xff00) | \
88 (((x) >> 24) & 0xff0000) | \
89 (((x) >> 8) & 0xff000000) | \
90 (((x) & 0xff000000) << 8) | \
91 (((x) & 0xff0000) << 24) | \
92 (((x) & 0xff00) << 40) | \
93 (((x) & 0xff) << 56)))
94 #endif
95
96 #define sys_le16_to_cpu(val) (val)
97 #define sys_cpu_to_le16(val) (val)
98 #define sys_be16_to_cpu(val) __bswap_16(val)
99 #define sys_cpu_to_be16(val) __bswap_16(val)
100 #define sys_le32_to_cpu(val) (val)
101 #define sys_cpu_to_le32(val) (val)
102 #define sys_le64_to_cpu(val) (val)
103 #define sys_cpu_to_le64(val) (val)
104 #define sys_be32_to_cpu(val) __bswap_32(val)
105 #define sys_cpu_to_be32(val) __bswap_32(val)
106 #define sys_be64_to_cpu(val) __bswap_64(val)
107 #define sys_cpu_to_be64(val) __bswap_64(val)
108
109 #ifndef MAX
110 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
111 #endif
112
113 #ifndef MIN
114 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
115 #endif
116
117 #ifndef BIT
118 #define BIT(n) (1UL << (n))
119 #endif
120
121 #ifndef BIT_MASK
122 #define BIT_MASK(n) (BIT(n) - 1)
123 #endif
124
125 /**
126 * @brief Check for macro definition in compiler-visible expressions
127 *
128 * This trick was pioneered in Linux as the config_enabled() macro.
129 * The madness has the effect of taking a macro value that may be
130 * defined to "1" (e.g. CONFIG_MYFEATURE), or may not be defined at
131 * all and turning it into a literal expression that can be used at
132 * "runtime". That is, it works similarly to
133 * "defined(CONFIG_MYFEATURE)" does except that it is an expansion
134 * that can exist in a standard expression and be seen by the compiler
135 * and optimizer. Thus much ifdef usage can be replaced with cleaner
136 * expressions like:
137 *
138 * if (IS_ENABLED(CONFIG_MYFEATURE))
139 * myfeature_enable();
140 *
141 * INTERNAL
142 * First pass just to expand any existing macros, we need the macro
143 * value to be e.g. a literal "1" at expansion time in the next macro,
144 * not "(1)", etc... Standard recursive expansion does not work.
145 */
146 #define IS_ENABLED(config_macro) _IS_ENABLED1(config_macro)
147
148 /* Now stick on a "_XXXX" prefix, it will now be "_XXXX1" if config_macro
149 * is "1", or just "_XXXX" if it's undefined.
150 * ENABLED: _IS_ENABLED2(_XXXX1)
151 * DISABLED _IS_ENABLED2(_XXXX)
152 */
153 #define _IS_ENABLED1(config_macro) _IS_ENABLED2(_XXXX##config_macro)
154
155 /* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string
156 * with a trailing comma), so it has the effect of making this a
157 * two-argument tuple to the preprocessor only in the case where the
158 * value is defined to "1"
159 * ENABLED: _YYYY, <--- note comma!
160 * DISABLED: _XXXX
161 */
162 #define _XXXX1 _YYYY,
163
164 /* Then we append an extra argument to fool the gcc preprocessor into
165 * accepting it as a varargs macro.
166 * arg1 arg2 arg3
167 * ENABLED: _IS_ENABLED3(_YYYY, 1, 0)
168 * DISABLED _IS_ENABLED3(_XXXX 1, 0)
169 */
170 #define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args 1, 0)
171
172 /* And our second argument is thus now cooked to be 1 in the case
173 * where the value is defined to 1, and 0 if not:
174 */
175 #define _IS_ENABLED3(ignore_this, val, ...) val
176
177 /* ESP Toolchain doesn't support section */
178 #define ___in_section(a, b, c)
179 #define __in_section(a, b, c) ___in_section(a, b, c)
180
181 #define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__)
182
183 #define popcount(x) __builtin_popcount(x)
184
185 /**
186 *
187 * @brief find most significant bit set in a 32-bit word
188 *
189 * This routine finds the first bit set starting from the most significant bit
190 * in the argument passed in and returns the index of that bit. Bits are
191 * numbered starting at 1 from the least significant bit. A return value of
192 * zero indicates that the value passed is zero.
193 *
194 * @return most significant bit set, 0 if @a op is 0
195 */
196
197 #if defined(__GNUC__)
198 static inline unsigned int find_msb_set(u32_t op)
199 {
200 if (!op) {
201 return 0;
202 }
203 return 32 - __builtin_clz(op);
204 }
205 #endif
206
207 /**
208 *
209 * @brief find least significant bit set in a 32-bit word
210 *
211 * This routine finds the first bit set starting from the least significant bit
212 * in the argument passed in and returns the index of that bit. Bits are
213 * numbered starting at 1 from the least significant bit. A return value of
214 * zero indicates that the value passed is zero.
215 *
216 * @return least significant bit set, 0 if @a op is 0
217 */
218
219 #if defined(__GNUC__)
220 static inline unsigned int find_lsb_set(u32_t op)
221 {
222 return __builtin_ffs(op);
223 }
224 #endif
225
226 /**
227 * @brief Put a 16-bit integer as big-endian to arbitrary location.
228 *
229 * Put a 16-bit integer, originally in host endianness, to a
230 * potentially unaligned memory location in big-endian format.
231 *
232 * @param val 16-bit integer in host endianness.
233 * @param dst Destination memory address to store the result.
234 */
235 static inline void sys_put_be16(u16_t val, u8_t dst[2])
236 {
237 dst[0] = val >> 8;
238 dst[1] = val;
239 }
240
241 /**
242 * @brief Put a 32-bit integer as big-endian to arbitrary location.
243 *
244 * Put a 32-bit integer, originally in host endianness, to a
245 * potentially unaligned memory location in big-endian format.
246 *
247 * @param val 32-bit integer in host endianness.
248 * @param dst Destination memory address to store the result.
249 */
250 static inline void sys_put_be32(u32_t val, u8_t dst[4])
251 {
252 sys_put_be16(val >> 16, dst);
253 sys_put_be16(val, &dst[2]);
254 }
255
256 /**
257 * @brief Put a 16-bit integer as little-endian to arbitrary location.
258 *
259 * Put a 16-bit integer, originally in host endianness, to a
260 * potentially unaligned memory location in little-endian format.
261 *
262 * @param val 16-bit integer in host endianness.
263 * @param dst Destination memory address to store the result.
264 */
265 static inline void sys_put_le16(u16_t val, u8_t dst[2])
266 {
267 dst[0] = val;
268 dst[1] = val >> 8;
269 }
270
271 /**
272 * @brief Put a 32-bit integer as little-endian to arbitrary location.
273 *
274 * Put a 32-bit integer, originally in host endianness, to a
275 * potentially unaligned memory location in little-endian format.
276 *
277 * @param val 32-bit integer in host endianness.
278 * @param dst Destination memory address to store the result.
279 */
280 static inline void sys_put_le32(u32_t val, u8_t dst[4])
281 {
282 sys_put_le16(val, dst);
283 sys_put_le16(val >> 16, &dst[2]);
284 }
285
286 /**
287 * @brief Put a 64-bit integer as little-endian to arbitrary location.
288 *
289 * Put a 64-bit integer, originally in host endianness, to a
290 * potentially unaligned memory location in little-endian format.
291 *
292 * @param val 64-bit integer in host endianness.
293 * @param dst Destination memory address to store the result.
294 */
295 static inline void sys_put_le64(u64_t val, u8_t dst[8])
296 {
297 sys_put_le32(val, dst);
298 sys_put_le32(val >> 32, &dst[4]);
299 }
300
301 /**
302 * @brief Get a 16-bit integer stored in big-endian format.
303 *
304 * Get a 16-bit integer, stored in big-endian format in a potentially
305 * unaligned memory location, and convert it to the host endianness.
306 *
307 * @param src Location of the big-endian 16-bit integer to get.
308 *
309 * @return 16-bit integer in host endianness.
310 */
311 static inline u16_t sys_get_be16(const u8_t src[2])
312 {
313 return ((u16_t)src[0] << 8) | src[1];
314 }
315
316 /**
317 * @brief Get a 32-bit integer stored in big-endian format.
318 *
319 * Get a 32-bit integer, stored in big-endian format in a potentially
320 * unaligned memory location, and convert it to the host endianness.
321 *
322 * @param src Location of the big-endian 32-bit integer to get.
323 *
324 * @return 32-bit integer in host endianness.
325 */
326 static inline u32_t sys_get_be32(const u8_t src[4])
327 {
328 return ((u32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]);
329 }
330
331 /**
332 * @brief Get a 16-bit integer stored in little-endian format.
333 *
334 * Get a 16-bit integer, stored in little-endian format in a potentially
335 * unaligned memory location, and convert it to the host endianness.
336 *
337 * @param src Location of the little-endian 16-bit integer to get.
338 *
339 * @return 16-bit integer in host endianness.
340 */
341 static inline u16_t sys_get_le16(const u8_t src[2])
342 {
343 return ((u16_t)src[1] << 8) | src[0];
344 }
345
346 /**
347 * @brief Get a 32-bit integer stored in little-endian format.
348 *
349 * Get a 32-bit integer, stored in little-endian format in a potentially
350 * unaligned memory location, and convert it to the host endianness.
351 *
352 * @param src Location of the little-endian 32-bit integer to get.
353 *
354 * @return 32-bit integer in host endianness.
355 */
356 static inline u32_t sys_get_le32(const u8_t src[4])
357 {
358 return ((u32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]);
359 }
360
361 /**
362 * @brief Get a 64-bit integer stored in little-endian format.
363 *
364 * Get a 64-bit integer, stored in little-endian format in a potentially
365 * unaligned memory location, and convert it to the host endianness.
366 *
367 * @param src Location of the little-endian 64-bit integer to get.
368 *
369 * @return 64-bit integer in host endianness.
370 */
371 static inline u64_t sys_get_le64(const u8_t src[8])
372 {
373 return ((u64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]);
374 }
375
376 const char *bt_hex(const void *buf, size_t len);
377
378 void mem_rcopy(u8_t *dst, u8_t const *src, u16_t len);
379
380 void _set(void *to, uint8_t val, unsigned int len);
381
382 unsigned int _copy(uint8_t *to, unsigned int to_len,
383 const uint8_t *from, unsigned int from_len);
384
385 void _set(void *to, uint8_t val, unsigned int len);
386
387 uint8_t _double_byte(uint8_t a);
388
389 int _compare(const uint8_t *a, const uint8_t *b, size_t size);
390
391 /**
392 * @brief Swap one buffer content into another
393 *
394 * Copy the content of src buffer into dst buffer in reversed order,
395 * i.e.: src[n] will be put in dst[end-n]
396 * Where n is an index and 'end' the last index in both arrays.
397 * The 2 memory pointers must be pointing to different areas, and have
398 * a minimum size of given length.
399 *
400 * @param dst A valid pointer on a memory area where to copy the data in
401 * @param src A valid pointer on a memory area where to copy the data from
402 * @param length Size of both dst and src memory areas
403 */
404 static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
405 {
406 #ifndef BLUERETRO
407 __ASSERT(((src < dst && (src + length) <= dst) ||
408 (src > dst && (dst + length) <= src)),
409 "Source and destination buffers must not overlap");
410 #endif
411
412 src += length - 1;
413
414 for (; length > 0; length--) {
415 *((u8_t *)dst++) = *((u8_t *)src--);
416 }
417 }
418
419 /**
420 * @brief Swap buffer content
421 *
422 * In-place memory swap, where final content will be reversed.
423 * I.e.: buf[n] will be put in buf[end-n]
424 * Where n is an index and 'end' the last index of buf.
425 *
426 * @param buf A valid pointer on a memory area to swap
427 * @param length Size of buf memory area
428 */
429 static inline void sys_mem_swap(void *buf, size_t length)
430 {
431 size_t i;
432
433 for (i = 0; i < (length / 2); i++) {
434 u8_t tmp = ((u8_t *)buf)[i];
435
436 ((u8_t *)buf)[i] = ((u8_t *)buf)[length - 1 - i];
437 ((u8_t *)buf)[length - 1 - i] = tmp;
438 }
439 }
440
441 63 static inline void data_dump(uint8_t *data, uint16_t len) {
442 63 uint8_t col;
443 63 uint16_t byte, line;
444 63 uint16_t line_max = len/16;
445
446
2/2
✓ Branch 0 (2→3) taken 60 times.
✓ Branch 1 (2→4) taken 3 times.
63 if (len % 16)
447 60 line_max++;
448
449
2/2
✓ Branch 0 (10→11) taken 362 times.
✓ Branch 1 (10→12) taken 63 times.
425 for (byte = 0, line = 0; line < line_max; line++) {
450 //printf("# %06X", byte);
451
2/2
✓ Branch 0 (7→5) taken 5084 times.
✓ Branch 1 (7→8) taken 362 times.
5446 for (col = 0; col < 16 && byte < len; col++, byte++) {
452 5084 printf(" %02X", data[byte]);
453 }
454 362 printf("\n");
455 }
456 63 }
457
458 #ifdef __cplusplus
459 }
460 #endif
461
462 #endif /* _BLE_MESH_UTIL_H_ */
463