I am using the Arduino GIGA R1 and am having issues with alloc and free. In the following code snippet I am trying to verify that my memory allocation of SDRAM stays within the true memory available. It is: SDRAM_START_ADDRESS and SDRAM_END_ADDRESS which are defined in the SDRAM library.
c1 = (unsigned char*)SDRAM.malloc(1);
// There is a 8 Bbye malloc overhead added to the byte size requested.
EndingAddress = (void*) (c1 + RequestedSize + 8 );
SDRAM.free(c1);
if ((int)EndingAddress < SDRAM_END_ADDRESS) {
RequestedMemoryPtrs.pHead = SDRAM.malloc(RequestedSize);
When the SDRAM.free(c1) is executed the system crashes and the red light on the back of the Arduino GIGA R1 starts flashing. If I comment out
SDRAM.free(c1);
My program works perfectly in writing to the SDRAM area. I can live with the few wasted bytes but i am wondering if there is another way to free SDRAM?
I never used that board but normally, malloc allocators place control structures before the returned pointer (e.g., ptr = block + sizeof(Header)) and you should not assume how much overhead the allocator requires or try to allocate memory.
You should trust that SDRAM.begin() initializes the allocator with the SDRAM start and end addresses and will play nice within that space.
The code is possibly wrong because it performs pointer arithmetic beyond the allocated memory (c1 + RequestedSize + 8), which is undefined behavior in C++. Once in UB territory all bets are off.
Also casting that pointer to int risks truncation or sign errors on a 32-bit system, making the comparison with SDRAM_END_ADDRESS likely invalid.
Yes the example program: Examples / Portenta_SDRAM / SDRAM_operations does run correctly. The one noticable difference between the verbose compiler outputs between my project and the example project is the following warning:
WARNING: library ArduinoGraphics claims to run on samd, renesas_uno architecture(s) and may be incompatible with your current board which runs on mbed_giga architecture(s).
Found out what was causing my board to crash. First I started with the Basic Example "ArduinoLogo" and added the SDRAM functionality. This did not crash my board. See the following:
/*
ArduinoLogo
created 17 Apr 2023
by Leonardo Cavagnis
*/
#include "Arduino_H7_Video.h"
#include "lvgl.h"
#include "ArduinoGraphics.h"
#include <SDRAM.h>
#include "img_arduinologo.h"
// Alternatively, any raw RGB565 image can be included on demand using this macro
// Online image converter: https://lvgl.io/tools/imageconverter (Output format: Binary RGB565)
/*
#define INCBIN_PREFIX
#include "incbin.h"
INCBIN(test, "/home/user/Downloads/test.bin");
*/
Arduino_H7_Video Display(800, 480, GigaDisplayShield);
//Arduino_H7_Video Display(1024, 768, USBCVideo);
Image img_arduinologo(ENCODING_RGB16, (uint8_t *) texture_raw, 300, 300);
void nonFrameBuffer() {
// Initilize SDRAM for non-framebuffer operations
// SDRAM.begin(); // is the same as SDRAM.begin(SDRAM_START_ADDRESS);
// Now we can malloc() and free() in the whole RAM space
// For example, let's create a 7MB array
uint8_t* myVeryBigArray = (uint8_t*)SDRAM.malloc(1024);
if (myVeryBigArray ==0) {
Serial.println("SDRAM myVeryBigArray did not allocate");
} else {
Serial.println("SDRAM myVeryBigArray allocated");
}
// and a small one
uint8_t* mySmallArray = (uint8_t*)SDRAM.malloc(128);
if (mySmallArray ==0) {
Serial.println("SDRAM mySmallArray did not allocate");
} else {
Serial.println("SDRAM mySmallArray allocated");
}
// and use then as usual
for (int i = 0; i<128; i++) {
myVeryBigArray[i] = i;
mySmallArray[i] = i*2;
}
// free the memory when you don't need them anymore
Serial.println("SDRAM deallocating");
SDRAM.free(myVeryBigArray);
SDRAM.free(mySmallArray);
}
void setup() {
Serial.begin(115200);
while (!Serial);
Display.begin();
Display.beginDraw();
Display.image(img_arduinologo, (Display.width() - img_arduinologo.width())/2, (Display.height() - img_arduinologo.height())/2);
Display.endDraw();
nonFrameBuffer();
Serial.println("Back from NonFrameBuffer");
}
void loop() { }
After much dissection of my program it came down to the following statement:
SDRAM.begin();
This statement was in my program and not in the working above test program. I removed the SDRAM.begin from my main program and it now does not crash.
My question is: What does the SDRAM.begin function do and what does it do if it is not there? If I put in the above test program, it does not crash it.
Thank you that is very helpful. I spent the night stewing about the SDRAM.begin() issue and I decided to do more testing and then I update my test program (provided in previous message). The Following was added to more represent my full sketch.
I am trying to clear the screen with a white background before displaying the startup logo. when the Dispaly.noStroke() statement is commented out the function call to NonFrameBuffer does return and the message is printed. If that statement is not commented out the board crashes. Is there a guide to help me write stuff to the GIGA display correctly. I went through
âžś If you are using libraries that are not meant for that platform and the library uses straight malloc() instead of SDRAM.malloc() and free() instead SDRAM.free() then it might create memory issues.
Double check if your screen library has any of that. If so you’ll have to modify the library so that it uses the SDRAM API and of course ensure those calls are made after the call to begin() ➜ if they allocate memory in the constructor you’ll have to move it out into some init() or begin() function that you’ll call from setup() after calling SDRAM.begin() (and make sure nothing is done in the constructor that requires that buffer) if you leave stuff there.
If I change the “display” library, do I move it into one of my Sketch’s tabs so it does not get automatically updated when the community updates it?
Yes, you would copy the library files inside your project, modify the include to use the double quotes instead of the <> to tell to the compiler to look for the file locally before going looking in the other standard places.