Memory Usage for T4.1

gonzales

Well-known member
Hi,
Please explain, how to work with memory on T4.1. I have one big project and suddenly I noticed, that i have very little RAM1. I started experiments on memory optimization, read about memory organization, but some things I can't explain.

I tryed to use FLASHMEM to reduce the size of the memory used, but the result was the opposite.



изображение_2024-02-01_163425455.png


изображение_2024-02-01_163551199.png


I also observe this behavior in different parts of the code, for example when using Strings, sometimes 32kB is lost.
Please, tell me how to use FLASHMEM correctly
 
You must be changing more than that, the overall size of the code (the number on the FLASH line) is growing by nearly 4 times.
 
Well you started off saying you had very little RAM1, but the first screenshot shows you actually have quite a lot...
 
This is example. I clean all code from setup and loop section. After it i uncomment few strings in setup section and then make 1st screenshot. After it i add FLASHMEM and make 2nd screenshot.
Full project now is on 3rd screenshot.
 
When asking for help, it is usually very beneficial to post your entire sketch to allow those attempting to help to be able to reproduce the problem being addressed. Without this, it is nearly impossible to provide anything of any value that is anything other than an outright guess.

In this specific case, your RAM1 "variables" went from a pre-FLASHMEM value of 29952 to a post-FLASHMEM value of 44224. This almost certainly is not an apples-to-apples comparison. Other changes have been applied over & above the simple addition of the FLASHMEM attribute.

Here's a simple test to demonstrate why it seems that other changes are influencing that results you reported:

Simple test sketch (without FLASHMEM):

Code:
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */

// Pin 13 has an LED connected on most Arduino boards.
// Pin 11 has the LED on Teensy 2.0
// Pin 6  has the LED on Teensy++ 2.0
// Pin 13 has the LED on Teensy 3.0
// give it a name:
int led = 13;

boolean toggle = false;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  blinkIt();                 // toggle the LED on/off
  delay(1000);               // wait for a second
}

void blinkIt(void) {
   toggle = !toggle;

   digitalWrite(led, toggle);
}

Build memory report (without FLASHMEM):

Code:
Memory Usage on Teensy 4.0:
  FLASH: code:8036, data:3016, headers:8400   free for files:2012164
   RAM1: variables:3456, code:6256, padding:26512   free for local variables:488064
   RAM2: variables:12416  free for malloc/new:511872

NOTE that the code consumption of RAM1 is specifically 6256.


Simple test sketch (with addition of FLASHMEM):

Code:
/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */

// Pin 13 has an LED connected on most Arduino boards.
// Pin 11 has the LED on Teensy 2.0
// Pin 6  has the LED on Teensy++ 2.0
// Pin 13 has the LED on Teensy 3.0
// give it a name:
int led = 13;

boolean toggle = false;

// the setup routine runs once when you press reset:
FLASHMEM void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
FLASHMEM void loop() {
  blinkIt();                 // toggle the LED on/off
  delay(1000);               // wait for a second
}

FLASHMEM void blinkIt(void) {
   toggle = !toggle;

   digitalWrite(led, toggle);
}

Build memory report (with addition of FLASHMEM):

Code:
Memory Usage on Teensy 4.0:
  FLASH: code:8108, data:3016, headers:8328   free for files:2012164
   RAM1: variables:3456, code:6224, padding:26544   free for local variables:488064
   RAM2: variables:12416  free for malloc/new:511872

NOTE that the code consumption of RAM1 reduced to 6224.

It is also important to note that, in spite of the reduction in RAM1 usage for code, the overall "free for local variables" value did not change. This is due to the fact that RAM1 allocation is done in 32K chunks. Until a 32K reduction in RAM1 usage is made, any changes will be expected to simply show up in the "padding" value.

Hope this helps . . . and please post your entire sketch. Without that, not much help should be expected !!

Mark J Culross
KD5RXT
 
Last edited:
Thanks a lot for your answer and examples. Of course i tried to make a little examle to reproduce the problem, but everything worked correctly, as in your example. I can`t post my big project, it is very big, with more then 30 files and many libraries. I will try to copy a pieces of code step by step to example, hope, that i will catch the problem.
 
One more question, is it possible to use RAM2 for some variables?
for example i have some struct and want to put instance of it to RAM2

Code:
struct TTuyaDevice {
  byte Type;
  String AccessKey;
  String SecretKey;
  String Category_id;
  String Device_id;
  String SubDevice_id;
  String Remote_index;
  String Key_id;
  struct TValues Values;
  //struct TEvent* Event[MAX_EVENTS] = {NULL};
  //byte EventsCount = 0;
};

TTuyaDevice* TuyaDevice[MAX_TUYA_DEVICES] = { NULL };


byte ReadTuyaDeviceJSON(String filename) {
  byte result = 1;
  byte DevNum = JTasm["ID"];
  TuyaDevice[DevNum] = new TTuyaDevice;
  TuyaDevice[DevNum]->Type = JTasm["Type"];
  String s1 = JTasm["AccessKey"];
  TuyaDevice[DevNum]->AccessKey = s1;
  String s2 = JTasm["SecretKey"];
  TuyaDevice[DevNum]->SecretKey = s2;
  String s3 = JTasm["Category_id"];
  TuyaDevice[DevNum]->Category_id = s3;
  String s4 = JTasm["Device_id"];
  TuyaDevice[DevNum]->Device_id = s4;
  String s5 = JTasm["SubDevice_id"];
  TuyaDevice[DevNum]->SubDevice_id = s5;
  String s6 = JTasm["Remote_index"];
  TuyaDevice[DevNum]->Remote_index = s6;
  String s7 = JTasm["Key_id"];
  TuyaDevice[DevNum]->Key_id = s7;

  return result;
}
 
One more question, is it possible to use RAM2 for some variables?

Yes. In fact, as written your code will mostly use RAM2. Only the table of pointers will be placed in RAM1. Use of malloc() and C++ new allocates in RAM2. So each struct TTuyaDevice instance will be in RAM2. Also consider it has 7 String objects, which are 12 or 16 bytes (depending on version of Teensyduino) and each then uses malloc() to allocate the actual character data, which uses RAM2 because malloc().
 
Thank you!!! In Arduino IDE i found the option - Optimize. I set "Smallest code" and got an additional 50KB RAM1. But I am not sure that this will not affect the work of the entire project. Please give an explanation of what this optimization includes.
 
Smallest code compiles with "-Os", so your program might run slower. Best to try benchmarks like CoreMark to see the effect. Or build timing tests into your own code if you're really concerned about performance in particular way.

It also uses a minimal C library. The main thing you lose is floating point support in printf(), but Serial.print() can still handle floats.
 
Back
Top