Line 32... |
Line 32... |
|
|
The default toolchain prefix used by the project's makefiles is (can be changed in the makefiles): **`riscv32-unknown-elf`**
|
The default toolchain prefix used by the project's makefiles is (can be changed in the makefiles): **`riscv32-unknown-elf`**
|
|
|
[TIP]
|
[TIP]
|
More information regarding the toolchain (building from scratch or downloading the prebuilt ones)
|
More information regarding the toolchain (building from scratch or downloading the prebuilt ones)
|
can be found in section <<_toolchain_setup>>.
|
can be found in the user guides' section https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[Software Toolchain Setup].
|
|
|
|
|
|
|
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
Line 64... |
Line 64... |
| `neorv32_cfs.c` | `neorv32_cfs.h` | HW driver (stub)footnote:[This driver file only represents a stub, since the real CFS drivers are defined by the actual CFS implementation.] functions for the custom functions subsystem
|
| `neorv32_cfs.c` | `neorv32_cfs.h` | HW driver (stub)footnote:[This driver file only represents a stub, since the real CFS drivers are defined by the actual CFS implementation.] functions for the custom functions subsystem
|
| `neorv32_cpu.c` | `neorv32_cpu.h` | HW driver functions for the NEORV32 **CPU**
|
| `neorv32_cpu.c` | `neorv32_cpu.h` | HW driver functions for the NEORV32 **CPU**
|
| `neorv32_gpio.c` | `neorv32_gpio.h` | HW driver functions for the **GPIO**
|
| `neorv32_gpio.c` | `neorv32_gpio.h` | HW driver functions for the **GPIO**
|
| - | `neorv32_intrinsics.h` | macros for custom intrinsics/instructions
|
| - | `neorv32_intrinsics.h` | macros for custom intrinsics/instructions
|
| `neorv32_mtime.c` | `neorv32_mtime.h` | HW driver functions for the **MTIME**
|
| `neorv32_mtime.c` | `neorv32_mtime.h` | HW driver functions for the **MTIME**
|
| `neorv32_nco.c` | `neorv32_nco.h` | HW driver functions for the **NCO**
|
|
| `neorv32_neoled.c` | `neorv32_neoled.h` | HW driver functions for the **NEOLED**
|
| `neorv32_neoled.c` | `neorv32_neoled.h` | HW driver functions for the **NEOLED**
|
| `neorv32_pwm.c` | `neorv32_pwm.h` | HW driver functions for the **PWM**
|
| `neorv32_pwm.c` | `neorv32_pwm.h` | HW driver functions for the **PWM**
|
| `neorv32_rte.c` | `neorv32_rte.h` | NEORV32 **runtime environment** and helpers
|
| `neorv32_rte.c` | `neorv32_rte.h` | NEORV32 **runtime environment** and helpers
|
| `neorv32_spi.c` | `neorv32_spi.h` | HW driver functions for the **SPI**
|
| `neorv32_spi.c` | `neorv32_spi.h` | HW driver functions for the **SPI**
|
| `neorv32_trng.c` | `neorv32_trng.h` | HW driver functions for the **TRNG**
|
| `neorv32_trng.c` | `neorv32_trng.h` | HW driver functions for the **TRNG**
|
Line 116... |
Line 115... |
[cols="<3,<15"]
|
[cols="<3,<15"]
|
[grid="none"]
|
[grid="none"]
|
|=======================
|
|=======================
|
| `help` | Show a short help text explaining all available targets.
|
| `help` | Show a short help text explaining all available targets.
|
| `check` | Check the compiler toolchain. You should run this target at least once after installing the toolchain.
|
| `check` | Check the compiler toolchain. You should run this target at least once after installing the toolchain.
|
| `info` | Show the makefile configuration (see next chapter).
|
| `info` | Show the makefile configuration (see section <<_configuration>>).
|
| `exe` | Compile all sources and generate application executable for upload via bootloader.
|
| `exe` | Compile all sources and generate application executable for upload via bootloader.
|
| `install` | Compile all sources, generate executable (via exe target) for upload via bootloader and generate and install IMEM VHDL initialization image file `rtl/core/neorv32_application_image.vhd`.
|
| `install` | Compile all sources, generate executable (via exe target) for upload via bootloader and generate and install IMEM VHDL initialization image file `rtl/core/neorv32_application_image.vhd`.
|
| `all` | Execute `exe` and `install`.
|
| `all` | Execute `exe` and `install`.
|
| `clean` | Remove all generated files in the current folder.
|
| `clean` | Remove all generated files in the current folder.
|
| `clean_all` | Remove all generated files in the current folder and also removes the compiled core libraries and the compiled image generator tool.
|
| `clean_all` | Remove all generated files in the current folder and also removes the compiled core libraries and the compiled image generator tool.
|
Line 211... |
Line 210... |
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
:sectnums:
|
:sectnums:
|
=== Executable Image Format
|
=== Executable Image Format
|
|
|
When all the application sources have been compiled and linked, a final executable file has to be generated.
|
In order to generate a file, which can be executed by the processor, all source files have to be compiler, linked
|
For this purpose, the makefile uses the NEORV32-specific linker script `sw/common/neorv32.ld`. This linker script defines three memory sections:
|
and packed into a final _executable_.
|
`rom`, `ram` and `iodev`. These sections have specific access attributes: Read access (`r`), write access (`w`) and executable (`x`).
|
|
|
|
.Linker memory sections
|
:sectnums:
|
|
==== Linker Script
|
|
|
|
When all the application sources have been compiled, they need to be _linked_ in order to generate a unified
|
|
program file. For this purpose the makefile uses the NEORV32-specific linker script `sw/common/neorv32.ld` for
|
|
linking all object files that were generated during compilation.
|
|
|
|
The linker script defines three memory _sections_: `rom`, `ram` and `iodev`. Each section provides specific
|
|
access _attributes_: read access (`r`), write access (`w`) and executable (`x`).
|
|
|
|
.Linker memory sections - general
|
[cols="<2,^1,<7"]
|
[cols="<2,^1,<7"]
|
[options="header",grid="rows"]
|
[options="header",grid="rows"]
|
|=======================
|
|=======================
|
| Memory section | Attributes | Description
|
| Memory section | Attributes | Description
|
| `rom` | `rx` | Instruction memory (IMEM) **OR** bootloader ROM
|
| `ram` | `rwx` | Data memory address space (processor-internal/external DMEM)
|
| `ram` | `rwx` | Data memory (DMEM)
|
| `rom` | `rx` | Instruction memory address space (processor-internal/external IMEM) _or_ internal bootloader ROM
|
| `iodev` | `rw` | Memory-mapped IO/peripheral devices
|
| `iodev` | `rw` | Processor-internal memory-mapped IO/peripheral devices address space
|
|=======================
|
|=======================
|
|
|
The `iodev` section is reserved for processor-internal memory-mapped IO and peripheral devices. The linker does not use this section at all
|
These sections are defined right at the beginning of the linker script:
|
and just passes the start and end adresses of this section to the start-up code `crt0.S` (see next section).
|
|
|
|
[NOTE]
|
.Linker memory sections - cut-out from linker script `neorv32.ld`
|
The `rom` region is used to place the instructions of "normal" applications. If the bootloader is being compiled, the makefile defines the `make_bootloader`
|
[source,c]
|
symbol, which changes the _ORIGIN_ (base address) and _LENGTH_ (size) attributes of the `rom` region according to the BOOTROM definitions.
|
----
|
|
MEMORY
|
|
{
|
|
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
|
|
}
|
|
----
|
|
|
|
Each memory section provides a _base address_ `ORIGIN` and a _size_ `LENGTH`. The base address and size of the `iodev` section is
|
|
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>>).
|
|
|
|
[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
|
|
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 _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).
|
|
|
The linker maps all the regions from the compiled object files into only four final sections: `.text`, `.rodata`, `.data` and `.bss`
|
[IMPORTANT]
|
using the specified memory section. These four regions contain everything required for the application to run:
|
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. +
|
|
+
|
|
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:
|
|
|
.Executable regions
|
.Linker memory regions
|
[cols="<1,<9"]
|
[cols="<1,<9"]
|
[options="header",grid="rows"]
|
[options="header",grid="rows"]
|
|=======================
|
|=======================
|
| Region | Description
|
| Region | Description
|
| `.text` | Executable instructions generated from the start-up code and all application sources.
|
| `.text` | Executable instructions generated from the start-up code and all application sources.
|
Line 247... |
Line 288... |
| `.data` | This section is required for the address generation of fixed (= global) variables only.
|
| `.data` | This section is required for the address generation of fixed (= global) variables only.
|
| `.bss` | This section is required for the address generation of dynamic memory constructs only.
|
| `.bss` | This section is required for the address generation of dynamic memory constructs only.
|
|=======================
|
|=======================
|
|
|
The `.text` and `.rodata` sections are mapped to processor's instruction memory space and the `.data` and
|
The `.text` and `.rodata` sections are mapped to processor's instruction memory space and the `.data` and
|
`.bss` sections are mapped to the processor's data memory space. Finally, the `.text`, `.rodata` and `.data` sections are extracted and concatenated into a single file
|
`.bss` sections are mapped to the processor's data memory space. Finally, the `.text`, `.rodata` and `.data`
|
**`main.bin`**.
|
sections are extracted and concatenated into a single file `main.bin`.
|
|
|
|
|
|
:sectnums:
|
|
==== Executable Image Generator
|
|
|
|
The `main.bin` file is packed by the NEORV32 image generator (`sw/image_gen`) to generate the final executable file.
|
|
|
**Executable Image Generator**
|
[NOTE]
|
|
The sources of the image generator are automatically compiled when invoking the makefile.
|
|
|
The **`main.bin`** file is processed by the NEORV32 image generator (`sw/image_gen`) to generate the final
|
The image generator can generate three types of executables, selected by a flag when calling the generator:
|
executable. It is automatically compiled when invoking the makefile. The image generator can generate three
|
|
types of executables, selected by a flag when calling the generator:
|
|
|
|
[cols="<1,<9"]
|
[cols="<1,<9"]
|
[grid="none"]
|
[grid="none"]
|
|=======================
|
|=======================
|
| `-app_bin` | Generates an executable binary file `neorv32_exe.bin` (for UART uploading via the bootloader).
|
| `-app_bin` | Generates an executable binary file `neorv32_exe.bin` (for UART uploading via the bootloader).
|
| `-app_img` | Generates an executable VHDL memory initialization image for the processor-internal IMEM. This option generates the `rtl/core/neorv32_application_image.vhd` file.
|
| `-app_img` | Generates an executable VHDL memory initialization image for the processor-internal IMEM. This option generates the `rtl/core/neorv32_application_image.vhd` file.
|
| `-bld_img` | Generates an executable VHDL memory initialization image for the processor-internal BOOT ROM. This option generates the `rtl/core/neorv32_bootloader_image.vhd` file.
|
| `-bld_img` | Generates an executable VHDL memory initialization image for the processor-internal BOOT ROM. This option generates the `rtl/core/neorv32_bootloader_image.vhd` file.
|
|=======================
|
|=======================
|
|
|
All these options are managed by the makefile – so you don't actually have to think about them. The normal
|
All these options are managed by the makefile. The _normal application_ compilation flow will generate the `neorv32_exe.bin`
|
application compilation flow will generate the `neorv32_exe.bin` file in the current software project folder
|
executable to be upload via UART to the NEORV32 bootloader.
|
ready for upload via UART to the NEORV32 bootloader.
|
|
|
The image generator add a small header to the `neorv32_exe.bin` executable, which consists of three 32-bit words located right at the
|
The actual executable provides a very small header consisting of three 32-bit words located right at the
|
beginning of the file. The first word of the executable is the signature word and is always `0x4788cafe`. Based on this word the bootloader
|
beginning of the file. This header is generated by the image generator. The first word of the executable is the signature
|
can identify a valid image file. The next word represents the size in bytes of the actual program
|
word and is always `0x4788cafe`. Based on this word, the bootloader can identify a valid image file. The next word represents the size in bytes of the actual program
|
|
image in bytes. A simple "complement" checksum of the actual program image is given by the third word. This
|
image in bytes. A simple "complement" checksum of the actual program image is given by the third word. This
|
provides a simple protection against data transmission or storage errors.
|
provides a simple protection against data transmission or storage errors.
|
|
|
|
|
=== Start-Up Code (crt0)
|
:sectnums:
|
|
==== Start-Up Code (crt0)
|
|
|
|
The CPU and also the processor require a minimal start-up and initialization code to bring the CPU (and the SoC)
|
|
into a stable and initialized state and to initialize the C runtime environment before the actual application can be executed.
|
|
This start-up code is located in `sw/common/crt0.S` and is automatically linked _every_ application program
|
|
and placed right before the actual application code so it gets executed right after reset.
|
|
|
|
The `crt0.S` start-up performs the following operations:
|
|
|
|
[start=1]
|
|
. Initialize all integer registers `x1 - x31` (or jsut `x1 - x15` when using the `E` CPU extension) to a defined value.
|
|
. Initialize the global pointer `gp` and the stack pointer `sp` according to the `.data` segment layout provided by the linker script.
|
|
. Initialize all CPU core CSRs and also install a default "dummy" trap handler for _all_ traps. This handler catches all traps during the early boot phase.
|
|
. Clear IO area: Write zero to all memory-mapped registers within the IO region (`iodev` section). If certain devices have not been implemented, a bus access fault exception will occur. This exception is captured by the dummy trap handler.
|
|
. Clear the `.bss` section defined by the linker script.
|
|
. Copy read-only data from the `.text` section to the `.data` section to set initialized variables.
|
|
. Call the application's `main` function (with _no_ arguments: `argc` = `argv` = 0).
|
|
. If the `main` function returns `crt0` can call an "after-main handler" (see below)
|
|
. If there is no after-main handler or after returning from the after-main handler the processor goes to an endless sleep mode (using a simple loop or via the `wfi` instruction if available).
|
|
|
The CPU (and also the processor) requires a minimal start-up and initialization code o bring the CPU (and the SoC) into a stable and initialized state before the
|
:sectnums:
|
acutal application can be executed. This start-up code is located in `sw/common/crt0.S` and is automatically linked with _every_ application program.
|
===== After-Main Handler
|
The `crt0.S` is directly executed right after a reset and performs the following operations:
|
|
|
If the application's `main()` function actually returns, an _after main handler_ can be executed. This handler can be a normal function
|
* Initialize integer registers `x1 - x31` (or `x1 - x15` when using the `E` CPU extension) to a defined value.
|
since the C runtime is still available when executed. If this handler uses any kind of peripheral/IO modules make sure these are
|
* Initialize all CPU core CSRs and also install a default "dummy" trap handler for _all_ traps.
|
already initialized within the application or you have to initialize them _inside_ the handler.
|
* Initialize the global pointer `gp` and the stack pointer `sp` according to the `.data` segment layout provided by the linker script.
|
|
* Clear IO area: Write zero to all memory-mapped registers within the IO region (`iodev` section). If certain devices have not been implemented, a bus access fault exception will occur. This exception is captured by the dummy trap handler.
|
.After-main handler - function prototype
|
* Clear the `.bss` section defined by the linker script.
|
[source,c]
|
* Copy read-only data from the `.text` section to the `.data` section to set initialized variables.
|
----
|
* Call the application's `main` function (with no arguments: `argc` = `argv` = 0).
|
int __neorv32_crt0_after_main(int32_t return_code);
|
* If the `main` function returns, the processor goes to an endless sleep mode (using a simple loop or via the `wfi` instruction if available).
|
----
|
|
|
|
The function has exactly one argument (`return_code`) that provides the _return value_ of the application's main function.
|
|
For instance, this variable contains _-1_ if the main function returned with `return -1;`. The return value of the
|
|
`__neorv32_crt0_after_main` function is irrelevant as there is no further "software instance" executed afterwards that can check this.
|
|
However, the on-chip debugger could still evaluate the return value of the after-main handler.
|
|
|
|
A simple `printf` can be used to inform the user when the application main function return
|
|
(this example assumes that UART0 has been already properly configured in the actual application):
|
|
|
|
.After-main handler - example
|
|
[source,c]
|
|
----
|
|
int __neorv32_crt0_after_main(int32_t return_code) {
|
|
|
|
neorv32_uart_printf("Main returned with code: %i\n", return_code);
|
|
return 0;
|
|
}
|
|
----
|
|
|
|
|
|
|
// ####################################################################################################################
|
// ####################################################################################################################
|
:sectnums:
|
:sectnums:
|
=== Bootloader
|
=== Bootloader
|
|
|
The default bootloader (sw/bootloader/bootloader.c) of the NEORV32 processor allows to upload
|
[NOTE]
|
new program executables at every time. If there is an external SPI flash connected to the processor (like the
|
This section illustrated the **default** bootloader from the repository. The bootloader can be customized
|
FPGA's configuration memory), the bootloader can store the program executable to it. After reset, the
|
to target application-specific scenarios. See User Guide section
|
bootloader can directly boot from the flash without any user interaction.
|
https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader[Customizing the Internal Bootloader]
|
|
for more information.
|
[WARNING]
|
|
The bootloader is only implemented when the BOOTLOADER_EN generic is true and requires the
|
The default NEORV32 bootloader (source code `sw/bootloader/bootloader.c`) provides a build-in firmware that
|
CSR access CPU extension (CPU_EXTENSION_RISCV_Zicsr generic is true).
|
allows to upload new application executables via UART at every time and to optionally store/boot them to/from
|
|
an external SPI flash. It features a simple "automatic boot" feature that will try to fetch an executable
|
|
from SPI flash if there is _no_ UART user interaction. This allows to build processor setup with
|
|
non-volatile application storage, which can be updated at any time.
|
|
|
[IMPORTANT]
|
The bootloader is only implemented if the <<_int_bootloader_en>> generic is _true_. This will
|
The bootloader requires the primary UART (UART0) for user interaction (_IO_UART0_EN_ generic is _true_).
|
select the <<_indirect_boot>> boot configuration.
|
|
|
|
.Hardware requirements of the _default_ NEORV32 bootloader
|
[IMPORTANT]
|
[IMPORTANT]
|
For the automatic boot from an SPI flash, the SPI controller has to be implemented (_IO_SPI_EN_
|
**REQUIRED**: The bootloader requires the CSR access CPU extension (<<_cpu_extension_riscv_zicsr>> generic is _true_)
|
generic is _true_) and the machine system timer MTIME has to be implemented (_IO_MTIME_EN_
|
and at least 512 bytes of data memory (processor-internal DMEM or external DMEM). +
|
generic is _true_), too, to allow an auto-boot timeout counter.
|
+
|
|
_RECOMMENDED_: For user interaction via UART (like uploading executables) the primary UART (UART0) has to be
|
[WARNING]
|
implemented (<<_io_uart0_en>> generic is _true_). Without UART the bootloader does not make much sense. However, auto-boot
|
The bootloader is intended to work independent of the actual hardware (-configuration). Hence, it
|
via SPI is still supported but the bootloader should be customized (see User Guide) for this purpose. +
|
should be compiled with the minimal base ISA only. The current version of the bootloader uses the
|
+
|
`rv32i` ISA – so it will not work on `rv32e` architectures. To make the bootloader work on an embedded
|
_OPTIONAL_: The default bootloader uses bit 0 of the GPIO output port as "heart beat" and status LED if the
|
CPU configuration or on any other more sophisticated configuration, recompile it using the according ISA
|
GPIO controller is implemented (<<_io_gpio_en>> generic is _true_). +
|
(see section <<_customizing_the_internal_bootloader>>).
|
+
|
|
_OPTIONAL_: The MTIME machine timer (<<_io_mtime_en>> generic is _true_) and the SPI controller
|
|
(<<_io_spi_en>> generic is _true_) are required in order to use the bootloader's auto-boot feature
|
|
(automatic boot from external SPI flash if there is no user interaction via UART).
|
|
|
To interact with the bootloader, connect the primary UART (UART0) signals (`uart0_txd_o` and
|
To interact with the bootloader, connect the primary UART (UART0) signals (`uart0_txd_o` and
|
`uart0_rxd_o`) of the processor's top entity via a serial port (-adapter) to your computer (hardware flow control is
|
`uart0_rxd_o`) of the processor's top entity via a serial port (-adapter) to your computer (hardware flow control is
|
not used so the according interface signals can be ignored.), configure your
|
not used so the according interface signals can be ignored.), configure your
|
terminal program using the following settings and perform a reset of the processor.
|
terminal program using the following settings and perform a reset of the processor.
|
Line 345... |
Line 434... |
<< NEORV32 Bootloader >>
|
<< NEORV32 Bootloader >>
|
|
|
BLDV: Mar 23 2021
|
BLDV: Mar 23 2021
|
HWV: 0x01050208
|
HWV: 0x01050208
|
CLK: 0x05F5E100
|
CLK: 0x05F5E100
|
USER: 0x10000DE0
|
|
MISA: 0x40901105
|
MISA: 0x40901105
|
ZEXT: 0x00000023
|
ZEXT: 0x00000023
|
PROC: 0x0EFF0037
|
PROC: 0x0EFF0037
|
IMEM: 0x00004000 bytes @ 0x00000000
|
IMEM: 0x00004000 bytes @ 0x00000000
|
DMEM: 0x00002000 bytes @ 0x80000000
|
DMEM: 0x00002000 bytes @ 0x80000000
|
Line 362... |
Line 450... |
[cols="<2,<15"]
|
[cols="<2,<15"]
|
[grid="none"]
|
[grid="none"]
|
|=======================
|
|=======================
|
| `BLDV` | Bootloader version (built date).
|
| `BLDV` | Bootloader version (built date).
|
| `HWV` | Processor hardware version (from the `mimpid` CSR) in BCD format (example: `0x01040606` = v1.4.6.6).
|
| `HWV` | Processor hardware version (from the `mimpid` CSR) in BCD format (example: `0x01040606` = v1.4.6.6).
|
| `USER` | Custom user code (from the _USER_CODE_ generic).
|
|
| `CLK` | Processor clock speed in Hz (via the SYSINFO module, from the _CLOCK_FREQUENCY_ generic).
|
| `CLK` | Processor clock speed in Hz (via the SYSINFO module, from the _CLOCK_FREQUENCY_ generic).
|
| `MISA` | CPU extensions (from the `misa` CSR).
|
| `MISA` | CPU extensions (from the `misa` CSR).
|
| `ZEXT` | CPU sub-extensions (from the `mzext` CSR)
|
| `ZEXT` | CPU sub-extensions (from the `mzext` CSR)
|
| `PROC` | Processor configuration (via the SYSINFO module, from the IO_* and MEM_* configuration generics).
|
| `PROC` | Processor configuration (via the SYSINFO module, from the IO_* and MEM_* configuration generics).
|
| `IMEM` | IMEM memory base address and size in byte (from the _MEM_INT_IMEM_SIZE_ generic).
|
| `IMEM` | IMEM memory base address and size in byte (from the _MEM_INT_IMEM_SIZE_ generic).
|
Line 410... |
Line 497... |
* `r`: Restart the bootloader and the auto-boot sequence
|
* `r`: Restart the bootloader and the auto-boot sequence
|
* `u`: Upload new program executable (`neorv32_exe.bin`) via UART into the instruction memory
|
* `u`: Upload new program executable (`neorv32_exe.bin`) via UART into the instruction memory
|
* `s`: Store executable to SPI flash at `spi_csn_o(0)`
|
* `s`: Store executable to SPI flash at `spi_csn_o(0)`
|
* `l`: Load executable from SPI flash at `spi_csn_o(0)`
|
* `l`: Load executable from SPI flash at `spi_csn_o(0)`
|
* `e`: Start the application, which is currently stored in the instruction memory (IMEM)
|
* `e`: Start the application, which is currently stored in the instruction memory (IMEM)
|
* `#`: Shortcut for executing u and e afterwards (not shown in help menu)
|
|
|
|
A new executable can be uploaded via UART by executing the `u` command. After that, the executable can be directly
|
A new executable can be uploaded via UART by executing the `u` command. After that, the executable can be directly
|
executed via the `e` command. To store the recently uploaded executable to an attached SPI flash press `s`. To
|
executed via the `e` command. To store the recently uploaded executable to an attached SPI flash press `s`. To
|
directly load an executable from the SPI flash press `l`. The bootloader and the auto-boot sequence can be
|
directly load an executable from the SPI flash press `l`. The bootloader and the auto-boot sequence can be
|
manually restarted via the `r` command.
|
manually restarted via the `r` command.
|
|
|
[TIP]
|
[TIP]
|
The CPU is in machine level privilege mode after reset. When the bootloader boots an application,
|
The CPU is in machine level privilege mode after reset. When the bootloader boots an application,
|
this application is also started in machine level privilege mode.
|
this application is also started in machine level privilege mode.
|
|
|
:sectnums:
|
[TIP]
|
==== External SPI Flash for Booting
|
For detailed information on using an SPI flash for application storage see User Guide section
|
|
https://stnolting.github.io/neorv32/ug/#_programming_an_external_spi_flash_via_the_bootloader[Programming an External SPI Flash via the Bootloader].
|
If you want the NEORV32 bootloader to automatically fetch and execute an application at system start, you
|
|
can store it to an external SPI flash. The advantage of the external memory is to have a non-volatile program
|
|
storage, which can be re-programmed at any time just by executing some bootloader commands. Thus, no
|
|
FPGA bitstream recompilation is required at all.
|
|
|
|
**SPI Flash Requirements**
|
|
|
|
The bootloader can access an SPI compatible flash via the processor top entity's SPI port and connected to
|
|
chip select `spi_csn_o(0)`. The flash must be capable of operating at least at 1/8 of the processor's main
|
|
clock. Only single read and write byte operations are used. The address has to be 24 bit long. Furthermore,
|
|
the SPI flash has to support at least the following commands:
|
|
|
|
* READ (`0x03`)
|
|
* READ STATUS (`0x05`)
|
|
* WRITE ENABLE (`0x06`)
|
|
* PAGE PROGRAM (`0x02`)
|
|
* SECTOR ERASE (`0xD8`)
|
|
* READ ID (`0x9E`)
|
|
|
|
Compatible (FGPA configuration) SPI flash memories are for example the "Winbond W25Q64FV2 or the "Micron N25Q032A".
|
|
|
|
**SPI Flash Configuration**
|
|
|
|
The base address `SPI_FLASH_BOOT_ADR` for the executable image inside the SPI flash is defined in the
|
|
"user configuration" section of the bootloader source code (`sw/bootloader/bootloader.c`). Most
|
|
FPGAs that use an external configuration flash, store the golden configuration bitstream at base address 0.
|
|
Make sure there is no address collision between the FPGA bitstream and the application image. You need to
|
|
change the default sector size if your flash has a sector size greater or less than 64kB:
|
|
|
|
[source,c]
|
|
----
|
|
/** SPI flash boot image base address */
|
|
#define SPI_FLASH_BOOT_ADR 0x00800000
|
|
/** SPI flash sector size in bytes */
|
|
#define SPI_FLASH_SECTOR_SIZE (64*1024)
|
|
----
|
|
|
|
[IMPORTANT]
|
|
For any change you made inside the bootloader, you have to recompile the bootloader (see section
|
|
<<_customizing_the_internal_bootloader>>) and do a new synthesis of the processor.
|
|
|
|
|
|
:sectnums:
|
:sectnums:
|
==== Auto Boot Sequence
|
==== Auto Boot Sequence
|
When you reset the NEORV32 processor, the bootloader waits 8 seconds for a user console input before it
|
When you reset the NEORV32 processor, the bootloader waits 8 seconds for a UART console input before it
|
starts the automatic boot sequence. This sequence tries to fetch a valid boot image from the external SPI
|
starts the automatic boot sequence. This sequence tries to fetch a valid boot image from the external SPI
|
flash, connected to SPI chip select `spi_csn_o(0)`. If a valid boot image is found and can be successfully
|
flash, connected to SPI chip select `spi_csn_o(0)`. If a valid boot image is found that can be successfully
|
transferred into the instruction memory, it is automatically started. If no SPI flash was detected or if there
|
transferred into the instruction memory, it is automatically started. If no SPI flash is detected or if there
|
was no valid boot image found, the bootloader stalls and the status LED is permanently activated.
|
is no valid boot image found, and error code will be shown.
|
|
|
|
|
:sectnums:
|
:sectnums:
|
==== Bootloader Error Codes
|
==== Bootloader Error Codes
|
|
|
If something goes wrong during bootloader operation, an error code is shown. In this case the processor
|
If something goes wrong during bootloader operation, an error code is shown. In this case the processor
|
stalls, a bell command and one of the following error codes are send to the terminal, the bootloader status
|
stalls, a bell command and one of the following error codes are send to the terminal, the bootloader status
|
LED is permanently activated and the system must be reset manually.
|
LED is permanently activated and the system must be manually reset.
|
|
|
[cols="<2,<13"]
|
[cols="<2,<13"]
|
[grid="rows"]
|
[grid="rows"]
|
|=======================
|
|=======================
|
| **`ERROR_0`** | If you try to transfer an invalid executable (via UART or from the external SPI flash), this error message shows up. There might be a transfer protocol configuration error in the terminal program. See section <<_uploading_and_starting_of_a_binary_executable_image_via_uart>> for more information. Also, if no SPI flash was found during an auto-boot attempt, this message will be displayed.
|
| **`ERROR_0`** | If you try to transfer an invalid executable (via UART or from the external SPI flash), this error message shows up. There might be a transfer protocol configuration error in the terminal program. See section <<_uploading_and_starting_of_a_binary_executable_image_via_uart>> for more information. Also, if no SPI flash was found during an auto-boot attempt, this message will be displayed.
|
| **`ERROR_1`** | Your program is way too big for the internal processor’s instructions memory. Increase the memory size or reduce (optimize!) your application code.
|
| **`ERROR_1`** | Your program is way too big for the internal processor’s instructions memory. Increase the memory size or reduce (optimize!) your application code.
|
| **`ERROR_2`** | This indicates a checksum error. Something went wrong during the transfer of the program image (upload via UART or loading from the external SPI flash). If the error was caused by a UART upload, just try it again. When the error was generated during a flash access, the stored image might be corrupted.
|
| **`ERROR_2`** | This indicates a checksum error. Something went wrong during the transfer of the program image (upload via UART or loading from the external SPI flash). If the error was caused by a UART upload, just try it again. When the error was generated during a flash access, the stored image might be corrupted.
|
| **`ERROR_3`** | This error occurs if the attached SPI flash cannot be accessed. Make sure you have the right type of flash and that it is properly connected to the NEORV32 SPI port using chip select #0.
|
| **`ERROR_3`** | This error occurs if the attached SPI flash cannot be accessed. Make sure you have the right type of flash and that it is properly connected to the NEORV32 SPI port using chip select #0.
|
| **`ERROR_4`** | The instruction memory is marked as read-only. Set the _MEM_INT_IMEM_ROM_ generic to _false_ to allow write accesses.
|
|
| **`ERROR_5`** | This error pops up when an unexpected exception or interrupt was triggered. The cause of the trap (`mcause` CSR) is displayed for further investigation. This might be caused if an ISA extension is used that has not been synthesized.
|
|
| **`ERROR_?`** | Something really bad happened when there is no specific error code available :(
|
|
|=======================
|
|=======================
|
|
|
|
|
|
|
|
|