Loading...
Searching...
No Matches

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. More...

Files

file  common.h
 Macros and definitions common to all rp2 platforms but not specific to any library.
 
file  compiler.h
 Macros and definitions (and functions when included by non assembly code) to adapt for different compilers.
 

Macros

#define __fast_mul(a, b)   (__builtin_constant_p(b) && !__builtin_constant_p(a) && __builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b))
 multiply two integer values using the fastest method possible
 
#define __isr
 Marker for an interrupt handler.
 
#define __force_inline   __always_inline
 Attribute to force inlining of a function regardless of optimization level.
 
#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 __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.
 
#define __after_data(group)   __attribute__((section(".after_data." group)))
 Section attribute macro for placement in RAM after the .data section.
 
#define __in_ram(group)   __attribute__((section(".time_critical." group)))
 Section attribute macro for placement in RAM.
 
#define __in_scratch_x(group)   __attribute__((section(".scratch_x." group)))
 Section attribute macro for placement in the penultimate SRAM bank (known as "scratch X")
 
#define __scratch_x(group)   __in_scratch_x(group)
 Section attribute macro for placement in the penultimate SRAM bank (known as "scratch X")
 
#define __in_scratch_y(group)   __attribute__((section(".scratch_y." group)))
 Section attribute macro for placement in the final SRAM bank (known as "scratch Y")
 
#define __scratch_y(group)   __in_scratch_y(group)
 Section attribute macro for placement in the final SRAM bank (known as "scratch Y")
 
#define __in_psram(group)   __attribute__((section(".psram_initialised." group)))
 Section attribute macro for placement in PSRAM.
 
#define __uninitialized_psram(group)   __attribute__((section(".psram_uninitialised." group)))
 Section attribute macro for placement in uninitialised PSRAM.
 
#define __in_xip_ram(group)   x; static_assert(false, "Must set PICO_USE_XIP_CACHE_AS_RAM=1 to use the __in_xip_ram macro");
 Section attribute macro for placement in XIP SRAM.
 
#define __uninitialized_ram(group)   __attribute__((section(".uninitialized_data." #group))) group
 Section attribute macro for data that is to be left uninitialized.
 
#define __persistent_data(name)   __attribute__((section(".bss." #name))) name
 Section attribute macro for placement in a section persisted across default POWMAN resets.
 
#define __in_flash(group)   __attribute__((section(".flashdata." group)))
 Section attribute macro for placement in flash even in a COPY_TO_RAM binary.
 
#define __not_in_flash(group)   PICO_NOT_IN_FLASH_PLACEMENT(group)
 Section attribute macro for placement not in flash.
 
#define __not_in_flash_func(func_name)   __not_in_flash(__STRING(func_name)) func_name
 Indicates a function should not be stored in flash.
 
#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.
 
#define __time_critical_func(func_name)   __noinline PICO_TIME_CRITICAL_PLACEMENT(__STRING(func_name)) func_name
 Indicates a function is time/latency critical and should not run from flash.
 

Functions

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

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.

Macros and definitions for accessing the CPU registers.

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,
 
)    (__builtin_constant_p(b) && !__builtin_constant_p(a) && __builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b))

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

◆ __in_psram

#define __in_psram (   group)    __attribute__((section(".psram_initialised." group)))

Section attribute macro for placement in PSRAM.

PSRAM is commonly used for extra data sections. You can place data in initialised or uninitialised PSRAM, depending on how the data is loaded into the PSRAM.

For example a uint32_t variable placed in PSRAM

uint32_t __in_psram("my_group_name") foo = 23;

Or placed in uninitialised PSRAM

uint32_t __uninitialized_psram("my_group_name") foo;

The section attribute is .psram_initialised.<group> or .psram_uninitialised.<group>

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

◆ __in_ram

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

Section attribute macro for placement 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>, which is used to maintain compatibility with older linker scripts

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

◆ __in_scratch_x

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

Section attribute macro for placement in the penultimate SRAM bank (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 __in_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

◆ __in_scratch_y

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

Section attribute macro for placement in the final SRAM bank (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

◆ __in_xip_ram

#define __in_xip_ram (   group)    x; static_assert(false, "Must set PICO_USE_XIP_CACHE_AS_RAM=1 to use the __in_xip_ram macro");

Section attribute macro for placement in XIP SRAM.

The XIP Cache can be used as SRAM for extra data sections, however it will give a performance penalty if your binary runs from Flash (e.g. the default binary type).

For example a uint32_t variable placed in XIP SRAM

uint32_t __in_xip_ram("my_group_name") foo = 23;

The section attribute is .xip_ram.<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 using __not_in_flash, which defaults to __in_ram

◆ __not_in_flash

#define __not_in_flash (   group)    PICO_NOT_IN_FLASH_PLACEMENT(group)

Section attribute macro for placement not in flash.

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];

By default, this is identical to __in_ram, but this can be adjusted using the PICO_NOT_IN_FLASH_PLACEMENT define. This define can be set using the pico_set_not_in_flash_placement CMake function.

For example, for binaries that only use core 0, there is the option to use pico_set_not_in_flash_placement(TARGET scratch_x) to place this code/data in scratch X to move it out of the striped SRAM.

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 using __not_in_flash, which defaults to __in_ram

See also
__no_inline_not_in_flash_func

◆ __persistent_data

#define __persistent_data (   name)    __attribute__((section(".bss." #name))) name

Section attribute macro for placement in a section persisted across default POWMAN resets.

Data marked this way will retain its value across a default POWMAN reset, and will be zeroed on any other reset.

For example a uint32_t foo that will be zeroed initially, then retain its value if the program is restarted by default POWMAN reset.

uint32_t __persistent_data(foo);

The section attribute is .persistent_data.<name>

Parameters
namethe name of the variable to place in the section

◆ __scratch_x

#define __scratch_x (   group)    __in_scratch_x(group)

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

Alias for __in_scratch_x

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)    __in_scratch_y(group)

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

Alias for __in_scratch_y

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)    __noinline PICO_TIME_CRITICAL_PLACEMENT(__STRING(func_name)) 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 to avoid possible flash latency. By default, this macro is identical in implementation to __no_inline_not_in_flash_func, however the semantics are distinct and a __time_critical_func can be treated more specially to reduce the overhead when calling such a function.

For example a function called my_func taking an int parameter:

void __time_critical_func(my_func)(int some_arg) {

By default, the function is placed using __in_ram, but this can be adjusted using the PICO_TIME_CRITICAL_PLACEMENT define. This define can be set using the pico_set_time_critical_placement CMake function.

For example, for binaries that are not executing from flash (e.g. copy_to_ram and no_flash), there is the option to use pico_set_time_critical_placement(TARGET xip_ram) to place these functions in XIP RAM, as the XIP AHB ports would be otherwise unused.

See also
__not_in_flash

◆ __uninitialized_psram

#define __uninitialized_psram (   group)    __attribute__((section(".psram_uninitialised." group)))

Section attribute macro for placement in uninitialised PSRAM.

The version of __in_psram to use for uninitialised data

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

◆ __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

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 __force_inline uint __get_current_exception ( void  )
static

Get the current exception level on this core.

On Cortex-M this is the exception number defined in the architecture reference, which is equal to VTABLE_FIRST_IRQ + irq num if inside an interrupt handler. (VTABLE_FIRST_IRQ is defined in platform_defs.h).

On Hazard3, this function returns VTABLE_FIRST_IRQ + irq num if inside of an external IRQ handler (or a fault from such a handler), and 0 otherwise, generally aligning with the Cortex-M values.

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

◆ __mul_instruction()

static __force_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 __force_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 __force_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