added console options to configure/customize build-in bootloader

* updated according sections in data sheet and user guide
This commit is contained in:
stnolting 2021-06-26 20:03:10 +02:00
parent 2f15bf655c
commit 16cfbb63a0
5 changed files with 1265 additions and 1219 deletions

View file

@ -363,7 +363,6 @@ automatic boot sequence and to start the actual bootloader user interface consol
BLDV: Mar 23 2021
HWV: 0x01050208
CLK: 0x05F5E100
USER: 0x10000DE0
MISA: 0x40901105
ZEXT: 0x00000023
PROC: 0x0EFF0037
@ -598,65 +597,101 @@ The RISC-V ISA string (for _MARCH_) follows a certain _canonical_ structure:
:sectnums:
== Customizing the Internal Bootloader
You can either customized the default bootloader via provided configuration options or you can write
a completely new bootloader that is specialized for your application.
The NEORV32 bootloader provides several options to configure and customize it for a certain application setup.
This configuration is done by passing _defines_ when compiling the bootloader. Of course you can also
modify to bootloader source code to provide a setup that perfectly fits your needs.
[IMPORTANT]
Keep in mind that the maximum size for the bootloader is limited to 32kB.
Each time the bootloader sources are modified, the bootloader has to be re-compiled (and re-installed to the
bootloader ROM) and the processor has to be re-synthesized.
The most important user-defined configuration options of the default bootloader are available as C-language
`#defines` right at the beginning of the bootloader source code (`sw/bootloader/bootloader.c`):
[NOTE]
Keep in mind that the maximum size for the bootloader is limited to 32kB and should be compiled using the
base ISA `rv32i` only to ensure it can work independently of the actual CPU configuration.
.Cut-out from the bootloader source code `bootloader.c`: configuration parameters
[source,c]
.Bootloader configuration parameters
[cols="<2,^1,^2,<6"]
[options="header", grid="rows"]
|=======================
| Parameter | Default | Legal values | Description
4+^| Serial console interface
| `UART_EN` | `1` | `0`, `1` | Set to `0` to disable UART0 (no serial console at all)
| `UART_BAUD` | `19200` | _any_ | Baud rate of UART0
4+^| Status LED
| `STATUS_LED_EN` | `1` | `0`, `1` | Enable bootloader status led ("heart beat") at `GPIO` output port pin #`STATUS_LED_PIN` when `1`
| `STATUS_LED_PIN` | `0` | `0` ... `31` | `GPIO` output pin used for the high-active status LED
4+^| Boot configuration
| `AUTO_BOOT_SPI_EN` | `0` | `0`, `1` | Set `1` to enable immediate boot from external SPI flash
| `AUTO_BOOT_OCD_EN` | `0` | `0`, `1` | Set `1` to enable boot via on-chip debugger (OCD)
| `AUTO_BOOT_TIMEOUT` | `8` | _any_ | Time in seconds after the auto-boot sequence starts (if there is no UART input by user); set to 0 to disabled auto-boot sequence
4+^| SPI configuration
| `SPI_FLASH_CS` | `0` | `0` ... `7` | SPI chip select output (`spi_csn_o`) for selecting flash
| `SPI_FLASH_SECTOR_SIZE` | `65536` | _any_ | SPI flash sector size in bytes
| `SPI_FLASH_CLK_PRSC` | `CLK_PRSC_8` | `CLK_PRSC_2` `CLK_PRSC_4` `CLK_PRSC_8` `CLK_PRSC_64` `CLK_PRSC_128` `CLK_PRSC_1024` `CLK_PRSC_2024` `CLK_PRSC_4096` | SPI clock pre-scaler (dividing main processor clock)
| `SPI_BOOT_BASE_ADDR` | `0x08000000` | _any_ 32-bit value | Defines the _base_ address of the executable in external flash
|=======================
Each configuration parameter is implemented as C-language `define` that can be manually overridden (_redefined_) when
invoking the bootloader's makefile. The according parameter and its new value has to be _appended_
(using `+=`) to the makefile's `USER_FLAGS` variable. Make sure to use the `-D` prefix here.
For example, to configure a UART Baud rate of 57600 and redirecting the status LED to output pin 20
use the following command (_in_ the bootloader's source folder `sw/bootloader`):
.Example: customizing, re-compiling and re-installing the bootloader
[source,console]
----
/** UART BAUD rate */
#define BAUD_RATE (19200)
/** Enable auto-boot sequence if != 0 */
#define AUTOBOOT_EN (1)
/** Time until the auto-boot sequence starts (in seconds) */
#define AUTOBOOT_TIMEOUT 8
/** Set to 0 to disable bootloader status LED */
#define STATUS_LED_EN (1)
/** SPI_DIRECT_BOOT_EN: Define/uncomment to enable SPI direct boot */
//#define SPI_DIRECT_BOOT_EN
/** Bootloader status LED at GPIO output port */
#define STATUS_LED (0)
/** SPI flash boot image base address (warning! address might wrap-around!) */
#define SPI_FLASH_BOOT_ADR (0x00800000)
/** SPI flash chip select line at spi_csn_o */
#define SPI_FLASH_CS (0)
/** Default SPI flash clock prescaler */
#define SPI_FLASH_CLK_PRSC (CLK_PRSC_8)
/** SPI flash sector size in bytes (default = 64kb) */
#define SPI_FLASH_SECTOR_SIZE (64*1024)
/** ASCII char to start fast executable upload process */
#define FAST_UPLOAD_CMD '#'
$ make USER_FLAGS+=-DUART_BAUD=57600 USER_FLAGS+=-DSTATUS_LED_PIN=20 clean_all bootloader
----
[NOTE]
The `clean_all` target ensure that all libraries are re-compiled. The `bootloader` target will automatically
compile and install the bootloader to the HDL boot ROM (updating `rtl/core/neorv32_bootloader_image.vhd`).
:sectnums:
=== Re-Compiling and Re-Installing the Bootloader
=== Bootloader Boot Configuration
Whenever you have modified the bootloader's C sources you need to recompile and re-install it and
re-synthesize your design afterwards.
The bootloader provides several _boot configurations_ that define where the actual application's executable
shall be fetched from. Note that the non-default boot configurations provide a smaller memory footprint
reducing boot ROM implementation costs.
[start=1]
.Compile and install the bootloader using the explicit `bootloader` makefile target.
[source,bash]
----
neorv32/sw/bootloader$ make clean_all bootloader
----
:sectnums!:
==== Default Boot Configuration
.Advanced
[NOTE]
You can also use the `bootloader` makefile target for any "normal" application. This will install that application
directly to the processor's internal boot ROM.
The _default_ bootloader configuration provides a UART-based user interface that allows to upload new executables
at any time. Optionally, the executable can also be programmed to an external SPI flash by the bootloader (see
section <<_programming_an_external_spi_flash_via_the_bootloader>>).
This configuration also provides an _automatic boot sequence_ (auto-boot) which will start fetching an executable
from external SPI flash using the default SPI configuration. By this, the default bootloader configuration
provides a "non volatile program storage" mechanism that automatically boot from external SPI flash
(after `AUTO_BOOT_TIMEOUT`) while still providing the option to re-program SPI flash at any time
via the UART interface.
:sectnums!:
==== `AUTO_BOOT_SPI_EN`
The automatic boot from SPI flash (enabled when `AUTO_BOOT_SPI_EN` is `1`) will fetch an executable from an external
SPI flash (using the according _SPI configuration_) right after reset. The bootloader will start fetching
the image at SPI flash base address `SPI_BOOT_BASE_ADDR`.
Note that there is _no_ UART console to interact with the bootloader. However, this boot configuration will
output minimal status messages via UART (if `UART_EN` is `1`).
:sectnums!:
==== `AUTO_BOOT_OCD_EN`
If `AUTO_BOOT_OCD_EN` is `1` the bootloader is implemented as minimal "halt loop" to be used with the on-chip debugger.
After initializing the hardware, the CPU waits in this endless loop until the on-chip debugger takes control over
the core (to upload and run the actual executable). See section <<_debugging_using_the_on_chip_debugger>>
for more information on how to use the on-chip debugger to upload and run executables.
[NOTE]
The bootloader is intended to work regardless of the actual NEORV32 hardware configuration
especially when it comes to CPU ISA extensions. Hence, the bootloader should be compiled using the
minimal `rv32i` ISA only.
All bootloader boot configuration support uploading new executables via the on-chip debugger.
[WARNING]
Note that this boot configuration does not load any executable at all! Hence,
this boot configuration is intended to be used with the on-chip debugger only.
@ -667,11 +702,34 @@ minimal `rv32i` ISA only.
The default processor-internal NEORV32 bootloader supports automatic booting from an external SPI flash.
This guide shows how to write an executable to the SPI flash via the bootloader so it can be automatically
fetched and executed after processor reset.
fetched and executed after processor reset. For example, you can use a section of the FPGA bitstream configuration
memory to store an application executable.
[TIP]
The SPI flash requirements are shown in section
https://stnolting.github.io/neorv32/#_external_spi_flash_for_booting[External SPI Flash for Booting] of the datasheet.
[NOTE]
This section assumes the _default_ configuration of the NEORV32 bootloader.
See section <<_customizing_the_internal_bootloader>> on how to customize the bootloader and its setting
(for example the SPI chip-select port, the SPI clock speed or the flash base address for storing the executable).
:sectnums:
=== SPI Flash
The bootloader can access an SPI compatible flash via the processor top entity's SPI port. By default, the flash
chip-select line is to `spi_csn_o(0)` and uses 1/8 of the processor's main clock as clock frequency.
The SPI flash has to support single-byte read and write, 24-bit addresses and at least the following standard 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".
:sectnums:
=== Programming an Executable
[start=1]
. At first, reset the NEORV32 processor and wait until the bootloader start screen appears in your terminal program.
@ -711,7 +769,7 @@ to specify the base address of the executable inside the SPI flash.
CMD:> u
Awaiting neorv32_exe.bin... OK
CMD:> p
Write 0x000013FC bytes to SPI flash @ 0x00800000? (y/n) y
Write 0x000013FC bytes to SPI flash @ 0x08000000? (y/n) y
Flashing... OK
CMD:>
----