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 | /* * 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 Utility Functions * @{ */ /** @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 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) { ((uint8_t *)dst)[i] = ((uint8_t *)src)[i]; } } /** * @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); #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) /** * @} */ #endif /* ZEPHYR_INCLUDE_SYS_UTIL_H_ */ |