跳到主要内容

pico-platform

为 RP2 系列设备/架构提供针对底层编译器/平台特定内容的通用抽象的宏、定义(以及在非汇编代码中包含时的函数)。

详细描述

用于访问 CPU 寄存器的宏和定义。

此头文件可被汇编代码包含。

此头文件可被汇编代码包含。

  • #define __fast_mul(a, b)
  • #define __isr
  • #define __force_inline __always_inline
  • #define count_of(a) (sizeof(a)/sizeof\((a)[0]))
  • #define [MAX](a, b) \((a)>(b)?(a):(b))
  • #define [MIN](a, b) \((b)>(a)?(a):(b))
  • #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));`
  • #define __after_data(group) __attribute__\((section(".after_data." group)))
  • #define __scratch_x(group) __attribute__\((section(".scratch_x." group)))
  • #define __scratch_y(group) __attribute__\((section(".scratch_y." group)))
  • #define __uninitialized_ram(group) __attribute__\((section(".uninitialized_data." #group))) group
  • #define __in_flash(group) __attribute__\((section(".flashdata." group)))
  • #define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name)`

函数

  • static void busy_wait_at_least_cycles (uint32_t minimum_cycles): 忙等待至少给定数量的时钟周期的辅助方法。 static __force_inline void __breakpoint (void)
     执行断点指令。

static __force_inline uint get_core_num (void)
 获取当前核心编号。

static __force_inline uint __get_current_exception (void)
 获取此核心上当前的异常级别。

static __force_inline bool pico_processor_state_is_nonsecure (void) RP2350
 如果当前在 NonSecure 状态下执行则返回 true(仅 Arm)。

uint8_t rp2350_chip_version (void) RP2350
 返回 RP2350 芯片版本号。

static uint8_t rp2040_chip_version (void) RP2350
 为兼容性返回 RP2040 芯片版本号。

  • static uint8_t rp2040_rom_version (void): 返回 RP2040 ROM 版本号。 static __force_inline int32_t __mul_instruction (int32_t a, int32_t b)<br/>&emsp;使用汇编 MUL 指令将两个整数相乘。

static __force_inline void tight_loop_contents (void)
 用于紧密循环体的空操作函数。

static __always_inline void __compiler_memory_barrier (void)
 确保编译器不会将内存访问移过此方法调用。

  • void panic_unsupported (void): 以"Unsupported"消息触发 panic。 void panic (const char *fmt,...)
     显示 panic 消息并停止执行。

宏定义文档

__fast_mul

#define __fast_mul(a, b) __builtin_choose_expr(__builtin_constant_p(b) && !__builtin_constant_p(a), \
(__builtin_popcount(b) >= 2 ? __mul_instruction(a,b) : (a)*(b)), \
(a)*(b))

使用最快方式将两个整数值相乘。

高效地将值 a 与可能为常量的值 b 相乘。

如果 b 是已知常量且非零或非 2 的幂次,则使用 mul 指令而非 gcc 默认的移位和加法组合(后者通常较慢)。如果 b 是 2 的幂次,则显然优先使用单次移位。

参数

  • a: 第一个操作数
  • b: 第二个操作数

返回

a * b

__isr

#define __isr

中断处理函数的标记。

例如,名为 my_interrupt_handler 的 IRQ 处理函数:

void __isr my_interrupt_handler(void) {

__force_inline

#define __force_inline __always_inline

强制内联函数(无论优化级别)的属性。

例如,此处的 my_function 将始终被内联:

int __force_inline my_function(int x) {

count_of

#define count_of(a) (sizeof(a)/sizeof\((a)[0]))

用于确定数组元素数量的宏。

MAX

#define MAX(a, b) \((a)>(b)?(a):(b))

返回两个可比较值中较大值的宏。

MIN

#define MIN(a, b) \((b)>(a)?(a):(b))

返回两个可比较值中较小值的宏。

__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));`

用于断言两个类型等价的工具宏。

此宏可在其他宏中与 typeof 配合使用,断言两个参数的类型等价(或单个参数为预期类型)。

__after_data

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

用于在 .data 节之后的 RAM 中放置数据的节属性宏。

例如,一个放置在 .data 节之后的 400 元素 uint32_t 数组:

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

节属性为 .after_data.<group>

参数

  • group: 用于区分可被链接器独立垃圾回收的组的节名后缀字符串

__scratch_x

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

用于不在 flash 中放置(即放置在 RAM 中)的节属性宏。

例如,一个放置在 RAM 中的 3 元素 `uint32_t 数组(即使它是 static const):

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

节属性为 .time_critical.<group>

参数

  • group: 用于区分可被链接器独立垃圾回收的组的节名后缀字符串

用于在 SRAM bank 4(称为"scratch X")中放置数据的节属性宏。

Scratch X 通常用于仅被一个核心访问的关键数据和函数(当只有一个核心访问该 RAM bank 时,不存在停顿机会)。

例如,一个放置在"scratch X"中的 uint32_t 变量:

uint32_t __scratch_x("my_group_name") foo = 23;

节属性为 .scratch_x.<group>

参数

  • group: 用于区分可被链接器独立垃圾回收的组的节名后缀字符串

__scratch_y

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

用于在 SRAM bank 5(称为"scratch Y")中放置数据的节属性宏。

Scratch Y 通常用于仅被一个核心访问的关键数据和函数(当只有一个核心访问该 RAM bank 时,不存在停顿机会)。

例如,一个放置在"scratch Y"中的 uint32_t 变量:

uint32_t __scratch_y("my_group_name") foo = 23;

节属性为 .scratch_y.<group>

参数

  • group: 用于区分可被链接器独立垃圾回收的组的节名后缀字符串

__uninitialized_ram

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

用于标记不需要初始化的数据的节属性宏。

以此方式标记的数据在复位后将保留其值(通常,未初始化数据——在 .bss 节中——在运行时初始化期间会被清零)。

例如,一个在程序因复位重启后仍保留其值的 uint32_t foo:

uint32_t __uninitialized_ram(foo);

节属性为 .uninitialized_data.<group>

参数

  • group: 用于区分可被链接器独立垃圾回收的组的节名后缀字符串

__in_flash

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

在 COPY_TO_RAM 二进制文件中也强制放置在 flash 中的节属性宏。

例如,一个明确放置在 flash 中的 uint32_t 变量(如果尝试写入它将会发生硬故障!):

uint32_t __in_flash("my_group_name") foo = 23;

节属性为 .flashdata.<group>

参数

  • group: 用于区分可被链接器独立垃圾回收的组的节名后缀字符串

__no_inline_not_in_flash_func

#define __no_inline_not_in_flash_func(func_name) __noinline __not_in_flash_func(func_name)`

指示函数不应存储在 flash 中。

修饰函数名,使该函数从 RAM 执行(假设编译器未将其内联到 flash 函数中)。

例如,一个接受 int 参数的函数 my_func:

void __not_in_flash_func(my_func)(int some_arg) {

函数被放置在 .time_critical.<func_name> 链接器节中。

参见

__no_inline_not_in_flash_func

指示函数对时间/延迟敏感,不应从 flash 运行。

修饰函数名,使该函数从 RAM 执行(假设编译器未将其内联到 flash 函数中),以避免可能的 flash 延迟。目前此宏的实现与 __not_in_flash_func 相同,但语义不同,__time_critical_func` 将来可能会受到特殊处理,以减少从 flash 函数调用此类函数的开销。

例如,一个接受 int 参数的函数 my_func:

void __time_critical_func(my_func)(int some_arg) {

函数被放置在 .time_critical.<func_name> 链接器节中。

参见

__not_in_flash_func

指示函数不应存储在 flash 中且不应被内联。

修饰函数名,使该函数从 RAM 执行,并明确标记为 noinline 以防止编译器将其内联到 flash 函数中。

例如,一个接受 int 参数的函数 my_func:

void __no_inline_not_in_flash_func(my_func)(int some_arg) {

函数被放置在 .time_critical.<func_name> 链接器节中。

函数文档

__breakpoint

static __force_inline void __breakpoint (void) [static]

执行断点指令。

__compiler_memory_barrier

static __always_inline void __compiler_memory_barrier (void) [static]

确保编译器不会将内存访问移过此方法调用。

例如在以下代码中:

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

编译器不会将从 some_other_memory_location 的读取移到内存屏障之前(否则它可能会这样做——甚至移到内存写入之前!)。

__get_current_exception

static __force_inline uint __get_current_exception (void) [static]

获取此核心上当前的异常级别。

在 Cortex-M 上,这是架构参考手册中定义的异常编号,在中断处理程序内等于 VTABLE_FIRST_IRQ + irq num(VTABLE_FIRST_IRQ 在 platform_defs.h 中定义)。

在 Hazard3 上,若在外部 IRQ 处理程序内(或该处理程序引发的故障中),此函数返回 VTABLE_FIRST_IRQ + irq num,否则返回 0,与 Cortex-M 的值大体对齐。

返回

若 CPU 正在处理异常则返回异常编号,否则返回 0。

__mul_instruction

static __force_inline int32_t __mul_instruction (int32_t a, int32_t b) [static]

使用汇编 MUL 指令将两个整数相乘。

无论操作数取值如何,都使用 ARM mul 指令将 a 与 b 相乘(编译器可能会选择移位/加法组合),即这是一个单周期操作。

参数

  • a: 第一个操作数
  • b: 第二个操作数

返回

a * b

busy_wait_at_least_cycles

static void busy_wait_at_least_cycles (uint32_t minimum_cycles) [inline], [static]

忙等待至少给定数量的时钟周期的辅助方法。

此方法可用于引入极短的延迟。

此方法在紧密循环中忙等待给定数量的系统时钟周期。总等待时间精度仅在 2 个周期以内,且此方法使用循环计数器而非硬件定时器,因此若在忙等待期间调用核心处理了中断,该方法的实际等待时间将始终比预期更长;当然,可以禁用中断来避免这种情况。

如需将实际时间转换为周期数,可使用 clock_get_hz(clk_sys) 确定每秒时钟周期数。

参数

  • minimum_cycles: 要延迟的最少系统时钟周期数

get_core_num

static __force_inline uint get_core_num (void) [static]

获取当前核心编号。

返回

发起调用的核心编号。

panic

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

显示 panic 消息并停止执行。

会尝试将消息输出到所有已注册的 STDOUT 驱动程序,之后此方法执行 BKPT 指令。

参数

  • fmt: 格式字符串(类似 printf)
  • ...: 类似 printf 的参数

panic_unsupported

void panic_unsupported (void)

以"Unsupported"消息触发 panic。

参见

pico_processor_state_is_nonsecure RP2350

static __force_inline bool pico_processor_state_is_nonsecure (void) [static]

如果当前在 NonSecure 状态下执行则返回 true(仅 Arm)。

返回

若当前在 Arm 处理器的 NonSecure 状态下执行则返回 true。

rp2040_chip_version RP2350

static uint8_t rp2040_chip_version (void) [inline], [static]

为兼容性返回 RP2040 芯片版本号。

返回

2(RP2040 B2 中修复的勘误在 RP2350 中均已修复)。

rp2040_rom_version

static uint8_t rp2040_rom_version (void) [inline], [static]

返回 RP2040 ROM 版本号。

返回

RP2040 ROM 版本号(RP2040-B0 为 1,RP2040-B1 为 2,RP2040-B2 为 3)。

rp2350_chip_version RP2350

uint8_t rp2350_chip_version (void)

返回 RP2350 芯片版本号。

返回

RP2350 芯片版本号(B0/B1 为 1,B2 为 2)。

tight_loop_contents

static __force_inline void tight_loop_contents (void) [static]

用于紧密循环体的空操作函数。

此空操作函数旨在被任何紧密硬件轮询循环调用。普遍使用此函数可以更容易地找到紧密循环,并且将来可能会添加 #ifdef 化的锁死调试支持。


中文翻译版以英文版相同知识授权方式共享:CC-BY-SA 4.0。交流 Q群:498908352