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