|
| 1 | +/*! ********************************************************************************* |
| 2 | + * Copyright 2022-2025 NXP |
| 3 | + * SPDX-License-Identifier: BSD-3-Clause |
| 4 | + ********************************************************************************** */ |
| 5 | +#ifndef _HAL_MACROS_H_ |
| 6 | +#define _HAL_MACROS_H_ |
| 7 | + |
| 8 | +#include <stdint.h> |
| 9 | + |
| 10 | +/* Required for __REV definition */ |
| 11 | +#include "cmsis_compiler.h" |
| 12 | + |
| 13 | +/*============================================================================ |
| 14 | + USEFUL MACROS |
| 15 | +=============================================================================*/ |
| 16 | + |
| 17 | +/*! |
| 18 | + **************************************************************************************** |
| 19 | + * @brief |
| 20 | + * HAL_CLZ implementation : count leading zeroes from MSB |
| 21 | + * HAL_CTZ implementation : count trailing zeroes from LSB |
| 22 | + * HAL_RBIT implementation : bit mirror 32-bit operation:bit n moves to bit (31-n) |
| 23 | + * |
| 24 | + *****************************************************************************************/ |
| 25 | +#if defined(__GNUC__) |
| 26 | + |
| 27 | +#define HAL_CLZ(x) ((uint8_t)(__builtin_clz(x) & 0x3fUL)) |
| 28 | +#define HAL_CTZ(x) ((uint8_t)(__builtin_ctz(x) & 0x3fUL)) |
| 29 | +static inline uint32_t __hal_revb(uint32_t x) |
| 30 | +{ |
| 31 | + unsigned int res; |
| 32 | + __asm volatile("rbit %0, %1 \n\t" : "=r"(res) : "r"(x)); |
| 33 | + return res; |
| 34 | +} |
| 35 | +#define HAL_RBIT(x) __hal_revb(x) |
| 36 | + |
| 37 | +#elif defined(__IAR_SYSTEMS_ICC__) |
| 38 | + |
| 39 | +#define HAL_CLZ(x) ((uint8_t)(__iar_builtin_CLZ(x) & 0x3fUL)) |
| 40 | +#define HAL_RBIT(x) ((uint32_t)(__iar_builtin_RBIT(x))) |
| 41 | + |
| 42 | +static inline uint8_t __hal_ctz(uint32_t x) |
| 43 | +{ |
| 44 | + uint8_t res; |
| 45 | + x = HAL_RBIT((unsigned int)x); |
| 46 | + res = HAL_CLZ((unsigned int)x); |
| 47 | + return res; |
| 48 | +} |
| 49 | + |
| 50 | +#define HAL_CTZ(x) __hal_ctz(x) |
| 51 | + |
| 52 | +#else |
| 53 | +#define HAL_CLZ(x) HAL_CLZ_UNDEFINED(x) |
| 54 | +#define HAL_CTZ(x) HAL_CTZ_UNDEFINED(x) |
| 55 | +#endif |
| 56 | + |
| 57 | +/*! |
| 58 | + **************************************************************************************** |
| 59 | + * @brief |
| 60 | + * HAL_BSR Bit Scan Reverse ( find MSB bit set in a bit field ) |
| 61 | + * HAL_BSF Bit Scan Forward ( find LSB bit set in a bit field ) |
| 62 | + * HAL_FFS Find First Bit Set Find LSB bit position + 1 per standard ffs definition |
| 63 | + * |
| 64 | + **************************************************************************************** |
| 65 | + */ |
| 66 | +#define HAL_BSR(x) (((x) != 0UL) ? (uint8_t)(31U - (HAL_CLZ(x) & 0x1fU)) : 0xffU) |
| 67 | +#define HAL_BSF(x) HAL_CTZ(x) |
| 68 | +#define HAL_FFS(x) (HAL_CTZ(x) + 1U) |
| 69 | + |
| 70 | +/*! |
| 71 | + **************************************************************************************** |
| 72 | + * @brief |
| 73 | + * HAL_REV16 swap bytes in a 16 bit word : useful for htons/ntohs and all endianness conversions |
| 74 | + * HAL_REV32 swap bytes in a 32 bit word : useful for htonl/ntohl and all endianness conversions |
| 75 | + **************************************************************************************** |
| 76 | + */ |
| 77 | +#if defined(__GNUC__) |
| 78 | +#define HAL_REV16(x) ((uint32_t)__builtin_bswap16(x)) |
| 79 | +#define HAL_REV32(x) ((uint32_t)__builtin_bswap32(x)) |
| 80 | + |
| 81 | +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__CC_ARM) |
| 82 | + |
| 83 | +#define HAL_REV16(x) ((uint32_t)__REV16(x)) |
| 84 | +#define HAL_REV32(x) ((uint32_t)__REV(x)) |
| 85 | + |
| 86 | +#endif |
| 87 | + |
| 88 | +#define HAL_HTONS(_x_) HAL_REV16((_x_)) |
| 89 | +#define HAL_NTOHS(_x_) HAL_REV16((_x_)) |
| 90 | + |
| 91 | +#define HAL_HTONL(_x_) HAL_REV32((_x_)) |
| 92 | +#define HAL_NTOHL(_x_) HAL_REV32((_x_)) |
| 93 | + |
| 94 | +#define HAL_BSWAP16(_x_) HAL_REV16((_x_)) |
| 95 | +#define HAL_BSWAP32(_x_) HAL_REV32((_x_)) |
| 96 | + |
| 97 | +/*! |
| 98 | + **************************************************************************************** |
| 99 | + * @brief |
| 100 | + * KB used to define memory sizes expressed in kilobytes |
| 101 | + * MB used to define memory sizes expressed in megabytes |
| 102 | + **************************************************************************************** |
| 103 | + */ |
| 104 | +#ifndef KB |
| 105 | +#define KB(x) (((uint32_t)x) << 10U) |
| 106 | +#endif |
| 107 | +#ifndef MB |
| 108 | +#define MB(x) (((uint32_t)x) << 20U) |
| 109 | +#endif |
| 110 | + |
| 111 | +/*! |
| 112 | + **************************************************************************************** |
| 113 | + * @brief |
| 114 | + * KHz used to define frequencies in kHz |
| 115 | + * MHz used to define frequencies in MHz |
| 116 | + **************************************************************************************** |
| 117 | + */ |
| 118 | +#define KHz(x) (((uint32_t)x) * 1000U) |
| 119 | +#define MHz(x) (((uint32_t)x) * 1000000U) |
| 120 | + |
| 121 | +#define SET_BIT(bitmap, i) bitmap[((i) >> 5U)] |= (1U << ((i)&0x1fU)) |
| 122 | +#define CLR_BIT(bitmap, i) bitmap[((i) >> 5U)] &= ~(1U << ((i)&0x1fU)) |
| 123 | +#define GET_BIT(bitmap, i) (((bitmap[(i) >> 5U] & (1U << ((i)&0x1fU))) >> ((i)&0x1f)) != 0U) |
| 124 | + |
| 125 | +/* LOG_1, LOG_2, LOG_4, LOG_8: used by LOG macro */ |
| 126 | +#define LOG_1(n) (((n) >= (1u << 1U)) ? 1U : 0U) |
| 127 | +#define LOG_2(n) (((n) >= (1u << 2U)) ? (2U + LOG_1((n) >> 2U)) : LOG_1(n)) |
| 128 | +#define LOG_4(n) (((n) >= (1u << 4U)) ? (4U + LOG_2((n) >> 4U)) : LOG_2(n)) |
| 129 | +#define LOG_8(n) (((n) >= (1u << 8U)) ? (8U + LOG_4((n) >> 8U)) : LOG_4(n)) |
| 130 | +/* |
| 131 | + * Macro to compute log2 (logarithm) of a constant at compile time. |
| 132 | + * Does not make sense for runtime log2 calculation. |
| 133 | + * Computation should be based on __builtin_clz. |
| 134 | + * For in |
| 135 | + * |
| 136 | + */ |
| 137 | +#define LOG(n) (((n) >= (1U << 16U)) ? (16U + LOG_8((n) >> 16U)) : LOG_8(n)) |
| 138 | + |
| 139 | +#if !defined(__IAR_SYSTEMS_ICC__) |
| 140 | +#undef BUILD_ASSERT /* clear out common version */ |
| 141 | +/* C++11 has static_assert built in */ |
| 142 | +#if defined(__cplusplus) && (__cplusplus >= 201103L) |
| 143 | +#define BUILD_ASSERT(EXPR, MSG...) static_assert(EXPR, "" MSG) |
| 144 | + |
| 145 | +/* |
| 146 | + * GCC 4.6 and higher have the C11 _Static_assert built in and its |
| 147 | + * output is easier to understand than the common BUILD_ASSERT macros. |
| 148 | + * Don't use this in C++98 mode though (which we can hit, as |
| 149 | + * static_assert() is not available) |
| 150 | + */ |
| 151 | +#elif !defined(__cplusplus) && \ |
| 152 | + ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) || (__STDC_VERSION__) >= 201100) |
| 153 | +#define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG) |
| 154 | +#else |
| 155 | +#define BUILD_ASSERT(EXPR, MSG...) |
| 156 | +#endif |
| 157 | + |
| 158 | +/** |
| 159 | + * @brief Validate if two entities have a compatible type |
| 160 | + * |
| 161 | + * @param a the first entity to be compared |
| 162 | + * @param b the second entity to be compared |
| 163 | + * @return 1 if the two elements are compatible, 0 if they are not |
| 164 | + */ |
| 165 | +#define SAME_TYPE(a, b) __builtin_types_compatible_p(__typeof__(a), __typeof__(b)) |
| 166 | + |
| 167 | +/** |
| 168 | + * @brief Validate CONTAINER_OF parameters, only applies to C mode. |
| 169 | + */ |
| 170 | +#ifndef __cplusplus |
| 171 | +#define CONTAINER_OF_VALIDATE(ptr, type, field) \ |
| 172 | + BUILD_ASSERT(SAME_TYPE(*(ptr), ((type *)0)->field) || SAME_TYPE(*(ptr), void), \ |
| 173 | + "pointer type mismatch in CONTAINER_OF"); |
| 174 | +#else /* __cplusplus */ |
| 175 | +#define CONTAINER_OF_VALIDATE(ptr, type, field) |
| 176 | +#endif /* __cplusplus */ |
| 177 | +#else /* __IAR_SYSTEMS_ICC__ */ |
| 178 | +/* No CONTAINER_OF_VALIDATE macros for IAR */ |
| 179 | +#define CONTAINER_OF_VALIDATE(ptr, type, field) |
| 180 | +/* Neither BUILD_ASSERT nor SAME_TYPE defined for IAR */ |
| 181 | +#endif /* __IAR_SYSTEMS_ICC__ */ |
| 182 | + |
| 183 | +#define _DO_CONCAT(x, y) x##y |
| 184 | +#define _CONCAT(x, y) _DO_CONCAT(x, y) |
| 185 | + |
| 186 | +#define DECL_ALIGN(type) __aligned(__alignof(type)) type |
| 187 | + |
| 188 | +/** |
| 189 | + * @brief Get a pointer to a structure containing the element |
| 190 | + * |
| 191 | + * Example: |
| 192 | + * |
| 193 | + * struct foo { |
| 194 | + * int bar; |
| 195 | + * }; |
| 196 | + * |
| 197 | + * struct foo my_foo; |
| 198 | + * int *ptr = &my_foo.bar; |
| 199 | + * |
| 200 | + * struct foo *container = CONTAINER_OF(ptr, struct foo, bar); |
| 201 | + * |
| 202 | + * Above, @p container points at @p my_foo. |
| 203 | + * |
| 204 | + * @param ptr pointer to a structure element |
| 205 | + * @param type name of the type that @p ptr is an element of |
| 206 | + * @param field the name of the field within the struct @p ptr points to |
| 207 | + * @return a pointer to the structure that contains @p ptr |
| 208 | + */ |
| 209 | +#define CONTAINER_OF(_PTR_, _TYPE_, _FIELD_) \ |
| 210 | + ({ \ |
| 211 | + CONTAINER_OF_VALIDATE(_PTR_, _TYPE_, _FIELD_) \ |
| 212 | + ((_TYPE_ *)(void *)(((char *)(_PTR_)) - offsetof(_TYPE_, _FIELD_))); \ |
| 213 | + }) |
| 214 | + |
| 215 | +#endif |
0 commit comments