Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 | /* * Copyright (c) 2011-2014, Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Misc utilities * * Misc utilities usable by the kernel and application code. */ #ifndef ZEPHYR_INCLUDE_SYS_UTIL_H_ #define ZEPHYR_INCLUDE_SYS_UTIL_H_ #include <zephyr/sys/util_macro.h> #include <zephyr/toolchain.h> /* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn * into '1' and '0' for asm or linker scripts */ #include <stdbool.h> #ifndef _ASMLANGUAGE #include <zephyr/sys/__assert.h> #include <zephyr/types.h> #include <stddef.h> #include <stdint.h> /** @brief Number of bits that make up a type */ #define NUM_BITS(t) (sizeof(t) * 8) #ifdef __cplusplus extern "C" { #endif /** * @defgroup sys-util Utility Functions * @since 2.4 * @version 0.1.0 * @ingroup utilities * @{ */ /** @brief Cast @p x, a pointer, to an unsigned integer. */ #define POINTER_TO_UINT(x) ((uintptr_t) (x)) /** @brief Cast @p x, an unsigned integer, to a <tt>void*</tt>. */ #define UINT_TO_POINTER(x) ((void *) (uintptr_t) (x)) /** @brief Cast @p x, a pointer, to a signed integer. */ #define POINTER_TO_INT(x) ((intptr_t) (x)) /** @brief Cast @p x, a signed integer, to a <tt>void*</tt>. */ #define INT_TO_POINTER(x) ((void *) (intptr_t) (x)) #if !(defined(__CHAR_BIT__) && defined(__SIZEOF_LONG__) && defined(__SIZEOF_LONG_LONG__)) # error Missing required predefined macros for BITS_PER_LONG calculation #endif /** Number of bits in a byte. */ #define BITS_PER_BYTE (__CHAR_BIT__) /** Number of bits in a nibble. */ #define BITS_PER_NIBBLE (__CHAR_BIT__ / 2) /** Number of nibbles in a byte. */ #define NIBBLES_PER_BYTE (BITS_PER_BYTE / BITS_PER_NIBBLE) /** Number of bits in a long int. */ #define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__) /** Number of bits in a long long int. */ #define BITS_PER_LONG_LONG (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) /** * @brief Create a contiguous bitmask starting at bit position @p l * and ending at position @p h. */ #define GENMASK(h, l) \ (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) /** * @brief Create a contiguous 64-bit bitmask starting at bit position @p l * and ending at position @p h. */ #define GENMASK64(h, l) \ (((~0ULL) - (1ULL << (l)) + 1) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) /** @brief 0 if @p cond is true-ish; causes a compile error otherwise. */ #define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1) #if defined(__cplusplus) /* The built-in function used below for type checking in C is not * supported by GNU C++. */ #define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) #else /* __cplusplus */ /** * @brief Zero if @p array has an array type, a compile error otherwise * * This macro is available only from C, not C++. */ #define IS_ARRAY(array) \ ZERO_OR_COMPILE_ERROR( \ !__builtin_types_compatible_p(__typeof__(array), \ __typeof__(&(array)[0]))) /** * @brief Number of elements in the given @p array * * In C++, due to language limitations, this will accept as @p array * any type that implements <tt>operator[]</tt>. The results may not be * particularly meaningful in this case. * * In C, passing a pointer as @p array causes a compile error. */ #define ARRAY_SIZE(array) \ ((size_t) (IS_ARRAY(array) + (sizeof(array) / sizeof((array)[0])))) #endif /* __cplusplus */ /** * @brief Declare a flexible array member. * * This macro declares a flexible array member in a struct. The member * is named @p name and has type @p type. * * Since C99, flexible arrays are part of the C standard, but for historical * reasons many places still use an older GNU extension that is declare * zero length arrays. * * Although zero length arrays are flexible arrays, we can't blindly * replace [0] with [] because of some syntax limitations. This macro * workaround these limitations. * * It is specially useful for cases where flexible arrays are * used in unions or are not the last element in the struct. */ #define FLEXIBLE_ARRAY_DECLARE(type, name) \ struct { \ struct { } __unused_##name; \ type name[]; \ } /** * @brief Whether @p ptr is an element of @p array * * This macro can be seen as a slightly stricter version of @ref PART_OF_ARRAY * in that it also ensures that @p ptr is aligned to an array-element boundary * of @p array. * * In C, passing a pointer as @p array causes a compile error. * * @param array the array in question * @param ptr the pointer to check * * @return 1 if @p ptr is part of @p array, 0 otherwise */ #define IS_ARRAY_ELEMENT(array, ptr) \ ((ptr) && POINTER_TO_UINT(array) <= POINTER_TO_UINT(ptr) && \ POINTER_TO_UINT(ptr) < POINTER_TO_UINT(&(array)[ARRAY_SIZE(array)]) && \ (POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) % sizeof((array)[0]) == 0) /** * @brief Index of @p ptr within @p array * * With `CONFIG_ASSERT=y`, this macro will trigger a runtime assertion * when @p ptr does not fall into the range of @p array or when @p ptr * is not aligned to an array-element boundary of @p array. * * In C, passing a pointer as @p array causes a compile error. * * @param array the array in question * @param ptr pointer to an element of @p array * * @return the array index of @p ptr within @p array, on success */ #define ARRAY_INDEX(array, ptr) \ ({ \ __ASSERT_NO_MSG(IS_ARRAY_ELEMENT(array, ptr)); \ (__typeof__((array)[0]) *)(ptr) - (array); \ }) /** * @brief Check if a pointer @p ptr lies within @p array. * * In C but not C++, this causes a compile error if @p array is not an array * (e.g. if @p ptr and @p array are mixed up). * * @param array an array * @param ptr a pointer * @return 1 if @p ptr is part of @p array, 0 otherwise */ #define PART_OF_ARRAY(array, ptr) \ ((ptr) && POINTER_TO_UINT(array) <= POINTER_TO_UINT(ptr) && \ POINTER_TO_UINT(ptr) < POINTER_TO_UINT(&(array)[ARRAY_SIZE(array)])) /** * @brief Array-index of @p ptr within @p array, rounded down * * This macro behaves much like @ref ARRAY_INDEX with the notable * difference that it accepts any @p ptr in the range of @p array rather than * exclusively a @p ptr aligned to an array-element boundary of @p array. * * With `CONFIG_ASSERT=y`, this macro will trigger a runtime assertion * when @p ptr does not fall into the range of @p array. * * In C, passing a pointer as @p array causes a compile error. * * @param array the array in question * @param ptr pointer to an element of @p array * * @return the array index of @p ptr within @p array, on success */ #define ARRAY_INDEX_FLOOR(array, ptr) \ ({ \ __ASSERT_NO_MSG(PART_OF_ARRAY(array, ptr)); \ (POINTER_TO_UINT(ptr) - POINTER_TO_UINT(array)) / sizeof((array)[0]); \ }) /** * @brief Iterate over members of an array using an index variable * * @param array the array in question * @param idx name of array index variable */ #define ARRAY_FOR_EACH(array, idx) for (size_t idx = 0; (idx) < ARRAY_SIZE(array); ++(idx)) /** * @brief Iterate over members of an array using a pointer * * @param array the array in question * @param ptr pointer to an element of @p array */ #define ARRAY_FOR_EACH_PTR(array, ptr) \ for (__typeof__(*(array)) *ptr = (array); (size_t)((ptr) - (array)) < ARRAY_SIZE(array); \ ++(ptr)) /** * @brief Validate if two entities have a compatible type * * @param a the first entity to be compared * @param b the second entity to be compared * @return 1 if the two elements are compatible, 0 if they are not */ #define SAME_TYPE(a, b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) /** * @brief Validate CONTAINER_OF parameters, only applies to C mode. */ #ifndef __cplusplus #define CONTAINER_OF_VALIDATE(ptr, type, field) \ BUILD_ASSERT(SAME_TYPE(*(ptr), ((type *)0)->field) || \ SAME_TYPE(*(ptr), void), \ "pointer type mismatch in CONTAINER_OF"); #else #define CONTAINER_OF_VALIDATE(ptr, type, field) #endif /** * @brief Get a pointer to a structure containing the element * * Example: * * struct foo { * int bar; * }; * * struct foo my_foo; * int *ptr = &my_foo.bar; * * struct foo *container = CONTAINER_OF(ptr, struct foo, bar); * * Above, @p container points at @p my_foo. * * @param ptr pointer to a structure element * @param type name of the type that @p ptr is an element of * @param field the name of the field within the struct @p ptr points to * @return a pointer to the structure that contains @p ptr */ #define CONTAINER_OF(ptr, type, field) \ ({ \ CONTAINER_OF_VALIDATE(ptr, type, field) \ ((type *)(((char *)(ptr)) - offsetof(type, field))); \ }) /** * @brief Report the size of a struct field in bytes. * * @param type The structure containing the field of interest. * @param member The field to return the size of. * * @return The field size. */ #define SIZEOF_FIELD(type, member) sizeof((((type *)0)->member)) /** * @brief Concatenate input arguments * * Concatenate provided tokens into a combined token during the preprocessor pass. * This can be used to, for ex., build an identifier out of multiple parts, * where one of those parts may be, for ex, a number, another macro, or a macro argument. * * @param ... Tokens to concatencate * * @return Concatenated token. */ #define CONCAT(...) \ UTIL_CAT(_CONCAT_, NUM_VA_ARGS_LESS_1(__VA_ARGS__))(__VA_ARGS__) /** * @brief Check if @p ptr is aligned to @p align alignment */ #define IS_ALIGNED(ptr, align) (((uintptr_t)(ptr)) % (align) == 0) /** * @brief Value of @p x rounded up to the next multiple of @p align. */ #define ROUND_UP(x, align) \ ((((unsigned long)(x) + ((unsigned long)(align) - 1)) / \ (unsigned long)(align)) * (unsigned long)(align)) /** * @brief Value of @p x rounded down to the previous multiple of @p align. */ #define ROUND_DOWN(x, align) \ (((unsigned long)(x) / (unsigned long)(align)) * (unsigned long)(align)) /** @brief Value of @p x rounded up to the next word boundary. */ #define WB_UP(x) ROUND_UP(x, sizeof(void *)) /** @brief Value of @p x rounded down to the previous word boundary. */ #define WB_DN(x) ROUND_DOWN(x, sizeof(void *)) /** * @brief Divide and round up. * * Example: * @code{.c} * DIV_ROUND_UP(1, 2); // 1 * DIV_ROUND_UP(3, 2); // 2 * @endcode * * @param n Numerator. * @param d Denominator. * * @return The result of @p n / @p d, rounded up. */ #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) /** * @brief Divide and round to the nearest integer. * * Example: * @code{.c} * DIV_ROUND_CLOSEST(5, 2); // 3 * DIV_ROUND_CLOSEST(5, -2); // -3 * DIV_ROUND_CLOSEST(5, 3); // 2 * @endcode * * @param n Numerator. * @param d Denominator. * * @return The result of @p n / @p d, rounded to the nearest integer. */ #define DIV_ROUND_CLOSEST(n, d) \ ((((n) < 0) ^ ((d) < 0)) ? ((n) - ((d) / 2)) / (d) : \ ((n) + ((d) / 2)) / (d)) #ifndef MAX /** * @brief Obtain the maximum of two values. * * @note Arguments are evaluated twice. Use Z_MAX for a GCC-only, single * evaluation version * * @param a First value. * @param b Second value. * * @returns Maximum value of @p a and @p b. */ #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef MIN /** * @brief Obtain the minimum of two values. * * @note Arguments are evaluated twice. Use Z_MIN for a GCC-only, single * evaluation version * * @param a First value. * @param b Second value. * * @returns Minimum value of @p a and @p b. */ #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef CLAMP /** * @brief Clamp a value to a given range. * * @note Arguments are evaluated multiple times. Use Z_CLAMP for a GCC-only, * single evaluation version. * * @param val Value to be clamped. * @param low Lowest allowed value (inclusive). * @param high Highest allowed value (inclusive). * * @returns Clamped value. */ #define CLAMP(val, low, high) (((val) <= (low)) ? (low) : MIN(val, high)) #endif /** * @brief Checks if a value is within range. * * @note @p val is evaluated twice. * * @param val Value to be checked. * @param min Lower bound (inclusive). * @param max Upper bound (inclusive). * * @retval true If value is within range * @retval false If the value is not within range */ #define IN_RANGE(val, min, max) ((val) >= (min) && (val) <= (max)) /** * @brief Is @p x a power of two? * @param x value to check * @return true if @p x is a power of two, false otherwise */ static inline bool is_power_of_two(unsigned int x) { return IS_POWER_OF_TWO(x); } /** * @brief Is @p p equal to ``NULL``? * * Some macros may need to check their arguments against NULL to support * multiple use-cases, but NULL checks can generate warnings if such a macro * is used in contexts where that particular argument can never be NULL. * * The warnings can be triggered if: * a) all macros are expanded (e.g. when using CONFIG_COMPILER_SAVE_TEMPS=y) * or * b) tracking of macro expansions are turned off (-ftrack-macro-expansion=0) * * The warnings can be circumvented by using this inline function for doing * the NULL check within the macro. The compiler is still able to optimize the * NULL check out at a later stage. * * @param p Pointer to check * @return true if @p p is equal to ``NULL``, false otherwise */ static ALWAYS_INLINE bool is_null_no_warn(void *p) { return p == NULL; } /** * @brief Arithmetic shift right * @param value value to shift * @param shift number of bits to shift * @return @p value shifted right by @p shift; opened bit positions are * filled with the sign bit */ static inline int64_t arithmetic_shift_right(int64_t value, uint8_t shift) { int64_t sign_ext; if (shift == 0U) { return value; } /* extract sign bit */ sign_ext = (value >> 63) & 1; /* make all bits of sign_ext be the same as the value's sign bit */ sign_ext = -sign_ext; /* shift value and fill opened bit positions with sign bit */ return (value >> shift) | (sign_ext << (64 - shift)); } /** * @brief byte by byte memcpy. * * Copy `size` bytes of `src` into `dest`. This is guaranteed to be done byte by byte. * * @param dst Pointer to the destination memory. * @param src Pointer to the source of the data. * @param size The number of bytes to copy. */ static inline void bytecpy(void *dst, const void *src, size_t size) { size_t i; for (i = 0; i < size; ++i) { ((volatile uint8_t *)dst)[i] = ((volatile const uint8_t *)src)[i]; } } /** * @brief byte by byte swap. * * Swap @a size bytes between memory regions @a a and @a b. This is * guaranteed to be done byte by byte. * * @param a Pointer to the first memory region. * @param b Pointer to the second memory region. * @param size The number of bytes to swap. */ static inline void byteswp(void *a, void *b, size_t size) { uint8_t t; uint8_t *aa = (uint8_t *)a; uint8_t *bb = (uint8_t *)b; for (; size > 0; --size) { t = *aa; *aa++ = *bb; *bb++ = t; } } /** * @brief Convert a single character into a hexadecimal nibble. * * @param c The character to convert * @param x The address of storage for the converted number. * * @return Zero on success or (negative) error code otherwise. */ int char2hex(char c, uint8_t *x); /** * @brief Convert a single hexadecimal nibble into a character. * * @param c The number to convert * @param x The address of storage for the converted character. * * @return Zero on success or (negative) error code otherwise. */ int hex2char(uint8_t x, char *c); /** * @brief Convert a binary array into string representation. * * @param buf The binary array to convert * @param buflen The length of the binary array to convert * @param hex Address of where to store the string representation. * @param hexlen Size of the storage area for string representation. * * @return The length of the converted string, or 0 if an error occurred. */ size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen); /** * @brief Convert a hexadecimal string into a binary array. * * @param hex The hexadecimal string to convert * @param hexlen The length of the hexadecimal string to convert. * @param buf Address of where to store the binary data * @param buflen Size of the storage area for binary data * * @return The length of the binary array, or 0 if an error occurred. */ size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen); /** * @brief Convert a binary coded decimal (BCD 8421) value to binary. * * @param bcd BCD 8421 value to convert. * * @return Binary representation of input value. */ static inline uint8_t bcd2bin(uint8_t bcd) { return ((10 * (bcd >> 4)) + (bcd & 0x0F)); } /** * @brief Convert a binary value to binary coded decimal (BCD 8421). * * @param bin Binary value to convert. * * @return BCD 8421 representation of input value. */ static inline uint8_t bin2bcd(uint8_t bin) { return (((bin / 10) << 4) | (bin % 10)); } /** * @brief Convert a uint8_t into a decimal string representation. * * Convert a uint8_t value into its ASCII decimal string representation. * The string is terminated if there is enough space in buf. * * @param buf Address of where to store the string representation. * @param buflen Size of the storage area for string representation. * @param value The value to convert to decimal string * * @return The length of the converted string (excluding terminator if * any), or 0 if an error occurred. */ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value); /** * @brief Sign extend an 8, 16 or 32 bit value using the index bit as sign bit. * * @param value The value to sign expand. * @param index 0 based bit index to sign bit (0 to 31) */ static inline int32_t sign_extend(uint32_t value, uint8_t index) { __ASSERT_NO_MSG(index <= 31); uint8_t shift = 31 - index; return (int32_t)(value << shift) >> shift; } /** * @brief Sign extend a 64 bit value using the index bit as sign bit. * * @param value The value to sign expand. * @param index 0 based bit index to sign bit (0 to 63) */ static inline int64_t sign_extend_64(uint64_t value, uint8_t index) { __ASSERT_NO_MSG(index <= 63); uint8_t shift = 63 - index; return (int64_t)(value << shift) >> shift; } /** * @brief Properly truncate a NULL-terminated UTF-8 string * * Take a NULL-terminated UTF-8 string and ensure that if the string has been * truncated (by setting the NULL terminator) earlier by other means, that * the string ends with a properly formatted UTF-8 character (1-4 bytes). * * @htmlonly * Example: * char test_str[] = "€€€"; * char trunc_utf8[8]; * * printf("Original : %s\n", test_str); // €€€ * strncpy(trunc_utf8, test_str, sizeof(trunc_utf8)); * trunc_utf8[sizeof(trunc_utf8) - 1] = '\0'; * printf("Bad : %s\n", trunc_utf8); // €€� * utf8_trunc(trunc_utf8); * printf("Truncated: %s\n", trunc_utf8); // €€ * @endhtmlonly * * @param utf8_str NULL-terminated string * * @return Pointer to the @p utf8_str */ char *utf8_trunc(char *utf8_str); /** * @brief Copies a UTF-8 encoded string from @p src to @p dst * * The resulting @p dst will always be NULL terminated if @p n is larger than 0, * and the @p dst string will always be properly UTF-8 truncated. * * @param dst The destination of the UTF-8 string. * @param src The source string * @param n The size of the @p dst buffer. Maximum number of characters copied * is @p n - 1. If 0 nothing will be done, and the @p dst will not be * NULL terminated. * * @return Pointer to the @p dst */ char *utf8_lcpy(char *dst, const char *src, size_t n); #define __z_log2d(x) (32 - __builtin_clz(x) - 1) #define __z_log2q(x) (64 - __builtin_clzll(x) - 1) #define __z_log2(x) (sizeof(__typeof__(x)) > 4 ? __z_log2q(x) : __z_log2d(x)) /** * @brief Compute log2(x) * * @note This macro expands its argument multiple times (to permit use * in constant expressions), which must not have side effects. * * @param x An unsigned integral value to compute logarithm of (positive only) * * @return log2(x) when 1 <= x <= max(x), -1 when x < 1 */ #define LOG2(x) ((x) < 1 ? -1 : __z_log2(x)) /** * @brief Compute ceil(log2(x)) * * @note This macro expands its argument multiple times (to permit use * in constant expressions), which must not have side effects. * * @param x An unsigned integral value * * @return ceil(log2(x)) when 1 <= x <= max(type(x)), 0 when x < 1 */ #define LOG2CEIL(x) ((x) < 1 ? 0 : __z_log2((x)-1) + 1) /** * @brief Compute next highest power of two * * Equivalent to 2^ceil(log2(x)) * * @note This macro expands its argument multiple times (to permit use * in constant expressions), which must not have side effects. * * @param x An unsigned integral value * * @return 2^ceil(log2(x)) or 0 if 2^ceil(log2(x)) would saturate 64-bits */ #define NHPOT(x) ((x) < 1 ? 1 : ((x) > (1ULL<<63) ? 0 : 1ULL << LOG2CEIL(x))) /** * @brief Determine if a buffer exceeds highest address * * This macro determines if a buffer identified by a starting address @a addr * and length @a buflen spans a region of memory that goes beyond the highest * possible address (thereby resulting in a pointer overflow). * * @param addr Buffer starting address * @param buflen Length of the buffer * * @return true if pointer overflow detected, false otherwise */ #define Z_DETECT_POINTER_OVERFLOW(addr, buflen) \ (((buflen) != 0) && \ ((UINTPTR_MAX - (uintptr_t)(addr)) <= ((uintptr_t)((buflen) - 1)))) /** * @brief XOR n bytes * * @param dst Destination of where to store result. Shall be @p len bytes. * @param src1 First source. Shall be @p len bytes. * @param src2 Second source. Shall be @p len bytes. * @param len Number of bytes to XOR. */ static inline void mem_xor_n(uint8_t *dst, const uint8_t *src1, const uint8_t *src2, size_t len) { while (len--) { *dst++ = *src1++ ^ *src2++; } } /** * @brief XOR 32 bits * * @param dst Destination of where to store result. Shall be 32 bits. * @param src1 First source. Shall be 32 bits. * @param src2 Second source. Shall be 32 bits. */ static inline void mem_xor_32(uint8_t dst[4], const uint8_t src1[4], const uint8_t src2[4]) { mem_xor_n(dst, src1, src2, 4U); } /** * @brief XOR 128 bits * * @param dst Destination of where to store result. Shall be 128 bits. * @param src1 First source. Shall be 128 bits. * @param src2 Second source. Shall be 128 bits. */ static inline void mem_xor_128(uint8_t dst[16], const uint8_t src1[16], const uint8_t src2[16]) { mem_xor_n(dst, src1, src2, 16); } #ifdef __cplusplus } #endif /* This file must be included at the end of the !_ASMLANGUAGE guard. * It depends on macros defined in this file above which cannot be forward declared. */ #include <zephyr/sys/time_units.h> #endif /* !_ASMLANGUAGE */ /** @brief Number of bytes in @p x kibibytes */ #ifdef _LINKER /* This is used in linker scripts so need to avoid type casting there */ #define KB(x) ((x) << 10) #else #define KB(x) (((size_t)(x)) << 10) #endif /** @brief Number of bytes in @p x mebibytes */ #define MB(x) (KB(x) << 10) /** @brief Number of bytes in @p x gibibytes */ #define GB(x) (MB(x) << 10) /** @brief Number of Hz in @p x kHz */ #define KHZ(x) ((x) * 1000) /** @brief Number of Hz in @p x MHz */ #define MHZ(x) (KHZ(x) * 1000) /** * @brief For the POSIX architecture add a minimal delay in a busy wait loop. * For other architectures this is a no-op. * * In the POSIX ARCH, code takes zero simulated time to execute, * so busy wait loops become infinite loops, unless we * force the loop to take a bit of time. * Include this macro in all busy wait/spin loops * so they will also work when building for the POSIX architecture. * * @param t Time in microseconds we will busy wait */ #if defined(CONFIG_ARCH_POSIX) #define Z_SPIN_DELAY(t) k_busy_wait(t) #else #define Z_SPIN_DELAY(t) #endif /** * @brief Wait for an expression to return true with a timeout * * Spin on an expression with a timeout and optional delay between iterations * * Commonly needed when waiting on hardware to complete an asynchronous * request to read/write/initialize/reset, but useful for any expression. * * @param expr Truth expression upon which to poll, e.g.: XYZREG & XYZREG_EN * @param timeout Timeout to wait for in microseconds, e.g.: 1000 (1ms) * @param delay_stmt Delay statement to perform each poll iteration * e.g.: NULL, k_yield(), k_msleep(1) or k_busy_wait(1) * * @retval expr As a boolean return, if false then it has timed out. */ #define WAIT_FOR(expr, timeout, delay_stmt) \ ({ \ uint32_t _wf_cycle_count = k_us_to_cyc_ceil32(timeout); \ uint32_t _wf_start = k_cycle_get_32(); \ while (!(expr) && (_wf_cycle_count > (k_cycle_get_32() - _wf_start))) { \ delay_stmt; \ Z_SPIN_DELAY(10); \ } \ (expr); \ }) /** * @} */ #endif /* ZEPHYR_INCLUDE_SYS_UTIL_H_ */ |