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