RP2040 PIO 编程模型与状态机原理:从硬件架构到工作逻辑全解析

PIO 的编程模型与状态机工作原理

PIO​ 外设的编程模型与通用处理器存在共性:均通过顺序执行预编写的程序实现功能,且可通过 ​DMA​ / 中断系统完成数据交互、通过读写控制寄存器实现状态控制。但与通用处理器不同,PIO 是专为输入输出场景设计的硬件子系统,因此具备时序确定性强、操作精度高的特点,且与 GPIO、DMA 等固定功能硬件深度绑定。

PIO 的功能实现核心是其包含的 4 个独立状态机,每个状态机的硬件结构高度集成(对应状态机结构图),其组成及工作原理如下:

9a8163d2-7ed1-485e-97f8-f5b582bc1c9a.png

包括:

  • 两个 32 位移位寄存器​:​对应结构图中的 “Out Shift(输出移位寄存器)” 与 “In Shift(输入移位寄存器)”,均为 32 位宽度,支持任意方向、任意位数的数据移位操作:
    • 输出移位寄存器​​OSR​):​接收来自 TX FIFO 的数据,按指令配置的规则移位后输出至 GPIO;
    • 输入移位寄存器​​ISR​):​从 GPIO 读取数据,按指令规则移位暂存后,写入 RX FIFO。移位寄存器是状态机连接 FIFO 与 GPIO 的核心数据通路。
  • ​两个 32 位可擦写寄存器:​对应结构图中的 “Scratch X”和“Scratch Y”,均为 32 位宽度,是状态机执行程序时的临时数据存储单元,可类比为通用编程中的 “变量”,用于暂存运算中间结果、配置参数等;
  • ​每个方向上(TX/RX)都有 4x32 位总线 FIFO:​对应结构图中与移位寄存器连接的 “TX FIFO”和“RX FIFO”,是状态机与外部(CPU/DMA)的异步数据缓冲单元:
    • ​硬件规格:​每个状态机默认配备双向各 4×32 位的 FIFO(TX FIFO、RX FIFO 各 4 个 32 位数据深度),我们可以通过 SHIFTCTRL_FJOIN 选项合并为 8×32 位的单向 FIFO,适用于 DPI 图像显示等高带宽场景;
    • 数据交互:
      • TX FIFO:由 CPU 或 DMA 写入待输出数据,供状态机从 Out Shift 寄存器读取;
      • RX FIFO:由状态机将 In Shift 寄存器中的数据写入,供 CPU 或 DMA 读取。
    • ​速率适配:​FIFO 可产生 DREQs 请求信号(外围设备与 DMA 的通信通道),DMA 控制器可依据该信号感知 FIFO 的存储状态(满 / 非空 / 空等),动态调整传输节奏以实现速率匹配。
  • 时钟分频器​(Clock Div):​对应结构图中的 “Clock Div”,是 16 位整数 + 8 位小数的小数分频器:
    • 时钟源为系统时钟(如 125MHz),可将状态机时钟分频至系统时钟的 1/65536(125MHz 下最低分频后时钟约为 1908Hz);
    • 核心作用是为串行通信等场景设置精确的操作速率,保证时序匹配。
  • 灵活的 ​GPIO​​ 映射:​状态机支持 4 种独立的 GPIO 映射方式(输入映射、输出映射、设置映射、侧置映射),每个状态机可独立将其 I/O 操作映射至 RP2040 的 GPIO 引脚(最多支持 30 个可用 GPIO),实现灵活的引脚分配;
  • ​DMA​接口:状态机通过 DMA 接口与片内 DMA 控制器连接,最高可实现 “每个系统时钟传输 1 字节数据” 的交互速率,支持大数据量的高效传输;
  • ​中断系统:​对应结构图中的 “IRQ Set, Clear, Status”,PIO 外设共包含 8 个中断标志位:
    • 中断源可来自 FIFO(如 FIFO 满 / 空)、状态机(如指令执行完成);
    • 可通过中断标志的设置、清除、状态查询,实现状态机之间、状态机与主 CPU 之间的同步。
  • ​程序计数器 PC:​对应结构图中的 “PC” 模块,是状态机的指令地址指针,用于指向当前待执行的 PIO 汇编指令在指令内存中的存储位置,控制指令的顺序执行流程;
  • ​控制逻辑块:​对应结构图中的 “Control Logic” 模块,是状态机的控制中枢,系统可通过读写该模块内的寄存器,实现对状态机其他组件(移位寄存器、时钟分频器等)的配置与工作状态控制。

PIO 状态机无法直接执行人类编写的汇编指令,需借助 pioasm 编译器(PIO Assembler)将专用汇编指令编译为对应的机器码,再加载至 PIO 的指令内存中供状态机执行。PIO 提供了 9 个核心的 pioasm 汇编指令,覆盖了跳转、数据传输、GPIO 控制、中断处理等所有的相关基础操作,是实现 PIO 功能的核心语法,具体指令及功能如下:

  • JMP:跳转指令
    • ​功能:​修改状态机的程序计数器(PC)值,使指令执行流程跳转到指定的内存地址,支持无条件跳转和条件跳转(如根据寄存器值、引脚状态、FIFO 状态等条件判断是否跳转)。
    • ​用途:​实现程序的分支、循环、条件执行等逻辑,是构建复杂 PIO 程序的基础指令。
  • WAIT:等待指令
    • ​功能:​使状态机暂停执行,直到满足预设的等待条件后再继续执行后续指令。等待条件主要分为两类:
      • 一是 GPIO 引脚状态条件(如等待某 GPIO 引脚为高电平 / 低电平);
      • 二是时钟周期条件(如等待指定数量的状态机时钟周期,实现精准延时)。
    • ​用途:​实现与外部设备的时序同步(如等待传感器的就绪信号)、生成精确的延时操作,保证 PIO 操作的时序确定性。
  • IN:数据读出指令
    • ​功能:​将数据从指定源读取并移入输入移位寄存器(ISR),数据源包括 GPIO 引脚(读取单个或多个 GPIO 的电平状态)、FIFO 存储器、状态机内部寄存器等,支持指定读取的位数。
    • ​用途:​实现从外部设备(通过 GPIO)或内部单元读取数据的核心操作,是 PIO 输入数据的主要方式。
  • OUT:数据写入指令
    • ​功能:​将输出移位寄存器(OSR)中的数据移出并写入指定目标,目标包括 GPIO 引脚(控制 GPIO 输出电平)、FIFO 存储器、状态机内部寄存器等,支持指定写入的位数。
    • ​用途:​实现向外部设备(通过 GPIO)或内部单元发送数据的核心操作,是 PIO 输出数据的主要方式。
  • PUSH:数据推送指令
    • ​功能:​将输入移位寄存器(ISR)中的数据完整推送至 RX FIFO 中,推送后可选择清空 ISR 或保留数据,同时可配置是否在推送时触发中断。
    • ​用途:​将状态机从 GPIO 读取的数据传递给 CPU 或 DMA(通过 RX FIFO),完成 PIO 输入数据的向外交互。
  • PULL:数据拉取指令
    • ​功能:​从 TX FIFO 中拉取数据并加载至输出移位寄存器(OSR)中,拉取后可配置是否在 TX FIFO 为空时等待数据,同时可选择清空 OSR 或保留原有数据。
    • ​用途:​将 CPU 或 DMA 写入的数据(存储在 TX FIFO)传递给状态机,为 PIO 输出数据提供数据源。
  • MOV:数据移动指令
    • ​功能:​将数据在状态机的内部寄存器之间进行移动或复制,支持的操作对象包括输入移位寄存器(ISR)、输出移位寄存器(OSR)、X/Y 可擦写寄存器、GPIO 引脚配置寄存器等,也可实现数据的取反、清零等简单运算。
    • ​用途:​实现状态机内部的数据处理和寄存器间的数据交互,相当于通用编程中的变量赋值操作。
  • IRQ:中断写入或清除指令
    • ​功能:​对 PIO 的中断标志位进行操作,包括设置中断标志(触发中断)、清除中断标志(取消中断)、等待中断标志(暂停执行直到中断被触发),可指定操作的中断标志位(PIO 共 8 个中断标志位)。
    • ​用途:​实现状态机之间的同步、状态机与主 CPU 之间的事件通知,是 PIO 中断机制的核心操作指令。
  • SET:设置映射 GPIO 指令
    • ​功能:​直接设置指定 GPIO 引脚的电平状态(高电平 / 低电平),或配置 GPIO 的映射模式(输入 / 输出 / 设置 / 侧置),操作的 GPIO 为状态机已映射的引脚。
    • ​用途:​实现对 GPIO 引脚的快速电平控制,适用于简单的输出操作或 GPIO 模式配置。

1.PIO 的控制流

PIO 状态机的核心特征之一是​指令执行的时序确定性​,这一特征由其固定的控制流机制保障。状态机的指令执行流程遵循严格的时钟周期规则,且支持灵活的指令获取与执行方式,具体机制如下。

1.1 状态机的指令执行周期

每个 PIO 状态机在每个系统时钟周期内,会完成一条 pioasm 汇编指令的获取、解码、执行三个阶段(这三个阶段在单个时钟周期内完成,无流水线延迟)。仅有特殊指令(如 WAIT 指令,需等待条件满足后才能继续执行)会打破这一规则,使状态机暂停执行。

为了实现周期精确的程序编写,PIO 指令还支持插入延迟周期:在执行下一条指令之前,可人为配置插入 1~31 个额外的时钟周期延迟。这种延迟配置是指令级的,能精准匹配外部设备的时序要求(如串行通信的时钟节拍、外设的响应时间等)。

1.2 程序计数器(PC)的工作机制

程序计数器(PC)是状态机控制指令执行顺序的核心组件,其工作逻辑为:

  • 默认行为​:在正常执行流程中,PC 的值会在每个时钟周期​自动加 1​,指向指令内存中的下一条指令地址,实现指令的顺序执行。
  • 例外情况​:当执行 JMP(跳转)指令时,PC 的默认自增逻辑会被覆盖,JMP 指令会明确指定 PC 的下一个值(即下一条需要执行的指令在指令内存中的位置),实现程序的分支、循环、条件跳转等控制流逻辑。

1.3 指令的扩展获取来源

状态机执行的指令默认从 PIO 的指令内存中获取,但为了提升灵活性,PIO 还支持从以下特殊区域获取并执行指令,这些方式可实现 “指令与数据流融合” 的高级操作:

  • 特殊配置寄存器(SMx INSTR)
    • 机制:向状态机对应的 SMx INSTR 寄存器(x 为状态机编号,0~3)写入指令时,该指令会立即中断状态机当前的指令执行流程,优先执行此指令。
    • 示例:向 SMx INSTR 写入一条 JMP 指令,状态机会立刻放弃当前执行的指令序列,从 JMP 指定的地址开始执行新的指令。
    • 特点:执行优先级最高,适用于紧急的指令干预或状态机的即时重定向。
  • MOV EXEC 指令
    • 机制:通过 MOV EXEC 指令,状态机可从内部寄存器中读取并执行指令(指令以数据形式存储在寄存器中)。
    • 执行时序:MOV EXEC 指令本身的执行需要 1 个时钟周期,之后再花费 1 个时钟周期执行从寄存器中读取的目标指令。
  • OUT EXEC 指令
    • 机制:通过 OUT EXEC 指令,状态机可从输出移位寄存器(OSR)中读取并执行指令(指令以数据形式嵌入在移位寄存器的数据流中)。
    • 执行时序:与 MOV EXEC 一致,OUT EXEC 指令本身占用 1 个时钟周期,随后执行目标指令。

2.PIO 状态机内部寄存器介绍

每个状态机都拥有几个内部寄存器,这些寄存器用于保存输入或输出数据,以及循环变量等临时数据。

fd252c52-fb17-435c-84df-45d374d09afe.png

多个寄存器之间通过状态机的控制逻辑(Control Logic)实现数据流转:例如 IN 指令将 GPIO 数据移入 In Shift 后,可通过 MOV 指令将数据复制到 Scratch X 暂存;待处理完成后,再通过 MOV 指令将数据写入 Out Shift,最终由 OUT 指令输出至 GPIO,全程无需主 CPU 介入,保障了 PIO 的独立高效与时序精确性。

2.1 输出移位寄存器 OSR

699bf0e9-98a7-4172-9a01-c0c32be9bce5.png

对应输出数据流转示意图中的 Output Shift Register 模块,是状态机输出数据的暂存与处理单元,其硬件连接关系为:TX FIFO(发送 FIFO 存储器)→ OSR → 双向移位器(Shifter)→ 输出目的地(Pins Output enables 等)。

负责在 TX FIFO 与 GPIO 引脚(或可擦写寄存器等其他输出目标)之间,实现数据的存储与移位输出,单次最多支持 32 位数据并行输出;未被使用的输出数据会被双向移位器回收,避免数据丢失:

  • 数据加载​:通过 PULL 指令从 TX FIFO 中拉取数据,存储至 OSR;当 OSR 为空时,也会自动从 TX FIFO 加载数据。
  • 数据输出​:通过 OUT 指令将 OSR 中的数据输出至指定目标,单次可输出 1~32 位数据;输出完成后,OSR 会被全部填充为 0。
  • 自动加载(autopull)​:可通过配置控制逻辑块启用该功能,当输出移位计数器达到设定阈值时,状态机会自动执行 PULL 指令从 TX FIFO 加载数据。此功能无需手动执行 PULL 指令,可节省指令周期,提升数据吞吐量。

2.2 输入移位寄存器 ISR

218088b6-a2e9-4932-a275-d4a98025b0df.png

对应输入数据流转示意图中的 Input Shift Register 模块,是状态机输入数据的暂存与处理单元,其硬件连接关系为:输入源(Pins 等)→ 双向移位器(Shifter)→ ISR → RX FIFO(接收 FIFO 存储器)。

负责在 GPIO 引脚(或其他输入源)与 RX FIFO 之间,实现数据的存储与移位输入,单次最多支持 32 位数据并行输入;未被处理的输入数据会被双向移位器暂存,保障数据连续性:

  • 数据输入​:通过 IN 指令将双向移位器中的数据移入 ISR,单次可输入 1~32 位数据。
  • 数据推送​:通过 PUSH 指令将 ISR 中的数据写入 RX FIFO,供 CPU 或 DMA 读取。
  • 自动推送(autopush​​​:可通过配置控制逻辑块启用该功能,当输入移位计数器达到设定阈值时,状态机会自动执行 PUSH 指令,将 ISR 中的数据推送至 RX FIFO。

2.3 移位计数器 Shifiter

它是状态机内置的一对硬件计数器(输入移位计数器、输出移位计数器),用于跟踪 ISR 的输入数据位数与 OSR 的输出数据位数,计数范围为 0~32(包含边界值):

  • 每次执行 IN 指令,输入移位计数器会增加对应的数据位数;
  • 每次执行 OUT 指令,输出移位计数器会增加对应的数据位数;
  • 移位计数量的最大值为 32(与移位寄存器的宽度一致)。

可通过控制逻辑块配置计数器达到指定阈值时,自动触发以下操作:

  • 输出移位计数器达阈值:自动执行 OUT 指令,将 OSR 数据输出至目标;
  • 输入移位计数器达阈值:自动执行 IN 指令,将双向移位器数据移入 ISR;
  • 基于计数器条件自动执行 PUSH/PULL
    • 自动 PULL(OSR 与 TX FIFO 间):执行后输出移位计数器清零;
    • 自动 PUSH(ISR 与 RX FIFO 间):执行后输入移位计数器清零。

复位(或启用 CTRL_SM_RESTART)时:输入移位计数器清零(表示 ISR 无输入数据),输出移位计数器置为 32(表示 OSR 无输出数据):

  • MOV OSR, ...(写入 OSR 的 MOV 指令):输出移位计数器清零;
  • MOV ISR, ...(写入 ISR 的 MOV 指令):输入移位计数器清零;
  • OUT ISR, count:将输入移位计数器设置为 count

2.4 可擦写寄存器

每个状态机包含 2 个独立的 32 位通用寄存器(命名为 X、Y),无固定功能绑定,是 PIO 程序的 “临时变量载体”:

  • 作为数据操作的源 / 目标地址:支持 IN/OUT/SET/MOV 等指令的数据传输;
  • 作为分支条件的数据源:支持 JMP 等指令的条件判断。

以下为操作可擦写寄存器的示例汇编程序,在下列代码中我们生成多段高电平长脉冲信号和低电平短脉冲信号序列生成 WS2812 所需的时序信号从而控制 WS2812 LED 灯条:

.program ws2812_led 

public entry_point: 
    pull ; 用于获取输入引脚的当前状态
    set x, 23 ; 将寄存器x初始化为23,用于循环控制24个位
    
bitloop: 
    set pins, 1 ; 将输出引脚驱动为高电平
    out y, 1 [5] ; 将输出移位寄存器的1位数据输出,并写入y寄存器中
    jmp !y skip ; 根据y寄存器的值判断是否需要执行额外的延时,若y为0则跳转到skip程序
    nop [5] ; 延时5个时钟周期
    
skip: 
    set pins, 0 [5] ; 将输出引脚驱动为低电平
    jmp x-- bitloop ; 若x寄存器非0则递减,并根据x的值判断是否需要继续循环,非0则继续跳转到bitloop程序
    jmp entry_point ; 循环结束后,跳转回程序入口点

其中 public entry_point: 语句用于定义程序入口点,bitloop: 语句标签定义了位循环的起始位置:

  • 寄存器 X 的作用​:作为循环计数器,初始值 23 对应 24 位数据(WS2812 单颗灯珠的颜色数据长度),每次循环通过 x-- 递减,实现 24 次位输出的控制;
  • 寄存器 Y 的作用​:作为临时变量,存储从 OSR 移出的 1 位数据,用于 JMP 指令的条件判断(区分 0/1 对应的不同延时,匹配 WS2812 的时序要求);

代码的执行过程如下:

  1. 程序首先获取输入引脚的当前状态,从 TX FIFO 拉取灯珠数据;
  2. 然后进入位循环,通过 X 控制 24 次位循环,每次循环输出一个 bit 值(0 或 1)到 LED 灯带;
  3. 循环 24 次,完成对 24 个位的输出,通过 Y 区分位值并生成对应时序;
  4. 最后跳转回程序入口点,重复执行上述过程。

3.PIO 状态机的等待状态

PIO 状态机的指令执行通常遵循单周期完成的规则,但在特定条件下,状态机会进入​等待状态​(暂停指令执行)。等待状态是 PIO 为适配外部时序、数据交互节奏而设计的硬件行为,其触发条件、硬件表现及特殊处理机制如下。

3.1 状态机进入等待状态的触发条件

状态机暂停执行的核心原因是当前指令的执行条件未满足,具体分为以下五类场景:

  • ​WAIT 指令的延时条件未满足:​执行 WAIT 延时指令时,若预设的延时时间尚未到达(或 GPIO 引脚状态、中断标志位未满足等待条件),状态机会暂停执行,直到条件达成;
  • 阻塞型 PULL/PUSH 指令的 FIFO 状态异常:
    • 执行阻塞模式PULL 指令时,若 TX FIFO 为空(无数据可供拉取),状态机会暂停,直到 CPU/DMA 向 TX FIFO 写入数据;
    • 执行阻塞模式PUSH 指令时,若 RX FIFO 为满(无空间存储数据),状态机会暂停,直到 CPU/DMA 从 RX FIFO 读取数据;
    • PIO 的 PULL/PUSH 指令支持阻塞 / 非阻塞模式,上述为阻塞模式下的行为,非阻塞模式不会触发等待。
  • ​IRQ WAIT 指令的中断标志位未清空:​执行 IRQ WAIT 指令时,若指令中设置的 IRQ 中断标志位未被清空(中断未解除),状态机会暂停执行,直到中断标志位被清除;
  • ​自动加载(autopull)下的 OUT 指令触发等待:​启用 autopull 功能后,当 OSR 达到移位计数器的计数阈值时,状态机会触发自动 PULL 操作;若此时 TX FIFO 为空(无数据可加载),状态机会暂停,等待 CPU/DMA 向 TX FIFO 写入数据。
  • ​自动推送(autopush)下的 IN 指令触发等待:​启用 autopush 功能后,当 ISR 达到移位计数器的计数阈值时,状态机会触发自动 PUSH 操作;若此时 RX FIFO 为满(无空间存储),状态机会暂停,等待 CPU/DMA 从 RX FIFO 读取数据。

3.2 等待状态下的程序计数器(PC)行为

当状态机处于等待状态时,​程序计数器(PC)的值会保持不变​,不会执行自增或跳转操作。状态机会在每个时钟周期重新检查等待条件,若条件仍未解除,则继续暂停;若条件解除,会立即继续执行当前指令,之后恢复正常的 PC 自增或指令跳转逻辑。

3.3 侧集(Side-set)操作和侧集映射

侧集(Side-set)是 PIO 状态机的特殊 GPIO 映射方式 + 指令级操作的组合,既是 4 种 GPIO 映射方式之一,也是应对等待状态的核心同步工具。

3.4 侧集映射(硬件配置层面)

侧集映射是 PIO 的 4 种 GPIO 映射方式之一,其核心是将特定 GPIO 与状态机的指令执行流程深度绑定,是侧集操作的硬件基础:

  • ​核心定义:​预先为状态机配置 “侧集引脚”(最多 5 个 GPIO),并指定侧置信号的有效电平(高 / 低);状态机执行任意指令时,可同步输出预设侧集信号,控制对应引脚电平;
  • ​关键特性:​侧集操作与指令执行同周期完成,无额外时钟开销,实现极精准的时序控制。

ScreenShot_2026-06-08_114639_944.png

3.5 侧集操作

侧集操作是基于侧集映射的指令级行为,是侧集功能的实际落地方式:

  • 侧集引脚数:通过 PIO_SM_CONFIGside_set_bits 配置(1~5 位,对应 1~5 个侧集引脚);
  • 驱动模式:通过控制寄存器配置侧集引脚的有效电平(高 / 低)、驱动类型(推挽 / 开漏)。

3.6 侧集(Side-set)操作的特殊作用

状态机的等待状态会暂停大部分指令相关的操作,但 Side-set(侧集)操作不受等待状态的影响:

  • 侧集操作与指令绑定,无论指令是否进入等待状态,侧集操作都会在所属指令的第一个时钟周期执行;
  • 该特性的核心价值是:即使状态机暂停,仍可通过侧集操作控制指定 GPIO 引脚的电平(如通信协议的控制引脚),保证外部设备的时序同步不被中断。

侧集映射与操作的核心价值是实现指令与 GPIO 控制的无延迟绑定,尤其在等待状态下能维持外部设备的时序稳定,典型场景包括:

  • 通信协议同步​:SPI 通信中,将片选(CS)引脚配置为侧集引脚,执行 OUT 发数据时同步拉低 CS;即使 pull 指令因 TX FIFO 空等待,CS 仍保持选中,避免从设备通信异常;
  • 高速时序生成​:DPI 显示驱动中,将行同步(HSYNC)引脚设为侧集引脚,与数据输出指令同步执行,保证同步信号与数据的时序精准匹配;
  • 等待状态的状态保持​:状态机因中断等待时,通过侧集引脚输出 “忙” 信号,避免外部设备重复请求。

4.PIO 的 GPIO 引脚映射

PIO 的 GPIO 引脚映射是其与外部硬件交互的物理连接配置机制,定义了状态机如何控制、读取 GPIO 引脚的规则,是 PIO 实现外部接口功能的基础,其核心逻辑如下:

  • ​PIO 的 GPIO 控制能力:​PIO 支持对最多 32 个 GPIO 的输出电平、方向控制,以及输入电平读取;在 RP2040 硬件中,实际可映射的用户 GPIO 数量为 30 个;
  • ​每个时钟周期的 GPIO 操作限制:​在单个系统时钟周期内,每个状态机对 GPIO 的操作数量最多为 2 个,支持的操作组合包括:
    • 指令类操作​:通过 OUT/SET 指令修改 GPIO 的电平 / 方向,或通过 IN 指令读取 GPIO 电平;
    • 侧集类操作​:通过 side-set 操作修改 GPIO 的电平 / 方向;
    • 每个周期可执行 “零个、一个(指令 / 侧集二选一)、两个(指令 + 侧集)” 操作。

状态机对 GPIO 的操作范围由其 PINCTRL 寄存器控制:

  • 每个操作(OUT/SET/IN/side-set)可指定一段连续的 4 个 GPIO,通过 PINCTRL 寄存器配置该段 GPIO 的起始管脚编号;
  • 单个操作的 GPIO 覆盖范围可扩展至 PIO 块内的任意数量 GPIO(RP2040 中为 30 个用户 GPIO);
  • 不同操作(如 OUT 与 side-set)的 GPIO 范围可重叠,支持同一组 GPIO 被多种操作控制。

当多个操作在同一时钟周期对同一个 GPIO 进行写入时,PIO 会按照以下优先级规则应用操作结果:

  • ​状态机优先级:​从编号最大的状态机开始,依次应用其写入操作;
  • ​同状态机操作优先级:​同一状态机对同一 GPIO 同时执行 SET/OUT 和 side-set 操作时,side-set 操作的结果优先生效;
  • ​无写入的保持规则:​若没有任何状态机对某个 GPIO 执行写入操作,该 GPIO 的电平 / 方向保持上一个周期的状态。

实际使用中,通常会将每个状态机的输出操作映射到不同的 GPIO 组,使单个 PIO 块可同时驱动多个独立的外部接口(例如一个状态机映射 GPIO0~3 实现 UART,另一个状态机映射 GPIO4~7 实现 SPI),最大化 PIO 的硬件资源利用率。

5.PIO 的 IRQ 中断标志位

PIO 的 IRQ 中断机制是实现状态机间同步、状态机与主 CPU 通信的核心方式,其核心由 “IRQ 中断标志位” 与 “中断使能寄存器(IRQ0_INTE、IRQ1_INTE)” 组成。

PIO 的 IRQ 中断标志位是可被状态机或系统设置 / 清除的状态位,用于标识特定事件的发生,共包含 12 个标志位(对应寄存器位定义),分为三类:

  • ​SMx 标志位(x=0~3):​系统级中断标志位,由状态机或系统主动设置,用于状态机间同步或触发主 CPU 中断;
  • ​SMx_TXNFULL 标志位(x=0~3):​状态机 x 的 TX FIFO 非满标志位,当 TX FIFO 有空闲空间时触发;
  • ​SMx_RXNEMPTY 标志位(x=0~3):​状态机 x 的 RX FIFO 非空标志位,当 RX FIFO 有数据时触发。

这些标志位的状态可通过 PIO 的 INTR(中断状态寄存器)和 INTS(中断原始状态寄存器)读取。

IRQ0_INTEIRQ1_INTE 是 PIO 的中断使能配置寄存器,用于控制​哪些 IRQ 标志位可以触发中断请求​(分别对应 RP2040 的 irq0、irq1 中断线),两者结构完全一致,仅对应中断线不同。

c7d90f01-b01f-4619-971d-df31d79d7629.png

03318532-a436-4013-9a9a-28a5ae666603.png

IRQ0_INTEIRQ1_INTE 寄存器的低 12 位(Bit0~Bit11),对应 PIO 的各类 IRQ 中断标志位(包含 4 个系统级 SMx 标志位、4 个 TX FIFO 非满标志位、4 个 RX FIFO 非空标志位),高位(Bit12~Bit31)是芯片预留的保留位(无功能,不用管):

  • 使能配置​:向寄存器对应位写入 1,表示使能该标志位触发对应 irq(irq0 或 irq1);写入 0 则屏蔽该标志位的中断请求;
  • 复位状态​:寄存器所有位的复位值为 0x0,即 PIO 初始化后,所有 IRQ 标志位的中断默认处于屏蔽状态;
  • 中断触发​:当某标志位被置位,且对应使能位为 1 时,PIO 会向 RP2040 的中断控制器发送 irq0/irq1 请求,触发主 CPU 的中断处理流程。

IRQ 标志的用途主要有:

  • 状态机程序内的事件处理​:状态机可通过 IRQ 指令(设置 / 清除标志位)、WAIT 指令(等待标志位状态),实现程序内的条件执行逻辑;
  • 状态机间同步​:多个状态机可通过共享 IRQ 标志位,实现执行节奏的同步(如状态机 A 完成操作后置位标志位,状态机 B 等待该标志位后启动);
  • 与主 CPU 的通信​:通过使能标志位的中断,状态机可向主 CPU 通知事件(如 TX FIFO 空闲、RX FIFO 有数据),触发 CPU 的后续处理。

6.PIO 状态机的同步

PIO 的 4 个状态机具备并行执行、独立操作的特性,同时支持通过 IRQ 中断标志位实现精准的时钟周期级同步,这是 PIO 能同时处理多个接口或复杂时序任务的核心能力,PIO 的 4 个状态机共享指令内存,但在执行层面完全并行,多个状态机可在同一个系统时钟周期内,从指令内存中读取并执行同一条指令(或不同指令),无需互相等待:

  • 多状态机执行同一个程序:
    • 场景:需要同时驱动多个相同的外部设备(如多组 WS2812 LED 灯条、多个相同的 SPI 从设备)。
    • 优势:只需编写一份 PIO 汇编程序,多个状态机并行执行,减少程序开发工作量,保证设备控制逻辑的一致性。
  • 多状态机执行不同的程序:
    • 场景:需要同时实现多种不同的通信协议或 I/O 功能(如一个状态机实现 UART 发送、一个实现 SPI 接收、一个实现 GPIO 脉冲检测)。
    • 优势:单个 PIO 块可同时处理多个独立的 I/O 任务,最大化利用 PIO 的硬件资源,避免占用主 CPU 的算力。
  • 多状态机分工执行同一接口的不同单元:
    • 场景:复杂接口的功能拆分,将不同时序任务分配给不同状态机。
    • 示例:
      • UART 通信:一个状态机负责 TX(发送)端,另一个负责 RX(接收)端;
      • DPI 图像显示:一个状态机负责时钟 / 水平同步信号生成,另一个负责像素数据输出。
    • 优势:将复杂时序拆分为简单子任务,降低单个程序的编写难度,同时保证接口各单元的时序同步。

PIO 的状态机之间无法直接进行数据通信,但可通过 IRQ 中断标志位实现精准同步,且同步精度可达单个时钟周期,具体实现方式如下:

  • 同步的核心工具​:PIO 的 8 个 IRQ 中断标志位(系统级 SMx 标志位、FIFO 状态标志位)是状态机间的 “同步信号载体”,所有状态机均可读取、设置、清除这些标志位。
  • 同步的指令支持​:
    • IRQ 指令​:任意状态机可通过该指令设置或清除任意 IRQ 标志位(如状态机 0 完成数据发送后,置位 SM0 标志位);
    • WAIT IRQ 指令​:状态机可通过该指令等待某个 IRQ 标志位被设置或清除(如状态机 1 等待 SM0 标志位置位后,启动数据接收)。
  • 同步的实现逻辑​:通过 “状态机 A 置位 / 清除标志位 → 状态机 B 等待标志位状态变化后执行操作” 的流程,实现多个状态机的执行节奏对齐,达到时钟周期级的同步效果。
posted @ 2026-09-01 14:28  FreakStudio  阅读(4)  评论(0)    收藏  举报