]> git.sur5r.net Git - freertos/blob
1c976873560de9ceb38d59aa193dd0249fce6373
[freertos] /
1 /*\r
2  * @brief Endianness declaration\r
3  *\r
4  * @note\r
5  * Copyright(C) NXP Semiconductors, 2012\r
6  * Copyright(C) Dean Camera, 2011, 2012\r
7  * All rights reserved.\r
8  *\r
9  * @par\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
23  *\r
24  * @par\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
30  * this code.\r
31 */\r
32 \r
33 \r
34 \r
35 /** @ingroup Group_Endianness\r
36  *  @defgroup Group_ByteSwapping Byte Reordering\r
37  *  @brief Macros and functions for forced byte reordering.\r
38  */\r
39 \r
40 /** @ingroup Group_Endianness\r
41  *  @defgroup Group_EndianConversion Endianness Conversion\r
42  *  @brief Macros and functions for automatic endianness conversion.\r
43  */\r
44 \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
48  *\r
49  *  Common library convenience macros and functions relating to byte (re-)ordering.\r
50  *\r
51  *  @{\r
52  */\r
53 \r
54 #ifndef __LPCUSBlib_ENDIANNESS_H__\r
55 #define __LPCUSBlib_ENDIANNESS_H__\r
56 \r
57         /* Enable C linkage for C++ Compilers: */\r
58                 #if defined(__cplusplus)\r
59                         extern "C" {\r
60                 #endif\r
61 \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
65                 #endif\r
66                 \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
69                 #endif\r
70 \r
71         /* Public Interface - May be used in end-application: */\r
72                 /* Macros: */\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
77                          *\r
78                          *  @ingroup Group_ByteSwapping\r
79                          *\r
80                          *  @param     x  16-bit value whose byte ordering is to be swapped.\r
81                          *\r
82                          *  @return Input value with the byte ordering reversed.\r
83                          */\r
84                         #define SWAPENDIAN_16(x)            (uint16_t)((((x) & 0xFF00) >> 8) | (((x) & 0x00FF) << 8))\r
85 \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
90                          *\r
91                          *  @ingroup Group_ByteSwapping\r
92                          *\r
93                          *  @param     x  32-bit value whose byte ordering is to be swapped.\r
94                          *\r
95                          *  @return Input value with the byte ordering reversed.\r
96                          */\r
97                         #define SWAPENDIAN_32(x)            (uint32_t)((((x) & 0xFF000000UL) >> 24UL) | (((x) & 0x00FF0000UL) >> 8UL) | \\r
98                                                                        (((x) & 0x0000FF00UL) << 8UL)  | (((x) & 0x000000FFUL) << 24UL))\r
99 \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
119                                 //@{\r
120                         \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
123                                  *\r
124                                  *  On little endian architectures, this macro does nothing.\r
125                                  *\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
128                                  *\r
129                                  *  @ingroup Group_EndianConversion\r
130                                  *\r
131                                  *  @param     x  Data to perform the endianness conversion on.\r
132                                  *\r
133                                  *  @return Endian corrected version of the input value.\r
134                                  */\r
135                                 #define le16_to_cpu(x)           (x)\r
136 \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
139                                  *\r
140                                  *  On little endian architectures, this macro does nothing.\r
141                                  *\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
144                                  *\r
145                                  *  @ingroup Group_EndianConversion\r
146                                  *\r
147                                  *  @param     x  Data to perform the endianness conversion on.\r
148                                  *\r
149                                  *  @return Endian corrected version of the input value.\r
150                                  */\r
151                                 #define le32_to_cpu(x)           (x)\r
152 \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
155                                  *\r
156                                  *  On big endian architectures, this macro does nothing.\r
157                                  *\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
160                                  *\r
161                                  *  @ingroup Group_EndianConversion\r
162                                  *\r
163                                  *  @param     x  Data to perform the endianness conversion on.\r
164                                  *\r
165                                  *  @return Endian corrected version of the input value.\r
166                                  */\r
167                                 #define be16_to_cpu(x)           SwapEndian_16(x)\r
168 \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
171                                  *\r
172                                  *  On big endian architectures, this macro does nothing.\r
173                                  *\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
176                                  *\r
177                                  *  @ingroup Group_EndianConversion\r
178                                  *\r
179                                  *  @param     x  Data to perform the endianness conversion on.\r
180                                  *\r
181                                  *  @return Endian corrected version of the input value.\r
182                                  */\r
183                                 #define be32_to_cpu(x)           SwapEndian_32(x)\r
184 \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
187                                  *\r
188                                  *  On little endian architectures, this macro does nothing.\r
189                                  *\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
192                                  *\r
193                                  *  @ingroup Group_EndianConversion\r
194                                  *\r
195                                  *  @param     x  Data to perform the endianness conversion on.\r
196                                  *\r
197                                  *  @return Endian corrected version of the input value.\r
198                                  */\r
199                                 #define cpu_to_le16(x)           (x)\r
200 \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
203                                  *\r
204                                  *  On little endian architectures, this macro does nothing.\r
205                                  *\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
208                                  *\r
209                                  *  @ingroup Group_EndianConversion\r
210                                  *\r
211                                  *  @param     x  Data to perform the endianness conversion on.\r
212                                  *\r
213                                  *  @return Endian corrected version of the input value.\r
214                                  */\r
215                                 #define cpu_to_le32(x)           (x)\r
216 \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
219                                  *\r
220                                  *  On big endian architectures, this macro does nothing.\r
221                                  *\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
224                                  *\r
225                                  *  @ingroup Group_EndianConversion\r
226                                  *\r
227                                  *  @param     x  Data to perform the endianness conversion on.\r
228                                  *\r
229                                  *  @return Endian corrected version of the input value.\r
230                                  */\r
231                                 #define cpu_to_be16(x)           SwapEndian_16(x)\r
232 \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
235                                  *\r
236                                  *  On big endian architectures, this macro does nothing.\r
237                                  *\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
240                                  *\r
241                                  *  @ingroup Group_EndianConversion\r
242                                  *\r
243                                  *  @param     x  Data to perform the endianness conversion on.\r
244                                  *\r
245                                  *  @return Endian corrected version of the input value.\r
246                                  */\r
247                                 #define cpu_to_be32(x)           SwapEndian_32(x)\r
248 \r
249                                 //@}\r
250 \r
251                                 /** \name Compile-time endianness conversion */\r
252                                 //@{\r
253 \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
256                                  *\r
257                                  *  On little endian architectures, this macro does nothing.\r
258                                  *\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
261                                  *\r
262                                  *  @ingroup Group_EndianConversion\r
263                                  *\r
264                                  *  @param     x  Data to perform the endianness conversion on.\r
265                                  *\r
266                                  *  @return Endian corrected version of the input value.\r
267                                  */\r
268                                 #define LE16_TO_CPU(x)           (x)\r
269 \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
272                                  *\r
273                                  *  On little endian architectures, this macro does nothing.\r
274                                  *\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
277                                  *\r
278                                  *  @ingroup Group_EndianConversion\r
279                                  *\r
280                                  *  @param     x  Data to perform the endianness conversion on.\r
281                                  *\r
282                                  *  @return Endian corrected version of the input value.\r
283                                  */\r
284                                 #define LE32_TO_CPU(x)           (x)\r
285 \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
288                                  *\r
289                                  *  On big endian architectures, this macro does nothing.\r
290                                  *\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
293                                  *\r
294                                  *  @ingroup Group_EndianConversion\r
295                                  *\r
296                                  *  @param     x  Data to perform the endianness conversion on.\r
297                                  *\r
298                                  *  @return Endian corrected version of the input value.\r
299                                  */\r
300                                 #define BE16_TO_CPU(x)           SWAPENDIAN_16(x)\r
301 \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
304                                  *\r
305                                  *  On big endian architectures, this macro does nothing.\r
306                                  *\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
309                                  *\r
310                                  *  @ingroup Group_EndianConversion\r
311                                  *\r
312                                  *  @param     x  Data to perform the endianness conversion on.\r
313                                  *\r
314                                  *  @return Endian corrected version of the input value.\r
315                                  */\r
316                                 #define BE32_TO_CPU(x)           SWAPENDIAN_32(x)\r
317 \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
320                                  *\r
321                                  *  On little endian architectures, this macro does nothing.\r
322                                  *\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
325                                  *\r
326                                  *  @ingroup Group_EndianConversion\r
327                                  *\r
328                                  *  @param     x  Data to perform the endianness conversion on.\r
329                                  *\r
330                                  *  @return Endian corrected version of the input value.\r
331                                  */\r
332                                 #define CPU_TO_LE16(x)           (x)\r
333 \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
336                                  *\r
337                                  *  On little endian architectures, this macro does nothing.\r
338                                  *\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
341                                  *\r
342                                  *  @ingroup Group_EndianConversion\r
343                                  *\r
344                                  *  @param     x  Data to perform the endianness conversion on.\r
345                                  *\r
346                                  *  @return Endian corrected version of the input value.\r
347                                  */\r
348                                 #define CPU_TO_LE32(x)           (x)\r
349 \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
352                                  *\r
353                                  *  On big endian architectures, this macro does nothing.\r
354                                  *\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
357                                  *\r
358                                  *  @ingroup Group_EndianConversion\r
359                                  *\r
360                                  *  @param     x  Data to perform the endianness conversion on.\r
361                                  *\r
362                                  *  @return Endian corrected version of the input value.\r
363                                  */\r
364                                 #define CPU_TO_BE16(x)           SWAPENDIAN_16(x)\r
365 \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
368                                  *\r
369                                  *  On big endian architectures, this macro does nothing.\r
370                                  *\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
373                                  *\r
374                                  *  @ingroup Group_EndianConversion\r
375                                  *\r
376                                  *  @param     x  Data to perform the endianness conversion on.\r
377                                  *\r
378                                  *  @return Endian corrected version of the input value.\r
379                                  */\r
380                                 #define CPU_TO_BE32(x)           SWAPENDIAN_32(x)\r
381 \r
382                                 //! @}\r
383                         #endif\r
384 \r
385                 /* Inline Functions: */\r
386                         /** Function to reverse the byte ordering of the individual bytes in a 16 bit value.\r
387                          *\r
388                          *  @ingroup Group_ByteSwapping\r
389                          *\r
390                          *  @param     Word  Word of data whose bytes are to be swapped.\r
391                          */\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
394                         {\r
395                                 if (GCC_IS_COMPILE_CONST(Word))\r
396                                   return SWAPENDIAN_16(Word);\r
397                         \r
398                                 uint8_t Temp;\r
399 \r
400                                 union\r
401                                 {\r
402                                         uint16_t Word;\r
403                                         uint8_t  Bytes[2];\r
404                                 } Data;\r
405 \r
406                                 Data.Word = Word;\r
407 \r
408                                 Temp = Data.Bytes[0];\r
409                                 Data.Bytes[0] = Data.Bytes[1];\r
410                                 Data.Bytes[1] = Temp;\r
411 \r
412                                 return Data.Word;\r
413                         }\r
414 \r
415                         /** Function to reverse the byte ordering of the individual bytes in a 32 bit value.\r
416                          *\r
417                          *  @ingroup Group_ByteSwapping\r
418                          *\r
419                          *  @param     DWord  Double word of data whose bytes are to be swapped.\r
420                          */\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
423                         {\r
424                                 if (GCC_IS_COMPILE_CONST(DWord))\r
425                                   return SWAPENDIAN_32(DWord);\r
426 \r
427                                 uint8_t Temp;\r
428 \r
429                                 union\r
430                                 {\r
431                                         uint32_t DWord;\r
432                                         uint8_t  Bytes[4];\r
433                                 } Data;\r
434 \r
435                                 Data.DWord = DWord;\r
436 \r
437                                 Temp = Data.Bytes[0];\r
438                                 Data.Bytes[0] = Data.Bytes[3];\r
439                                 Data.Bytes[3] = Temp;\r
440 \r
441                                 Temp = Data.Bytes[1];\r
442                                 Data.Bytes[1] = Data.Bytes[2];\r
443                                 Data.Bytes[2] = Temp;\r
444 \r
445                                 return Data.DWord;\r
446                         }\r
447 \r
448                         /** Function to reverse the byte ordering of the individual bytes in a n byte value.\r
449                          *\r
450                          *  @ingroup Group_ByteSwapping\r
451                          *\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
454                          */\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
458                                                         uint8_t Length)\r
459                         {\r
460                                 uint8_t* CurrDataPos = (uint8_t*)Data;\r
461 \r
462                                 while (Length > 1)\r
463                                 {\r
464                                         uint8_t Temp = *CurrDataPos;\r
465                                         *CurrDataPos = *(CurrDataPos + Length - 1);\r
466                                         *(CurrDataPos + Length - 1) = Temp;\r
467 \r
468                                         CurrDataPos++;\r
469                                         Length -= 2;\r
470                                 }\r
471                         }\r
472 \r
473         /* Disable C linkage for C++ Compilers: */\r
474                 #if defined(__cplusplus)\r
475                         }\r
476                 #endif\r
477 \r
478 #endif\r
479 \r
480 /** @} */\r