cancel
Showing results for 
Search instead for 
Did you mean: 

The Build Analyzer says my processor STM32L443CC has 64K RAM and 16K RAM2. And I am not using any RAM2. What is RAM2 and how do I use it?

KiptonM
Lead

On other processors sometimes there are keywords when defining variables to specify which memory area the variable should be stored in. Or there is a #pragma statement.

I have not seen either in the STM32 or the IDE.

I am guessing RAM2 might be a good place to put DMA transfers so the processor working in RAM does not interfere as much with the transfer. But I do not know how to access it in any case.

According to the memory map SRAM1 starts at address 0x2000 0000 and SRAM2 starts at 0x2000 C000, (it drives me crazy when different documents use different names for the same thing) which makes me think they overlap? Unless the memory map is dealing in 32-bit dwords rather than 8-bit bytes. But then I would expect to see a gap between SRAM1 and SRAM2.

I see SRAM2 can be write protected. But still nothing about how to access it.

And SRAM2 can be retained in standby mode.

In the STM32L443CC STM32L443RC and STM32443VC datasheet (DS11421 Rev 5

On page 83/220 it says CODE memory goes from 0x0000 0000 to 0x1FFF FFFF.

SRAM1 goes from 0x2000 0000 to 0x2BFF FFFF and SRAM2 is from 0x2C00 0000 to undefined from the picture but less than 0x4000 0000 where the peripherals start.

But then it shows SRAM2 also from 0x1000 0000 to 0x1000 4000. So it has two mappings? How do you know which one to use?

Still I have not seen how to access it using the IDE.

16 REPLIES 16

Looks like that is what it did using:

uint16_t kbuffer[1024] __attribute__((section(".sram2")));

After that it was just like uninitialized memory.

Thanks for the response.

gbm
Lead III

Dangerous. You did not reduce RAM size. The stack is placed at the end of RAM, so it effectively uses RAM2. The linker is unable to detect this overlap and to warn about full memory or stack overlapping your data in RAM2 cause it believes that your MCU has 64 + 16 KiB of RAM, which is not true. If you want to use RAM2 explicitly, reduce the size of main RAM in the linker script to 48 KiB.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice

Yes, that is next. For now I was just trying to make something work.

Thanks for your response.

Thanks for this. What is the purpose of "*(.sram2.*)"

Everything else I understand.

Except:

If every section starts with ". = ALIGN(4);" why is it needed at the end?

Depends on how the compiler generates objects.

The first star is all files/objects, the term in brackets is the section name the assembler/compiler outputs related to the symbol name.

You're explicitly naming via the __attribute__, but the tools can generate others within that name-space.

Remember you can have "static" names in every file that would conflict within the global name-space, so the compiler substitutes/adds file unique naming, and things like C++ add name mangling so as to differentiate functions of the same name, but working with different parameter types.

From .MAP file, showing what the filter is supposed to be capturing / corralling

...
 .text.ADC_DiscModeChannelCountConfig
                0x00000000       0x10 out/stm32f4xx_adc.o
 .text.ADC_DiscModeCmd
                0x00000000       0x12 out/stm32f4xx_adc.o
 .text.ADC_GetConversionValue
                0x00000000        0x6 out/stm32f4xx_adc.o
 .text.ADC_GetMultiModeConversionValue
                0x00000000        0xc out/stm32f4xx_adc.o
 .text.ADC_DMACmd
                0x00000000       0x12 out/stm32f4xx_adc.o
 .text.ADC_DMARequestAfterLastTransferCmd
                0x00000000       0x12 out/stm32f4xx_adc.o
 .text.ADC_MultiModeDMARequestAfterLastTransferCmd
                0x00000000       0x18 out/stm32f4xx_adc.o
 .text.ADC_InjectedChannelConfig
                0x00000000       0x54 out/stm32f4xx_adc.o
 .text.ADC_InjectedSequencerLengthConfig
                0x00000000       0x10 out/stm32f4xx_adc.o
 .text.ADC_SetInjectedOffset
                0x00000000       0x16 out/stm32f4xx_adc.o
 .text.ADC_ExternalTrigInjectedConvConfig
                0x00000000        0xc out/stm32f4xx_adc.o
 .text.ADC_ExternalTrigInjectedConvEdgeConfig
                0x00000000        0xc out/stm32f4xx_adc.o
 .text.ADC_SoftwareStartInjectedConv
                0x00000000        0xa out/stm32f4xx_adc.o
 
...
 
 .text.SystemCoreClockUpdate
                0x00000000       0x60 out/system_stm32f4xx.o
 .rodata.AHBPrescTable.7483
                0x00000000       0x10 out/system_stm32f4xx.o
 .data.SystemCoreClock
                0x00000000        0x4 out/system_stm32f4xx.o

From the .MAP, interpreting the .LD rules

.data           0x20000000      0x8b4 load address 0x08006124
                0x20000000                . = ALIGN (0x4)
                0x20000000                _sdata = .
 *(.data)
 *(.data*)
 .data.APBAHBPrescTable
                0x20000000       0x10 out/stm32f4xx_rcc.o
 .data.__fdlib_version
                0x20000010        0x1 c:/tools/gcc49_2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-s_lib_ver.o)
                0x20000010                __fdlib_version
 *fill*         0x20000011        0x7
 .data.impure_data
                0x20000018      0x428 c:/tools/gcc49_2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-impure.o)
 .data._impure_ptr
                0x20000440        0x4 c:/tools/gcc49_2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-impure.o)
                0x20000440                _impure_ptr
 .data.lconv    0x20000444       0x38 c:/tools/gcc49_2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-locale.o)
 .data.lc_ctype_charset
                0x2000047c       0x20 c:/tools/gcc49_2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-locale.o)
 .data.__mb_cur_max
                0x2000049c        0x4 c:/tools/gcc49_2014q4/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-locale.o)
                0x2000049c                __mb_cur_max
...

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

A lot of this is tool chain specific, but comes under college level "Assemblers, Compilers, Linkers, Loaders" type classes about the mechanics of these things.

Why ALIGN? well so that you meet the rules/expectations of the ARM ABI, that you don't create output that breaks when you add/remove code, and allow the linker to generate serviceable code at every invocation. Why ALIGN at the end? because it's your data structures that are likely to be oddly or variably sized, and this precludes a knock-on effect for other sections constructed by the linker later.

The linker script is a set of packaging and arrangement rules. It's very complex, and most people just cut-n-paste what they think works. I don't claim to be a GNU/GCC expert, but I understand the premise of what the end goal is here, and I can fiddle with things until they fit.

A lot of the symbols ST adds to the linker script allow it to track the placement in memory vs placement in the file/image, allowing the startup.s code to zero BSS, and copy initial state from the FLASH image to the RAM. If you add more sections, you'll need to initialize them properly. Tools like KEIL, IAR, and Arduino have the linker generate tables that startup code can unpack in a more automatic fashion.

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

Thanks for the complete explanation.

It has been over 40 years since I took a compiler class. Those neurons have not fired in a while.