/* * 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 /* needs to be outside _ASMLANGUAGE so 'true' and 'false' can turn * into '1' and '0' for asm or linker scripts */ #include #ifndef _ASMLANGUAGE #include #include #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 void*. */ #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 void*. */ #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 operator[]. 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 bt_hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen); #define hex2bin bt_hex2bin /** * @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 n-1 (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 n-1 (inclusive) set, * or 0 if @p n is 0. */ #define BIT64_MASK(n) (BIT64(n) - 1ULL) /** * @} */ #endif /* ZEPHYR_INCLUDE_SYS_UTIL_H_ */