Is there a way to detect when ones dynamic memory has run out?

Is there a way to detect when ones dynamic memory has run out? The compiler reports the space global variables use, but that leaves the size of the heap and stack unknown. Is there a way to detect when these have run out, besides the program crashing in weird ways?

I am surprised that there is no internal mechanism that detects this failure mode and stops the program gracefully, rather than crash in unexpected ways.

What strategies are there to free dynamic memory besides storing data in PROGMEM? Would it be ok to put __attribute__((always_inline)) in front of a few smaller functions to reduce the need for dynamic memory? Any other tips and tricks you can share?

You can work out how much free memory is available using freeMemory().

The link below talks about the screen buffer being the largest consumer of memory and the idea of writing directly to the screen itself rather than buffering.

https://community.arduboy.com/t/frame-buffer-uses-almost-half-the-ram/1839

Are you using the F macro in front of any strings in your code? This always helps.

That would take more memory … thus compounding the problem! :slight_smile:

That’s because they can’t be known at compile time.

They can change at runtime based on user actions, thus figuring out the stack and heap size is equivalent to deciding whether or not a program halts, thus it’s just another form of the infamous halting problem, which means they’re undecidable.

Theoretically you can calculate the max stack size if there are no recursive functions, but if there’s a recursive function anywhere then calculating the max stack size effectively requires you to run the function and know the range of inputs that it might receive.

What is “stop gracefully” compared to “crash”?

On an embedded system your choices effectively amount to “halt” or “reset”, there’s no “close the program and return control to the OS”.

At any rate, because the stack and the heap grow into each other, you’d be running an extra check every time either grows which would seriously eat into your cycles and slow everything down. It might not be an issue on a desktop where you have gigahertz of processing speed but on an embedded system it’ll be really noticable.

Statically allocate all memory.

That might sound crazy if you’re used to desktop, but that’s actually what the vast majority of games here do.
You can’t avoid needing to grow the stack, but you can usually avoid using new/malloc.

That aside, without knowing more about your use case it’s impossible to say what techniques might help you. I could sit here and reel off a load of different techniques for saving RAM or progmem, but a lot of them probably won’t be relevant to your situation.

E.g. “use lookup tables in progmem instead of switch statements” is a situational technique that won’t be applicable to all switch statements, won’t be applicable if you aren’t using switch statements and might not even be useful if the compiler has beaten you to it (which is uncommon but does happen sometimes).

That would affect progmem usage (either for better or for worse) but in terms of RAM it would only save you the odd stack frame here and there if the function wasn’t already being inlined.

(The rule of thumb seems to be that the compiler stops inlining a function after the third time you call it, even if that’s not the ideal number.)

Are you trying to save RAM or progmem?

As @filmote said, using the frame buffer is a good tactic as long as you leave all your drawing until later.
I can confirm that trick works because I used it in Minesweeper for the EEPROM hash calculation.

There are ways to get rid of the frame buffer, but which techniques are suitable depends on what kind of game/program you’re making.

Either the link is broken or I do not have access to it.

Is there a way to make the compiler determine that?

Stop gracefully means for example not messing up the computer the Arduboy is connected to. I had cases where the program running on the Arduboy hung up my computer to which it was connected to. It appears it messed up something with the USB devices, because mouse and keyboard stopped working. That is not good if a faulty program takes down your entire development environment.

My application does some calculating and then displays a static result. I guess that means I can do without a frame buffer. I also have almost no strings. Currently at least I am not running into progmem limits.

RAM

Would love to learn more about it.

Can you elaborate what you mean by that and explain why that saves RAM? Do you mean make everything a global variable to avoid having to pass them in function calls?

Apparently yes:

That shouldn’t happen. I certainly don’t recall any cases of something like that happening before. There have been cases where the Arduboy stops being recognised, but none that I can recall that caused other devices to malfunction.

Was the program involved using normal serial communication or was it making use of the Keyboard.h library to mimic keystrokes?

The only eventuality I can think of that could cause something like that would be if the return address of a function were trampled by a heap allocation (after all, progmem can’t be overwritten so easily - it’s in a separate address space and uses flash memory instead of conventional RAM), and to mess up things on the computer’s end would imply sending a series of USB signals that were somehow faulty, a possibility which under most circumstances I would presume to be unlikely since ordinarily USB is only used to provide a serial connection, but if the Arduboy is being used to mimic a keyboard and/or mouse then the possibility of sending corrupted USB signals would possibly be amplified.

But then, I’m not an expert on how USB works or how it is manipulated in an AVR environment. If I knew more about how it works I might be able to make a better guess as to what kind of circumstances might cause such an event. It could well be easier than I’m imagining.

Strings only consume RAM if you aren’t using the F macro.
Otherwise they live happily in progmem.

(That’s assuming that by ‘string’ you don’t mean that ghastly String class Arduino cooked up.)

Probably yes, though doing away with it would require a degree of effort.

If your result is only text then you could do what old command-line only computers did by having a tile based ‘text mode’ akin to the old VGA text mode.
I.e. treat the screen as a grid of tiles and store one character per tile.
If, for example, you made use of the font that comes bundled with Arduboy2 which is (I think) 5x8, you could have 25x8 characters on screen, which is 200, so at one byte per character that would be 200 bytes instead of 1024, thus freeing up 824 bytes.

Although if you had a means to reuse the frame buffer that would net you 1024 bytes (1KB) to use, but whether or not that would be useful to you depends on the details of your ‘calculating’.

Usually the answer to conserving RAM is “shove more things into progmem”.

Dynamic allocation is any memory allocation that happens at runtime, i.e. by new/malloc.
Static allocation is any memory allocation that happens at compile time, i.e. memory that the compiler knows you will need and thus sets aside for a particular purpose.

Global variables are an example of statically allocated memory, but they are not the only example. Static member variables and static local variables are also statically allocated.

For the most part it doesn’t, it simply makes memory usage easier to gauge.
It changes the issue of “do I have enough memory?” to a compile-time problem instead of a runtime problem.

Certainly it’s possible to leverage dynamic allocation to be rid of memory when you no longer need it, but unless you’re very careful then dynamic allocation leads to its own special set of problems.

One prime example being heap fragmentation - instead of having 1KB of usable memory you end up with 512B used and 512B unusable because the heap is riddled with holes that are too small to fit the thing you want to allocate.

With static allocation there is no risk of fragmentation, hence in that respect it could be said to save memory - when all memory is allocated as early as possible it can be allocated end to end and you’re left with no gaping oddly-sized holes that can’t be filled.

That’s not really what I had in mind, but thinking about it it’s possible that could have a positive effect in some cases.

So much of optimisation is circumstantial that it’s only really viable to talk about possibilities and probabilities, and without specific details to talk only in a general sense. If what’s being done by a program is in any way exceptional it could skew matters. Even within unremarkable examples, sometimes optimisations have a knock-on effect where one can counteract another or two can be compounded because one permits another.

Thanks for the explanations. Heap fragmentation makes sense and could be an issue with my application. I will experiment with it.

During the calculation all I would want to display is some kind of progress bar so that the user has an idea of how long it will take. Isn’t there a way to directly write to the screen without a frame buffer? And how do I eliminate the frame buffer? Not call arduboy.begin();? Or do I have to use a different library?

On this page https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory (scroll down) there is a neat visualization of dynamic memory which nicely explains what happens with heap fragmentation and how it grows into the stack.

Yes, but you have to send an entire screen’s worth of data to the screen every time you want to update it, and you need some way to construct that information.

Essentially you just pipe 1KB worth of data in the screen’s native format over SPI to the screen.

In case you aren’t familiar with the native format yet:
122aae02ad9e5ec21319b177889378bb2f73c03a

Avoid any function that references Arduboy2Base::sbuffer.

I believe begin is one of those, so to avoid that you’d have to call several of the functions it calls.

I believe the assortment required would be:

arduboy.boot();
arduboy.flashlight();
arduboy.systemButtons();
arduboy.audio.begin();
arduboy.waitNoButtons();

If you’re going to scrap the RAM buffer then you can also drop down to Arduboy2Base because you won’t be using any of the printing functions that Arduboy2 provides.

(Arduboy2 essentially just adds the printing functions to Arduboy2Base, hence anyone using any custom method of printing, e.g. a separate font library, can opt to use Arduboy2Base instead.)

The best illustration of heap fragmentation that I’ve seen so far is as thus:

(From ‘Munificent’ Bob Nystrom’s Game Programming Patterns, Chapter 19 Object Pool.)

And if you want a more in-depth explanation of the ways in which RAM may be configured on AVR devices, there’s a very in-depth explanation here:

(Note it mentions brkval and malloc heap start.)

It includes this detailed (albeit less dramatic) graphic:
malloc-std

I would presume Arduino makes use of avr-libc’s implementation of malloc and that the advice provided here is still valid, but I can’t be certain. I can however be reasonably confident that this wouldn’t apply to other devices, but that’s not much of a concern because anything that has enough memory on AVR isn’t likely to run out of memory on an ARM chip or ESP chip.

Is there some example code that writes directly to the screen? I also remember reading somewhere a note that it is possible to update only parts of the screen.

The link works - not sure why you couldn’t access it.

Anyhow … in there is this nugget if you want text:

Hi

I just wanted to mention u8g2 here. Install and download directly from Arduino IDE. Arduboy is supported.
Documentation is here: https://github.com/olikraus/u8g2/wiki

U8g2 includes a sub library U8x8, which writes directly to the OLED.
U8g2 itself has a page buffer mode, which requires only 128 bytes instead of the 1024 bytes. Page mode allows setting of individual pixel, but is a little bit slower.

Oliver

This might help write straight to the screen.

There is also code in the library that shows how to write directly to the screen via SPI:

Another (often frowned upon) way to save a lot of PROGMEM and some RAM is :

1 Like

You can configure the OLED display to accept data in way that makes it a linear 1bpp 64x128 screen rotated right.

OLEDSendCMD(0x20, 0x01); // address mode, vertical
OLEDSendCMD(0xA0 | 0); // X flip

(Dunno what the Arduboy library names its display-command-sending function but command 0x20 and 0xA0 are the ones to remap the screen like a normal bitmap or not)

Makes printing text a bit more annoying but great to send entire “scanlines” made of only 8 bytes at a time.

And Command 21 (Set Column Address) can be used to update only part of the screen

I use it in Starduino Turbo to update the OLED memory as I had to free some RAM for a vertex cache the frame buffer had to take the hit.

The linked post is in the Developers category, which has a restricted membership.

You could use the Arduboy2Core class instead of Arduboy2 or Arduboy2Base. You would use function Arduboy2Core::boot() to initialise the hardware. You could then use some of the display control functions to interact directly with the display:

Arduboy2Core::blank()
Arduboy2Core::paint8Pixels()
Arduboy2Core::sendLCDCommand()

and possibly lower level functions:

Arduboy2Core::LCDCommandMode()
Arduboy2Core::LCDDataMode()
Arduboy2Core::SPItransfer()

If you needed higher level functions that are available in the Arduboy2 or Arduboy2Base classes, such as for reading the buttons, you would have to create local equivalents in your sketch. You could also create a child class that inherits Arduboy2Core and copies the required Arduboy2 and Arduboy2Base members to it.

Documentation for control of the SSD1306 display controller can be found in the datasheet:

1 Like

Thank you. This is very helpful to get me started.

With the help provided in this thread I wrote a few functions that allow one to write directly to the screen without needing the frame buffer. Hope it is helpful to some. Has freed up 1k of dynamic memory enabling me to run faster crypto algorithms which trade memory for speed.

#include <Arduboy2.h>
Arduboy2Base arduboy;
uint8_t cursor_line = 0;
uint8_t cursor_column = 0;

void paintInt(int a){
  char cstr[8];
  itoa(a, cstr, 10);
  paintString(cstr);
}
void paintString(char* c){
  while(*c) {
    paintChar(cursor_line, cursor_column, *c++);
    cursor_column += 6;
  }
}
void paintlnString(char* c){
  while(*c) {
    paintChar(cursor_line, cursor_column, *c++);
    cursor_column += 6;
  }
  cursor_column = 0;
  cursor_line++;
}
//paint a character of the 5x7 font directly to the screen without using the frame buffer
void paintChar(uint8_t line, uint8_t column, uint8_t c) {
  //set the position the character should be painted on the screen
  arduboy.sendLCDCommand(0xb0 | (line & (uint8_t)0x0f));//set line; can be 0-7
  arduboy.sendLCDCommand(0x00 | (column & (uint8_t)0x0f));//set lower nibble of column
  arduboy.sendLCDCommand(0x10 | (column>>4));//set higher nibble of column

  const uint8_t* bitmap = &Arduboy2::font5x7[c * 5];
  for (uint8_t i = 0; i < 5; i++) {
    arduboy.paint8Pixels(pgm_read_byte(bitmap++));
  }
}
3 Likes