hardware-pio
可编程 I/O(PIO)API。
详细描述
可编程输入/输出块(PIO)是一种多功能硬件接口,可支持多种不同的 IO 标准。
RP2040 中有两个 PIO 块。
RP2350 中有三个 PIO 块。
每个 PIO 与处理器的可编程性相同:四个状态机独立执行简短的顺序程序,以操作 GPIO 并传输数据。与通用处理器不同,PIO 状态机高度专业化于 IO,注重确定性、精确时序以及与固定功能硬件的紧密集成。每个状态机配备:
-
两个 32 位移位寄存器——任意方向,任意移位计数
-
两个 32 位暂存寄存器
-
每个方向(TX/RX)4×32 位总线 FIFO,可重新配置为单方向 8×32
-
分数时钟分频器(16 位整数,8 位分数)
-
灵活的 GPIO 映射
-
DMA 接口,系统 DMA 每时钟最高持续吞吐量为 1 个字
-
IRQ 标志置位/清除/状态
PIO 的完整详细信息请参阅相应的 RP 系列数据手册。请注意,RP2350 PIO 实现中有额外功能,因此在编写需要同时在 RP2040 和 RP2350 上运行的 PIO 代码时需要注意。
在 RP2040 上,引脚编号始终可以指定为 0-31
在 RP2350A 上,引脚编号始终可以指定为 0-31。
在 RP2350B 上,有 48 个引脚,但每个 PIO 实例只能寻址 32 个引脚(PIO 实例根据 pio_set_gpio_base 寻址引脚 0-31 或 16-47)。直接影响硬件的 pio_sm_ 方法始终采用完整范围内的实际引脚编号,但:
-
若
PICO_PIO_USE_GPIO_BASE != 1,则引脚编号的第 5 位被忽略。这样做是为了使针对 RP2350A 开发板编译的程序不会因处理不存在的高编号引脚而产生额外开销。在这种情况下,这些函数的行为与 RP2040 完全相同。注意,若 PICO_RP2350A 为 1,则PICO_PIO_USE_GPIO_BASE` 默认为 0。 -
若
PICO_PIO_USE_GPIO_BASE == 1,则传入的引脚编号会在内部减去 GPIO 基址,从 PIO 角度得到 0-31 范围内的引脚编号。
您可以设置 PARAM_ASSERTIONS_ENABLED_HARDWARE_PIO = 1 以启用参数检查,用于调试 hardware_pio 方法中的引脚(或其他)问题。
注意,引脚掩码遵循与单个引脚相同的规则;32 位或 64 位掩码中的位 N 始终指引脚 N。
模块
sm_config
PIO 状态机配置。
pio_instructions
PIO 指令编码。
宏
#define pio0 pio0_hw#define pio1 pio1_hw#define [PIO_NUM](pio)#define [PIO_INSTANCE](instance)#define [PIO_FUNCSEL_NUM](pio, gpio)#define [PIO_DREQ_NUM](pio, sm, is_tx)#define [PIO_IRQ_NUM](pio, irqn)
类型定义
- `typedef enum pio_interrupt_source pio_interrupt_source_t``: PIO 相关 IRQ 的 PIO 中断源编号。
枚举
enum pio_fifo_join { [PIO_FIFO_JOIN_NONE] = 0, [PIO_FIFO_JOIN_TX] = 1, [PIO_FIFO_JOIN_RX] = 2 }: FIFO 连接状态。enum pio_mov_status_type { STATUS_TX_LESSTHAN = 0, STATUS_RX_LESSTHAN = 1 }: MOV 状态类型。enum pio_interrupt_source { pis_interrupt0= PIO_INTR_SM0_LSB, pis_interrupt1 = PIO_INTR_SM1_LSB,pis_interrupt2 = PIO_INTR_SM2_LSB, pis_interrupt3 = PIO_INTR_SM3_LSB,pis_sm0_tx_fifo_not_full= PIO_INTR_SM0_TXNFULL_LSB, pis_sm1_tx_fifo_not_full = PIO_INTR_SM1_TXNFULL_LSB, pis_sm2_tx_fifo_not_full= PIO_INTR_SM2_TXNFULL_LSB, pis_sm3_tx_fifo_not_full = PIO_INTR_SM3_TXNFULL_LSB,pis_sm0_rx_fifo_not_empty = PIO_INTR_SM0_RXNEMPTY_LSB, pis_sm1_rx_fifo_not_empty = PIO_INTR_SM1_RXNEMPTY_LSB,pis_sm2_rx_fifo_not_empty= PIO_INTR_SM2_RXNEMPTY_LSB, pis_sm3_rx_fifo_not_empty = PIO_INTR_SM3_RXNEMPTY_LSB }: PIO 相关 IRQ 的 PIO 中断源编号。
函数
static uint pio_get_gpio_base (PIO pio): 返回 PIO 实例的 GPIO 基址。static int pio_sm_set_config (PIO pio, uint sm, const pio_sm_config *config)
将状态机配置应用到状态机。static uint pio_get_index (PIO pio): 返回 PIO 实例的实例编号。static uint pio_get_funcsel (PIO pio): 返回 PIO 实例的功能选择编号。static [PIO] pio_get_instance (uint instance): 将 PIO 实例转换为硬件实例。static void pio_gpio_init (PIO pio, uint pin): 设置 GPIO 的功能选择以使用给定 PIO 实例的输出。static uint pio_get_dreq (PIO pio, uint sm, bool is_tx): 返回用于调节特定状态机 FIFO 传输速率的 DREQ。int pio_set_gpio_base (PIO pio, uint gpio_base): 设置 PIO 实例的 GPIO 基址。bool pio_can_add_program (PIO pio, const pio_program_t *program)
确定给定程序当前是否可以加载到 PIO 实例。
bool pio_can_add_program_at_offset (PIO pio, const pio_program_t *program, uint offset)
确定给定程序当前是否可以从特定位置加载到 PIO 实例。
int pio_add_program (PIO pio, const pio_program_t *program)
尝试加载程序。
int pio_add_program_at_offset (PIO pio, const pio_program_t *program, uint offset)
尝试在指定指令内存偏移处加载程序。
void pio_remove_program (PIO pio, const pio_program_t *program, uint loaded_offset)
从 PIO 实例的指令内存中移除程序。
void pio_clear_instruction_memory (PIO pio): 清除 PIO 实例的所有指令内存。int pio_sm_init (PIO pio, uint sm, uint initial_pc, const pio_sm_config *config)
将状态机重置为一致状态并进行配置。static void pio_sm_set_enabled (PIO pio, uint sm, bool enabled): 启用或禁用 PIO 状态机。static void pio_set_sm_mask_enabled (PIO pio, uint32_t mask, bool enabled): 启用或禁用多个 PIO 状态机。static void pio_sm_restart (PIO pio, uint sm): 以已知状态重启状态机。static void pio_restart_sm_mask (PIO pio, uint32_t mask): 以已知状态重启多个状态机。static void pio_sm_clkdiv_restart (PIO pio, uint sm): 从相位 0 重启状态机的时钟分频器。static void pio_clkdiv_restart_sm_mask (PIO pio, uint32_t mask): 从相位 0 重启多个状态机的时钟分频器。static void pio_enable_sm_mask_in_sync (PIO pio, uint32_t mask): 同步时钟分频器地启用多个 PIO 状态机。static void pio_set_irq0_source_enabled (PIO pio, pio_interrupt_source_t source, bool enabled): 启用/禁用 PIO 的 IRQ 0 上的单个源。static void pio_set_irq1_source_enabled (PIO pio, pio_interrupt_source_t source, bool enabled): 启用/禁用 PIO 的 IRQ 1 上的单个源。static void pio_set_irq0_source_mask_enabled (PIO pio, uint32_t source_mask, bool enabled): 启用/禁用 PIO 的 IRQ 0 上的多个源。static void pio_set_irq1_source_mask_enabled (PIO pio, uint32_t source_mask, bool enabled): 启用/禁用 PIO 的 IRQ 1 上的多个源。static void pio_set_irqn_source_enabled (PIO pio, uint irq_index, pio_interrupt_source_t source, bool enabled): 启用/禁用 PIO 指定(0/1)IRQ 索引上的单个源。static void pio_set_irqn_source_mask_enabled (PIO pio, uint irq_index, uint32_t source_mask, bool enabled): 启用/禁用 PIO 指定(0/1)IRQ 索引上的多个源。static bool pio_interrupt_get (PIO pio, uint pio_interrupt_num): 确定特定 PIO 中断是否已设置。static void pio_interrupt_clear (PIO pio, uint pio_interrupt_num): 清除特定 PIO 中断。static uint8_t pio_sm_get_pc (PIO pio, uint sm): 返回状态机的当前程序计数器。static void pio_sm_exec (PIO pio, uint sm, uint instr): 立即在状态机上执行指令。static bool pio_sm_is_exec_stalled (PIO pio, uint sm): 确定由pio_sm_exec()` 设置的指令是否停滞执行。static void pio_sm_exec_wait_blocking (PIO pio, uint sm, uint instr): 立即在状态机上执行指令并等待完成。static void pio_sm_set_wrap (PIO pio, uint sm, uint wrap_target, uint wrap): 设置状态机的当前回绕配置。static void pio_sm_set_out_pins (PIO pio, uint sm, uint out_base, uint out_count): 设置状态机的当前"out"引脚。static void pio_sm_set_set_pins (PIO pio, uint sm, uint set_base, uint set_count): 设置状态机的当前"set"引脚。static void pio_sm_set_in_pins (PIO pio, uint sm, uint in_base): 设置状态机的当前"in"引脚。static void pio_sm_set_sideset_pins (PIO pio, uint sm, uint sideset_base): 设置状态机的当前"sideset"引脚。static void pio_sm_set_jmp_pin (PIO pio, uint sm, uint pin): 设置状态机的"jmp"引脚。static void pio_sm_put (PIO pio, uint sm, uint32_t data): 向状态机的 TX FIFO 写入一个字的数据。static uint32_t pio_sm_get (PIO pio, uint sm): 从状态机的 RX FIFO 读取一个字的数据。static bool pio_sm_is_rx_fifo_full (PIO pio, uint sm): 确定状态机的 RX FIFO 是否已满。static bool pio_sm_is_rx_fifo_empty (PIO pio, uint sm): 确定状态机的 RX FIFO 是否为空。static uint pio_sm_get_rx_fifo_level (PIO pio, uint sm): 返回状态机 RX FIFO 中当前的元素数量。static bool pio_sm_is_tx_fifo_full (PIO pio, uint sm): 确定状态机的 TX FIFO 是否已满。static bool pio_sm_is_tx_fifo_empty (PIO pio, uint sm): 确定状态机的 TX FIFO 是否为空。static uint pio_sm_get_tx_fifo_level (PIO pio, uint sm): 返回状态机 TX FIFO 中当前的元素数量。static void pio_sm_put_blocking (PIO pio, uint sm, uint32_t data): 向状态机的 TX FIFO 写入一个字的数据,若 FIFO 满则阻塞。static uint32_t pio_sm_get_blocking (PIO pio, uint sm): 从状态机的 RX FIFO 读取一个字的数据,若 FIFO 为空则阻塞。void pio_sm_drain_tx_fifo (PIO pio, uint sm): 清空状态机的 TX FIFO。static void pio_sm_set_clkdiv_int_frac8 (PIO pio, uint sm, uint32_t div_int, uint8_t div_frac8): 使用 16:8 分数值设置状态机的当前时钟分频器static void pio_sm_set_clkdiv (PIO pio, uint sm, float div): 设置状态机的当前时钟分频器static void pio_sm_clear_fifos (PIO pio, uint sm): 清除状态机的 TX 和 RX FIFO。void pio_sm_set_pins (PIO pio, uint sm, uint32_t pin_values): 使用状态机为 PIO 实例的所有引脚设置值。void pio_sm_set_pins64 (PIO pio, uint sm, uint64_t pin_values): 使用状态机为 PIO 实例的所有引脚设置值。void pio_sm_set_pins_with_mask (PIO pio, uint sm, uint32_t pin_values, uint32_t pin_mask): 使用状态机为 PIO 实例的多个引脚设置值。void pio_sm_set_pins_with_mask64 (PIO pio, uint sm, uint64_t pin_values, uint64_t pin_mask): 使用状态机为 PIO 实例的多个引脚设置值。void pio_sm_set_pindirs_with_mask (PIO pio, uint sm, uint32_t pin_dirs, uint32_t pin_mask): 使用状态机为 PIO 实例的多个引脚设置引脚方向。void pio_sm_set_pindirs_with_mask64 (PIO pio, uint sm, uint64_t pin_dirs, uint64_t pin_mask): 使用状态机为 PIO 实例的多个引脚设置引脚方向。int pio_sm_set_consecutive_pindirs (PIO pio, uint sm, uint pins_base, uint pin_count, bool is_out): 使用状态机为 PIO 实例的多个连续引脚设置相同的引脚方向。void pio_sm_claim (PIO pio, uint sm): 将状态机标记为已使用。void pio_claim_sm_mask (PIO pio, uint sm_mask): 将多个状态机标记为已使用。void pio_sm_unclaim (PIO pio, uint sm): 将状态机标记为不再使用。int pio_claim_unused_sm (PIO pio, bool required): 在 PIO 实例上占用一个空闲状态机。bool pio_sm_is_claimed (PIO pio, uint sm): 确定 PIO 状态机是否已被占用。bool pio_claim_free_sm_and_add_program (const pio_program_t **program, PIO **pio, uint **sm, uint **offset)
查找 PIO 和状态机并将程序添加到 PIO 内存。
bool pio_claim_free_sm_and_add_program_for_gpio_range (const pio_program_t **program, PIO **pio, uint **sm, uint **offset, uint gpio_base, uint gpio_count, bool set_gpio_base)
查找 PIO 和状态机并将程序添加到 PIO 内存。
void pio_remove_program_and_unclaim_sm (const pio_program_t *program, PIO pio, uint sm, uint offset)
从 PIO 内存中移除程序并释放状态机。
static int pio_get_irq_num (PIO pio, uint irqn): 返回 PIO 硬件实例的 IRQ。static pio_interrupt_source_t pio_get_tx_fifo_not_full_interrupt_source(uint sm)`: 返回状态机 TX FIFO 非满中断的中断源。static pio_interrupt_source_t pio_get_rx_fifo_not_empty_interrupt_source(uint sm)`: 返回状态机 RX FIFO 非空中断的中断源。