guild icon
Toit
#MALLOC Failed Re-Creating SPI Device
Thread channel in help
z3ugma
z3ugma 08/06/2025 06:26 PM
Heap report @ out of memory in primitive 8:2: ┌───────────┬──────────┬─────────────────────────────────────────────────────┐ │ Bytes │ Count │ Type │ ├───────────┼──────────┼─────────────────────────────────────────────────────┤ │ 5648 │ 513 │ heap overhead │ │ 173528 │ 467 │ untagged │ └───────────┴──────────┴─────────────────────────────────────────────────────┘ Total: 179176 bytes in 467 allocations (53%), largest free 116k, total free 152k ****************************************************************************** MALLOC_FAILED error. 0: S6d05a1.draw-test-pattern s6d05a1.toit:560:20 1: main.<block> display_new.toit:43:12 2: SmallInteger_.repeat <sdk>/core/numbers.toit:1288:3 3: main display_new.toit:42:5 ******************************************************************************
I can reliably make this memory allocation fail by commenting and uncommenting a line in this code:


main: print "initializing display..." driver := S6d05a1 bus cs 320 320 --reset=reset 5.repeat: driver.draw-test-pattern sleep --ms=600
z3ugma
z3ugma 08/06/2025 06:26 PM
...
in draw-test-pattern

draw-test-pattern: start:= Time.monotonic-us left := random 0 250 right := left + 75 top := random 0 250 bottom := top + 75 set-range_ CMD-CASET_ top bottom set-range_ CMD-RASET_ left right color := random 255 print "Color: $color" bluary := #[color, color, color, color, color, color, 0,0] chomps := #[] times := 12 times.repeat: chomps += chomp bluary device_.transfer --command=0 #[0x2C] device_ = bus_.device --cs=cs_ --frequency=6_000_000 //Here is where we shift into manually having calculated the 9-bit arrays called Chomps //Set the device back device_ = bus_.device --cs=cs_ --command-bits=1 --frequency=100_000 end := Time.monotonic-us print "Duration: $((end - start) / 1_000) ms"
z3ugma
z3ugma 08/06/2025 06:26 PM
The line that I can turn on that causes the out of memory is:

device_ = bus_.device --cs=cs_ --frequency=6_000_000
z3ugma
z3ugma 08/06/2025 06:26 PM
MALLOC_FAILED error. 0: S6d05a1.draw-test-pattern s6d05a1.toit:560:20 1: main.<block> display_new.toit:43:12 2: SmallInteger_.repeat <sdk>/core/numbers.toit:1288:3 3: main display_new.toit:42:5
z3ugma
z3ugma 08/06/2025 06:28 PM
why I need to do this:

- I need to support 3-wire SPI which uses 9-bit "bytes" that I call "chomps" <- slightly bigger than a bite
z3ugma
z3ugma 08/06/2025 06:29 PM
- the SPI primitives allow for this using the --command flag but it slows down drawing significantly vs packing my own byte arrays and using device.transfer
z3ugma
z3ugma 08/06/2025 06:29 PM
so I switch back and forth between a "convenient" spi device, where I use the --command-bits flag; and a "fast" spi device, where I insert my own command bits as needed
z3ugmaOPz3ugma
``` Heap report @ out of memory in primitive 8:2: ┌───────────┬──────────┬─────────────────────────────────────────────────────┐ │ Bytes │ Count │ Type ...
floitsch
floitsch 08/06/2025 06:31 PM
Program your microcontrollers in a fast and robust high-level language. - toitlang/toit
z3ugma
z3ugma 08/06/2025 06:32 PM
ok that fits what I am seeing where if I add in the lines that re-set device_ to a new instance of the SPI primitive then it runs OOM
floitsch
floitsch 08/06/2025 06:33 PM
Now the question is why there is an OOM error.
floitsch
floitsch 08/06/2025 06:33 PM
It looks like there is still quite a lot of free memory.
z3ugma
z3ugma 08/06/2025 06:33 PM
I mean I guess technically it's not an OOM error but a MALLOC_FAILED error.
z3ugma
z3ugma 08/06/2025 06:34 PM
so allocating memory could fail for other reasons apart from there not being enough?
z3ugma
z3ugma 08/06/2025 06:34 PM
like are SPI instances special because of DMA
floitsch
floitsch 08/06/2025 06:34 PM
I don't think DMA is relevant, but we have a separation of Toit heap, and C-heap.
floitsch
floitsch 08/06/2025 06:34 PM
Also, there could be fragmentation.
floitsch
floitsch 08/06/2025 06:35 PM
There are a few functions that help debug memory issues. I'm searching in the discord history to find them.
z3ugma
z3ugma 08/06/2025 06:36 PM
if it helps, here is what I get on a regular ESP32 instead of the past traces which have been ESP32-C6

Heap report @ out of memory in primitive 8:2: ┌───────────┬──────────┬─────────────────────────────────────────────────────┐ │ Bytes │ Count │ Type │ ├───────────┼──────────┼─────────────────────────────────────────────────────┤ │ 4112 │ 3 │ external byte array │ │ 45056 │ 13 │ toit processes │ │ 16384 │ 4 │ system 0 c6e1701e-f05b-c078-c7ca-86c80db24c59 │ │ 20480 │ 5 │ other 1 e83e33a6-0922-fccf-aef3-e6d2215dfaef │ │ 8192 │ 2 │ current 3 512c9a75-e49f-7a4b-0f71-b2f7206ac0bb │ │ 16384 │ 1 │ heap metadata │ │ 4096 │ 1 │ spare new-space │ │ 6280 │ 30 │ lwip │ │ 6224 │ 476 │ heap overhead │ │ 2192 │ 33 │ event source │ │ 7848 │ 129 │ thread/other │ │ 26400 │ 21 │ thread/spawn │ │ 50944 │ 161 │ untagged │ │ 11608 │ 50 │ wifi │ └───────────┴──────────┴─────────────────────────────────────────────────────┘ Total: 181144 bytes in 440 allocations (75%), largest free 32k, total free 58k *********************************************************** MALLOC_FAILED error. 0: S6d05a1.draw-test-pattern s6d05a1.toit:555:20 1: main.<block> display_new.toit:43:12 2: SmallInteger_.repeat <sdk>/core/numbers.toit:1288:3 3: main display_new.toit:42:5
floitsch
floitsch 08/06/2025 06:37 PM
- system.print-objects. Makes it easier to see whether there are leaks.
- esp32.memory-page-report. Makes it easier to detect fragmentation.
- esp32.dump-heap. Big fat dump of how Toit sees the memory.

And system.serial-print-heap-report prints something similar to what happens when there is an OOM.
floitsch
floitsch 08/06/2025 06:38 PM
So my suggestion is: try to run these functions when you get close to an OOM.
It might help us determine what the reason is (fragmentation, no malloc-heap, ...).
floitsch
floitsch 08/06/2025 06:39 PM
There is also the possibility, that the primitive reports the wrong error. Where it claims that there is no memory, but in reality something else is failing. This has happened in i2c, where we just assumed that a failed operation was due to OOM. iirc.(edited)
floitsch
floitsch 08/06/2025 06:40 PM
And sometimes there is memory that is independent. Like for BLE where there is "special" BLE memory. But that's unlikely to be the case here.
floitsch
floitsch 08/06/2025 06:41 PM
also: make sure to close the devices when you don't use them anymore.
floitsch
floitsch 08/06/2025 06:41 PM
The GC should get rid of them eventually, but for hw-resources an explicit close is preferred.
z3ugma
z3ugma 08/06/2025 06:43 PM
welp, adding in close did the trick.
floitsch
floitsch 08/06/2025 06:43 PM
might still mean that we are missing a finalizer.
floitsch
floitsch 08/06/2025 06:44 PM
but nice that it solved the issue.
z3ugma
z3ugma 08/06/2025 06:46 PM
here's the memory allocation after adding in the close
z3ugma
z3ugma 08/06/2025 06:48 PM
Heap report @ out of memory in primitive 8:2: ┌───────────┬──────────┬─────────────────────────────────────────────────────┐ │ Bytes │ Count │ Type │ ├───────────┼──────────┼─────────────────────────────────────────────────────┤ │ 4192 │ 12 │ external byte array │ │ 45056 │ 13 │ toit processes │ │ 16384 │ 4 │ system 0 c6e1701e-f05b-c078-c7ca-86c80db24c59 │ │ 20480 │ 5 │ other 1 e83e33a6-0922-fccf-aef3-e6d2215dfaef │ │ 8192 │ 2 │ current 12 3aa61f86-aee4-8c91-982a-f143894a47d0 │ │ 16384 │ 1 │ heap metadata │ │ 4096 │ 1 │ spare new-space │ │ 6256 │ 29 │ lwip │ │ 6368 │ 494 │ heap overhead │ │ 2192 │ 33 │ event source │ │ 8032 │ 136 │ thread/other │ │ 26400 │ 21 │ thread/spawn │ │ 50912 │ 160 │ untagged │ │ 11608 │ 50 │ wifi │ └───────────┴──────────┴─────────────────────────────────────────────────────┘ Total: 181496 bytes in 454 allocations (76%), largest free 28k, total free 58k ****************************************************************************** MALLOC_FAILED error. 0: S6d05a1.draw-test-pattern s6d05a1.toit:563:20 1: main.<block> display_new.toit:45:12 2: SmallInteger_.repeat <sdk>/core/numbers.toit:1288:3 3: main display_new.toit:43:6 ******************************************************************************
z3ugma
z3ugma 08/06/2025 06:48 PM
well now I can make it run out of memory allocation again if I try to allocate too big of a buffer to send over SPI
z3ugma
z3ugma 08/06/2025 06:49 PM
Chops array size: 576
Heap report @ out of memory in primitive 8:2:
z3ugma
z3ugma 08/06/2025 06:51 PM
@floitsch here's the new area where commenting it in or out causes the crash:

device_.close device_ = bus_.device --cs=cs_ --frequency=6_000_000 //((left - right) * (top - bottom) / 8 * 3 / times).repeat: // device_.transfer chomps

if I comment those lines back in then I get a MALLOC_FAILED. I will add in those 3 lines and try to get a file attached here
floitsch
floitsch 08/06/2025 06:52 PM
Can you try to figure what kind of memory issues we are having by using the functions mentioned above?
I will try to repro tomorrow, but more information is always welcome
👌🏻1
z3ugma
z3ugma 08/06/2025 07:08 PM
started a GH issue at https://github.com/toitlang/toit/issues/2900 so that I can attach bigger files
Continuation of a thread in Discord at https://discord.com/channels/918498540232253480/1402719429430870088 Using GH issue so I can attach longer files. I can reliably make this memory allocation fa...
👍1
floitsch
floitsch 08/07/2025 09:49 PM
Didn't have the time today, but I'm optimistic for tomorrow
36 messages in total