External Interrupt Send

Hi!
Is there any limit on what functions can be called on an ExtInt callback? my code specifically involves sending an array over I2C on a pin getting pulled low
here’s the code:

import sensor, image, time, math, ustruct
import pyb
from pyb import UART

#if switch on:
#    enemycolor = blue
#else:
#    enemycolor = yellow

fieldwidth = 200
fieldheight = 300

blobdev = 10 # how far blobs are allowed to deviate

BLUE_REGION = (135, 220, 30, 10)
YELLOW_REGION = (135, 65, 30, 10)

blobsx = []
blobsy = []

def absloc():
    mone = tan(180-goal1())
    mtwo = tan(goal2()-180)
    return fieldheight/(mone+mtwo), ((fieldheight/(mone+mtwo)*mone)+150)

def angletoenemy():
    return atan(blob.cy(), blob.cx())

def thresholds(r,g,b, pm=20, ):
    l, a, b = image.rgb_to_lab((r, g, b))
    return ((l-pm, l+pm, a-pm, a+pm, b-pm, b+pm))

def I2CSend(out):
    text = str(out) + "\n"
    data = ustruct.pack("<%ds" % len(text), text)
    try:
        bus.send(ustruct.pack("<h", len(data)), timeout=70) # Send the len first (16-bits), original was 10000
        try:
            bus.send(data, timeout=70) # Send the data second.
            print("Sent Data!") # Only reached on no error.
        except OSError as err:
            pass # Don't care about errors - so pass.
            # Note that there are 3 possible errors. A timeout error, a general purpose error, or
            # a busy error. The error codes are 116, 5, 16 respectively for "err.arg[0]".
    except OSError as err:
        pass # Don't care about errors - so pass.
        # Note that there are 3 possible errors. A timeout error, a general purpose error, or
        # a busy error. The error codes are 116, 5, 16 respectively for "err.arg[0]".

def callback(line):
    print("line =", line)
    I2CSend([blobsx, blobsy])

bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
bus.deinit() # Fully reset I2C device...
bus = pyb.I2C(2, pyb.I2C.SLAVE, addr=0x12)
print("Waiting for Arduino...")

kancho = 0
extint = pyb.ExtInt('P7', pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_NONE, callback)

sensor.reset()                      # Reset and initialize the sensor.
sensor.set_pixformat(sensor.RGB565) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QVGA)   # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.
sensor.set_auto_exposure(True)
sensor.set_auto_whitebal(True)
sensor.set_auto_gain(True)

img = sensor.snapshot()
bluecall = img.get_statistics(roi = BLUE_REGION)
print("found the blue")
blue = [bluecall.l_mode(), bluecall.a_mode(), bluecall.b_mode()]

yellowcall = img.get_statistics(roi = YELLOW_REGION)
print("found the yellow")

LMode_Y = yellowcall.l_mode()
LMode_B = bluecall.l_mode()
AMode_Y = yellowcall.a_mode()
AMode_B = bluecall.l_mode()
BMode_Y = yellowcall.b_mode()
BMode_B = bluecall.l_mode()

yellow = [
    ((LMode_Y + blobdev), (LMode_Y - blobdev), (AMode_Y + blobdev), (AMode_Y - blobdev), (BMode_Y + blobdev), (BMode_Y - blobdev))
]

blue = [
    ((LMode_B + blobdev), (LMode_B - blobdev), (AMode_B + blobdev), (AMode_B - blobdev), (BMode_B + blobdev), (BMode_B - blobdev))
]

sensor.set_auto_exposure(False)
sensor.set_auto_whitebal(False)
sensor.set_auto_gain(False)

# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green/blue things. You may wish to tune them...
thresholds = [
    yellow[0],              # generic_red_thresholds
    blue[0],                # generic_green_thresholds
    (0, 30, 0, 64, -128, 0) # ???
]


# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are
# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the
# camera resolution. "merge=True" merges all overlapping blobs in the image.


while(True):
    blobsx = []
    blobsy = []
    clock.tick()
    img = sensor.snapshot()
    for blob in img.find_blobs(thresholds, pixels_threshold=200, area_threshold=200, merge=True): #add rotation to determine orientation
        # These values depend on the blob not being circular - otherwise they will be shaky.
        if blob.elongation() > 0.5:
            img.draw_edges(blob.min_corners(), color=(255,0,0))
            img.draw_line(blob.major_axis_line(), color=(0,255,0))
            img.draw_line(blob.minor_axis_line(), color=(0,0,255))
        # These values are stable all the time.
        img.draw_rectangle(blob.rect())
        img.draw_cross(blob.cx(), blob.cy())
        # Note - the blob rotation is unique to 0-180 only.
        img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)
        blobsx.append(blob.cx())
        blobsy.append(blob.cy())

    print(clock.fps())
    img.draw_rectangle(BLUE_REGION)
    img.draw_rectangle(YELLOW_REGION)

I run the code, and have fixed the global variable errors. However, the I2C function doesn’t seem to be calling.
Thanks!

edit: nevermind, it’s throwing uncaught MemoryError exceptions

Did you find a solution for the MemoryError exceptions? In my case I’m trying to do it for a SPI bus.
I’m stuck too to pack a ustruct in a callback.
I had to pack it outside.

You cannot allocate memory during an interrupt.

OK.
Nevertheless, it forced me to keep the interrupt very minimal. Which is what I should have firstly take care of.