Using SDRAM on Portenta H7 - here my hints:
You have to enable SDRAM. I do this in my code:
#include <SDRAM.h>
...
void setup() {
//initialize SDRAM, even we do not use yet
sdram.begin();
#if 0
GsdramStart = (uint8_t*)sdram.malloc((8 * 1024 * 1024)/8 - 12); //first 12 bytes are used for malloc?
#else
GsdramStart = (uint8_t*)0x60000000; //hard-coded start of SDRAM (bank 1, NOR/PSRAM)
#endif
if (GsdramStart)
strcpy((char*)GsdramStart, (const char *)"SDRAM"); //0x60000000, but string starts at 0x6000000C
//before, on 0x60000008 seems to be the allocated length
The SDRAM appears at address 0x60000000.
When you use malloc() - the first entries on SDRAM become the management structure for malloc. I do not use it, so entire SDRAM starting from 0x60000000 becomes available.
BUT:
-
you CANNOT modify and use the linker script!
Even, you would properly extend your linker script, e.g. by adding a section .SDRAM and assign code or data to be placed on .SDRAM - even it becomes compile clean - it CANNOT work:
-
the linker script would assign data or code to be located on SDRAM - ok
-
but the file 'startup.s' had to copy these data and code from flash to SDAM - missing
-
And this is NOT POSSIBLE (your code would crash!) - even adding code in startup.s to initialize SDRAM
Reason:
The linker would assign properly to move from flash to SDRAM. But the 'startup.s' does NOT have any code inside to move code and/or data from flash to SDRAM. The part to initialize also (global) variables with zero (zeroinit) is NOT in 'startup.s'.
And even you would extend the 'startup.s' file to do so, e.g. to copy from flash to SDRAM, or do the zeroinit for global variables in SDRAM - it CANNOT work:
The 'startup.s' is the very first code executed after reset. But your SDRAM is just initialized in main(), actually in setup() function. So, the SDRAM is enabled (and available) just way later. During startup the SDRAM is not enabled, not available. Just after setup() done - the SDRAM (when call the init there) becomes available.
You can only use SDRAM after this
sdram.begin()
was called, never before! Never in startup.s, never via linker.ld script etc.
You can use SDRAM like 'dynamic memory': you have to move code, data etc. yourself (in setup() or loop() function).
You have to be careful also with these issues (questions):
-
how is the MPU configures? Can I execute code on SDRAM? Is SDRAM cached or not?
(there is no code loaded to SDRAM! if cached (but just via MPU configured) - you might need 'cache maintenance' functions, e.g. when doing DMA from peripherals to SDRAM)
-
is a not-aligned access to SDRAM possible, e.g. uint32_t write/read with not word-aligned addresses? (you should never try to do unaligned access)
-
when you call some functions, e.g. ETH (network) reception or SDCARD functions, and they use a DMA (to transfer from/to driver/peripheral to/from SDRAM) - is this path possible (bus matrix)? It could be possible that a DMA to/from SDRAM is not possible (just via MCU SW, e.g. memcpy()). Check carefully if API code uses DMA to/from SDRAM and if it can work.
So, think about that SDRAM as a memory becomes only available way later, after main init code was done, never during boot and startup. So, it will never have a startup config and is not available right after boot, not during startup.
SDRAM is only available if your main program has done the initialization and only afterwards usable (whereby the content of SDRAM is uninitialized/random). You cannot trust a global variable on SDRAM is zero-initialized - you have to initialize SDRAM stuff (variables, codes) yourself, explicitly.