Shellminator V3.0.1
Simple Terminal
|
When working with embedded systems, one of the most critical aspects to consider is memory usage. Unlike personal computers, these devices have very limited memory resources.
Take, for example, the good old Arduino Uno R3 —one of the most popular microcontrollers on the market even today. It has only 32KB of Flash for program storage and a mere 2KB of dynamic (RAM) memory. To make things even trickier, the AVR core inside the Uno doesn't allow direct access to program memory.
This means that even if you declare a string as const char*
, it will still be stored in dynamic memory, not in Flash. The same applies to the ESP8266. While the ESP8266 has significantly more RAM than the Uno R3, it’s still useful to have a way to store long strings (such as those used in terminal outputs) in program memory instead of consuming precious RAM.
Based on our experience, microcontrollers built on ARM Cortex cores handle this automatically. The linker takes care of placing constants in the appropriate memory sections without requiring manual intervention.
Let’s see how we can optimize terminal memory usage while keeping the same functionality as before.
The first key difference is that we declare the command tree as a global variable, but we don't populate it with command data at the time of declaration (this is due to linking constraints). However, we must know in advance how many commands we will have, as we need to define the array size.
Next, at the beginning of the initialization section, we need to manually fill each array element with the corresponding command data. The order doesn’t matter, but be extra careful with indexing errors (accidental copy-paste mistakes can shift the indices and break things).
Additionally, instead of using the systemCommand
macro, we must use systemCommand_P
. This macro is designed to work across different platforms, but this method introduces more potential issues compared to the approach described in Example 200.
We’ve also created a smart little macro that helps optimize print
and println
-style functions in a platform-independent way.
🚨 Important: This macro is generally meant to be used only inside print
and println
functions!
Let’s see how it works:
By wrapping your text inside the __CONST_TXT__
macro, you can optimize how string literals are stored and used in your program.
If everything is set up correctly, this should work just fine! Below, we’ve summarized the difference between the optimized and non-optimized versions:
Version | Program Memory Usage | Dynamic Memory Usage |
---|---|---|
Optimized | 10,502 bytes (34%) | 655 bytes (31%) |
Non-optimized | 10,338 bytes (33%) | 935 bytes (45%) |
By reducing dynamic memory usage, we free up valuable RAM, which is especially important on microcontrollers with limited resources.