cancel
Showing results for 
Search instead for 
Did you mean: 

What parts of the DDR can I reserve using device tree without upsetting U-Boot?

Spamfast
Associate II

I've been trying to build-time reserve a 64KiB memory region anywhere between 0xC0000000 & 0xDFFFFFFF for the Cortex-M4 core using a device tree reserved-memory node. I've tried 0xC0000000, 0xD0000000 & 0xDFFF0000 but each time U-Boot fails either during flash programming or when trying to boot the Linux kernel.

I've managed to kludge a reservation at 0xC0000000 by changing the root memory@c0000000 node to have "reg = <0xc0010000 0x3fff0000>;" after which I can read & write the 64KiB from the M4 without crashing the running Linux kernel and use it, for example, as additional M4 heap.

However this is icky. Ideally, I'd like the flexibility to assign it to the memory-region property in the &m4_rproc node and have rproc able to load data or code into it or use it for true zero-copy shared memory between the two domains. (Unlike the provided mechanism that uses DMA to move data between SRAM & DDR.)

I have searched the ST & community wikis to no avail for more detail. At this point I'm wondering if I'm going to have to reverse-engineer why U-Boot is objecting to reserved-memory nodes below 0xE0000000.

6 REPLIES 6
Olivier GALLIEN
ST Employee

Hi @Spamfast​ ,

Reserving DDR memory to M4 is not a good path.

Please read this old post :

Reserved memory region for M4 in ddr (st.com)

Olivier

Olivier GALLIEN
In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
Spamfast
Associate II

Hi Olivier. Thanks for the reply and the pointers to previous discussion which is very useful.

However you've not actually answered my question. Is there any documentation on where I can reserve DDR without U-Boot choking? This would be useful knowledge in general. I've reverse-engineered enough so that I have discovered that I can use a reserved-memory node in low DDR if I set the U-Boot 'fdt_high' environment variable before 'run bootcmd' but again, that's something of a kludge.

Regarding my use case, I am hoping that by not using SRAM4 on the A7 side for DMA and by using the whole of the RETRAM and SRAM3 in the linker load map we won't need to use DDR but I would like to have that option as a last resort.

Regarding the extremely misleadingly named shared buffers features implemented via the rproc/OPENAMP channel, surely sharing DDR or SRAM between the M4 & A7 has got to be less of a load on the bus matrix than the M4 writing SRAM, the DMA controller copying it to DDR and the A7s reading (or vice versa)? Okay, so the CPUs aren't involved during the DMA transfer but it's still using memory and bus matrix bandwidth, not to mention the overheads of the DMA setup & interrupts.

Indeed, the caveat at the end of https://wiki.st.com/stm32mpu/wiki/How_to_exchange_data_buffers_with_the_coprocessor shows that DMA streams choke when the load gets too high whereas direct access would be self-limiting, wouldn't it?

Hi @Spamfast​ ,

I'm not an U-boot expert , but maybe I can help you.

The mapping of u-boot is based on the config files that you can find in include/configs/ and normally the one for a board STM32MP15 is stm32mp1.h.

In this file, you can see the different address that will be used by U-boot.

For instance:

#define CONFIG_SYS_SDRAM_BASE			STM32_DDR_BASE

with STM32_DDR_BASE = 0xC0000000

arch/arm/mach-stm32mp/include/mach/stm32.h:38:#define STM32_DDR_BASE			0xC0000000

In the .config of your build folder, you can find where u-boot will be loaded (CONFIG_SYS_TEXT_BASE) and the size of the u-boot environment :

CONFIG_SYS_TEXT_BASE=0xC0100000
CONFIG_SYS_MALLOC_F_LEN=0x3000
CONFIG_NR_DRAM_BANKS=1
CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0x480000
CONFIG_ENV_SECT_SIZE=0x40000

And at the end of include/configs/stm32mp1.h, you can find a part of the u-boot environment with some address that are used for some script, the splashimage or something related to the kernel:

#define CONFIG_EXTRA_ENV_SETTINGS \
	"kernel_addr_r=0xc2000000\0" \
	"fdt_addr_r=0xc4000000\0" \
	"scriptaddr=0xc4100000\0" \
	"pxefile_addr_r=0xc4200000\0" \
	"splashimage=0xc4300000\0"  \
	"ramdisk_addr_r=0xc4400000\0" \
	"altbootcmd=run bootcmd\0" \
	"env_check=if env info -p -d -q; then env save; fi\0" \
	STM32MP_BOOTCMD \
	BOOTENV \
	"boot_net_usb_start=true\0"

It doesn't answer all your questions, but it explains why u-boot crash if you try to reserve the address 0xC0000000.

Hope it help you,

Regards,

Kevin

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.
Spamfast
Associate II

Thanks for the reply Kevin.

I had actually looked at those but they don't explain why a "reserved-memory" node at 0xDFFF0000-to 0xDFFFFFFF causes U-Boot to fail claiming that it can't reserve memory for the FDT below 0xD0000000.

Nor do they explain why when I reserved memory by changing the "memory" node to exclude it, I was able to use 0xC0000000-0xC000FFFF but not when using a "reserved-memory" node.

I what have to start trawling through the U-Boot forums and raise the question there as well.

As you can probably tell, I'm fairly new to kernel/U-Boot-land. The documentation is generally more comprehensive with a bare metal threading library - and the reverse-engineering simpler! ;)

PatrickD
ST Employee

Hi,

Can you indicate

  • the OpenSTLinux version used
  • the U-Boot verison used
  • which U-Boot defconfig

At boot, the U-Boot binary is loaded at the beginning of the memory,

than it find the DDR memory size (=> board_get_usable_ram_top() )

and relocate the U-Boot binary at the END of the DDR

U-Boot let a the start of memory (up to U-Boot relocation address - alloc size - other U-Boot reseved memeory)

https://wiki.st.com/stm32mpu/wiki/U-Boot_overview#U-Boot_execution_sequence

I have information with the U-Boot command: "bdinfo", the relocation address for exmaple.

In the last U-Boot version (in OpenSTLinux v3.1) , the arch/arm/mach-stm32mp/dram_init.c::board_get_usable_ram_top()

avoids the reserved memory with lmb livrary, present in U-Boot device tree

=> The reserved memory need ot be present in U-Boot device tree

then when the U-Boot load the kernel image and the kernel device tree

the bootm command parse the LINUX device tree to chack possible conflict

with U-boot relocation added and memory address

to avoid conflict (it is linked to EFI support, activated by default)

=> The reserved memory need to be present also in LINUX device tree

accroding the decription, I assume

  • the 2 device tree (U-Boot and Linux) are not aligned on memory reserved location

or

  • the U-Boot relocation address is not correctly managed in

arch/arm/mach-stm32mp/dram_init.c::board_get_usable_ram_top()

=> you can experiment by traces in this function or hack it with :

ulong board_get_usable_ram_top(ulong total_size)

{

return 0xDFFF0000;

}

Spamfast
Associate II

Thanks for the details & pointers @Community member​ .I'll take a look.

FYI:-

We're still using ST's ecosystem v2.1.0 (dunfell-5.4) as we have drivers that have not yet been ported to kernel > 5.4. (We plan to move everything up of course but we're still in the process of getting our platform running to our satisfaction.)

The CubeMX-based TF-A, U-Boot & kernel device trees are aligned by means of common include dtsi files. U-Boot & kernel share common memory allocation & reservation nodes.

We've not touched board_get_usable_ram_top() so it is whatever we're getting from the ecosystem.

We're using the U-Boot configs/stm32mp15_trusted_defconfig that is pulled in by the meta-st layers.