2 * @brief Endianness declaration
\r
5 * Copyright(C) NXP Semiconductors, 2012
\r
6 * Copyright(C) Dean Camera, 2011, 2012
\r
7 * All rights reserved.
\r
10 * Software that is described herein is for illustrative purposes only
\r
11 * which provides customers with programming information regarding the
\r
12 * LPC products. This software is supplied "AS IS" without any warranties of
\r
13 * any kind, and NXP Semiconductors and its licensor disclaim any and
\r
14 * all warranties, express or implied, including all implied warranties of
\r
15 * merchantability, fitness for a particular purpose and non-infringement of
\r
16 * intellectual property rights. NXP Semiconductors assumes no responsibility
\r
17 * or liability for the use of the software, conveys no license or rights under any
\r
18 * patent, copyright, mask work right, or any other intellectual property rights in
\r
19 * or to any products. NXP Semiconductors reserves the right to make changes
\r
20 * in the software without notification. NXP Semiconductors also makes no
\r
21 * representation or warranty that such application will be suitable for the
\r
22 * specified use without further testing or modification.
\r
25 * Permission to use, copy, modify, and distribute this software and its
\r
26 * documentation is hereby granted, under NXP Semiconductors' and its
\r
27 * licensor's relevant copyrights in the software, without fee, provided that it
\r
28 * is used in conjunction with NXP Semiconductors microcontrollers. This
\r
29 * copyright, permission, and disclaimer notice must appear in all copies of
\r
35 /** @ingroup Group_Endianness
\r
36 * @defgroup Group_ByteSwapping Byte Reordering
\r
37 * @brief Macros and functions for forced byte reordering.
\r
40 /** @ingroup Group_Endianness
\r
41 * @defgroup Group_EndianConversion Endianness Conversion
\r
42 * @brief Macros and functions for automatic endianness conversion.
\r
45 /** @ingroup Group_Common
\r
46 * @defgroup Group_Endianness Endianness and Byte Ordering
\r
47 * @brief Convenience macros and functions relating to byte (re-)ordering
\r
49 * Common library convenience macros and functions relating to byte (re-)ordering.
\r
54 #ifndef __LPCUSBlib_ENDIANNESS_H__
\r
55 #define __LPCUSBlib_ENDIANNESS_H__
\r
57 /* Enable C linkage for C++ Compilers: */
\r
58 #if defined(__cplusplus)
\r
62 /* Preprocessor Checks: */
\r
63 #if !defined(__INCLUDE_FROM_COMMON_H)
\r
64 #error Do not include this file directly. Include LPCUSBlib/Common/Common.h instead to gain this functionality.
\r
67 #if !(defined(ARCH_BIG_ENDIAN) || defined(ARCH_LITTLE_ENDIAN))
\r
68 #error ARCH_BIG_ENDIAN or ARCH_LITTLE_ENDIAN not set for the specified architecture.
\r
71 /* Public Interface - May be used in end-application: */
\r
73 /** Swaps the byte ordering of a 16-bit value at compile-time. Do not use this macro for swapping byte orderings
\r
74 * of dynamic values computed at runtime, use @ref SwapEndian_16() instead. The result of this macro can be used
\r
75 * inside struct or other variable initializers outside of a function, something that is not possible with the
\r
76 * inline function variant.
\r
78 * @ingroup Group_ByteSwapping
\r
80 * @param x 16-bit value whose byte ordering is to be swapped.
\r
82 * @return Input value with the byte ordering reversed.
\r
84 #define SWAPENDIAN_16(x) (uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))
\r
86 /** Swaps the byte ordering of a 32-bit value at compile-time. Do not use this macro for swapping byte orderings
\r
87 * of dynamic values computed at runtime- use @ref SwapEndian_32() instead. The result of this macro can be used
\r
88 * inside struct or other variable initializers outside of a function, something that is not possible with the
\r
89 * inline function variant.
\r
91 * @ingroup Group_ByteSwapping
\r
93 * @param x 32-bit value whose byte ordering is to be swapped.
\r
95 * @return Input value with the byte ordering reversed.
\r
97 #define SWAPENDIAN_32(x) (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | (((x) & 0x00FF0000UL) >> 8UL) | \
\r
98 (((x) & 0x0000FF00UL) << 8UL) | (((x) & 0x000000FFUL) << 24UL))
\r
100 #if defined(ARCH_BIG_ENDIAN) && !defined(le16_to_cpu)
\r
101 #define le16_to_cpu(x) SwapEndian_16(x)
\r
102 #define le32_to_cpu(x) SwapEndian_32(x)
\r
103 #define be16_to_cpu(x) (x)
\r
104 #define be32_to_cpu(x) (x)
\r
105 #define cpu_to_le16(x) SwapEndian_16(x)
\r
106 #define cpu_to_le32(x) SwapEndian_32(x)
\r
107 #define cpu_to_be16(x) (x)
\r
108 #define cpu_to_be32(x) (x)
\r
109 #define LE16_TO_CPU(x) SWAPENDIAN_16(x)
\r
110 #define LE32_TO_CPU(x) SWAPENDIAN_32(x)
\r
111 #define BE16_TO_CPU(x) (x)
\r
112 #define BE32_TO_CPU(x) (x)
\r
113 #define CPU_TO_LE16(x) SWAPENDIAN_16(x)
\r
114 #define CPU_TO_LE32(x) SWAPENDIAN_32(x)
\r
115 #define CPU_TO_BE16(x) (x)
\r
116 #define CPU_TO_BE32(x) (x)
\r
117 #elif !defined(le16_to_cpu)
\r
118 /** \name Run-time endianness conversion */
\r
121 /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
\r
122 * Endianness of the currently selected CPU architecture.
\r
124 * On little endian architectures, this macro does nothing.
\r
126 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
127 * conversion, use @ref LE16_TO_CPU instead.
\r
129 * @ingroup Group_EndianConversion
\r
131 * @param x Data to perform the endianness conversion on.
\r
133 * @return Endian corrected version of the input value.
\r
135 #define le16_to_cpu(x) (x)
\r
137 /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
\r
138 * Endianness of the currently selected CPU architecture.
\r
140 * On little endian architectures, this macro does nothing.
\r
142 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
143 * conversion, use @ref LE32_TO_CPU instead.
\r
145 * @ingroup Group_EndianConversion
\r
147 * @param x Data to perform the endianness conversion on.
\r
149 * @return Endian corrected version of the input value.
\r
151 #define le32_to_cpu(x) (x)
\r
153 /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
\r
154 * Endianness of the currently selected CPU architecture.
\r
156 * On big endian architectures, this macro does nothing.
\r
158 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
159 * conversion, use @ref BE16_TO_CPU instead.
\r
161 * @ingroup Group_EndianConversion
\r
163 * @param x Data to perform the endianness conversion on.
\r
165 * @return Endian corrected version of the input value.
\r
167 #define be16_to_cpu(x) SwapEndian_16(x)
\r
169 /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
\r
170 * Endianness of the currently selected CPU architecture.
\r
172 * On big endian architectures, this macro does nothing.
\r
174 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
175 * conversion, use @ref BE32_TO_CPU instead.
\r
177 * @ingroup Group_EndianConversion
\r
179 * @param x Data to perform the endianness conversion on.
\r
181 * @return Endian corrected version of the input value.
\r
183 #define be32_to_cpu(x) SwapEndian_32(x)
\r
185 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
\r
186 * is in Little Endian format regardless of the currently selected CPU architecture.
\r
188 * On little endian architectures, this macro does nothing.
\r
190 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
191 * conversion, use @ref CPU_TO_LE16 instead.
\r
193 * @ingroup Group_EndianConversion
\r
195 * @param x Data to perform the endianness conversion on.
\r
197 * @return Endian corrected version of the input value.
\r
199 #define cpu_to_le16(x) (x)
\r
201 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
\r
202 * is in Little Endian format regardless of the currently selected CPU architecture.
\r
204 * On little endian architectures, this macro does nothing.
\r
206 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
207 * conversion, use @ref CPU_TO_LE32 instead.
\r
209 * @ingroup Group_EndianConversion
\r
211 * @param x Data to perform the endianness conversion on.
\r
213 * @return Endian corrected version of the input value.
\r
215 #define cpu_to_le32(x) (x)
\r
217 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
\r
218 * is in Big Endian format regardless of the currently selected CPU architecture.
\r
220 * On big endian architectures, this macro does nothing.
\r
222 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
223 * conversion, use @ref CPU_TO_BE16 instead.
\r
225 * @ingroup Group_EndianConversion
\r
227 * @param x Data to perform the endianness conversion on.
\r
229 * @return Endian corrected version of the input value.
\r
231 #define cpu_to_be16(x) SwapEndian_16(x)
\r
233 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
\r
234 * is in Big Endian format regardless of the currently selected CPU architecture.
\r
236 * On big endian architectures, this macro does nothing.
\r
238 * @note This macro is designed for run-time conversion of data - for compile-time endianness
\r
239 * conversion, use @ref CPU_TO_BE32 instead.
\r
241 * @ingroup Group_EndianConversion
\r
243 * @param x Data to perform the endianness conversion on.
\r
245 * @return Endian corrected version of the input value.
\r
247 #define cpu_to_be32(x) SwapEndian_32(x)
\r
251 /** \name Compile-time endianness conversion */
\r
254 /** Performs a conversion between a Little Endian encoded 16-bit piece of data and the
\r
255 * Endianness of the currently selected CPU architecture.
\r
257 * On little endian architectures, this macro does nothing.
\r
259 * @note This macro is designed for compile-time conversion of data - for run time endianness
\r
260 * conversion, use @ref le16_to_cpu instead.
\r
262 * @ingroup Group_EndianConversion
\r
264 * @param x Data to perform the endianness conversion on.
\r
266 * @return Endian corrected version of the input value.
\r
268 #define LE16_TO_CPU(x) (x)
\r
270 /** Performs a conversion between a Little Endian encoded 32-bit piece of data and the
\r
271 * Endianness of the currently selected CPU architecture.
\r
273 * On little endian architectures, this macro does nothing.
\r
275 * @note This macro is designed for compile-time conversion of data - for run time endianness
\r
276 * conversion, use @ref le32_to_cpu instead.
\r
278 * @ingroup Group_EndianConversion
\r
280 * @param x Data to perform the endianness conversion on.
\r
282 * @return Endian corrected version of the input value.
\r
284 #define LE32_TO_CPU(x) (x)
\r
286 /** Performs a conversion between a Big Endian encoded 16-bit piece of data and the
\r
287 * Endianness of the currently selected CPU architecture.
\r
289 * On big endian architectures, this macro does nothing.
\r
291 * @note This macro is designed for compile-time conversion of data - for run-time endianness
\r
292 * conversion, use @ref be16_to_cpu instead.
\r
294 * @ingroup Group_EndianConversion
\r
296 * @param x Data to perform the endianness conversion on.
\r
298 * @return Endian corrected version of the input value.
\r
300 #define BE16_TO_CPU(x) SWAPENDIAN_16(x)
\r
302 /** Performs a conversion between a Big Endian encoded 32-bit piece of data and the
\r
303 * Endianness of the currently selected CPU architecture.
\r
305 * On big endian architectures, this macro does nothing.
\r
307 * @note This macro is designed for compile-time conversion of data - for run-time endianness
\r
308 * conversion, use @ref be32_to_cpu instead.
\r
310 * @ingroup Group_EndianConversion
\r
312 * @param x Data to perform the endianness conversion on.
\r
314 * @return Endian corrected version of the input value.
\r
316 #define BE32_TO_CPU(x) SWAPENDIAN_32(x)
\r
318 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
\r
319 * is in Little Endian format regardless of the currently selected CPU architecture.
\r
321 * On little endian architectures, this macro does nothing.
\r
323 * @note This macro is designed for compile-time conversion of data - for run-time endianness
\r
324 * conversion, use @ref cpu_to_le16 instead.
\r
326 * @ingroup Group_EndianConversion
\r
328 * @param x Data to perform the endianness conversion on.
\r
330 * @return Endian corrected version of the input value.
\r
332 #define CPU_TO_LE16(x) (x)
\r
334 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
\r
335 * is in Little Endian format regardless of the currently selected CPU architecture.
\r
337 * On little endian architectures, this macro does nothing.
\r
339 * @note This macro is designed for compile-time conversion of data - for run-time endianness
\r
340 * conversion, use @ref cpu_to_le32 instead.
\r
342 * @ingroup Group_EndianConversion
\r
344 * @param x Data to perform the endianness conversion on.
\r
346 * @return Endian corrected version of the input value.
\r
348 #define CPU_TO_LE32(x) (x)
\r
350 /** Performs a conversion on a natively encoded 16-bit piece of data to ensure that it
\r
351 * is in Big Endian format regardless of the currently selected CPU architecture.
\r
353 * On big endian architectures, this macro does nothing.
\r
355 * @note This macro is designed for compile-time conversion of data - for run-time endianness
\r
356 * conversion, use @ref cpu_to_be16 instead.
\r
358 * @ingroup Group_EndianConversion
\r
360 * @param x Data to perform the endianness conversion on.
\r
362 * @return Endian corrected version of the input value.
\r
364 #define CPU_TO_BE16(x) SWAPENDIAN_16(x)
\r
366 /** Performs a conversion on a natively encoded 32-bit piece of data to ensure that it
\r
367 * is in Big Endian format regardless of the currently selected CPU architecture.
\r
369 * On big endian architectures, this macro does nothing.
\r
371 * @note This macro is designed for compile-time conversion of data - for run-time endianness
\r
372 * conversion, use @ref cpu_to_be32 instead.
\r
374 * @ingroup Group_EndianConversion
\r
376 * @param x Data to perform the endianness conversion on.
\r
378 * @return Endian corrected version of the input value.
\r
380 #define CPU_TO_BE32(x) SWAPENDIAN_32(x)
\r
385 /* Inline Functions: */
\r
386 /** Function to reverse the byte ordering of the individual bytes in a 16 bit value.
\r
388 * @ingroup Group_ByteSwapping
\r
390 * @param Word Word of data whose bytes are to be swapped.
\r
392 static inline uint16_t SwapEndian_16(const uint16_t Word) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
\r
393 static inline uint16_t SwapEndian_16(const uint16_t Word)
\r
395 if (GCC_IS_COMPILE_CONST(Word))
\r
396 return SWAPENDIAN_16(Word);
\r
408 Temp = Data.Bytes[0];
\r
409 Data.Bytes[0] = Data.Bytes[1];
\r
410 Data.Bytes[1] = Temp;
\r
415 /** Function to reverse the byte ordering of the individual bytes in a 32 bit value.
\r
417 * @ingroup Group_ByteSwapping
\r
419 * @param DWord Double word of data whose bytes are to be swapped.
\r
421 static inline uint32_t SwapEndian_32(const uint32_t DWord) ATTR_WARN_UNUSED_RESULT ATTR_CONST;
\r
422 static inline uint32_t SwapEndian_32(const uint32_t DWord)
\r
424 if (GCC_IS_COMPILE_CONST(DWord))
\r
425 return SWAPENDIAN_32(DWord);
\r
435 Data.DWord = DWord;
\r
437 Temp = Data.Bytes[0];
\r
438 Data.Bytes[0] = Data.Bytes[3];
\r
439 Data.Bytes[3] = Temp;
\r
441 Temp = Data.Bytes[1];
\r
442 Data.Bytes[1] = Data.Bytes[2];
\r
443 Data.Bytes[2] = Temp;
\r
448 /** Function to reverse the byte ordering of the individual bytes in a n byte value.
\r
450 * @ingroup Group_ByteSwapping
\r
452 * \param[in,out] Data Pointer to a number containing an even number of bytes to be reversed.
\r
453 * @param Length Length of the data in bytes.
\r
455 static inline void SwapEndian_n(void* const Data,
\r
456 uint8_t Length) ATTR_NON_NULL_PTR_ARG(1);
\r
457 static inline void SwapEndian_n(void* const Data,
\r
460 uint8_t* CurrDataPos = (uint8_t*)Data;
\r
464 uint8_t Temp = *CurrDataPos;
\r
465 *CurrDataPos = *(CurrDataPos + Length - 1);
\r
466 *(CurrDataPos + Length - 1) = Temp;
\r
473 /* Disable C linkage for C++ Compilers: */
\r
474 #if defined(__cplusplus)
\r