Macros

#define __isr
 Marker for an interrupt handler. More...
 
#define __after_data(group)   __attribute__((section(".after_data." group)))
 Section attribute macro for placement in RAM after the .data section. More...
 
#define __not_in_flash(group)   __attribute__((section(".time_critical." group)))
 Section attribute macro for placement not in flash (i.e in RAM) More...
 
#define __scratch_x(group)   __attribute__((section(".scratch_x." group)))
 Section attribute macro for placement in the SRAM bank 4 (known as "scratch X") More...
 
#define __scratch_y(group)   __attribute__((section(".scratch_y." group)))
 Section attribute macro for placement in the SRAM bank 5 (known as "scratch Y") More...
 
#define __uninitialized_ram(group)   __attribute__((section(".uninitialized_data." #group))) group
 Section attribute macro for data that is to be left uninitialized. More...
 
#define __in_flash(group)   __attribute__((section(".flashdata." group)))
 Section attribute macro for placement in flash even in a COPY_TO_RAM binary. More...
 
#define __not_in_flash_func(func_name)   __not_in_flash(__STRING(func_name)) func_name
 Indicates a function should not be stored in flash. More...
 
#define __time_critical_func(func_name)   __not_in_flash_func(func_name)
 Indicates a function is time/latency critical and should not run from flash. More...
 
#define __no_inline_not_in_flash_func(func_name)   __noinline __not_in_flash_func(func_name)
 Indicate a function should not be stored in flash and should not be inlined. More...
 
#define __force_inline   __always_inline
 Attribute to force inlining of a function regardless of optimization level. More...
 
#define count_of(a)   (sizeof(a)/sizeof((a)[0]))
 Macro to determine the number of elements in an array.
 
#define MAX(a, b)   ((a)>(b)?(a):(b))
 Macro to return the maximum of two comparable values.
 
#define MIN(a, b)   ((b)>(a)?(a):(b))
 Macro to return the minimum of two comparable values.
 
#define host_safe_hw_ptr(x)   ((uintptr_t)(x))
 Macro for converting memory addresses to 32 bit addresses suitable for DMA. More...
 
#define __fast_mul(a, b)
 multiply two integer values using the fastest method possible More...
 
#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));
 Utility macro to assert two types are equivalent. More...
 

Functions

static void __breakpoint (void)
 Execute a breakpoint instruction.
 
static __always_inline void __compiler_memory_barrier (void)
 Ensure that the compiler does not move memory access across this method call. More...
 
void panic_unsupported (void)
 Panics with the message "Unsupported". More...
 
void panic (const char *fmt,...)
 Displays a panic message and halts execution. More...
 
uint8_t rp2040_chip_version (void)
 Returns the RP2040 chip revision number. More...
 
static uint8_t rp2040_rom_version (void)
 Returns the RP2040 rom version number. More...
 
static __always_inline void tight_loop_contents (void)
 No-op function for the body of tight loops. More...
 
static __always_inline int32_t __mul_instruction (int32_t a, int32_t b)
 Multiply two integers using an assembly MUL instruction. More...
 
static __always_inline uint __get_current_exception (void)
 Get the current exception level on this core. More...
 
static void busy_wait_at_least_cycles (uint32_t minimum_cycles)
 Helper method to busy-wait for at least the given number of cycles. More...
 
static __always_inline uint get_core_num (void)
 Get the current core number. More...
 

Detailed Description

Macros and definitions (and functions when included by non assembly code) for the RP2 family device / architecture to provide a common abstraction over low level compiler / platform specifics.

This header may be included by assembly code

Macro Definition Documentation

◆ __after_data

#define __after_data (   group)    __attribute__((section(".after_data." group)))

Section attribute macro for placement in RAM after the .data section.

For example a 400 element uint32_t array placed after the .data section

uint32_t __after_data("my_group_name") a_big_array[400];

The section attribute is .after_data.<group>

Parameters
groupa string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently

◆ __check_type_compatible

#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));

Utility macro to assert two types are equivalent.

This macro can be useful in other macros along with typeof to assert that two parameters are of equivalent type (or that a single parameter is of an expected type)

◆ __fast_mul

#define __fast_mul (   a,
 
)
Value:
__builtin_choose_expr(__builtin_constant_p(b) && !__builtin_constant_p(a), \
(__builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b)), \
(a)*(b))
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

multiply two integer values using the fastest method possible

Efficiently multiplies value a by possibly constant value b.

If b is known to be constant and not zero or a power of 2, then a mul instruction is used rather than gcc's default which is often a slow combination of shifts and adds. If b is a power of 2 then a single shift is of course preferable and will be used

Parameters
athe first operand
bthe second operand
Returns
a * b

◆ __force_inline

#define __force_inline   __always_inline

Attribute to force inlining of a function regardless of optimization level.

For example my_function here will always be inlined:

int __force_inline my_function(int x) {

◆ __in_flash

#define __in_flash (   group)    __attribute__((section(".flashdata." group)))

Section attribute macro for placement in flash even in a COPY_TO_RAM binary.

For example a uint32_t variable explicitly placed in flash (it will hard fault if you attempt to write it!)

uint32_t __in_flash("my_group_name") foo = 23;

The section attribute is .flashdata.<group>

Parameters
groupa string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently

◆ __isr

#define __isr

Marker for an interrupt handler.

For example an IRQ handler function called my_interrupt_handler:

void __isr my_interrupt_handler(void) {

◆ __no_inline_not_in_flash_func

#define __no_inline_not_in_flash_func (   func_name)    __noinline __not_in_flash_func(func_name)

Indicate a function should not be stored in flash and should not be inlined.

Decorates a function name, such that the function will execute from RAM, explicitly marking it as noinline to prevent it being inlined into a flash function by the compiler

For example a function called my_func taking an int parameter:

void __no_inline_not_in_flash_func(my_func)(int some_arg) {

The function is placed in the .time_critical.<func_name> linker section

◆ __not_in_flash

#define __not_in_flash (   group)    __attribute__((section(".time_critical." group)))

Section attribute macro for placement not in flash (i.e in RAM)

For example a 3 element uint32_t array placed in RAM (even though it is static const)

static const uint32_t __not_in_flash("my_group_name") an_array[3];

The section attribute is .time_critical.<group>

Parameters
groupa string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently

◆ __not_in_flash_func

#define __not_in_flash_func (   func_name)    __not_in_flash(__STRING(func_name)) func_name

Indicates a function should not be stored in flash.

Decorates a function name, such that the function will execute from RAM (assuming it is not inlined into a flash function by the compiler)

For example a function called my_func taking an int parameter:

void __not_in_flash_func(my_func)(int some_arg) {

The function is placed in the .time_critical.<func_name> linker section

See also
__no_inline_not_in_flash_func

◆ __scratch_x

#define __scratch_x (   group)    __attribute__((section(".scratch_x." group)))

Section attribute macro for placement in the SRAM bank 4 (known as "scratch X")

Scratch X is commonly used for critical data and functions accessed only by one core (when only one core is accessing the RAM bank, there is no opportunity for stalls)

For example a uint32_t variable placed in "scratch X"

uint32_t __scratch_x("my_group_name") foo = 23;

The section attribute is .scratch_x.<group>

Parameters
groupa string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently

◆ __scratch_y

#define __scratch_y (   group)    __attribute__((section(".scratch_y." group)))

Section attribute macro for placement in the SRAM bank 5 (known as "scratch Y")

Scratch Y is commonly used for critical data and functions accessed only by one core (when only one core is accessing the RAM bank, there is no opportunity for stalls)

For example a uint32_t variable placed in "scratch Y"

uint32_t __scratch_y("my_group_name") foo = 23;

The section attribute is .scratch_y.<group>

Parameters
groupa string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently

◆ __time_critical_func

#define __time_critical_func (   func_name)    __not_in_flash_func(func_name)

Indicates a function is time/latency critical and should not run from flash.

Decorates a function name, such that the function will execute from RAM (assuming it is not inlined into a flash function by the compiler) to avoid possible flash latency. Currently this macro is identical in implementation to __not_in_flash_func, however the semantics are distinct and a __time_critical_func may in the future be treated more specially to reduce the overhead when calling such function from a flash function.

For example a function called my_func taking an int parameter:

void __time_critical(my_func)(int some_arg) {

The function is placed in the .time_critical.<func_name> linker section

See also
__not_in_flash_func

◆ __uninitialized_ram

#define __uninitialized_ram (   group)    __attribute__((section(".uninitialized_data." #group))) group

Section attribute macro for data that is to be left uninitialized.

Data marked this way will retain its value across a reset (normally uninitialized data - in the .bss section) is initialized to zero during runtime initialization

For example a uint32_t foo that will retain its value if the program is restarted by reset.

uint32_t __uninitialized_ram(foo);

The section attribute is .uninitialized_data.<group>

Parameters
groupa string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently

◆ host_safe_hw_ptr

#define host_safe_hw_ptr (   x)    ((uintptr_t)(x))

Macro for converting memory addresses to 32 bit addresses suitable for DMA.

This is just a cast to uintptr_t on the RP2040, however you may want to use this when developing code that also runs in "host" mode. If the host mode is 64 bit and you are embedding data pointers in other data (e.g. DMA chaining), then there is a need in "host" mode to convert a 64 bit native pointer to a 32 bit value for storage, which can be done using this macro.

Function Documentation

◆ __compiler_memory_barrier()

static __always_inline void __compiler_memory_barrier ( void  )
static

Ensure that the compiler does not move memory access across this method call.

For example in the following code:

*some_memory_location = var_a;
__compiler_memory_barrier();
uint32_t var_b = *some_other_memory_location

The compiler will not move the load from some_other_memory_location above the memory barrier (which it otherwise might - even above the memory store!)

◆ __get_current_exception()

static __always_inline uint __get_current_exception ( void  )
static

Get the current exception level on this core.

Returns
the exception number if the CPU is handling an exception, or 0 otherwise

◆ __mul_instruction()

static __always_inline int32_t __mul_instruction ( int32_t  a,
int32_t  b 
)
static

Multiply two integers using an assembly MUL instruction.

This multiplies a by b using multiply instruction using the ARM mul instruction regardless of values (the compiler might otherwise choose to perform shifts/adds), i.e. this is a 1 cycle operation.

Parameters
athe first operand
bthe second operand
Returns
a * b

◆ busy_wait_at_least_cycles()

static void busy_wait_at_least_cycles ( uint32_t  minimum_cycles)
inlinestatic

Helper method to busy-wait for at least the given number of cycles.

This method is useful for introducing very short delays.

This method busy-waits in a tight loop for the given number of system clock cycles. The total wait time is only accurate to within 2 cycles, and this method uses a loop counter rather than a hardware timer, so the method will always take longer than expected if an interrupt is handled on the calling core during the busy-wait; you can of course disable interrupts to prevent this.

You can use clock_get_hz(clk_sys) to determine the number of clock cycles per second if you want to convert an actual time duration to a number of cycles.

Parameters
minimum_cyclesthe minimum number of system clock cycles to delay for

◆ get_core_num()

static __always_inline uint get_core_num ( void  )
static

Get the current core number.

Returns
The core number the call was made from

◆ panic()

void panic ( const char *  fmt,
  ... 
)

Displays a panic message and halts execution.

An attempt is made to output the message to all registered STDOUT drivers after which this method executes a BKPT instruction.

Parameters
fmtformat string (printf-like)
...printf-like arguments

◆ panic_unsupported()

void panic_unsupported ( void  )

Panics with the message "Unsupported".

See also
panic

◆ rp2040_chip_version()

uint8_t rp2040_chip_version ( void  )

Returns the RP2040 chip revision number.

Returns
the RP2040 chip revision number (1 for B0/B1, 2 for B2)

◆ rp2040_rom_version()

static uint8_t rp2040_rom_version ( void  )
inlinestatic

Returns the RP2040 rom version number.

Returns
the RP2040 rom version number (1 for RP2040-B0, 2 for RP2040-B1, 3 for RP2040-B2)

◆ tight_loop_contents()

static __always_inline void tight_loop_contents ( void  )
static

No-op function for the body of tight loops.

No-op function intended to be called by any tight hardware polling loop. Using this ubiquitously makes it much easier to find tight loops, but also in the future #ifdef-ed support for lockup debugging might be added