|  | /* | 
|  | * 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 <sys/util_macro.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/types.h> | 
|  | #include <stddef.h> | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | extern "C" { | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @defgroup sys-util Zephyr 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__)) | 
|  | #	error Missing required predefined macros for BITS_PER_LONG calculation | 
|  | #endif | 
|  |  | 
|  | /** Number of bits in a long int. */ | 
|  | #define BITS_PER_LONG	(__CHAR_BIT__ * __SIZEOF_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 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 | 
|  | * particulary meaningful in this case. | 
|  | * | 
|  | * In C, passing a pointer as @p array causes a compile error. | 
|  | */ | 
|  | #define ARRAY_SIZE(array) \ | 
|  | ((long) (IS_ARRAY(array) + (sizeof(array) / sizeof((array)[0])))) | 
|  |  | 
|  | #endif /* __cplusplus */ | 
|  |  | 
|  | /** | 
|  | * @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 ptr a pointer | 
|  | * @param array an array | 
|  | * @return 1 if @p ptr is part of @p array, 0 otherwise | 
|  | */ | 
|  | #define PART_OF_ARRAY(array, ptr) \ | 
|  | ((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)])) | 
|  |  | 
|  | /** | 
|  | * @brief Get a pointer to a container structure from an 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) \ | 
|  | ((type *)(((char *)(ptr)) - offsetof(type, field))) | 
|  |  | 
|  | /** | 
|  | * @brief Value of @p x rounded up to the next multiple of @p align, | 
|  | *        which must be a power of 2. | 
|  | */ | 
|  | #define ROUND_UP(x, align)                                   \ | 
|  | (((unsigned long)(x) + ((unsigned long)(align) - 1)) & \ | 
|  | ~((unsigned long)(align) - 1)) | 
|  |  | 
|  | /** | 
|  | * @brief Value of @p x rounded down to the previous multiple of @p | 
|  | *        align, which must be a power of 2. | 
|  | */ | 
|  | #define ROUND_DOWN(x, align)                                 \ | 
|  | ((unsigned long)(x) & ~((unsigned long)(align) - 1)) | 
|  |  | 
|  | /** @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 Ceiling function applied to @p numerator / @p divider as a fraction. | 
|  | */ | 
|  | #define ceiling_fraction(numerator, divider) \ | 
|  | (((numerator) + ((divider) - 1)) / (divider)) | 
|  |  | 
|  | /** | 
|  | * @def MAX | 
|  | * @brief The larger value between @p a and @p b. | 
|  | * @note Arguments are evaluated twice. | 
|  | */ | 
|  | #ifndef MAX | 
|  | /* Use Z_MAX for a GCC-only, single evaluation version */ | 
|  | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @def MIN | 
|  | * @brief The smaller value between @p a and @p b. | 
|  | * @note Arguments are evaluated twice. | 
|  | */ | 
|  | #ifndef MIN | 
|  | /* Use Z_MIN for a GCC-only, single evaluation version */ | 
|  | #define MIN(a, b) (((a) < (b)) ? (a) : (b)) | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @def CLAMP | 
|  | * @brief Clamp a value to a given range. | 
|  | * @note Arguments are evaluated multiple times. | 
|  | */ | 
|  | #ifndef CLAMP | 
|  | /* Use Z_CLAMP for a GCC-only, single evaluation version */ | 
|  | #define CLAMP(val, low, high) (((val) <= (low)) ? (low) : MIN(val, high)) | 
|  | #endif | 
|  |  | 
|  | /** | 
|  | * @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 (x != 0U) && ((x & (x - 1U)) == 0U); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * @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      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 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); | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #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) | 
|  |  | 
|  | #ifndef BIT | 
|  | #if defined(_ASMLANGUAGE) | 
|  | #define BIT(n)  (1 << (n)) | 
|  | #else | 
|  | /** | 
|  | * @brief Unsigned integer with bit position @p n set (signed in | 
|  | * assembly language). | 
|  | */ | 
|  | #define BIT(n)  (1UL << (n)) | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | /** @brief 64-bit unsigned integer with bit position @p _n set. */ | 
|  | #define BIT64(_n) (1ULL << (_n)) | 
|  |  | 
|  | /** | 
|  | * @brief Set or clear a bit depending on a boolean value | 
|  | * | 
|  | * The argument @p var is a variable whose value is written to as a | 
|  | * side effect. | 
|  | * | 
|  | * @param var Variable to be altered | 
|  | * @param bit Bit number | 
|  | * @param set if 0, clears @p bit in @p var; any other value sets @p bit | 
|  | */ | 
|  | #define WRITE_BIT(var, bit, set) \ | 
|  | ((var) = (set) ? ((var) | BIT(bit)) : ((var) & ~BIT(bit))) | 
|  |  | 
|  | /** | 
|  | * @brief Bit mask with bits 0 through <tt>n-1</tt> (inclusive) set, | 
|  | * or 0 if @p n is 0. | 
|  | */ | 
|  | #define BIT_MASK(n) (BIT(n) - 1UL) | 
|  |  | 
|  | /** | 
|  | * @brief 64-bit bit mask with bits 0 through <tt>n-1</tt> (inclusive) set, | 
|  | * or 0 if @p n is 0. | 
|  | */ | 
|  | #define BIT64_MASK(n) (BIT64(n) - 1ULL) | 
|  |  | 
|  | /** | 
|  | * @} | 
|  | */ | 
|  |  | 
|  | #endif /* ZEPHYR_INCLUDE_SYS_UTIL_H_ */ |