platform.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_PLATFORM_H
8 #define _PICO_PLATFORM_H
9 
19 #include "hardware/platform_defs.h"
20 #include "hardware/regs/addressmap.h"
21 #include "hardware/regs/sio.h"
22 
23 // Marker for builds targeting the RP2040
24 #define PICO_RP2040 1
25 
26 // PICO_CONFIG: PICO_STACK_SIZE, Stack Size, min=0x100, default=0x800, advanced=true, group=pico_platform
27 #ifndef PICO_STACK_SIZE
28 #define PICO_STACK_SIZE _u(0x800)
29 #endif
30 
31 // PICO_CONFIG: PICO_HEAP_SIZE, Heap size to reserve, min=0x100, default=0x800, advanced=true, group=pico_platform
32 #ifndef PICO_HEAP_SIZE
33 #define PICO_HEAP_SIZE _u(0x800)
34 #endif
35 
36 // PICO_CONFIG: PICO_NO_RAM_VECTOR_TABLE, Enable/disable the RAM vector table, type=bool, default=0, advanced=true, group=pico_platform
37 #ifndef PICO_NO_RAM_VECTOR_TABLE
38 #define PICO_NO_RAM_VECTOR_TABLE 0
39 #endif
40 
41 // PICO_CONFIG: PICO_RP2040_B0_SUPPORTED, Whether to include any specific software support for RP2040 B0 revision, type=bool, default=1, advanced=true, group=pico_platform
42 #ifndef PICO_RP2040_B0_SUPPORTED
43 #define PICO_RP2040_B0_SUPPORTED 1
44 #endif
45 
46 // PICO_CONFIG: PICO_FLOAT_SUPPORT_ROM_V1, Include float support code for RP2040 B0 when that chip revision is supported , type=bool, default=1, advanced=true, group=pico_platform
47 #ifndef PICO_FLOAT_SUPPORT_ROM_V1
48 #define PICO_FLOAT_SUPPORT_ROM_V1 1
49 #endif
50 
51 // PICO_CONFIG: PICO_DOUBLE_SUPPORT_ROM_V1, Include double support code for RP2040 B0 when that chip revision is supported , type=bool, default=1, advanced=true, group=pico_platform
52 #ifndef PICO_DOUBLE_SUPPORT_ROM_V1
53 #define PICO_DOUBLE_SUPPORT_ROM_V1 1
54 #endif
55 
56 
57 // PICO_CONFIG: PICO_RP2040_B1_SUPPORTED, Whether to include any specific software support for RP2040 B1 revision, type=bool, default=1, advanced=true, group=pico_platform
58 #ifndef PICO_RP2040_B1_SUPPORTED
59 #define PICO_RP2040_B1_SUPPORTED 1
60 #endif
61 
62 // PICO_CONFIG: PICO_RP2040_B2_SUPPORTED, Whether to include any specific software support for RP2040 B2 revision, type=bool, default=1, advanced=true, group=pico_platform
63 #ifndef PICO_RP2040_B2_SUPPORTED
64 #define PICO_RP2040_B2_SUPPORTED 1
65 #endif
66 
67 // --- remainder of file is not included by assembly code ---
68 
69 #ifndef __ASSEMBLER__
70 
71 #if defined __GNUC__
72 #include <sys/cdefs.h>
73 // note LLVM defines __GNUC__
74 #ifdef __clang__
75 #define PICO_C_COMPILER_IS_CLANG 1
76 #else
77 #define PICO_C_COMPILER_IS_GNU 1
78 #endif
79 #elif defined __ICCARM__
80 #ifndef __aligned
81 #define __aligned(x) __attribute__((__aligned__(x)))
82 #endif
83 #ifndef __always_inline
84 #define __always_inline __attribute__((__always_inline__))
85 #endif
86 #ifndef __noinline
87 #define __noinline __attribute__((__noinline__))
88 #endif
89 #ifndef __packed
90 #define __packed __attribute__((__packed__))
91 #endif
92 #ifndef __printflike
93 #define __printflike(a, b)
94 #endif
95 #ifndef __unused
96 #define __unused __attribute__((__unused__))
97 #endif
98 #ifndef __used
99 #define __used __attribute__((__used__))
100 #endif
101 #ifndef __CONCAT1
102 #define __CONCAT1(a, b) a ## b
103 #endif
104 #ifndef __CONCAT
105 #define __CONCAT(a, b) __CONCAT1(a, b)
106 #endif
107 #ifndef __STRING
108 #define __STRING(a) #a
109 #endif
110 /* Compatible definitions of GCC builtins */
111 
112 static inline uint __builtin_ctz(uint x) {
113  extern uint32_t __ctzsi2(uint32_t);
114  return __ctzsi2(x);
115 }
116 #define __builtin_expect(x, y) (x)
117 #define __builtin_isnan(x) __iar_isnan(x)
118 #else
119 #error Unsupported toolchain
120 #endif
121 
122 #include "pico/types.h"
123 
124 // GCC_Like_Pragma(x) is a pragma on GNUC compatible compilers
125 #ifdef __GNUC__
126 #define GCC_Like_Pragma _Pragma
127 #else
128 #define GCC_Like_Pragma(x)
129 #endif
130 
131 // Clang_Pragma(x) is a pragma on Clang only
132 #ifdef __clang__
133 #define Clang_Pragma _Pragma
134 #else
135 #define Clang_Pragma(x)
136 #endif
137 
138 // GCC_Pragma(x) is a pragma on GCC only
139 #if PICO_C_COMPILER_IS_GNU
140 #define GCC_Pragma _Pragma
141 #else
142 #define GCC_Pragma(x)
143 #endif
144 
145 #ifdef __cplusplus
146 extern "C" {
147 #endif
148 
156 #define __isr
157 
170 #define __after_data(group) __attribute__((section(".after_data." group)))
171 
184 #define __not_in_flash(group) __attribute__((section(".time_critical." group)))
185 
201 #define __scratch_x(group) __attribute__((section(".scratch_x." group)))
202 
218 #define __scratch_y(group) __attribute__((section(".scratch_y." group)))
219 
235 #define __uninitialized_ram(group) __attribute__((section(".uninitialized_data." #group))) group
236 
249 #define __in_flash(group) __attribute__((section(".flashdata." group)))
250 
265 #define __not_in_flash_func(func_name) __not_in_flash(__STRING(func_name)) func_name
266 
284 #define __time_critical_func(func_name) __not_in_flash_func(func_name)
285 
298 #define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name)
299 
300 #define __packed_aligned __packed __aligned(4)
301 
311 #if PICO_C_COMPILER_IS_GNU && (__GNUC__ <= 6 || (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || !defined(__cplusplus))))
312 #define __force_inline inline __always_inline
313 #else
314 #define __force_inline __always_inline
315 #endif
316 
320 #ifndef count_of
321 #define count_of(a) (sizeof(a)/sizeof((a)[0]))
322 #endif
323 
327 #ifndef MAX
328 #define MAX(a, b) ((a)>(b)?(a):(b))
329 #endif
330 
334 #ifndef MIN
335 #define MIN(a, b) ((b)>(a)?(a):(b))
336 #endif
337 
338 #define pico_default_asm(...) __asm (".syntax unified\n" __VA_ARGS__)
339 #define pico_default_asm_volatile(...) __asm volatile (".syntax unified\n" __VA_ARGS__)
340 
344 static inline void __breakpoint(void) {
345  pico_default_asm ("bkpt #0");
346 }
347 
361  pico_default_asm_volatile ("" : : : "memory");
362 }
363 
372 #define host_safe_hw_ptr(x) ((uintptr_t)(x))
373 #define native_safe_hw_ptr(x) host_safe_hw_ptr(x)
374 
375 
380 void __attribute__((noreturn)) panic_unsupported(void);
381 
391 void __attribute__((noreturn)) panic(const char *fmt, ...);
392 
393 #ifdef NDEBUG
394 #define panic_compact(...) panic(__VA_ARGS__)
395 #else
396 #define panic_compact(...) panic("")
397 #endif
398 
399 // PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=0, advanced=true, group=pico_runtime
400 #ifndef PICO_NO_FPGA_CHECK
401 #define PICO_NO_FPGA_CHECK 0
402 #endif
403 
404 #if PICO_NO_FPGA_CHECK
405 static inline bool running_on_fpga(void) {return false;}
406 #else
407 bool running_on_fpga(void);
408 #endif
409 
414 uint8_t rp2040_chip_version(void);
415 
420 static inline uint8_t rp2040_rom_version(void) {
421 GCC_Pragma("GCC diagnostic push")
422 GCC_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
423  return *(uint8_t*)0x13;
424 GCC_Pragma("GCC diagnostic pop")
425 }
426 
435 
446 __force_inline static int32_t __mul_instruction(int32_t a, int32_t b) {
447  pico_default_asm ("muls %0, %1" : "+l" (a) : "l" (b) : );
448  return a;
449 }
450 
464 #define __fast_mul(a, b) __builtin_choose_expr(__builtin_constant_p(b) && !__builtin_constant_p(a), \
465 (__builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b)), \
466 (a)*(b))
467 
474 #define __check_type_compatible(type_a, type_b) static_assert(__builtin_types_compatible_p(type_a, type_b), __STRING(type_a) " is not compatible with " __STRING(type_b));
475 
482  uint exception;
483  pico_default_asm( "mrs %0, ipsr" : "=l" (exception));
484  return exception;
485 }
486 
487 #define WRAPPER_FUNC(x) __wrap_ ## x
488 #define REAL_FUNC(x) __real_ ## x
489 
504 static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) {
505  pico_default_asm_volatile(
506  "1: subs %0, #3\n"
507  "bcs 1b\n"
508  : "+l" (minimum_cycles) : : "memory"
509  );
510 }
511 
517 __force_inline static uint get_core_num(void) {
518  return (*(uint32_t *) (SIO_BASE + SIO_CPUID_OFFSET));
519 }
520 
521 #ifdef __cplusplus
522 }
523 #endif
524 
525 #else // __ASSEMBLER__
526 
527 #if defined __GNUC__
528 // note LLVM defines __GNUC__
529 #ifdef __clang__
530 #define PICO_ASSEMBLER_IS_CLANG 1
531 #else
532 #define PICO_ASSEMBLER_IS_GNU 1
533 #endif
534 #elif defined __ICCARM__
535 #else
536 #error Unsupported toolchain
537 #endif
538 
539 #define WRAPPER_FUNC_NAME(x) __wrap_##x
540 #define SECTION_NAME(x) .text.##x
541 #define RAM_SECTION_NAME(x) .time_critical.##x
542 
543 #endif // !__ASSEMBLER__
544 
545 #endif
#define __force_inline
Attribute to force inlining of a function regardless of optimization level.
Definition: platform.h:314
void panic_unsupported(void)
Panics with the message "Unsupported".
uint8_t rp2040_chip_version(void)
Returns the RP2040 chip revision number.
Definition: platform.c:29
static void busy_wait_at_least_cycles(uint32_t minimum_cycles)
Helper method to busy-wait for at least the given number of cycles.
Definition: platform.h:504
static __always_inline int32_t __mul_instruction(int32_t a, int32_t b)
Multiply two integers using an assembly MUL instruction.
Definition: platform.h:446
static __always_inline uint __get_current_exception(void)
Get the current exception level on this core.
Definition: platform.h:481
static void __breakpoint(void)
Execute a breakpoint instruction.
Definition: platform.h:344
static __always_inline uint get_core_num(void)
Get the current core number.
Definition: platform.h:517
static __always_inline void __compiler_memory_barrier(void)
Ensure that the compiler does not move memory access across this method call.
Definition: platform.h:360
void panic(const char *fmt,...)
Displays a panic message and halts execution.
static uint8_t rp2040_rom_version(void)
Returns the RP2040 rom version number.
Definition: platform.h:420
static __always_inline void tight_loop_contents(void)
No-op function for the body of tight loops.
Definition: platform.h:434