OpenMV M7 : Memory error - how to make frozen code ?

Hi everyone,

================
Summary / TL;DR :

I have an OpenMV M7 Board. Memory allocation error. Unsure on how to produce frozen code.
Questions :

  • Can I follow methods 1 and 2 listed below for my OpenMV M7 or do I lack the correct files ?
  • If so, can I do anything about it, or is it impossible for an OpenMV M7 ?
  • Is there an option 3 ? Ideally I’d like to cross-compile my frozen code and then load it onto the board.

Answers so far :

  • => apparently it’s possible to build a frozen code-capable firmware. OpenMV M7 uses the OPENMV3 firmware version
  • => if I understand correctly, there is no way to simply load code that’s been frozen on Ubuntu on the OpenMV
  • => threading is not supported so far ; this seems to be the root cause of the memory problem

============
THE PROBLEM

I use Ubuntu 4.15.0-51-generic x86_64.
I have an OpenMV M7 Board with default firmware.
It’s barely used, mostly for running a few examples in OpenMV IDE and testing a UART-based GPS logger through minicom.

I’ve written what seems to be a pretty memory-thrifty code (see at end of post) compared to some of the imaging sample applications that seem to run fine, but when testing it, it get this error :

MemoryError: memory allocation failed, allocating 4096 bytes

I don’t know exactly why, I’ve only been working with this board for a few days. But one fix coming to mind would be to run frozen code. Even if I could use another method now, the bigger programs that will follow will require frozen code.

So far, I’ve read about 2 methods of going about it :

  1. Building and loading a new firmware : https://forums.openmv.io/viewtopic.php?p=3401#p3401
  2. Building (and loading?) a purpose-build mpy-cross binary for the STM32F765VI : GitHub - openmv/micropython: The Micro Python project

But I have a few problems :

  • Problem with method #1 : in the github firmware folder, I don’t see an OPENMV7 folder. It stops at OPENMV4. Although I don’t know if the “M7” in “OpenMV M7” means that I have to have an “OPENMV7” firmware version. Is it the case ?
  • Problem with method #2 : same thing, really. In the github board folder, I can see a few STM32F7 supported, but not the STM32F765VI. Do I need an exact match, or can I use another STM32F7 version to produce a working mpy-cross?*
  • Problem with #1 and #2 : If I understand correctly, these 2 options require flashing a new firmware onto the board, but I’m uneasy about it. I would feel much more comfortable if I could cross-compile on Ubuntu and then upload frozen code files onto the OpenMV. Is that feasible ?

========
MY CODE (nothing else after this section)

The micropyGPS.py file can be found at micropyGPS/micropyGPS.py at master · inmcm/micropyGPS · GitHub
And here is my code (could be faulty, I haven’t had the chance to really test it).
The memory exception happens when calling gpst.start() :

from micropyGPS import MicropyGPS
#import micropyGPS
from machine import UART
import _thread
#from time import time

class JwGPSThread(MicropyGPS):
    UPDATE_PERIOD_SEC = 1
    TIMEOUT_SEC = 1
    def __init__(self, uart):
        # using GMT +1 as time offset
        MicropyGPS.__init__(self, 1)
        self._running = False
        self._thread_joined = False
        self._uart = uart

    def start(self, period_sec=None):
        if period_sec is None:
            period_sec = self.UPDATE_PERIOD_SEC
        _thread.start_new_thread(self.update_loop, ())

    def stop(wait_for_join=False):
        self._running = False
        if wait_for_join:
            return self.join()
        else:
            return True

    def join(self, timeout_sec=None):
        if timeout_sec is None:
            timeout_sec = self.TIMEOUT_SEC
        start_time = time.time()
        while True:
            if time.time() > start_time + timeout_sec:
                return False
            if self._thread_joined:
                return True

    def update_loop(self, period_sec=None):
        if period_sec is None:
            period_sec = self.UPDATE_PERIOD_SEC

        self._running = True
        self._thread_joined = False
        line = ""
        while self._running:
            start_time = time.time()
            end_time = start_time + period_sec
            line = self._uart.readline().decode()
            for c in line:
                self.update(c)
            print(".", end="")
            time.sleep(end_time - time())
        self._thread_joined = True

if __name__ == "__main__":
    uart = UART(3, 9600, timeout_char=10)
    uart.init(9600, bits=8, parity=None, stop=1)

    print("jw_gps_thread main")

    gpst = JwGPSThread(uart)

    printout = False
    gpst.start()
    s = ""
    while(True):
        s = input("> ")
        if s == "q":
            break
        elif s == "h" or s == "help":
            print("q, h/help, u, p, s, tstart, tstop, tjoin, tshow")
        elif s == "p":
            printout = not printout
        elif s == "tstart":
            gpst.start()
        elif s == "tstop":
            gpst.stop()
        elif s == "tjoin":
            print("Joining... ", gpst.join())
        elif s == "tshow":
            print("LAT=",gpst.latitude)
            print("LON=",gpst.longitude)
            print("TIM=",gpst.timestamp)
        else:
            print("Unknown command")
    # end while
    gpst.stop()
    print("Joining... ", gpst.join())

The M7 is OPENMV3 board. Frozen code is built into the image (otherwise it would need RAM), so it will require a firmware flash yes. The easiest solution would be to get the H7 with more RAM (128KBs heap).

EDIT: I don’t think you’re running out of heap memory, I think it’s an issue with threads. We don’t really support the threading module if you can avoid it your code should work.

Okay I tested your code on H7 and it doesn’t run out of memory, but you’re still going to have issues with threading. I see threading is only used in the main script and not in the library, so you should be able to get this code working without threads on the M7 (maybe with frozen code) or on the H7.

Wow, thank you for replying so fast :slight_smile:
I might try to produce frozen code some time next week.
In the meantime I’ll try to do away with threads (maybe some kind of homemade scheduler) and test if it works.