If you are wondering like me as: "how to enable SDRAM?", "which API calls to do in order to enable SDRAM?" ...
This board works a bit differently (as other boards with external SDRAM): there is nothing to call, just to set macros (at best via "Preprocessor" in "C/C++ Build" -> "Settings")
global for the entire project.
You can find my project, enabling and using the SDRAM (via command "test") here:
GitHub - tjaekel/MaaXBoard-RT_SPIder: MaaXBoard-RT SPIder framework
Enable SDRAM:
In order to enable SDRAM, define (in IDE) as macros:
XIP_BOOT_HEADER_ENABLE=1
XIP_BOOT_HEADER_DCD_ENABLE=1
Set also a macro as:
USE_SDRAM
This will enable and configure the SDRAM (see Details below, if you are interested).
Use SDRAM
Nothing is assigned (loaded) to SDRAM. You have to specify a variable which is located on SDRAM, e.g. via:
uint32_t sdRAM[1024] __attribute__((section(".data.$BOARD_SDRAM"))) = {0x11223344, 0x55667788, 0x99AABBCC};
Watch the __attribute__, which will locate this variable on the external SDRAM (and linker script will place it on SDRAM).
The beauty is:
- you can also initialize such variable on SDRAM (or assume it is "zero-initialized"):
The startup code will enable SDRAM first and then it writes the initial values to the memory (see on Details below).
Now, this variable is usable.
Remarks
The macro "USE_SDRAM" is used during the MPU configuration, as:
#ifdef USE_SDRAM
#if defined(CACHE_MODE_WRITE_THROUGH) && CACHE_MODE_WRITE_THROUGH
/* Region 9 setting: Memory with Normal type, not shareable, write trough */
MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 0, 0, ARM_MPU_REGION_SIZE_64MB);
#else
/* Region 9 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(9, 0x80000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64MB);
#endif
You have to check which "cache policy" do you want to have for SDRAM:
- regular cache or "Write-Through"?
- important, when you want to use both cores or DMAs (topic: "cache coherency")
- BTW: even the MPU is configured for 64MB - just 32MB are available (and usable) - do not access SDRAM memory beyond its size
Details (as I understand)
The SDRAM configuration is done via this "code" (looking like a data array):
const uint8_t dcd_data[] = {
If you set the macros, this array with "strange code words" becomes now active.
Otherwise, with no macros set, this data array is empty.
I understand it as this:
- this "code" in "dcd_data[]" looks like "micro-code" (or ARM CPU instruction codes) - do not touch it
- it will be placed in a certain ("well known") location in Flash Memory
- a bootloader seems to be involved on startup:
when the bootloader sees there is a "valid" data array for "dcd_data[]" - it executes it - this is done/executed before the bootloader would jump to "ResetHandler" which is the real entry point for your FW
- this "code" initializes the Memory Controller, makes the SDRAM access-able so that it can be also initialized during startup (done in ResetHandler afterwards)
So, you can have also pre-initialized data on SDRAM variables (often, on other SDKs and MCUs: SDRAM is enabled, but not initialized, still random content).
Side Effects
As I have realized (and obvious for me):
When you enable SDRAM, and you have also pre-initialized variables on SDRAM - it takes a long time until the debugger is responding:
The startup time is now increased (a lot), potentially also for non-debug (standalone) FW startups.
Bear in mind:
- enabling SDRAM
- having "non-zero" variables on SDRAM which need to be written on startup
will slow down your startup time (before system, debugger ... become responsive). "Be patient" (esp. on debug sessions).
Attention
All the pre-initialization for variables comes from the FLASH ROM:
The FLASH contains "copies" (or data structures) for the initialization for all static and global variables (incl. SDRAM).
The SDRAM size is 32MB but the HyperFlash size is way smaller (8 MB, I guess, but for code, data, ... everything "persistent" and needed to be copied on startup).
You cannot have a copy for SDRAM values not as zero for so much data sitting in FLASH - which has to be copied from FLASH to SDRAM!
"Zero-Initialized" variables should be OK (just run-time overhead during startup).
It means:
- just define variables on SDRAM which are "zero-initialized" (assuming zero as default)
- or better: assume (and write your code in a way), that SDRAM is not-initialized (having random values on power-up)
- the more "non-zero" values you want to have for SDRAM variables - the more space is allocated in FLASH (which can become too small for all the copies for data)
Other Remarks
You HAVE to use the "dcd.c" file for the MaaXBoard-RT - NOT the one provided by the SDK! (when you import an SDK example)!
The memory is a different one, the bus width is different: the original SDK "dcd.c" does NOT work on MaaXBoard-RT!
(see the User Guideline for this board)
The (external) SDRAM is not so fast as internal memory (they call it "OC...", like OnChip, or TCM which is the fastest memory in MCU you have).
The speed of the Memory Controller (talking to the SDRAM) is not so fast as the MCU Core Clock, the memory width is just 16bit
(I think), even you can do 32bit read/writes (but done in two half-cycles).
I use the SDRAM for non-real-time critical stuff, e.g. buffers for interactive UART, web-pages (and buffers for network access),
"Pico-C" interpreter code ...
Place data on SDRAM which is used by code which is not "real-time sensitive" (and never the stack, the heap for malloc - it depends ...).
And have the "cache policy" for SDRAM in mind (when you use both cores, accessing SDRAM, or using DMAs reading/writing SDRAM).