mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-24 06:24:17 +00:00

Add documentation for system RAM utilization in U-Boot. Signed-off-by: Neha Malcom Francis <n-francis@ti.com>
205 lines
7.1 KiB
ReStructuredText
205 lines
7.1 KiB
ReStructuredText
.. SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
Memory Management
|
|
=================
|
|
|
|
.. note::
|
|
|
|
This information is outdated and needs to be updated.
|
|
|
|
U-Boot runs in system state and uses physical addresses, i.e. the
|
|
MMU is not used either for address mapping nor for memory protection.
|
|
|
|
The available memory is mapped to fixed addresses using the
|
|
memory-controller. In this process, a contiguous block is formed for each
|
|
memory type (Flash, SDRAM, SRAM), even when it consists of several
|
|
physical-memory banks.
|
|
|
|
U-Boot is installed in XIP flash memory, or may be loaded into a lower region of
|
|
RAM by a secondary program loader (SPL). After
|
|
booting and sizing and initialising DRAM, the code relocates itself
|
|
to the upper end of DRAM. Immediately below the U-Boot code some
|
|
memory is reserved for use by malloc() [see CONFIG_SYS_MALLOC_LEN
|
|
configuration setting]. Below that, a structure with global Board-Info
|
|
data is placed, followed by the stack (growing downward).
|
|
|
|
Additionally, some exception handler code may be copied to the low 8 kB
|
|
of DRAM (0x00000000 ... 0x00001fff).
|
|
|
|
So a typical memory configuration with 16 MB of DRAM could look like
|
|
this::
|
|
|
|
0x0000 0000 Exception Vector code
|
|
:
|
|
0x0000 1fff
|
|
0x0000 2000 Free for Application Use
|
|
:
|
|
:
|
|
|
|
:
|
|
:
|
|
0x00fb ff20 Monitor Stack (Growing downward)
|
|
0x00fb ffac Board Info Data and permanent copy of global data
|
|
0x00fc 0000 Malloc Arena
|
|
:
|
|
0x00fd ffff
|
|
0x00fe 0000 RAM Copy of Monitor Code
|
|
... eventually: LCD or video framebuffer
|
|
... eventually: pRAM (Protected RAM - unchanged by reset)
|
|
0x00ff ffff [End of RAM]
|
|
|
|
System RAM Utilization in U-Boot in ARM
|
|
---------------------------------------
|
|
|
|
Let us break down the relevant parts of the execution sequence where system RAM
|
|
comes into play. Please note that these are individual pieces of the entire
|
|
boot sequence. It is not exhaustive, rather it aims to show only the pieces
|
|
where the system RAM is modified. See arch/arm/lib/crt0* to understand the
|
|
complete execution sequence.
|
|
|
|
Also note that the below sequence is not a hard and fast rule on how DRAM usage
|
|
would be and an architecture and board specific analysis is required for the
|
|
exact flow.
|
|
|
|
SPL Flow
|
|
........
|
|
|
|
#. Pre-DRAM
|
|
|
|
Prior to setting up of the DRAM, the stack, malloc is defined as below
|
|
possibly sitting on a smaller readily available memory (SRAM etc.):
|
|
|
|
.. image:: pics/spl_before_reloc.svg
|
|
:alt: contents of ready RAM before relocation in SPL
|
|
|
|
Please see CONFIG_SPL_EARLY_BSS if BSS initialization is needed prior
|
|
to entering board_init_f().
|
|
|
|
|
|
#. DRAM Initialization
|
|
|
|
This is typically triggered by board_init_f prior to relocating the stack
|
|
and the GD (optionally) to the system RAM. DRAM drivers reside in
|
|
drivers/ram/. Their probe/configuration can be done either via placing the
|
|
logic in dram_init() or wherever deemed applicable within board_init_f.
|
|
|
|
Post board_init_f, spl_relocate_stack_gd() is called to relocate the stack
|
|
and the GD to the newly initialized DRAM. If CONFIG_SPL_SYS_MALLOC_SIMPLE
|
|
is set it is also possible to use some amount of this DRAM stack as memory
|
|
pool for malloc_simple.
|
|
|
|
Both of which are an optional move at this point in the sequence. This is
|
|
still an intermediate environment.
|
|
|
|
#. Final Environment Set Up
|
|
|
|
The final environment is setup and the system RAM now looks like this:
|
|
|
|
.. image:: pics/spl_after_reloc.svg
|
|
:alt: contents of DRAM after relocation in SPL
|
|
|
|
Again stack and gd are an optional move and may still remain in the
|
|
available RAM (SRAM, locked cache etc.)
|
|
|
|
U-Boot Proper Flow
|
|
..................
|
|
|
|
TODO: this section is still under progress
|
|
|
|
#. DRAM Initialization
|
|
|
|
This follows the same as in SPL flow. In board_init_f(), a part of memory
|
|
is reserved at the end of RAM (see reserve_* functions in init_sequence_f)
|
|
|
|
#. Code Relocation
|
|
|
|
relocate_code() is called which relocates U-Boot code from the current
|
|
location into the relocation destination in system RAM. Typically it is
|
|
relocated to the upper portion of the memory. So DRAM now has:
|
|
* stack
|
|
* gd
|
|
* code
|
|
|
|
The code relocation happens to the upper portion of the memory after certain
|
|
portion of memory is reserved. This is memory that is intended to not be
|
|
"touched" by U-Boot.
|
|
|
|
#. Final Environment Set Up
|
|
|
|
At this stage we are completely running out of the system RAM with:
|
|
* stack
|
|
* gd
|
|
* code
|
|
* bss
|
|
* initialized non-const data
|
|
* initialized const data
|
|
|
|
It is better to do a complete analysis to visualize the layers the system
|
|
RAM is composed of at the end of this flow. This is entirely dependent on
|
|
CPU/SoC architecture.
|
|
|
|
Getting information about system RAM
|
|
....................................
|
|
|
|
At boot:
|
|
|
|
The prints given by announce_dram_init() and show_dram_config() come up in the
|
|
boot banner like so::
|
|
|
|
DRAM: 2 GiB (total 32 GiB)
|
|
|
|
U-Boot supports addressing upto 39-bit. To avoid trying to access higher
|
|
addresses in systems with > 39-bit addresses, U-Boot caps itself (gd->ram_size)
|
|
to the first bank. This is also inline with philosophy that U-Boot is a
|
|
bootloader and not a full-fledged operating system. The first value represents
|
|
this memory that is available for U-Boot while the "total" value represents the
|
|
total system RAM available on the device.
|
|
|
|
Getting the most basic information on how system RAM has been set up is by
|
|
running `bdinfo` at U-Boot prompt::
|
|
|
|
=> bdinfo
|
|
boot_params = 0x0000000000000000
|
|
DRAM bank = 0x0000000000000000
|
|
-> start = 0x0000000080000000
|
|
-> size = 0x0000000080000000
|
|
DRAM bank = 0x0000000000000001
|
|
-> start = 0x0000000880000000
|
|
-> size = 0x0000000780000000
|
|
flashstart = 0x0000000000000000
|
|
flashsize = 0x0000000000000000
|
|
flashoffset = 0x0000000000000000
|
|
baudrate = 115200 bps
|
|
relocaddr = 0x00000000ffec1000
|
|
reloc off = 0x000000007f6c1000
|
|
Build = 64-bit
|
|
current eth = ethernet@46000000port@1
|
|
ethaddr = 3c:e0:64:62:4b:4e
|
|
IP addr = <NULL>
|
|
fdt_blob = 0x00000000fde7df60
|
|
lmb_dump_all:
|
|
memory.count = 0x1
|
|
memory[0] [0x80000000-0xffffffff], 0x80000000 bytes flags: none
|
|
reserved.count = 0x2
|
|
reserved[0] [0x9e800000-0xabffffff], 0x0d800000 bytes flags: no-map
|
|
reserved[1] [0xfce79f50-0xffffffff], 0x031860b0 bytes flags: no-overwrite
|
|
devicetree = separate
|
|
serial addr = 0x0000000002880000
|
|
width = 0x0000000000000000
|
|
shift = 0x0000000000000002
|
|
offset = 0x0000000000000000
|
|
clock = 0x0000000002dc6c00
|
|
arch_number = 0x0000000000000000
|
|
TLB addr = 0x00000000ffff0000
|
|
irq_sp = 0x00000000fde7df50
|
|
sp start = 0x00000000fde7df50
|
|
Early malloc usage: 3288 / 8000
|
|
|
|
|
|
Here you are able to see the banks of DDR that have been set up in DRAM bank
|
|
-> start and -> size as well as the reserved memories in lmb_dump_all.
|
|
|
|
Testing Memory
|
|
--------------
|
|
|
|
Please see doc/README.memory-test
|