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