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...
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 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... | |
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
#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>
group | a string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently |
#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)
#define __fast_mul | ( | 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
a | the first operand |
b | the second operand |
#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) {
#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>
group | a string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently |
#define __isr |
Marker for an interrupt handler.
For example an IRQ handler function called my_interrupt_handler:
void __isr my_interrupt_handler(void) {
#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
#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>
group | a string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently |
#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
#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>
group | a string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently |
#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>
group | a string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently |
#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
#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>
group | a string suffix to use in the section name to distinguish groups that can be linker garbage-collected independently |
#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.
|
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!)
|
inlinestatic |
Get the current exception level on this core.
|
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.
a | the first operand |
b | the second operand |
|
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.
minimum_cycles | the minimum number of system clock cycles to delay for |
|
static |
Get the current core number.
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.
fmt | format string (printf-like) |
... | printf-like arguments |
void panic_unsupported | ( | void | ) |
Panics with the message "Unsupported".
uint8_t rp2040_chip_version | ( | void | ) |
Returns the RP2040 chip revision number.
|
inlinestatic |
Returns the RP2040 rom version number.
|
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