MicroPython中断服务程序(ISR)编写规范与最佳实践

MicroPython中断服务程序(ISR)编写规范与最佳实践

micropython MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems micropython 项目地址: https://gitcode.com/gh_mirrors/mi/micropython

中断处理基础概念

在MicroPython中,中断服务程序(ISR)是响应硬件事件(如定时器触发或引脚电平变化)而执行的Python回调函数。这些事件可能发生在程序执行的任何时刻,因此编写ISR时需要特别注意一些MicroPython特有的限制以及实时编程的通用原则。

MicroPython特有的ISR限制

紧急异常缓冲区

在ISR中发生错误时,MicroPython需要专门的缓冲区来存储错误信息。建议在所有使用中断的程序中都包含以下代码:

import micropython
micropython.alloc_emergency_exception_buf(100)

注意该缓冲区只能保存一个异常的堆栈跟踪信息,如果处理异常时又发生第二个异常,原始异常信息会被覆盖。

保持代码简洁

ISR代码应尽可能简短,只执行必须立即完成的操作:

  • 处理触发中断的硬件设备,使其准备好接收下一次中断
  • 通过更新共享数据来通知主循环中断已发生
  • 尽快返回控制权

与主程序通信

ISR通常需要通过共享数据对象与主程序通信,推荐使用:

  • 整数、bytes和bytearray对象
  • array模块中的数组(可存储多种数据类型)
  • 全局变量或通过类共享的变量

使用对象方法作为回调

MicroPython支持将对象方法作为回调函数,这种方式非常强大:

class Foo(object):
    def __init__(self, timer, led):
        self.led = led
        timer.callback(self.cb)
    
    def cb(self, tim):
        self.led.toggle()

这种方式可以实现:

  1. 单个类支持多个硬件实例
  2. 回调函数通过self访问实例数据
  3. 在多次调用间保持状态

内存分配限制

ISR中不能创建Python对象,因为:

  • MicroPython需要从堆中分配内存
  • 堆分配不可重入(中断可能发生在主程序正在分配内存时)

具体限制包括:

  • 不能使用浮点运算(浮点数是Python对象)
  • 不能向列表追加元素
  • 不能插入字典项

解决方案是使用预分配缓冲区,例如在类构造函数中创建bytearray和标志位,ISR只修改这些预分配对象的内容。

使用micropython.schedule

这个函数允许ISR将回调排队执行,此时堆未被锁定:

  • 可以创建Python对象和使用浮点数
  • 保证在主程序完成Python对象更新后执行

典型用法是处理传感器数据:ISR从硬件获取数据并启用下一次中断,然后调度回调处理数据。

实时编程通用原则

中断处理程序设计要点

  1. 执行时间:ISR应能在短且可预测的时间内完成

    • 避免循环结构
    • 最小化I/O操作(除中断设备外的设备访问)
    • 不要等待事件
  2. 中断优先级

    • 高优先级中断可以中断正在执行的ISR
    • 低优先级中断会被延迟直到当前ISR完成
  3. 共享数据问题

    • 主程序和ISR共享数据时需考虑一致性问题
    • 简单整数或字节数组通常安全
    • 复杂数据结构(如字典)可能引发问题

临界区保护

当主程序访问与ISR共享的数据时,应考虑禁用中断:

import micropython

# 禁用中断
micropython.disable_irq()

# 访问共享数据
shared_data = ...

# 重新启用中断
micropython.enable_irq()

与asyncio交互

ISR不应直接执行asyncio操作,安全的方式是使用ThreadSafeFlag:

tsf = asyncio.ThreadSafeFlag()

def isr(_):  # 中断处理程序
    tsf.set()

async def foo():
    while True:
        await tsf.wait()
        asyncio.create_task(bar())

最佳实践总结

  1. 保持ISR代码简短简单
  2. 避免内存分配(不使用列表追加、字典插入、浮点运算)
  3. 考虑使用micropython.schedule绕过限制
  4. 共享多字节数据时使用预分配bytearray
  5. 共享多个整数时考虑使用array.array
  6. 访问共享数据前禁用中断(临界区保护)
  7. 分配紧急异常缓冲区
  8. 避免在ISR中直接与asyncio交互

遵循这些原则可以编写出可靠、高效的中断处理程序,充分利用MicroPython的实时能力。

micropython MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems micropython 项目地址: https://gitcode.com/gh_mirrors/mi/micropython

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

石乾银

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值