v2.0.0
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
16#ifndef _PICO_PLATFORM_H
17#define _PICO_PLATFORM_H
18
19#ifndef _PICO_H
20#error pico/platform.h should not be included directly; include pico.h instead
21#endif
22
23#include "pico/platform/compiler.h"
24#include "pico/platform/sections.h"
25#include "pico/platform/panic.h"
26#include "hardware/regs/addressmap.h"
27#include "hardware/regs/sio.h"
28#ifdef __riscv
29#include "hardware/regs/rvcsr.h"
30#endif
31
32// PICO_CONFIG: PICO_RP2350A, Whether the current board has an RP2350 in an A (30 GPIO) package, type=bool, default=Usually provided via board header, group=pico_platform
33
34// PICO_CONFIG: PICO_STACK_SIZE, Minimum amount of stack space reserved in the linker script for each core. See also PICO_CORE1_STACK_SIZE, min=0x100, default=0x800, advanced=true, group=pico_platform
35#ifndef PICO_STACK_SIZE
36#define PICO_STACK_SIZE _u(0x800)
37#endif
38
39// PICO_CONFIG: PICO_HEAP_SIZE, Minimum amount of heap space reserved by the linker script, min=0x100, default=0x800, advanced=true, group=pico_platform
40#ifndef PICO_HEAP_SIZE
41#define PICO_HEAP_SIZE _u(0x800)
42#endif
43
44// PICO_CONFIG: PICO_NO_RAM_VECTOR_TABLE, Enable/disable the RAM vector table, type=bool, default=0, advanced=true, group=pico_platform
45#ifndef PICO_NO_RAM_VECTOR_TABLE
46#define PICO_NO_RAM_VECTOR_TABLE 0
47#endif
48
49#ifndef PICO_RAM_VECTOR_TABLE_SIZE
50#define PICO_RAM_VECTOR_TABLE_SIZE (VTABLE_FIRST_IRQ + NUM_IRQS)
51#endif
52
53// PICO_CONFIG: PICO_USE_STACK_GUARDS, Enable/disable stack guards, type=bool, default=0, advanced=true, group=pico_platform
54#ifndef PICO_USE_STACK_GUARDS
55#define PICO_USE_STACK_GUARDS 0
56#endif
57
58#ifndef __ASSEMBLER__
59
67 static __force_inline void tight_loop_contents(void) {}
68
83 static inline void busy_wait_at_least_cycles(uint32_t minimum_cycles) {
84 pico_default_asm_volatile (
85#ifdef __riscv
86 // Note the range is halved on RISC-V due to signed comparison (no carry flag)
87 ".option push\n"
88 ".option norvc\n" // force 32 bit addi, so branch prediction guaranteed
89 ".p2align 2\n"
90 "1: \n"
91 "addi %0, %0, -2 \n"
92 "bgez %0, 1b\n"
93 ".option pop"
94#else
95 "1: subs %0, #3\n"
96 "bcs 1b\n"
97#endif
98 : "+r" (minimum_cycles) : : "cc", "memory"
99 );
100}
101
102// PICO_CONFIG: PICO_NO_FPGA_CHECK, Remove the FPGA platform check for small code size reduction, type=bool, default=platform dependent, advanced=true, group=pico_runtime
103#ifndef PICO_NO_FPGA_CHECK
104#if !PICO_RP2040
105#define PICO_NO_FPGA_CHECK 1
106#endif
107#endif
108
109// PICO_CONFIG: PICO_NO_SIM_CHECK, Remove the SIM platform check for small code size reduction, type=bool, default=1, advanced=true, group=pico_runtime
110#ifndef PICO_NO_SIM_CHECK
111#define PICO_NO_SIM_CHECK 1
112#endif
113
114#if PICO_NO_FPGA_CHECK
115static inline bool running_on_fpga(void) {return false;}
116#else
117bool running_on_fpga(void);
118#endif
119#if PICO_NO_SIM_CHECK
120static inline bool running_in_sim(void) {return false;}
121#else
122bool running_in_sim(void);
123#endif
124
128 static __force_inline void __breakpoint(void) {
129#ifdef __riscv
130 __asm ("ebreak");
131#else
132 pico_default_asm_volatile ("bkpt #0" : : : "memory");
133#endif
134}
135
141__force_inline static uint get_core_num(void) {
142 return (*(uint32_t *) (SIO_BASE + SIO_CPUID_OFFSET));
143}
144
158 static __force_inline uint __get_current_exception(void) {
159#ifdef __riscv
160 uint32_t meicontext;
161 pico_default_asm_volatile (
162 "csrr %0, %1\n"
163 : "=r" (meicontext) : "i" (RVCSR_MEICONTEXT_OFFSET)
164 );
165 if (meicontext & RVCSR_MEICONTEXT_NOIRQ_BITS) {
166 return 0;
167 } else {
168 return VTABLE_FIRST_IRQ + (
169 (meicontext & RVCSR_MEICONTEXT_IRQ_BITS) >> RVCSR_MEICONTEXT_IRQ_LSB
170 );
171 }
172#else
173 uint exception;
174 pico_default_asm_volatile (
175 "mrs %0, ipsr\n"
176 "uxtb %0, %0\n"
177 : "=l" (exception)
178 );
179 return exception;
180#endif
181}
182
188__force_inline static bool pico_processor_state_is_nonsecure(void) {
189#ifndef __riscv
190 // todo add a define to disable NS checking at all?
191 // IDAU-Exempt addresses return S=1 when tested in the Secure state,
192 // whereas executing a tt in the NonSecure state will always return S=0.
193 uint32_t tt;
194 pico_default_asm_volatile (
195 "movs %0, #0\n"
196 "tt %0, %0\n"
197 : "=r" (tt) : : "cc"
198 );
199 return !(tt & (1u << 22));
200#else
201 // NonSecure is an Arm concept, there is nothing meaningful to return
202 // here. Note it's not possible in general to detect whether you are
203 // executing in U-mode as, for example, M-mode is classically
204 // virtualisable in U-mode.
205 return false;
206#endif
207}
208
209#define host_safe_hw_ptr(x) ((uintptr_t)(x))
210#define native_safe_hw_ptr(x) host_safe_hw_ptr(x)
211
216uint8_t rp2350_chip_version(void);
217
222 static inline uint8_t rp2040_chip_version(void) {
223 return 2;
224}
225
230 static inline uint8_t rp2040_rom_version(void) {
231 GCC_Pragma("GCC diagnostic push")
232 GCC_Pragma("GCC diagnostic ignored \"-Warray-bounds\"")
233 return *(uint8_t*)0x13;
234 GCC_Pragma("GCC diagnostic pop")
235}
236
247__force_inline static int32_t __mul_instruction(int32_t a, int32_t b) {
248#ifdef __riscv
249 __asm ("mul %0, %0, %1" : "+l" (a) : "l" (b) : );
250#else
251 pico_default_asm ("muls %0, %1" : "+l" (a) : "l" (b) : "cc");
252#endif
253 return a;
254}
255
269#define __fast_mul(a, b) __builtin_choose_expr(__builtin_constant_p(b) && !__builtin_constant_p(a), \
270 (__builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b)), \
271 (a)*(b))
272
273#endif // __ASSEMBLER__
274
275#endif
276
__get_current_exception
static __force_inline uint __get_current_exception(void)
Get the current exception level on this core.
Definition: platform.h:158
rp2350_chip_version
uint8_t rp2350_chip_version(void)
Returns the RP2350 chip revision number.
Definition: platform.c:34
__force_inline
#define __force_inline
Attribute to force inlining of a function regardless of optimization level.
Definition: compiler.h:125
busy_wait_at_least_cycles
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:83
get_core_num
static __force_inline uint get_core_num(void)
Get the current core number.
Definition: platform.h:141
pico_processor_state_is_nonsecure
static __force_inline bool pico_processor_state_is_nonsecure(void)
Return true if executing in the NonSecure state (Arm-only)
Definition: platform.h:188
__breakpoint
static __force_inline void __breakpoint(void)
Execute a breakpoint instruction.
Definition: platform.h:128
tight_loop_contents
static __force_inline void tight_loop_contents(void)
No-op function for the body of tight loops.
Definition: platform.h:67
__mul_instruction
static __force_inline int32_t __mul_instruction(int32_t a, int32_t b)
Multiply two integers using an assembly MUL instruction.
Definition: platform.h:247
rp2040_chip_version
static uint8_t rp2040_chip_version(void)
Returns the RP2040 chip revision number for compatibility.
Definition: platform.h:222
rp2040_rom_version
static uint8_t rp2040_rom_version(void)
Returns the RP2040 rom version number.
Definition: platform.h:230