:sectnums:
=== Bootloader

[NOTE]
This section refers to the **default** bootloader from the repository. The bootloader can be customized
to target application-specific scenarios. See User Guide section
https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader[Customizing the Internal Bootloader]
for more information.

The NEORV32 bootloader (source code `sw/bootloader/bootloader.c`) provides an optional build-in firmware that
allows to upload new application executables without the need to re-synthesize the FPGA's bitstream.
A UART connection is used to provide a simple text-based user interface that allows to upload executables.

Furthermore, the bootloader provides options to program executable to a processor-external SPI flash.
An "auto boot" feature can optionally fetch this executable
right after reset if there is no user interaction via UART. This allows to build processor setup with
non-volatile application storage, which can still be updated at any time.

The bootloader is implemented if the <<_int_bootloader_en>> generic is _true_ (default). This will automatically
select the CPU's <<_indirect_boot>> boot configuration.

.Hardware Requirements for the _Default_ NEORV32 Bootloader
[IMPORTANT]
**REQUIRED**: The bootloader requires the privileged architecture CPU extension
(<<_zicsr_control_and_status_register_access_privileged_architecture>>)
and at least 512 bytes of data memory (processor-internal DMEM or external DMEM). +
 +
**RECOMMENDED**: For user interaction via UART (like uploading executables) the primary UART
(<<_primary_universal_asynchronous_receiver_and_transmitter_uart0>>) has to be implemented.
Without UART0 the auto-boot via SPI is still supported but the bootloader should be customized
(see User Guide) for this purpose. +
 +
**RECOMMENDED**: The default bootloader uses bit 0 of the GPIO controller's
(<<_general_purpose_input_and_output_port_gpio>>) output port to drive a high-active "heart beat" status LED. +
 +
**RECOMMENDED**: The MTIME machine timer (<<_machine_system_timer_mtime>> generic is _true_) is used to control
blinking of the status LED and also to automatically trigger the auto-boot sequence. +
 +
**OPTIONAL**: The SPI controller (<<_serial_peripheral_interface_controller_spi>>) is required
to store/load executable from external flash (for the auto boot feature).

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
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 console settings (`19200-8-N-1`):

* 19200 Baud
* 8 data bits
* no parity bit
* 1 stop bit
* newline on `\r\n` (carriage return, newline)
* no transfer protocol / control flow protocol - just raw bytes

[IMPORTANT]
_Any_ terminal program that can connect to a serial port should work. However, make sure the program
can transfer data in _raw_ byte mode without any protocol overhead around it. Some terminal programs struggle with
transmitting files larger than 4kB (see https://github.com/stnolting/neorv32/pull/215). Try a different program
if uploading a binary does not work.

The bootloader uses the LSB of the top entity's `gpio_o` output port as high-active **status LED** (all other
output pin are set to low level). After reset, this LED will start blinking at ~2Hz and the
following intro screen should show up in your terminal:

[source]
----
<< NEORV32 Bootloader >>

BLDV: Feb 16 2022
HWV:  0x01060709
CLK:  0x05f5e100
ISA:  0x40901107 + 0xc000068b
SOC:  0x7b7f402f
IMEM: 0x00008000 bytes @0x00000000
DMEM: 0x00004000 bytes @0x80000000

Autoboot in 8s. Press any key to abort.
----

This start-up screen also gives some brief information about the bootloader and several system configuration parameters:

[cols="<2,<15"]
[grid="none"]
|=======================
| `BLDV` | Bootloader version (built date).
| `HWV`  | Processor hardware version (the <<_mimpid>> CSR); in BCD format; example: `0x01040606` = v1.4.6.6).
| `CLK`  | Processor clock speed in Hz (via the `CLK` register from <<_system_configuration_information_memory_sysinfo>>; defined by the <<_clock_frequency>> generic).
| `ISA`  | CPU extensions (<<_misa>> CSR + <<_mxisa>> CSR).
| `SOC`  | Processor configuration (via the `SOC` register from the <<_system_configuration_information_memory_sysinfo>>; defined by the `IO_*` and `MEM_*` configuration generics).
| `IMEM` | IMEM memory base address and size in byte (via the `IMEM_SIZE` and `ISPACE_BASE` registers from the <<_system_configuration_information_memory_sysinfo>>; defined by the <<_mem_int_imem_size>> generic).
| `DMEM` | DMEM memory base address and size in byte (via the `DMEM_SIZE` and `DSPACE_BASE` registers from the <<_system_configuration_information_memory_sysinfo>>; defined by the <<_mem_int_dmem_size>> generic).
|=======================

Now you have 8 seconds to press _any_ key. Otherwise, the bootloader starts the <<_auto_boot_sequence>>. When
you press any key within the 8 seconds, the actual bootloader user console starts:

[source]
----
<< NEORV32 Bootloader >>

BLDV: Feb 16 2022
HWV:  0x01060709
CLK:  0x05f5e100
ISA:  0x40901107 + 0xc000068b
SOC:  0x7b7f402f
IMEM: 0x00008000 bytes @0x00000000
DMEM: 0x00004000 bytes @0x80000000

Autoboot in 8s. Press any key to abort.
Aborted. <1>

Available commands:
 h: Help
 r: Restart
 u: Upload
 s: Store to flash
 l: Load from flash
 e: Execute
CMD:>
----
<1> Auto boot sequence aborted due to user console input.

The auto boot countdown is stopped and the bootloader's user console is ready to receive one of the following commands:

* `h`: Show the help text (again)
* `r`: Restart the bootloader and the auto-boot sequence
* `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)` (little-endian byte order)
* `l`: Load executable from SPI flash at `spi_csn_o(0)` (little-endian byte order)
* `e`: Start the application, which is currently stored in the instruction memory (IMEM)

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
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.

[TIP]
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.

[TIP]
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].


:sectnums:
==== Auto Boot Sequence

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
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 is detected or if there
is no valid boot image found, and error code will be shown.


:sectnums:
==== Bootloader Error Codes

If something goes wrong during bootloader operation, an error code and a short message is shown. In this case the processor
stalls,, the bootloader status LED is permanently activated and the processor must be reset manually.

[TIP]
In many cases the error source is just _temporary_ (like some HF spike during an UART upload). Just try again.

[cols="<2,<8"]
[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. 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 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_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 - Unexpected exception!`** | The bootloader encountered an exception during operation. This might be caused when it tries to access peripherals that were not implemented during synthesis. Example: executing commands `l` or `s` (SPI flash operations) without the SPI module beeing implemented.
|=======================
