cancel
Showing results for 
Search instead for 
Did you mean: 

Initialization of RAM_D2 in STM32H743

asdfasdf
Associate II
Posted on March 09, 2018 at 18:47

Dear all,

I'm using the Nucelo-144 board with a STM32H743ZI, with the GCC+Makefile toolchain, and am trying to get the RAM in the D2 domain to work.

I generated a Makefile-project with CubeMX and added the following to the linker file:

/* used by the startup to initialize data */

_siRAM_D2 = LOADADDR(.RAM_D2.data);

/* Initialized data sections goes into RAM_D2, load LMA copy after code */

.RAM_D2.data :

{

   . = ALIGN(4);

   _sRAM_D2 = .; /* create a global symbol at data start */

   *(.RAM_D2.data) /* .data sections */

   *(.RAM_D2.data*) /* .data* sections */

   . = ALIGN(4);

   _eRAM_D2 = .; /* define a global symbol at data end */

} >RAM_D2 AT> FLASH

/* Uninitialized data section */

. = ALIGN(4);

.RAM_D2.bss (NOLOAD) :

{

   /* This is used by the startup in order to initialize the .bss secion */

   _sbss_RAM_D2 = .; /* define a global symbol at bss start */

   *(.RAM_D2.bss)

   *(.RAM_D2.bss*)

   . = ALIGN(4);

   _ebss_RAM_D2 = .; /* define a global symbol at bss end */

} >RAM_D2

.RAM_D2 : {*(.RAM_D2)} >RAM_D2 AT> FLASH

Also, to initialize .

RAM_D2.data and zero the .RAM_D2.bss segment I added the following to the startup assembly file:

/* Copy the data segment initializers from flash to RAM_D2 */

   movs r1, #0

   b LoopCopyDataInit_RAM_D2

CopyDataInit_RAM_D2:

   ldr r3, =_siRAM_D2

   ldr r3, [r3, r1]

   str r3, [r0, r1]

   adds r1, r1, #4

LoopCopyDataInit_RAM_D2:

   ldr r0, =_sRAM_D2

   ldr r3, =_eRAM_D2

   adds r2, r0, r1

   cmp r2, r3

   bcc CopyDataInit_RAM_D2

   ldr r2, =_sbss_RAM_D2

   b LoopFillZerobss_RAM_D2

/* Zero fill the bss segment. */

FillZerobss_RAM_D2:

   movs r3, #0

   str r3, [r2], #4

LoopFillZerobss_RAM_D2:

   ldr r3, = _ebss_RAM_D2

   cmp r2, r3

   bcc FillZerobss_RAM_D2

Now, everything compiles and objdump shows the sections with correct length, position and attributes, and I can place variables in the D2 RAM using __attribute__((section('.RAM_d1.data')) directives.

However, it looks like these memory regions are neither initialized (for .RAM_D2.data) nor zeroed out (for .RAM_D2.bss), that is, the initialization code in the startup assembly does not work. The interesting thing is that using exactly the same code and linker script but for the D1 and D3 RAM works perfectly fine?!

Also, I tried initializing the memory in C with the following code (only for .RAM_D2.data, .RAM_D2.bss is similar):

extern uint32_t _siRAM_D2;

extern uint32_t _sRAM_D2;

extern uint32_t _eRAM_D2;

void__initialize_data(uint32_t* flash_begin, uint32_t* data_begin, uint32_t* data_end){

   uint32_t *p = data_begin;

   while(p < data_end){

      *p++=*flash_begin++;

   }

}

In main():

__initialize_data(&_siRAM_D2,&_sRAM_D2,&_eRAM_D2);

Here the interesting thing is that when I place the call to __initialize_data immediately at the beginning of main(), it does not work, but at some later point in time (after HAL and board init) it does indeed work!

Does anyone have an idea what the problem could be here? Especially, is there a difference between the D1, D2, and D3 RAMs that could be causing this? Because, as I wrote above, everything is 100% fine for D1 and D3, just not for D2 RAM...

Thanks a lot!

Michael

1 ACCEPTED SOLUTION

Accepted Solutions
Posted on March 14, 2018 at 00:56

 ,

 ,

One of the purposes of SystemInit() in the CMSIS model is to initialize the clocks and memory subsystems BEFORE initializing the statics into them.

The GNU startup.s files don't do this, whereas Keil calls SystemInit before __main, and in this case __main is the code that initializes the statics and unpacks the load regions described by the linker before calling the user's main() function.

Having the SP in the vector table point to an uninitialized memory can be problematic too. The value in the vector table could be set to a convenient IRAM address and then changed in the early execution after clocks are brought up.

See Ibrahim's post here

https://community.st.com/0D70X000006SzASSA0

 ,
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

4 REPLIES 4
asdfasdf
Associate II
Posted on March 10, 2018 at 22:41

After some more investigation it seems that for D2 RAM one needs to initialize the clock first. Adding the following at the beginning of main does work:

__HAL_RCC_D2SRAM1_CLK_ENABLE();

__HAL_RCC_D2SRAM2_CLK_ENABLE();

__HAL_RCC_D2SRAM3_CLK_ENABLE();

__initialize_data(&_siRAM_D2, &_sRAM_D2, &_eRAM_D2);

__initialize_bss(&_sbss_RAM_D2, &_ebss_RAM_D2);

So the remaining question is: is there anything similar I have to do for D1 and D3 RAMs? I was expecting CubeMX to generate these sort of init routines for me but it seems it doesn't (why?). Also, initializing D2 RAM in the startup assembly file will not work because at that point in time the clocks aren't enabled yet. However, the CubeH7 MDMA example does it that way, am I missing something here or is that example simply wrong?

Best

Michael

Posted on March 14, 2018 at 00:56

 ,

 ,

One of the purposes of SystemInit() in the CMSIS model is to initialize the clocks and memory subsystems BEFORE initializing the statics into them.

The GNU startup.s files don't do this, whereas Keil calls SystemInit before __main, and in this case __main is the code that initializes the statics and unpacks the load regions described by the linker before calling the user's main() function.

Having the SP in the vector table point to an uninitialized memory can be problematic too. The value in the vector table could be set to a convenient IRAM address and then changed in the early execution after clocks are brought up.

See Ibrahim's post here

https://community.st.com/0D70X000006SzASSA0

 ,
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 15, 2018 at 19:21

Thanks for the clarification Clive, that makes a lot of sense! Is there a way to notify ST about these problems so that they can be fixed in future CubeMX/CubeHAL versions? I think having such a fundamental issue in all projects generated for the GNU toolchain is quite severe and should probably be addressed in a more principled way then the hacky work-around I'm doing right now...

Posted on June 20, 2018 at 08:52

Yes, the same issue realized by me:

D2 RAMs are NOT (!!) powered on/enabled during reset. You had to enable the CLK for D2 RAMs, specifically.

The 'only' problem:

if you create project and linker script which should place code, data ... on D2 RAMs - it generates entries in a table which are used by startup.s assembly code (e.g. to copy .data from flash to D2 SRAMs, or do zero-init for .bss).

But D2 is still disabled. If you just call these CLK enable function later in main() - it is too late (startup.s, ResetVector was running already before and nothing was written due to D2 was off).

It is not a problem, it is a feature (save power, enable just what you need, keep D2 down to save power ...).

Just a need to understand the system: the datasheet is pretty clear on this D2 reset/startup behavior (that it needs explicit enable is the conclusion).

You have two options:

a) add the D2 clock enable into startup.s code, before any .data, .bss is copied, initialized - very messy and ugly!

b) do not use D2 for memory which must be initialized at start-up (assuming D2 SRAM is ready when main() runs - it is NOT!!!!):

if you use D2 SRAM locations for buffers, for mem-pools, for heap (malloc), after main() was running (and you enable

D2 in main() ) - it works fine, just to bear in mind when D2 is available and that after CLK enable it will have random

content, not cleared with zeros or any startup data loaded!

You c

annot

pre-load data into D2 on reset and system start-up (during power on)

(even not with a debugger, because it will not enable D2 for you before it will release system and startup.s will run).

Change your linker script

NOT

to map .data, .bss etc. to D2.