Mistake on this page?
Report an issue in GitHub or email us
mbed_toolchain.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2019 ARM Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef MBED_TOOLCHAIN_H
18 #define MBED_TOOLCHAIN_H
19 
20 #include "platform/mbed_preprocessor.h"
21 
22 /* Workaround to prevent GCC library defining error_t, which can collide */
23 #ifndef __error_t_defined
24 #define __error_t_defined 1
25 #endif
26 
27 /* Work around ARM Compiler 6 bug - assert does not work in constexpr
28  * functions unless you stop it from using its __promise built-in.
29  */
30 #ifdef __ARMCC_VERSION
31 #ifndef __DO_NOT_LINK_PROMISE_WITH_ASSERT
32 #define __DO_NOT_LINK_PROMISE_WITH_ASSERT
33 #endif
34 #endif
35 
36 /* Fix strrchr() not declared for IAR, used in MBED_FILENAME */
37 #if defined(__ICCARM__)
38 #include <string.h>
39 #endif
40 
41 // Warning for unsupported compilers
42 #if !defined(__GNUC__) /* GCC */ \
43  && !defined(__clang__) /* LLVM/Clang */ \
44  && !defined(__ICCARM__) /* IAR */
45 #warning "This compiler is not yet supported."
46 #endif
47 
48 /** \addtogroup platform-public-api */
49 /** @{*/
50 
51 /**
52  * \defgroup platform_toolchain Toolchain functions
53  * @{
54  */
55 
56 // Attributes
57 
58 /** MBED_PACKED
59  * Pack a structure, preventing any padding from being added between fields.
60  *
61  * @code
62  * #include "mbed_toolchain.h"
63  *
64  * MBED_PACKED(struct) foo {
65  * char x;
66  * int y;
67  * };
68  * @endcode
69  */
70 #ifndef MBED_PACKED
71 #if defined(__ICCARM__)
72 #define MBED_PACKED(struct) __packed struct
73 #else
74 #define MBED_PACKED(struct) struct __attribute__((packed))
75 #endif
76 #endif
77 
78 /** MBED_ALIGN(N)
79  * Declare a variable to be aligned on an N-byte boundary.
80  *
81  * @note
82  * IAR does not support alignment greater than word size on the stack
83  *
84  * @code
85  * #include "mbed_toolchain.h"
86  *
87  * MBED_ALIGN(16) char a;
88  * @endcode
89  */
90 #ifndef MBED_ALIGN
91 #if __cplusplus >= 201103
92 #define MBED_ALIGN(N) alignas(N)
93 #elif __STDC_VERSION__ >= 201112
94 #define MBED_ALIGN(N) _Alignas(N)
95 #elif defined(__ICCARM__)
96 #define MBED_ALIGN(N) _Pragma(MBED_STRINGIFY(data_alignment=N))
97 #else
98 #define MBED_ALIGN(N) __attribute__((aligned(N)))
99 #endif
100 #endif
101 
102 /** MBED_UNUSED
103  * Declare a function argument to be unused, suppressing compiler warnings
104  *
105  * @code
106  * #include "mbed_toolchain.h"
107  *
108  * void foo(MBED_UNUSED int arg) {
109  *
110  * }
111  * @endcode
112  */
113 #ifndef MBED_UNUSED
114 #if defined(__GNUC__) || defined(__clang__)
115 #define MBED_UNUSED __attribute__((__unused__))
116 #else
117 #define MBED_UNUSED
118 #endif
119 #endif
120 
121 /** MBED_USED
122  * Inform the compiler that a static variable is to be retained in the object file, even if it is unreferenced.
123  *
124  * @code
125  * #include "mbed_toolchain.h"
126  *
127  * MBED_USED int foo;
128  *
129  * @endcode
130  */
131 #ifndef MBED_USED
132 #if defined(__GNUC__) || defined(__clang__)
133 #define MBED_USED __attribute__((used))
134 #elif defined(__ICCARM__)
135 #define MBED_USED __root
136 #else
137 #define MBED_USED
138 #endif
139 #endif
140 
141 /** MBED_WEAK
142  * Mark a function as being weak.
143  *
144  * @note
145  * Functions should only be marked as weak in the source file. The header file
146  * should contain a regular function declaration to insure the function is emitted.
147  * A function marked weak will not be emitted if an alternative non-weak
148  * implementation is defined.
149  *
150  * @note
151  * Weak functions are not friendly to making code re-usable, as they can only
152  * be overridden once (and if they are multiply overridden the linker will emit
153  * no warning). You should not normally use weak symbols as part of the API to
154  * re-usable modules.
155  *
156  * @code
157  * #include "mbed_toolchain.h"
158  *
159  * MBED_WEAK void foo() {
160  * // a weak implementation of foo that can be overriden by a definition
161  * // without __weak
162  * }
163  * @endcode
164  */
165 #ifndef MBED_WEAK
166 #if defined(__ICCARM__)
167 #define MBED_WEAK __weak
168 #elif defined(__MINGW32__)
169 #define MBED_WEAK
170 #else
171 #define MBED_WEAK __attribute__((weak))
172 #endif
173 #endif
174 
175 /** MBED_COMPILER_BARRIER
176  * Stop the compiler moving memory accesses.
177  *
178  * The barrier stops memory accesses from being moved from one side of the
179  * barrier to the other for safety against other threads and interrupts.
180  *
181  * This macro should only be used if we know only one CPU is accessing the data,
182  * or we are otherwise synchronising CPUs via acquire/release instructions.
183  * Otherwise, use MBED_BARRIER, which will act as a compiler barrier and also
184  * a CPU barrier if necessary.
185  *
186  * @internal
187  * This is not for use by normal code - it is a building block for the
188  * higher-level functions in mbed_critical.h. Higher-level lock/unlock or
189  * acquire/release APIs always provide ordering semantics, using this if
190  * necessary.
191  *
192  * @code
193  * #include "mbed_toolchain.h"
194  *
195  * void atomic_flag_clear_armv8(atomic_flag *flagPtr)
196  * {
197  * // ARMv8 LDA and STL instructions provide sequential consistency against
198  * // other CPUs, so no CPU barrier is needed. But we still need compiler
199  * // barriers to give us sequentially-consistent release semantics with
200  * // respect to compiler reordering - __STLB does not currently
201  * // include this.
202  * MBED_COMPILER_BARRIER();
203  * __STLB(&flagPtr->_flag, false);
204  * MBED_COMPILER_BARRIER();
205  * }
206  */
207 #if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
208 #define MBED_COMPILER_BARRIER() asm volatile("" : : : "memory")
209 #else
210 #error "Missing MBED_COMPILER_BARRIER implementation"
211 #endif
212 
213 /** MBED_BARRIER
214  * Stop the compiler, and CPU if SMP, from moving memory accesses.
215  *
216  * The barrier stops memory accesses from being moved from one side of the
217  * barrier to the other for safety against other threads and interrupts,
218  * potentially on other CPUs.
219  *
220  * In a single-CPU system, this is just a compiler barrier.
221  * If we supported multiple CPUs, this would be a DMB (with implied compiler
222  * barrier).
223  *
224  * @internal
225  * This is not for use by normal code - it is a building block for the
226  * higher-level functions in mbed_critical.h. Higher-level lock/unlock or
227  * acquire/release APIs always provide ordering semantics, using this if
228  * necessary.
229  * @code
230  * #include "mbed_toolchain.h"
231  *
232  * void atomic_flag_clear_armv7(atomic_flag *flagPtr)
233  * {
234  * // ARMv7 LDR and STR instructions do not provide any ordering
235  * // consistency against other CPUs, so explicit barrier DMBs are needed
236  * // for a multi-CPU system, otherwise just compiler barriers for single-CPU.
237  * MBED_BARRIER();
238  * flagPtr->_flag = false;
239  * MBED_BARRIER();
240  * }
241  */
242 #define MBED_BARRIER() MBED_COMPILER_BARRIER()
243 
244 /** MBED_PURE
245  * Hint to the compiler that a function depends only on parameters
246  *
247  * @code
248  * #include "mbed_toolchain.h"
249  *
250  * MBED_PURE int foo(int arg){
251  * // no access to global variables
252  * }
253  * @endcode
254  */
255 #ifndef MBED_PURE
256 #if defined(__GNUC__) || defined(__clang__)
257 #define MBED_PURE __attribute__((const))
258 #else
259 #define MBED_PURE
260 #endif
261 #endif
262 
263 /** MBED_NOINLINE
264  * Declare a function that must not be inlined.
265  *
266  * @code
267  * #include "mbed_toolchain.h"
268  *
269  * MBED_NOINLINE void foo() {
270  *
271  * }
272  * @endcode
273  */
274 #ifndef MBED_NOINLINE
275 #if defined(__GNUC__) || defined(__clang__)
276 #define MBED_NOINLINE __attribute__((noinline))
277 #elif defined(__ICCARM__)
278 #define MBED_NOINLINE _Pragma("inline=never")
279 #else
280 #define MBED_NOINLINE
281 #endif
282 #endif
283 
284 /** MBED_FORCEINLINE
285  * Declare a function that must always be inlined. Failure to inline
286  * such a function will result in an error.
287  *
288  * @code
289  * #include "mbed_toolchain.h"
290  *
291  * MBED_FORCEINLINE void foo() {
292  *
293  * }
294  * @endcode
295  */
296 #ifndef MBED_FORCEINLINE
297 #if defined(__GNUC__) || defined(__clang__)
298 #define MBED_FORCEINLINE inline __attribute__((always_inline))
299 #elif defined(__ICCARM__)
300 #define MBED_FORCEINLINE _Pragma("inline=forced")
301 #else
302 #define MBED_FORCEINLINE inline
303 #endif
304 #endif
305 
306 /** MBED_NORETURN
307  * Declare a function that will never return.
308  *
309  * @code
310  * #include "mbed_toolchain.h"
311  *
312  * MBED_NORETURN void foo() {
313  * // must never return
314  * while (1) {}
315  * }
316  * @endcode
317  */
318 #ifndef MBED_NORETURN
319 #if __cplusplus >= 201103
320 #define MBED_NORETURN [[noreturn]]
321 #elif __STDC_VERSION__ >= 201112
322 #define MBED_NORETURN _Noreturn
323 #elif defined(__GNUC__) || defined(__clang__)
324 #define MBED_NORETURN __attribute__((noreturn))
325 #elif defined(__ICCARM__)
326 #define MBED_NORETURN __noreturn
327 #else
328 #define MBED_NORETURN
329 #endif
330 #endif
331 
332 /** MBED_UNREACHABLE
333  * An unreachable statement. If the statement is reached,
334  * behavior is undefined. Useful in situations where the compiler
335  * cannot deduce if the code is unreachable.
336  *
337  * @code
338  * #include "mbed_toolchain.h"
339  *
340  * void foo(int arg) {
341  * switch (arg) {
342  * case 1: return 1;
343  * case 2: return 2;
344  * ...
345  * }
346  * MBED_UNREACHABLE;
347  * }
348  * @endcode
349  */
350 #ifndef MBED_UNREACHABLE
351 #if (defined(__GNUC__) || defined(__clang__))
352 #define MBED_UNREACHABLE __builtin_unreachable()
353 #else
354 #define MBED_UNREACHABLE while (1)
355 #endif
356 #endif
357 
358 /** MBED_FALLTHROUGH
359  * Marks a point in a switch statement where fallthrough can occur.
360  * Should be placed as the last statement before a label.
361  *
362  * @code
363  * #include "mbed_toolchain.h"
364  *
365  * int foo(int arg) {
366  * switch (arg) {
367  * case 1:
368  * case 2:
369  * case 3:
370  * arg *= 2;
371  * MBED_FALLTHROUGH;
372  * default:
373  * return arg;
374  * }
375  * }
376  * @endcode
377  */
378 #ifndef MBED_FALLTHROUGH
379 #if __cplusplus >= 201703
380 #define MBED_FALLTHROUGH [[fallthrough]]
381 #elif defined(__clang__)
382 #if __cplusplus >= 201103
383 #define MBED_FALLTHROUGH [[clang::fallthrough]]
384 #elif __has_attribute(fallthrough)
385 #define MBED_FALLTHROUGH __attribute__((fallthrough))
386 #else
387 #define MBED_FALLTHROUGH
388 #endif
389 #elif defined (__GNUC__)
390 #define MBED_FALLTHROUGH __attribute__((fallthrough))
391 #else
392 #define MBED_FALLTHROUGH
393 #endif
394 #endif
395 
396 /** MBED_DEPRECATED("message string")
397  * Mark a function declaration as deprecated, if it used then a warning will be
398  * issued by the compiler possibly including the provided message. Note that not
399  * all compilers are able to display the message.
400  *
401  * @code
402  * #include "mbed_toolchain.h"
403  *
404  * MBED_DEPRECATED("don't foo any more, bar instead")
405  * void foo(int arg);
406  * @endcode
407  */
408 #ifndef MBED_DEPRECATED
409 #if defined(__GNUC__) || defined(__clang__)
410 #define MBED_DEPRECATED(M) __attribute__((deprecated(M)))
411 #else
412 #define MBED_DEPRECATED(M)
413 #endif
414 #endif
415 
416 /** MBED_DEPRECATED_SINCE("version", "message string")
417  * Mark a function declaration as deprecated, noting that the declaration was
418  * deprecated on the specified version. If the function is used then a warning
419  * will be issued by the compiler possibly including the provided message.
420  * Note that not all compilers are able to display this message.
421  *
422  * @code
423  * #include "mbed_toolchain.h"
424  *
425  * MBED_DEPRECATED_SINCE("mbed-os-5.1", "don't foo any more, bar instead")
426  * void foo(int arg);
427  * @endcode
428  */
429 #define MBED_DEPRECATED_SINCE(D, M) MBED_DEPRECATED(M " [since " D "]")
430 
431 /** MBED_CALLER_ADDR()
432  * Returns the caller of the current function.
433  *
434  * @note
435  * This macro is only implemented for GCC and ARMCC.
436  *
437  * @code
438  * #include "mbed_toolchain.h"
439  *
440  * printf("This function was called from %p", MBED_CALLER_ADDR());
441  * @endcode
442  *
443  * @return Address of the calling function
444  */
445 #ifndef MBED_CALLER_ADDR
446 #if (defined(__GNUC__) || defined(__clang__))
447 #define MBED_CALLER_ADDR() __builtin_extract_return_addr(__builtin_return_address(0))
448 #else
449 #define MBED_CALLER_ADDR() (NULL)
450 #endif
451 #endif
452 
453 #ifndef MBED_SECTION
454 #if (defined(__GNUC__) || defined(__clang__))
455 #define MBED_SECTION(name) __attribute__ ((section (name)))
456 #elif defined(__ICCARM__)
457 #define MBED_SECTION(name) _Pragma(MBED_STRINGIFY(location=name))
458 #else
459 #error "Missing MBED_SECTION directive"
460 #endif
461 #endif
462 
463 /**
464  * Macro expanding to a string literal of the enclosing function name.
465  *
466  * The string returned takes into account language specificity and yield human
467  * readable content.
468  *
469  * As an example, if the macro is used within a C++ function then the string
470  * literal containing the function name will contain the complete signature of
471  * the function - including template parameters - and namespace qualifications.
472  */
473 #ifndef MBED_PRETTY_FUNCTION
474 #define MBED_PRETTY_FUNCTION __PRETTY_FUNCTION__
475 #endif
476 
477 #ifndef MBED_PRINTF
478 #if defined(__GNUC__)
479 #define MBED_PRINTF(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx, first_param_idx)))
480 #else
481 #define MBED_PRINTF(format_idx, first_param_idx)
482 #endif
483 #endif
484 
485 #ifndef MBED_PRINTF_METHOD
486 #if defined(__GNUC__)
487 #define MBED_PRINTF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__printf__, format_idx+1, first_param_idx == 0 ? 0 : first_param_idx+1)))
488 #else
489 #define MBED_PRINTF_METHOD(format_idx, first_param_idx)
490 #endif
491 #endif
492 
493 #ifndef MBED_SCANF
494 #if defined(__GNUC__)
495 #define MBED_SCANF(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx, first_param_idx)))
496 #else
497 #define MBED_SCANF(format_idx, first_param_idx)
498 #endif
499 #endif
500 
501 #ifndef MBED_SCANF_METHOD
502 #if defined(__GNUC__)
503 #define MBED_SCANF_METHOD(format_idx, first_param_idx) __attribute__ ((__format__(__scanf__, format_idx+1, first_param_idx == 0 ? 0 : first_param_idx+1)))
504 #else
505 #define MBED_SCANF_METHOD(format_idx, first_param_idx)
506 #endif
507 #endif
508 
509 // Macro containing the filename part of the value of __FILE__. Defined as
510 // string literal.
511 #ifndef MBED_FILENAME
512 #if defined(__GNUC__)
513 #define MBED_FILENAME (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __builtin_strrchr(__FILE__, '\\') ? __builtin_strrchr(__FILE__, '\\') + 1 : __FILE__)
514 #elif defined(__ICCARM__)
515 #define MBED_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
516 #else
517 #define MBED_FILENAME __FILE__
518 #endif
519 #endif // #ifndef MBED_FILENAME
520 
521 // FILEHANDLE declaration
522 #if defined(TOOLCHAIN_ARM)
523 #include <rt_sys.h>
524 #endif
525 
526 #ifndef FILEHANDLE
527 typedef int FILEHANDLE;
528 #endif
529 
530 // Backwards compatibility
531 #ifndef WEAK
532 #define WEAK MBED_WEAK
533 #endif
534 
535 #ifndef PACKED
536 #define PACKED MBED_PACKED()
537 #endif
538 
539 #ifndef EXTERN
540 #define EXTERN extern
541 #endif
542 
543 /** MBED_NONSECURE_ENTRY
544  * Declare a function that can be called from non-secure world or secure world
545  *
546  * @code
547  * #include "mbed_toolchain.h"
548  *
549  * MBED_NONSECURE_ENTRY void foo() {
550  *
551  * }
552  * @endcode
553  */
554 #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L)
555 #if defined (__ICCARM__)
556 #define MBED_NONSECURE_ENTRY __cmse_nonsecure_entry
557 #else
558 #define MBED_NONSECURE_ENTRY __attribute__((cmse_nonsecure_entry))
559 #endif
560 #else
561 #define MBED_NONSECURE_ENTRY
562 #endif
563 
564 #endif
565 
566 /** @}*/
567 /** @}*/
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.