Pico PIO Interrupt Development: Principles, Timing & Practical Implementation
This demo uses PIO `irq()` instruction to trigger interrupts and print IRQ flags on RP2040 with MicroPython.
【Preliminary Note】The original hardware example in this article was written based on the RP2040. The actual hardware used in this hands-on demonstration features the W55RP20 as the main controller chip. The circuit logic and UF2 flashing operation principles are universally applicable, with only the main controller model differing. The original chip model mentioned in the circuit descriptions below is provided for reference purposes only.
# Python env : MicroPython v1.23.0
# -*- coding: utf-8 -*-
# @Time : 2024/7/28 上午10:32
# @Author : 李清水
# @File : main.py
# @Description : PIO类实验,在PIO程序中使用irq指令触发中断,并打印中断标志位
# ======================================== 导入相关模块 ========================================
# 导入时间相关的模块
import time
# 导入RP2040相关的模块
import rp2
# ======================================== 全局变量 ============================================
# ======================================== 功能函数 ============================================
# irq_test() 函数使用 rp2.asm_pio() 装饰器定义了一个 PIO(Programmable I/O)程序
@rp2.asm_pio()
def irq_test() -> None:
"""
定义一个用于测试中断的 PIO 程序。
Args:
None
Returns:
None
Description:
该 PIO 程序通过执行 nop 指令和触发中断来测试中断功能。
程序会依次触发状态机 0 和状态机 1 的中断,并在每次中断后插入延迟。
"""
# 标记了程序的开始位置
wrap_target()
# 4 个 nop() 无操作指令,每个指令都有 31 个时钟周期的延迟
nop() [31]
nop() [31]
nop() [31]
nop() [31]
# 触发状态机 0 的中断
irq(0)
# 4 个 nop() 无操作指令,每个指令都有 31 个时钟周期的延迟
nop() [31]
nop() [31]
nop() [31]
nop() [31]
# 触发状态机 1 的中断
irq(1)
# 标记了程序的结束位置,并返回到开始位置
wrap()
# 转为固定位数的二进制数据
def to_bin(value: int, num: int) -> str:
"""
将一个十进制数转为固定位数的二进制数。
Args:
value (int): 需要转换的十进制数。
num (int): 二进制数的固定位数。
Returns:
str: 转换后的二进制字符串。
"""
# 初始化一个空字符串 bin_chars 来存储最终的二进制数据
bin_chars = ""
# 将原始的十进制数 value 保存到一个临时变量 temp 中
temp = value
# 进行 num 次循环
for i in range(num):
# 获取 temp 除以 2 的余数,即二进制数的最后一位,转换为字符串并赋值给 bin_char
bin_char = bin(temp % 2)[-1]
# 将 temp 除以 2 (整除),得到新的值赋值给 temp
temp = temp // 2
# 将 bin_char 拼接到 bin_chars 的开头,建立正确的二进制位顺序
bin_chars = bin_char + bin_chars
# 返回转换后的二进制字符串 bin_chars,并将其转换为大写形式
return bin_chars.upper()
# ======================================== 自定义类 ============================================
# ======================================== 初始化配置 ==========================================
# 上电延时3s
time.sleep(3)
# 打印调试信息
print("FreakStudio: PIO IRQ Test")
# 设置了一个 lambda 函数作为 PIO 0 的中断处理程序。当发生 IRQ 时,该函数会打印中断标志位和中断标志位对应的二进制数(12位宽)
rp2.PIO(0).irq(lambda pio: print(pio.irq().flags(),to_bin(pio.irq().flags(),12)))
# 创建了一个状态机,将 irq_test() 函数作为程序,并设置频率为 系统时钟/2000 Hz
sm = rp2.StateMachine(0, irq_test, freq=2000)
# ======================================== 主程序 ===========================================
# 启动状态机
sm.active(1)
# 等待 5 秒
time.sleep(5)
# 停止状态机
sm.active(0)PIO0 interrupt handler section:# 设置了一个 lambda 函数作为 PIO 0 的中断处理程序。当发生 IRQ 时,该函数会打印中断标志位和中断标志位对应的二进制数(12位宽)
rp2.PIO(0).irq(lambda pio: print(pio.irq().flags(),to_bin(pio.irq().flags(),12)))pio is the parameter of the lambda function, representing the incoming PIO instance, followed by the expression part:pio. irq () gets the interrupt object of the current PIO, and. flags () is a method of this interrupt object, which returns the current interrupt flag bits;to_bin () is a custom function used to convert integers into fixed-length binary stringsPico, the remote connection is interrupted, and the data output is as follows:PIO0 's interrupt mask output register:0b001000000000, which indicates that SM1 generates an interrupt0b000100000000, which indicates that SM0 generates an interrupt