0

I'm trying to implement a UART interrupt in MicroPython on an RP2040-based custom board loaded with Adafruit Feather MicroPython 1.2. While I'm aware this feature is typically available for WiPy devices, it's essential for my custom board.

I can't make hardware changes so I've initialized the UART on pins 4 (TXD) and 5 (RXD) and assigned a pin-change interrupt on RXD. My code:

import _thread
from machine import Pin, UART, I2C, mem32, Timer
from micropython import schedule
import micropython

# ... Other code ...

Serial = UART(1, baudrate=115200, tx=txPin, rx=rxPin)
rxTrig = False

def onSerial(p):
    global rxTrig
    if Serial.any():
        rxTrig = True

# ... Other code ...

def main():
    global rxTrig

    rxPin.irq(handler=onSerial, trigger=Pin.IRQ_RISING, hard=True)

onSerial is called for every rising edge on RXD and if data is available it sets rxTrig to True, which is used in a continuous while loop running on Core 1. This works seamlessly.

I implemented two nested timers which got stuck due to the infinite loop on Core 1. I suspect the timers are executing on Core 1, causing this. So I moved away from using variable rxTrig and the while loop, to use another pin-change interrupt by modifying the onSerial(p) code:

cmdPin = Pin(0, Pin.OUT)

# ... Other code ...

def onSerial(p):
    global rxTrig
    if Serial.any():
        cmdPin.on()

# ... Other code ...

def onCommand():
    # Consume the command and execute the actions
    cmdPin.off()

def main():
    cmdPin.irq(handler=onCommand, trigger=Pin.IRQ_RISING, hard=True)

The cmdPin changed its output as anticipated, but the interrupt didn't fire. How to properly implement this?

user4157124
  • 2,809
  • 13
  • 27
  • 42
Aaditya Dengle
  • 136
  • 1
  • 8
  • This seems very pretty hacky; I hope you can find a simpler way to do this, preferably without interrupts. What is the reason you need interrupts in the first place? What problem are you solving with them? – David Grayson Aug 23 '23 at 18:10
  • IMO, steering clear of infinite while loops and Serial Communication can enhance code efficiency, especially when juggling multiple timers. In Micropython, timers occupy Core-1, rendering it unusable for other loops. To maximize unused GPIOs, I repurposed GPIO0 to trigger an interrupt upon UART activity. This obviates the need for a loop monitoring UART (typically infinite). Instead, I harnessed the RXD pin interrupt for UART handling, achieving UART Interrupts. Keen on exploring alternative approaches. – Aaditya Dengle Aug 24 '23 at 05:10

1 Answers1

0

Somehow cmdPin = Pin(0, Pin.OUT) was not executing correctly. Once I restarted Thonny it started working and now I have UART with interrupt successfully on the custom RP2040 board.

mdPin = Pin(0, Pin.OUT)

# ... Other code ...

def onSerial(p):
    global rxTrig
    if Serial.any():
        cmdPin.on()

# ... Other code ...

def onCommand():
    # Consume the command and execute the actions
    cmdPin.off()

def main():
    cmdPin.irq(handler=onCommand, trigger=Pin.IRQ_RISING, hard=True)

This is the correct code.

user4157124
  • 2,809
  • 13
  • 27
  • 42
Aaditya Dengle
  • 136
  • 1
  • 8