Protenta all memory allocations

Anyone got a simple sketch that shows some memory information for the Portenta, including the SDRAM memory. I would like to be able to load up some code and see how changing where I put it changes the amount of free memory.

Anyone even know all the different types of memory on the Portenta? Does it even have EEPROM?

I don't have any exemple with me but using the linker files it should be possible to measure the remaining memory? Link for core M7 :

For the different types of memory I am "almost" sure only the STM32H7 can store so here p.135 :
https://www.st.com/resource/en/reference_manual/dm00176879-stm32h745755-and-stm32h747757-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

1 Like

That manual is some light reading :laughing: I agree the linker file, here is the active version ArduinoCore-mbed/linker_script.ld at master · arduino/ArduinoCore-mbed · GitHub should be able to be accessed using a sketch to show those values. I will dig a bit more.

Thanks for the links

Since you seem to like reading (and STM has way too many manuals :smiley: ) here https://www.st.com/resource/en/programming_manual/pm0253-stm32f7-series-and-stm32h7-series-cortexm7-processor-programming-manual-stmicroelectronics.pdf starting from page 32 (especially page 38 ) might give you an alternative to the linker. Something like checking every memory address with CMSIS functions (LDREXH for exemple), might be slow as hell but might work. I base this theory on :

Software can use the synchronization primitives to implement a semaphore as follows:

  1. Use a Load-Exclusive instruction to read from the semaphore address to check
    whether the semaphore is free.
  2. If the semaphore is free, use a Store-Exclusive to write the claim value to the
    semaphore address.
  3. If the returned status bit from step 2 indicates that the Store-Exclusive succeeded then
    the software has claimed the semaphore. However, if the Store-Exclusive failed,
    another process might have claimed the semaphore after the software performed step
    1
1 Like

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.

1 Like

I would think: bear in mind, the SDRAM is a "strongly ordered device":
If you do not setup an MPU entry for SDRAM region:

  • it does not have any cache enabled for it (slow access, esp. if SDRAM chip is not a full 32bit wide bus)

  • it does not allow to execute code on this "device" (a device can never execute code = default)

  • it is not shared, so, not possible to have a parallel/concurrent access by MCU (e.g. reads from SDRAM) and a DMA (another master, e.g. writing from peripheral to SDRAM at the same time)

You might need to add an MPU entry for SDRAM region to make it more efficient (cache-able, code-execution allowed).

I do not know what calling sdram.begin() will do, etc. also create entry in MPU (?)

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.