ex
Fork of mbed-os-example-mbed5-blinky by
Embed:
(wiki syntax)
Show/hide line numbers
ns_types.h
Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 2014-2015 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 /* 00017 * ns_types.h - Basic compiler and type setup for Nanostack libraries. 00018 */ 00019 #ifndef NS_TYPES_H_ 00020 #define NS_TYPES_H_ 00021 00022 /** \file 00023 * \brief Basic compiler and type setup 00024 * 00025 * We currently assume C99 or later. 00026 * 00027 * C99 features being relied on: 00028 * 00029 * - <inttypes.h> and <stdbool.h> 00030 * - inline (with C99 semantics, not C++ as per default GCC); 00031 * - designated initialisers; 00032 * - compound literals; 00033 * - restrict; 00034 * - [static N] in array parameters; 00035 * - declarations in for statements; 00036 * - mixing declarations and statements 00037 * 00038 * Compilers should be set to C99 or later mode when building Nanomesh source. 00039 * For GCC this means "-std=gnu99" (C99 with usual GNU extensions). 00040 * 00041 * Also, a little extra care is required for public header files that could be 00042 * included from C++, especially as C++ lacks some C99 features. 00043 * 00044 * (TODO: as this is exposed to API users, do we need a predefine to distinguish 00045 * internal and external use, for finer control? Not yet, but maybe...) 00046 */ 00047 00048 /* Make sure <stdint.h> defines its macros if C++ */ 00049 #ifndef __STDC_LIMIT_MACROS 00050 #define __STDC_LIMIT_MACROS 00051 #endif 00052 #ifndef __STDC_CONSTANT_MACROS 00053 #define __STDC_CONSTANT_MACROS 00054 #endif 00055 00056 #include <stddef.h> 00057 #include <inttypes.h> // includes <stdint.h>; debugf() users need PRIu32 etc 00058 #include <stdbool.h> 00059 00060 #if defined __GNUC__ && defined __arm__ 00061 /* arm-none-eabi-gcc 4.8-2014q3 has a problem in its <inttypes.h>: 00062 * int_fast32_t is defined as int, but PRI<x>FAST32 are defined as "l<x>". 00063 * Try to detect this situation and override it. 00064 * Very hard to detect types in the preprocessor - this is best I could do. 00065 * Expansion works by: 00066 * NS_TEST_Y(INT_FAST32_MAX) -> NS_TEST_X(2147483647) -> __NS2147483647 -> 1 00067 * Nested macros are needed so we don't get __NSINT_FAST32_MAX. 00068 */ 00069 #define __NS2147483647 1 00070 #define __NS2147483647L 2 00071 #define NS_TEST_X(x) __NS##x 00072 #define NS_TEST_Y(x) NS_TEST_X(x) 00073 00074 #if NS_TEST_Y(INT_FAST32_MAX) == __NS2147483647 && \ 00075 NS_TEST_Y(INT_LEAST32_MAX) == __NS2147483647L && \ 00076 NS_TEST_Y(INT32_MAX) == __NS2147483647L 00077 00078 // Fast 32-bit types are int, others are long - this is the problem case in 00079 // arm-none-eabi-gcc. 00080 #undef PRIoFAST32 00081 #undef PRIuFAST32 00082 #undef PRIxFAST32 00083 #undef PRIXFAST32 00084 #undef PRIdFAST32 00085 #undef PRIiFAST32 00086 #define PRIoFAST32 "o" 00087 #define PRIuFAST32 "u" 00088 #define PRIxFAST32 "x" 00089 #define PRIXFAST32 "X" 00090 #define PRIdFAST32 "d" 00091 #define PRIiFAST32 "i" 00092 #endif 00093 #undef NS_TEST_X 00094 #undef NS_TEST_Y 00095 #undef __NS2147483647 00096 #undef __NS2147483647L 00097 #endif 00098 00099 /* 00100 * Create the optional <stdint.h> 24-bit types if they don't exist (worth trying 00101 * to use them, as they could exist and be more efficient than 32-bit on 8-bit 00102 * systems...) 00103 */ 00104 #ifndef UINT24_LEAST_MAX 00105 typedef uint_least32_t uint_least24_t; 00106 #define UINT_LEAST24_MAX UINT_LEAST32_MAX 00107 #define UINT24_C(x) UINT32_C(x) 00108 #define PRIoLEAST24 PRIoLEAST32 00109 #define PRIuLEAST24 PRIuLEAST32 00110 #define PRIxLEAST24 PRIxLEAST32 00111 #define PRIXLEAST24 PRIXLEAST32 00112 #endif 00113 00114 #ifndef INT24_LEAST_MAX 00115 typedef int_least32_t int_least24_t; 00116 #define INT24_LEAST_MIN INT_LEAST32_MIN 00117 #define INT24_LEAST_MAX INT_LEAST32_MAX 00118 #define INT24_C(x) INT32_C(x) 00119 #define PRIdLEAST24 PRIdLEAST32 00120 #define PRIiLEAST24 PRIiLEAST32 00121 #endif 00122 00123 #ifndef UINT24_FAST_MAX 00124 typedef uint_fast32_t uint_fast24_t; 00125 #define UINT_FAST24_MAX UINT_FAST32_MAX 00126 #define PRIoFAST24 PRIoFAST32 00127 #define PRIuFAST24 PRIuFAST32 00128 #define PRIxFAST24 PRIxFAST32 00129 #define PRIXFAST24 PRIXFAST32 00130 #endif 00131 00132 #ifndef INT24_FAST_MAX 00133 typedef int_fast32_t int_fast24_t; 00134 #define INT_FAST24_MIN INT_FAST32_MIN 00135 #define INT_FAST24_MAX INT_FAST32_MAX 00136 #define PRIdFAST24 PRIdFAST32 00137 #define PRIiFAST24 PRIiFAST32 00138 #endif 00139 00140 /* C11's "noreturn" macro, emulated if necessary */ 00141 #ifndef noreturn 00142 #if defined __cplusplus && __cplusplus >= 201103L 00143 // noreturn is a C++11 keyword 00144 #elif __STDC_VERSION__ >= 201112L 00145 #include <stdnoreturn.h> 00146 #elif defined __GNUC__ 00147 #define noreturn /*__attribute__((__noreturn__))*/ 00148 #elif defined __CC_ARM 00149 #define noreturn __declspec(noreturn) 00150 #elif defined __IAR_SYSTEMS_ICC__ 00151 #define noreturn __noreturn 00152 #else 00153 #define noreturn 00154 #endif 00155 #endif 00156 00157 /* C11's "alignas" macro, emulated for integer expressions if necessary */ 00158 #ifndef __alignas_is_defined 00159 #if __STDC_VERSION__ >= 201112L || (defined __cplusplus && __cplusplus >= 201103L) 00160 #include <stdalign.h> 00161 #elif defined __GNUC__ 00162 #define alignas(n) __attribute__((__aligned__(n))) 00163 #define __alignas_is_defined 1 00164 #elif defined __CC_ARM || defined __TASKING__ 00165 #define alignas(n) __align(n) 00166 #define __alignas_is_defined 1 00167 #elif defined __IAR_SYSTEMS_ICC__ 00168 /* Does this really just apply to the next variable? */ 00169 #define alignas(n) __Alignas(data_alignment=n) 00170 #define __Alignas(x) _Pragma(#x) 00171 #define __alignas_is_defined 1 00172 #endif 00173 #endif 00174 00175 /** 00176 * Marker for functions or objects that may be unused, suppressing warnings. 00177 * Place after the identifier: 00178 * ~~~ 00179 * static int X MAYBE_UNUSED = 3; 00180 * static int foo(void) MAYBE_UNUSED; 00181 * ~~~ 00182 */ 00183 #if defined __CC_ARM || defined __GNUC__ 00184 #define MAYBE_UNUSED __attribute__((unused)) 00185 #else 00186 #define MAYBE_UNUSED 00187 #endif 00188 00189 /* 00190 * C++ (even C++11) doesn't provide restrict: define away or provide 00191 * alternative. 00192 */ 00193 #if defined(__cplusplus) && defined(__GNUC__) 00194 #define restrict __restrict 00195 #else 00196 #define restrict 00197 #endif /* __cplusplus */ 00198 00199 00200 /** 00201 * C++ doesn't allow "static" in function parameter types: ie 00202 * ~~~ 00203 * entry_t *find_entry(const uint8_t address[static 16]) 00204 * ~~~ 00205 * If a header file may be included from C++, use this __static define instead. 00206 * 00207 * (Syntax introduced in C99 - `uint8_t address[16]` in a prototype was always 00208 * equivalent to `uint8_t *address`, but the C99 addition of static tells the 00209 * compiler that address is never NULL, and always points to at least 16 00210 * elements. This adds no new type-checking, but the information could aid 00211 * compiler optimisation, and it can serve as documentation). 00212 */ 00213 #ifdef __cplusplus 00214 #define __static 00215 #else 00216 #define __static static 00217 #endif 00218 00219 #ifdef __GNUC__ 00220 #define NS_GCC_VERSION (__GNUC__ * 10000 \ 00221 + __GNUC_MINOR__ * 100 \ 00222 + __GNUC_PATCHLEVEL__) 00223 #endif 00224 00225 /** \brief Compile-time assertion 00226 * 00227 * C11 provides _Static_assert, as does GCC even in C99 or C++ mode (and 00228 * as a freestanding implementation, we can't rely on <assert.h> to get 00229 * the static_assert macro). 00230 * C++11 provides static_assert as a keyword. 00231 * 00232 * The assertion acts as a declaration that can be placed at file scope, in a 00233 * code block (except after a label), or as a member of a struct/union. It 00234 * produces a compiler error if "test" evaluates to 0. 00235 * 00236 * Note that this *includes* the required semicolon when defined, else it 00237 * is totally empty, permitting use in structs. (If the user provided the `;`, 00238 * it would leave an illegal stray `;` if unavailable). 00239 */ 00240 #if __STDC_VERSION__ >= 201112L 00241 #define NS_STATIC_ASSERT(test, str) _Static_assert(test, str); 00242 #elif defined __cplusplus && __cplusplus >= 201103L 00243 #define NS_STATIC_ASSERT(test, str) static_assert(test, str); 00244 #elif defined __GNUC__ && NS_GCC_VERSION >= 40600 00245 //#define NS_STATIC_ASSERT(test, str) __extension__ _Static_assert(test, str); 00246 #define NS_STATIC_ASSERT(test, str) 00247 #else 00248 #define NS_STATIC_ASSERT(test, str) 00249 #endif 00250 00251 #define static_assert _Static_assert 00252 00253 /** \brief Pragma to suppress warnings about unusual pointer values. 00254 * 00255 * Useful if using "poison" values. 00256 */ 00257 #ifdef __IAR_SYSTEMS_ICC__ 00258 #define NS_FUNNY_INTPTR_OK _Pragma("diag_suppress=Pe1053") 00259 #define NS_FUNNY_INTPTR_RESTORE _Pragma("diag_default=Pe1053") 00260 #else 00261 #define NS_FUNNY_INTPTR_OK 00262 #define NS_FUNNY_INTPTR_RESTORE 00263 #endif 00264 00265 /** \brief Convert pointer to member to pointer to containing structure */ 00266 #define NS_CONTAINER_OF(ptr, type, member) \ 00267 ((type *) ((char *) (ptr) - offsetof(type, member))) 00268 00269 /* 00270 * Inlining could cause problems when mixing with C++; provide a mechanism to 00271 * disable it. This could also be turned off for other reasons (although 00272 * this can usually be done through a compiler flag, eg -O0 on gcc). 00273 */ 00274 #ifndef __cplusplus 00275 #define NS_ALLOW_INLINING 00276 #endif 00277 00278 /* There is inlining problem in GCC version 4.1.x and we know it works in 4.6.3 */ 00279 #if defined __GNUC__ && NS_GCC_VERSION < 40600 00280 #undef NS_ALLOW_INLINING 00281 #endif 00282 00283 /** \brief Mark a potentially-inlineable function. 00284 * 00285 * We follow C99 semantics, which requires precisely one external definition. 00286 * To also allow inlining to be totally bypassed under control of 00287 * NS_ALLOW_INLINING, code can be structured as per the example of ns_list: 00288 * 00289 * foo.h 00290 * ----- 00291 * ~~~ 00292 * NS_INLINE int my_func(int); 00293 * 00294 * #if defined NS_ALLOW_INLINING || defined FOO_FN 00295 * #ifndef FOO_FN 00296 * #define FOO_FN NS_INLINE 00297 * #endif 00298 * FOO_FN int my_func(int a) 00299 * { 00300 * definition; 00301 * } 00302 * #endif 00303 * ~~~ 00304 * foo.c 00305 * ----- 00306 * ~~~ 00307 * #define FOO_FN extern 00308 * #include "foo.h" 00309 * ~~~ 00310 * Which generates: 00311 * ~~~ 00312 * NS_ALLOW_INLINING set NS_ALLOW_INLINING unset 00313 * ===================== ======================= 00314 * Include foo.h Include foo.h 00315 * ------------- ------------- 00316 * inline int my_func(int); int my_func(int); 00317 * 00318 * // inline definition 00319 * inline int my_func(int a) 00320 * { 00321 * definition; 00322 * } 00323 * 00324 * Compile foo.c Compile foo.c 00325 * ------------- ------------- 00326 * (from .h) inline int my_func(int); int my_func(int); 00327 * 00328 * // external definition 00329 * // because of no "inline" // normal external definition 00330 * extern int my_func(int a) extern int my_func(int a) 00331 * { { 00332 * definition; definition; 00333 * } } 00334 * ~~~ 00335 * 00336 * Note that even with inline keywords, whether the compiler inlines or not is 00337 * up to it. For example, gcc at "-O0" will not inline at all, and will always 00338 * call the real functions in foo.o, just as if NS_ALLOW_INLINING was unset. 00339 * At "-O2", gcc could potentially inline everything, meaning that foo.o is not 00340 * referenced at all. 00341 * 00342 * Alternatively, you could use "static inline", which gives every caller its 00343 * own internal definition. This is compatible with C++ inlining (which expects 00344 * the linker to eliminate duplicates), but in C it's less efficient if the code 00345 * ends up non-inlined, and it's harder to breakpoint. I don't recommend it 00346 * except for the most trivial functions (which could then probably be macros). 00347 */ 00348 #ifdef NS_ALLOW_INLINING 00349 #define NS_INLINE inline 00350 #else 00351 #define NS_INLINE 00352 #endif 00353 00354 #if defined __SDCC_mcs51 || defined __ICC8051__ || defined __C51__ 00355 00356 /* The 8051 environments: SDCC (historic), IAR (current), Keil (future?) */ 00357 00358 #define NS_LARGE __xdata 00359 #define NS_LARGE_PTR __xdata 00360 #ifdef __ICC8051__ 00361 #define NS_REENTRANT 00362 #define NS_REENTRANT_PREFIX __idata_reentrant 00363 #else 00364 #define NS_REENTRANT __reentrant 00365 #define NS_REENTRANT_PREFIX 00366 #endif 00367 #define NS_NEAR_FUNC __near_func 00368 00369 #else 00370 00371 /* "Normal" systems. Define it all away. */ 00372 #define NS_LARGE 00373 #define NS_LARGE_PTR 00374 #define NS_REENTRANT 00375 #define NS_REENTRANT_PREFIX 00376 #define NS_NEAR_FUNC 00377 00378 #endif 00379 00380 /** \brief Scatter-gather descriptor 00381 * 00382 * Slightly optimised for small platforms - we assume we won't need any 00383 * element bigger than 64K. 00384 */ 00385 typedef struct ns_iovec 00386 { 00387 void *iov_base; 00388 uint_fast16_t iov_len; 00389 } ns_iovec_t; 00390 #endif /* NS_TYPES_H */
Generated on Tue Jul 12 2022 16:28:53 by
1.7.2
