made bootloader more configuration independent

bootloader only uses the _first_ 512 bytes of the DMEM; hence, DMEM size is irrelevant as long it is >= 512 bytes
This commit is contained in:
stnolting 2021-06-16 16:28:49 +02:00
parent 09dceaa0c5
commit 4314c3e500
6 changed files with 39 additions and 21 deletions

View file

@ -24,6 +24,7 @@ defined by the `hw_version_c` constant in the main VHDL package file [`rtl/core/
| Date (*dd.mm.yyyy*) | Version | Comment |
|:----------:|:-------:|:--------|
| 15.06.2021 | 1.5.6.11 | made bootloader more configuration-independent: bootloader now only uses the first 512 bytes of internal/external DMEM for runtime data - hence, the DMEM size is not further relevant as long as it greater than or equal to 512 bytes |
| 14.06.2021 | 1.5.6.10 | :sparkles: physical size of bootloader ROM (BOOTROM) is atutomatically determined during synthesis based on the size of the initialization image, max physical size is 32kB; simplified BOOTROM access check logic; added size check when using IMEM as ROM (check if application image fits); simplified linker script: _logical_ instruction address space 2GB now, no need to adapt this to hardware configuration, hardware checks if application fits into _physical_ memory size (which configured via generics) |
| 13.06.2021 | 1.5.6.9 | :warning: reworked boot configuration: removed `MEM_INT_IMEM_ROM` and `BOOTLOADER_EN` generics, replaced by single `INT_BOOTLOADER_EN` generic (type boolean): _true_ = implement processor-internal (default) bootloader, implement processor-internal IMEM (if implemented) as RAM; _false_ = boot from processor-internal IMEM implemented (if enabled) as pre-intialized ROM; reworked IMEM, DMEM and BOOTROM memory architecture; reworked image generator and generated application image files (now using unconstrained array as init images + unified array/memory types) |
| 12.06.2021 | 1.5.6.8 | :bug: fixed bug in instruction cache (cache controller might have missed resync/"clear-and-reload" requests from `fence.i` instructions); mino project/repo clean-ups |

View file

@ -243,7 +243,7 @@ These sections are defined right at the beginning of the linker script:
----
MEMORY
{
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 8*1024
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024
rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 32K : 2048M
iodev (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512
}
@ -253,23 +253,28 @@ Each memory section provides a _base address_ `ORIGIN` and a _size_ `LENGTH`. Th
fixed and must not be altered. The base addresses and sizes of the `ram` and `rom` regions correspond to the total available instruction
and data memory address space (see section <<_address_space_layout>>).
`ORIGIN` of the `ram` section has to be always identical to the processor's `dspace_base_c` hardware configuration. Additonally,
[IMPORTANT]
`ORIGIN` of the `ram` section has to be always identical to the processor's `dspace_base_c` hardware configuration. Additionally,
`ORIGIN` of the `rom` section has to be always identical to the processor's `ispace_base_c` hardware configuration.
The sizes of `ram` section has to be equal to the size of the _physical_ available data instruction memory. For example, if the processor
The sizes of `ram` section has to be equal to the size of the **physical available data instruction memory**. For example, if the processor
setup only uses processor-internal DMEM (<<_mem_int_dmem_en>> = _true_ and no external data memory attached) the `LENGTH` parameter of
this memory section has to be equal to the size configured by the <<_mem_int_dmem_size>> generic.
The sizes of `rom` section is a little bit more complicated. The default linker script configuration assumes a _maximum_ of 2GB for this
memory space which is also the default configuration of the processor's hardware instruction memory address space. This size _does not_ have
The sizes of `rom` section is a little bit more complicated. The default linker script configuration assumes a _maximum_ of 2GB _logical_
memory space, which is also the default configuration of the processor's hardware instruction memory address space. This size _does not_ have
to reflect the _actual_ physical size of the instruction memory (internal IMEM and/or processor-external memory). It just provides a maximum
limit. When uploading new executable via the bootloader, the bootloader itself checks if sufficient _physical_ instruction memory is available.
If a new executable is embedded right into the internal-IMEM the synthesis tool will check, if the configured instruction memory size
is sufficient (e.g., via the <<_mem_int_imem_size>> generic).
[NOTE]
[IMPORTANT]
The `rom` region uses a conditional assignment (via the `make_bootloader` symbol) for `ORIGIN` and `LENGTH` that is used to place
"normal executable" (i.e. for the IMEM) or "the bootloader image" to their according memories.
"normal executable" (i.e. for the IMEM) or "the bootloader image" to their according memories. +
+
The `ram` region also uses a conditional assignment (via the `make_bootloader` symbol) for `LENGTH`. When compiling the bootloader
(`make_bootloader` symbol is set) the generated bootloader will only use the _first_ 512 bytes of the data address space. This is
a fall-back to ensure the bootloader can operate independently of the actual _physical_ data memory size.
The linker maps all the regions from the compiled object files into four final sections: `.text`, `.rodata`, `.data` and `.bss`.
These four regions contain everything required for the application to run:
@ -382,8 +387,13 @@ bootloader can directly boot from the flash without any user interaction.
The bootloader is only implemented when the _INT_BOOTLOADER_EN_ generic is true and requires the
CSR access CPU extension (_CPU_EXTENSION_RISCV_Zicsr_ generic is true).
.Requirements
[IMPORTANT]
The bootloader requires the primary UART (UART0) for user interaction (_IO_UART0_EN_ generic is _true_).
The default bootloader requires the primary UART (UART0) for user interaction (_IO_UART0_EN_ generic is _true_).
Furthermore, the bootloader requires at least 512 bytes of data memory (processor-internal DMEM or external DMEM). +
+
The auto-boot feature, which is optional, requires the machine timer (MTIME; _IO_MTIME_EN_ generic is _true_)
and the SPI controller (_IO_SPI_EN_ generic is _true_) when used.
[IMPORTANT]
For the automatic boot from an SPI flash, the SPI controller has to be implemented (_IO_SPI_EN_

View file

@ -162,8 +162,8 @@ generic map (
...
----
<1> Clock frequency of `clk_i` signal in Hertz
<2> Default size of internal instruction memory: 16kB (no need to change that _now_)
<3> Default size of internal data memory: 8kB (no need to change that _now_)
<2> Default size of internal instruction memory: 16kB
<3> Default size of internal data memory: 8kB
[start=9]
. There is one generic that has to be set according to your FPGA board setup: the actual clock frequency
@ -236,15 +236,21 @@ beginning of this script you will find the `MEMORY` configuration listing the di
----
MEMORY
{
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 8*1024 # <1>
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024 # <1>
...
----
<1> Size of the data memory address space (internal/external DMEM); here 8kB
<1> Size of the data memory address space (right-most value) (internal/external DMEM); here 8kB
[start=2]
. We only need to change the `ram` section, which presents the available data address space.
If you have changed the DMEM (_MEM_INT_DMEM_SIZE_ generic) size adapt the `LENGTH` parameter of the `ram`
section (here: `8*1024`) so it is equal to your DMEM hardware configuration.
[IMPORTANT]
Make sure you only modify the _right-most_ value (here: 8*1024)! +
The "`512`" are not relevant for the application.
[start=3]
. Done! Save your changes and close the linker script.
.Advanced: Section base address and size

View file

@ -12,8 +12,8 @@ package neorv32_bootloader_image is
constant bootloader_init_image : mem32_t := (
00000000 => x"00000013",
00000001 => x"80012117",
00000002 => x"ff810113",
00000001 => x"80010117",
00000002 => x"1f810113",
00000003 => x"80010197",
00000004 => x"7f418193",
00000005 => x"00000517",
@ -981,7 +981,7 @@ package neorv32_bootloader_image is
00000967 => x"4c420a0a",
00000968 => x"203a5644",
00000969 => x"206e754a",
00000970 => x"32203331",
00000970 => x"32203631",
00000971 => x"0a313230",
00000972 => x"3a565748",
00000973 => x"00002020",

View file

@ -70,7 +70,7 @@ package neorv32_package is
-- Architecture Constants (do not modify!) ------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- native data path width - do not change!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050610"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01050611"; -- no touchy!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
constant rf_r0_is_reg_c : boolean := true; -- x0 is a *physical register* that has to be initialized to zero by the CPU

View file

@ -36,7 +36,7 @@
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
notice and this notice are preserved. */
/* modified for the NEORV32 processor by Stephan Nolting */
@ -50,18 +50,19 @@ SEARCH_DIR("/opt/riscv/riscv32-unknown-elf/lib"); SEARCH_DIR("=/opt/riscv/riscv6
/* NEORV32 memory section configuration. */
/* ************************************************************************** */
/* "ram" : data memory (int/ext DMEM) - make sure this is sync with the HW! */
/* ************************************************************************** */
/* "rom" : instruction memory (int/ext IMEM or bootloader ROM) */
/* "iodev" : peripheral/IO devices */
/* ************************************************************************** */
MEMORY
{
/* section sizes have to be a multiple of 4-bytes */
/* section base addresses and sizes have to be a multiple of 4-bytes */
/* ram section: first value of LENGTH => data memory used by bootloader (fixed!); second value of LENGTH => *physical* size of data memory */
/* adapt the right-most value to match the *total physical data memory size* of your setup */
ram (rwx) : ORIGIN = 0x80000000, LENGTH = 8*1024
ram (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 8*1024
/* rom and iodev sections should NOT be modified by the user at all! */
/* rom section: first value of ORIGIN/LENGTH => bootloader ROM; second value of ORIGIN/LENGTH => instruction memory */
/* rom section: first value of ORIGIN/LENGTH => bootloader ROM; second value of ORIGIN/LENGTH => maximum *logical* size of instruction memory */
rom (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 32K : 2048M
iodev (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512