Electric IMP out of memory crashing

Available mem in imp seems to be very scarce, in one of my test script I have 2 classes a few functions that read/write from SPI and already I cannot build a 512bytes array. Looks like I only have space for a 300 bytes array. Now I can probably take out some local buffers use a global one and get a 512bytes array, but the code will grow and and I’m afraid I will hit the limit very quick.
Did a small test:
imp.configure("memtest", [], []); local b=[0]; server.log("starting"); for (local i = 0; i < 4000; i++) { if (i % 100 == 0) server.log(format("i at: %d", i)); b.push(i); } server.log("done");

This simple script can alloc up to ~2000bytes before imp actually “crashes” and usually has to be powered off/on. Adding and instantiating a simple SPI class reduces this space with 200bytes. Crashing is bad enough but the available memory is even more scarier.

Are there any hopes that this limit will increase to something sensible ? Like at least 20K for user code ?

That isn’t an array of bytes: it’s an array of Squirrel objects, each of which happens to represent an integer. What you probably want is Squirrel’s “blob” class, which is represented much more efficiently: it really is an array of bytes (readable and writable in word, halfword, and byte units). A Squirrel “blob” can be directly passed to spi.write().

The available memory in an imp is still somewhat scarce, though; 20K is about as much as you could hope for, and because of fragmentation you’re much more likely to succeed in allocating (say) ten 2K blocks than one 20K one.

Peter

Squirrel documentation on the “blob” class here: http://www.squirrel-lang.org/doc/sqstdlib3.html#d0e823

I’ve just noticed that the spi.write() documentation didn’t mention blobs, sorry, fixed that now.

Here’s a simple but complete example impee which shows the use of the blob class for writing to SPI:

`// Strip of 16 WS2801 RGB LED drivers
server.log(“ledstrip starting”);

local r=0, g=0, b=0;

function timer()
{
imp.wakeup(0.01, timer);

r = (r+3) % 51000;
g = (g+11) % 51000;
b = (b+7) % 51000;

local r3 = r/100;
local g3 = g/100;
local b3 = b/100;

local r2 = (r3 > 255) ? 510-r3 : r3;
local g2 = (g3 > 255) ? 510-g3 : g3;
local b2 = (b3 > 255) ? 510-b3 : b3;

local out = blob(48);
for (local i=0; i<16; ++i) {
	out.writen(r2, 'b');
	out.writen(g2, 'b');
	out.writen(b2, 'b');
}

hardware.spi257.write(out);
// WS2801 datasheet says idle for 500us to latch
imp.sleep(0.001);

}

hardware.spi257.configure(SIMPLEX_TX, 15000); // Datasheet says max 25MHz
hardware.pin5.configure(DIGITAL_OUT);
hardware.pin5.write(0);
imp.sleep(0.01);
hardware.pin5.write(1);
hardware.configure(SPI_257);
timer();
server.log(“ledstrip started”);`

Peter

Thanks for the blob example I will have to use that to reduce footprint I guess.
There is indeed an overhead of using array class but the root issue of very small memory available remains.If you concatenate to a string there is still a small limit (strings stops to ~4000) unless there is a limitation to strings. With blob I get 16600 by using writen(n, ‘b’);

Concatenating strings involves a realloc() of memory, which will usually mean it needs to:

  • allocate a new buffer (big enough for the destination string)
  • copy the old string into the new buffer
  • free the old buffer (realloc is now complete)
  • copy the concatenated string into the end of the new buffer.

This takes a lot of memory on any system, and malloc space is always going to get fragmented.

You should be allocating your buffers (ideally as blobs) at the top of your script, then manipulating it vs creating and deleting big buffers dynamically - this reduces fragmentation significantly.

What are you trying to achieve? In the future, if you want to do things which are more memory intensive, you can push them up to a server-side vimp that has fewer memory limitations.

Indeed, I was thinking that I can only send strings with SPI but using blobs solve my issue at least temporary.