Memory allocation error at startup before first line executed

My main,py is currently 87KB (about 2250 lines) and when add just a few more lines of code, I get a MemoryError at startup, before the first line is executed (first line is print statement).

The error message on the serial terminal is:
MemoryError: memory allocation failed, allocating 362 bytes
MicroPython: v1.18-omv OpenMV: v4.3.0 HAL: v1.9.0 BOARD: OPENMV4-STM32H743

These are the imports:
import sensor, image, time
import math
import tf
import pyb
from pyb import Pin
from pyb import I2C
import gc
import micropython
from micropython import const

The STM32H7 has 2MB of flash. How can a program this small be causing a MemoryError at startup?

That’s the flash, the heap for the script is 230KB or so.

So why would a script of 87k cause a memory error before the first line is executed? What else is using the heap for the script? How can I debug this?

Perhaps it’s causing heap fragmentation, you could debug that using gc.info/free_mem etc… see the docs for the gc module functions and their output means.

Cannot get any information with gc.info because the memory error occurs before the first line of code is executed.

The memory might be running out/getting fragmented when loading and parsing the 2000+ lines script (when imported). Try removing the extra line(s) of code you added, print GC info and see if it is almost running out of memory. You could also try to cross-compile it with mpy-cross, .mpy files use less RAM when loading, if all fails, if you freeze the module in the firmware it should be static and stored in flash and executed in-place.

This is the output from Machine.info(1), gc.mem_alloc(), and gc.mem_free() before I add one more variable that causes the MemoryError at startup. There is ~114K free.

Machine.info(1):
ID=05000380:0c513731:33343838
DEVID=0x0450
REVID=0x1003
S=400000000
H=200000000
P1=100000000
P2=100000000
_etext=81f5268
_sidata=81f5270
_sdata=30000000
_edata=30000458
_sbss=30000458
_ebss=300028b4
_sstack=0
_estack=10000
_ram_start=30000000
_heap_start=300028b4
_heap_end=3003d8b4
_ram_end=3003e000
qstr:
  n_pool=5
  n_qstr=427
  n_str_data_bytes=6584
  n_total_bytes=9144
GC:
  236096 total
  121360 : 114736
  1=281 2=88 m=5406
LFS free: 2761883648 bytes
GC memory layout; from 30003e70:
00000: h=Thhh=ShThhhhShTh=h============================================
00400: ================================================================
00800: ================================================================
00c00: ================================================================
01000: ================================================================
01400: ================================================================
01800: ================================================================
01c00: ================================================================
02000: ================================================================
02400: ================================================================
02800: ================================================================
02c00: ================================================================
03000: ================================================================
03400: ================================================================
03800: ================================================================
03c00: ================================================================
04000: ================================================================
04400: ================================================================
04800: ================================================================
04c00: ================================================================
05000: ================================================================
05400: ================================================================
05800: ================================================================
05c00: ================================================================
06000: ================================================================
06400: ================================================================
06800: ================================================================
06c00: ================================================================
07000: ================================================================
07400: ================================================================
07800: ================================================================
07c00: ================================================================
08000: ================================================================
08400: ================================================================
08800: ================================================================
08c00: ================================================================
09000: ================================================================
09400: ================================================================
09800: ================================================================
09c00: ================================================================
0a000: ================================================================
0a400: ================================================================
0a800: ================================================================
0ac00: ================================================================
0b000: ================================================================
0b400: ================================================================
0b800: ================================================================
0bc00: ================================================================
0c000: ================================================================
0c400: ================================================================
0c800: ================================================================
0cc00: ================================================================
0d000: ================================================================
0d400: ================================================================
0d800: ================================================================
0dc00: ================================================================
0e000: ================================================================
0e400: ================================================================
0e800: ================================================================
0ec00: ================================================================
0f000: ================================================================
0f400: ================================================================
0f800: ================================================================
0fc00: ================================================================
10000: ================================================================
10400: ================================================================
10800: ================================================================
10c00: ================================================================
11000: ================================================================
11400: ================================================================
11800: ================================================================
11c00: ================================================================
12000: ================================================================
12400: ================================================================
12800: ================================================================
12c00: ================================================================
13000: ================================================================
13400: ================================================================
13800: ================================================================
13c00: ================================================================
14000: ================================================================
14400: ================================================================
14800: ================================================================
14c00: ================================================================
15000: =================================================BTThh.....SS...
15400: ......Shh========Sh=.........h=======.............Sh=.........Sh
15800: ..............................Sh.........Sh=Sh=SSh======hh=====.
15c00: ........S........hSShSh==........Sh==........h=h................
16000: ................Sh============...................S..............
16400: .h==========hh==========........Sh=======.......................
16800: ....................................h======h................Sh==
16c00: =============h======h........Sh=======........S........Sh=======
17000: ..............................................h=================
17400: ===.........................h=======............................
       (2 lines all free)
18000: .......................................h=======.................
18400: ...................SSh=hShSh=SS.................................
18800: .........................................................h======
18c00: h...............................................................
19000: ............................h=======............................
19400: ......h=....................................h=======............
19800: .................................................h=======.......
19c00: ................................................................
1a000: ............h=======.........h=======...........................
1a400: ...................................................h============
1a800: ============================..........................h=======..
1ac00: ................................................................
1b000: ..........................h=........Sh=======........Sh=........
1b400: ...................h=======...................................h=
1b800: =====S..........................................................
1bc00: .............................................hhh...hhh...hhh...h
1c000: hh...hhh...hh......hhhhh...hh...h.....hhhh.............h=======.
1c400: ................................................................
1c800: ......................h=======..................................
1cc00: ................................................................
1d000: .............................................h=======...........
1d400: ................................................................
1d800: h=............h======S..........................................
1dc00: ................................................h=======........
1e000: ......h=======....................h=======......................
1e400: .h=======.......................................................
1e800: ....................................................h=======....
1ec00: ........hh...h.....hhh...h.....h.....h..h.......................
       (2 lines all free)
1f800: ..............................h=................................
1fc00: ........................h======h................................
20000: ................................................................
20400: ......h=............h=======............................h=======
       (2 lines all free)
21000: ..............................h==...............................
21400: ......h======S...................................Sh==...........
21800: .................h.....hhh...h.....hh........h.........h=======.
21c00: ...........................h=...........h=......................
22000: ........................h=======................................
22400: .....................................................h=======...
22800: ...................................................h============
22c00: ================================================================
23000: ====............................................................
23400: ................................................................
23800: ...................................................h=======.....
23c00: .............................Sh=............................h===
24000: ====........SSh.................................h=...........h==
24400: =====...........................h=======........................
24800: ................................................................
24c00: ......................................................h=======..
25000: ................................................................
25400: ...................................................h======S.....
25800: ........................................................Sh......
25c00: ..hSh=......................................h======S............
26000: ..............................................................Sh
26400: =................................................Sh=............
26800: .......Sh..........Sh=.........................Sh=..............
26c00: Sh=..................................Sh=.........Sh........SSh..
27000: .........h=......................h=======.......................
27400: ....h=..........................................................
27800: ................................................................
27c00: ....h=======....................................................
28000: .......................Sh=......................................
28400: ...............Sh.........Sh=...................................
28800: ................................................................
28c00: ........................Sh=..................................Sh=
29000: .........Sh=................................................SSh.
29400: ....................h=======....................................
       (2 lines all free)
2a000: h..................................h=======.........Sh=.........
2a400: .....................Sh=..................................Sh=...
2a800: ...............................Sh=..............................
2ac00: .......Sh=................................Sh=...................
2b000: ...............Sh=..................................Sh=.........
       (4 lines all free)
2c400: .................Sh=............................................
       (2 lines all free)
2d000: ................................h====.......................h===
2d400: ====.........h........SSh.................h=....................
2d800: ................................................................
2dc00: ...............................Sh=..............................
2e000: ........................Sh=.........Sh=.........................
2e400: .........Sh=...................h=======..................Sh=....
2e800: ................................................................
2ec00: ..........................h=======..................Sh=.........
2f000: ...........................................................Sh==.
2f400: ..........................................Sh==........SSh===....
2f800: ..............................................................h=
2fc00: ................................................................
30000: ..Sh.......................................Sh=............Sh=...
30400: ...............................Sh=................Sh............
30800: ......Sh........................................................
30c00: ......Sh=............................................h=======...
31000: ................................................................
31400: .......Sh=........SSh=............h=...............Sh=..........
31800: ...................................Sh=..........................
31c00: ..............Sh=.........Sh.............................h======
32000: =.....................................Sh=...........Sh=.........
32400: Sh=.............................................................
32800: ................................................................
32c00: ..............................h.....h.....h...............hh...h
33000: .....hh=...hh=...h...............h=...hh=...h.....hhh........h=.
33400: .......hh=...h.....h....................h.....h.....hh........h=
33800: ........h=........h.....hhh...hhh.............hh...h.....h......
33c00: .........hh...h.................................................
34000: ...................hh........hh...hh=...hhh........hh...h=......
       (3 lines all free)
35000: ...............h================================================
35400: =================================h=======h======h==h===h===h===h
35800: ======h==h===h==============h===================================
35c00: ===========================================h==h===============h=
36000: ===============================h===h===h=======================h
36400: ===============h=====h=====h==h===h=============================
36800: ================================================================
36c00: =================h====h==h=======h==============================
37000: =h==================h===h====h===h===h===h====================h=
37400: =============================h=======hh=hh======================
37800: ===========================================h=h=================h
37c00: h==========hh========================hh=========================
38000: ===hh============hh====hh==hh==hh=======hh===================hh=
38400: ====hh======hh====hh==============hh=========hh====hh=hh========
38800: hh================hh=hh======hh=hh=====hh=======hh==============
38c00: ==============hh=hh=hh==hh=hh=hh=hh=hh=======hh=================
39000: =hh======hh=============================================h==h====
39400: =======================================hh========hh=hh=hh==hh===
39800: ===================hh=h.............
gc.mem_alloc():
121360
gc.mem_free():
114704
First Line of code
  UART #1 Pins: P1 = Tx, P0 = Rx
  I2C #2 Pins: P5 = SDA, P4 = SCL

Again this is irrelevant, from the dump above the heap looks fragmented. The free memory is just the total amount of free memory, it’s not necessarily contiguous, even if it’s allocating 1K it may still fail if there are no 1K free contiguous blocks. Here’s an example that shows a fragmented heap:

import gc, machine, random

l = []
while True:
    try:
        l.append('a'*random.randint(4, 8))
        l[random.randint(0, len(l)-1)] = None
    except MemoryError as e:
        print(machine.info(True))
        print("free mem:", gc.mem_free())
        print(e)
        break

Output:

....
free mem: 77232
memory allocation failed, allocating 32768 bytes

You can see even though there are 70KBs free mem it fails to alloc 32KBs.

Thanks this is helpful to understand fragmentation.

However, the memoryError I’ve encountered is occurring before execution of the first line of code. If the cause is fragmentation, why is there fragmentation before the code starts? How do I prevent fragmentation before the code starts execution?

I already answered that, maybe you missed it:

I removed a few lines to get the code to start as you suggested and shared result of that test which showed that there is plenty of memory available. Cross compiling or freezing the module in firmware would make development with OpenMV very difficult and impractical. Does this mean that 2000 lines of code is approaching the upper limit with OpenMV IDE?

To continue development with OpenMV IDE, is there a way to clean up memory fragmentation that is present before the first line of code is executed?

This has nothing to do with the OpenMV IDE and more to do with how your script allocates memory, and how MicroPython loads it (the above example is ~5 lines of code). Not sure what other fix you’re looking for, maybe if you split it into multiple modules, one imports the other, it would help if the issue is re-allocating some large MP struct used when importing. If that doesn’t work, sorry I have no fix other than mpy or frozen code.

Hi,

If you can, just move some of your code into modules and don’t have a 2k line script.

This allows the MicroPython to parse and load into RAM a section at a time. Versus all at once.

You can store the modules on your internal flash memory or SD card.

1 Like

I have 2 classes that are each using the I2C to communicate with different devices. When I move each class to its own file, they cannot access the i2c that is setup in main.py. Error is NameError: name ‘i2c’ isn’t defined.

How do I setup the i2c in main.py so it can be accessed by different classes in different files?

main.py
i2c = I2C(2, I2C.MASTER, baudrate=100000)

ADXL345.py
result = i2c.mem_read(1,self.ADDR_ADXL345,self.ADXL345_REG_DEVICE_ID,timeout=1000)

AW9523.py
result = i2c.mem_read(1,self.AW9523_ADDR,self.AW9523_REG_DEVICE_ID,timeout=1000)

Just pass the object to the two files.

Python always lookups things via the reference you pass. So, you don’t need to import a namespace or anything.

Moved code into modules and the problem persists.

Do you import i2c in both modules?