OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [docs/] [datasheet/] [software.adoc] - Diff between revs 73 and 74

Only display areas with differences | Details | Blame | View Log

Rev 73 Rev 74
:sectnums:
:sectnums:
== Software Framework
== Software Framework
To make actual use of the NEORV32 processor, the project comes with a complete software ecosystem. This
To make actual use of the NEORV32 processor, the project comes with a complete software ecosystem. This
ecosystem is based on the RISC-V port of the GCC GNU Compiler Collection and consists of the following elementary parts:
ecosystem is based on the RISC-V port of the GCC GNU Compiler Collection and consists of the following elementary parts:
* <<_compiler_toolchain>>
* <<_compiler_toolchain>>
* <<_core_libraries>>
* <<_core_libraries>>
* <<_application_makefile>>
* <<_application_makefile>>
* <<_executable_image_format>>
* <<_executable_image_format>>
** <<_linker_script>>
** <<_linker_script>>
** <<_ram_layout>>
** <<_ram_layout>>
** <<_c_standard_library>>
** <<_c_standard_library>>
** <<_start_up_code_crt0>>
** <<_start_up_code_crt0>>
* <<_bootloader>>
* <<_bootloader>>
* <<_neorv32_runtime_environment>>
* <<_neorv32_runtime_environment>>
A summarizing list of the most important elements of the software framework and their according
A summarizing list of the most important elements of the software framework and their according
files and folders is shown below:
files and folders is shown below:
[cols="<6,<4"]
[cols="<6,<4"]
[grid="none"]
[grid="none"]
|=======================
|=======================
| Application start-up code               | `sw/common/crt0.S`
| Application start-up code               | `sw/common/crt0.S`
| Application linker script               | `sw/common/neorv32.ld`
| Application linker script               | `sw/common/neorv32.ld`
| Core hardware driver libraries ("HAL")  | `sw/lib/include/` & `sw/lib/source/`
| Core hardware driver libraries ("HAL")  | `sw/lib/include/` & `sw/lib/source/`
| Central application makefile            | `sw/common/common.mk`
| Central application makefile            | `sw/common/common.mk`
| Tool for generating NEORV32 executables | `sw/image_gen/`
| Tool for generating NEORV32 executables | `sw/image_gen/`
| Default bootloader                      | `sw/bootloader/bootloader.c`
| Default bootloader                      | `sw/bootloader/bootloader.c`
| Example programs                        | `sw/example`
| Example programs                        | `sw/example`
|=======================
|=======================
.Software Documentation
.Software Documentation
[TIP]
[TIP]
All core libraries and example programs are highly documented using **Doxygen**.
All core libraries and example programs are highly documented using **Doxygen**.
See section <>.
See section <>.
The documentation is automatically built and deployed to GitHub pages and is available online
The documentation is automatically built and deployed to GitHub pages and is available online
at https://stnolting.github.io/neorv32/sw/files.html .
at https://stnolting.github.io/neorv32/sw/files.html .
// ####################################################################################################################
// ####################################################################################################################
:sectnums:
:sectnums:
=== Compiler Toolchain
=== Compiler Toolchain
The toolchain for this project is based on the free RISC-V GCC-port. You can find the compiler sources and
The toolchain for this project is based on the free RISC-V GCC-port. You can find the compiler sources and
build instructions on the official RISC-V GNU toolchain GitHub page: https://github.com/riscv/riscv-gnutoolchain.
build instructions on the official RISC-V GNU toolchain GitHub page: https://github.com/riscv/riscv-gnutoolchain.
The NEORV32 implements a 32-bit RISC-V architecture and uses a 32-bit integer and soft-float ABI by default.
The NEORV32 implements a 32-bit RISC-V architecture and uses a 32-bit integer and soft-float ABI by default.
Make sure the toolchain / toolchain build is configured accordingly.
Make sure the toolchain / toolchain build is configured accordingly.
* MARCH = `rv32i`
* MARCH = `rv32i`
* MABI = `ilp32`
* MABI = `ilp32`
Alternatively, you can download my prebuilt `rv32i/e` toolchains for 64-bit x86 Linux from: https://github.com/stnolting/riscv-gcc-prebuilt
Alternatively, you can download my prebuilt `rv32i/e` toolchains for 64-bit x86 Linux from: https://github.com/stnolting/riscv-gcc-prebuilt
The default toolchain prefix used by the project's makefiles is **`riscv32-unknown-elf`**, which can be changes
The default toolchain prefix used by the project's makefiles is **`riscv32-unknown-elf`**, which can be changes
using makefile flags at any time.
using makefile flags at any time.
[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 the user guides' section https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[Software Toolchain Setup].
can be found in the user guides' section https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[Software Toolchain Setup].
<<<
<<<
// ####################################################################################################################
// ####################################################################################################################
:sectnums:
:sectnums:
=== Core Libraries
=== Core Libraries
The NEORV32 project provides a set of C libraries that allows an easy usage of the processor/CPU features
The NEORV32 project provides a set of C libraries that allows an easy usage of the processor/CPU features
(also called "HAL" - hardware abstraction layer). All driver and runtime-related files are located in
(also called "HAL" - hardware abstraction layer). All driver and runtime-related files are located in
`sw/lib`. These are automatically included and linked by adding the following _include statement_:
`sw/lib`. These are automatically included and linked by adding the following _include statement_:
[source,c]
[source,c]
----
----
#include  // add NEORV32 HAL and runtime libraries
#include  // add NEORV32 HAL and runtime libraries
----
----
[cols="<3,<4,<8"]
[cols="<3,<4,<8"]
[options="header",grid="rows"]
[options="header",grid="rows"]
|=======================
|=======================
| C source file | C header file | Description
| C source file | C header file | Description
| -                   | `neorv32.h`            | main NEORV32 definitions and library file
| -                   | `neorv32.h`            | main NEORV32 definitions and library file
| `neorv32_cfs.c`     | `neorv32_cfs.h`        | HW driver (stubs) functions for the custom functions subsystem
| `neorv32_cfs.c`     | `neorv32_cfs.h`        | HW driver (stubs) functions for the custom functions subsystem
footnote:[This driver file only represents a stub, since the real CFS drivers are defined by the actual CFS implementation.]
footnote:[This driver file only represents a stub, since the real CFS drivers are defined by the actual CFS implementation.]
| `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_cpu_cfu.c` | `neorv32_cpu_cfu.h`    | HW driver functions for the NEORV32 **CFU** (custom instructions)
| `neorv32_cpu_cfu.c` | `neorv32_cpu_cfu.h`    | HW driver functions for the NEORV32 **CFU** (custom instructions)
| `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_gptmr.c`   | `neorv32_gptmr.h`      | HW driver functions for the **GPTRM**
| `neorv32_gptmr.c`   | `neorv32_gptmr.h`      | HW driver functions for the **GPTRM**
| -                   | `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_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 helper functions
| `neorv32_rte.c`     | `neorv32_rte.h`        | NEORV32 **runtime environment** and helper functions
| `neorv32_slink.c`   | `neorv32_slink.h`      | HW driver functions for the **SLINK**
| `neorv32_slink.c`   | `neorv32_slink.h`      | HW driver functions for the **SLINK**
| `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**
| `neorv32_twi.c`     | `neorv32_twi.h`        | HW driver functions for the **TWI**
| `neorv32_twi.c`     | `neorv32_twi.h`        | HW driver functions for the **TWI**
| `neorv32_uart.c`    | `neorv32_uart.h`       | HW driver functions for the **UART0** and **UART1**
| `neorv32_uart.c`    | `neorv32_uart.h`       | HW driver functions for the **UART0** and **UART1**
| `neorv32_wdt.c`     | `neorv32_wdt.h`        | HW driver functions for the **WDT**
| `neorv32_wdt.c`     | `neorv32_wdt.h`        | HW driver functions for the **WDT**
| `neorv32_xip.c`     | `neorv32_xip.h`        | HW driver functions for the **XIP**
| `neorv32_xip.c`     | `neorv32_xip.h`        | HW driver functions for the **XIP**
| `neorv32_xirq.c`    | `neorv32_xirq.h`       | HW driver functions for the **XIRQ**
| `neorv32_xirq.c`    | `neorv32_xirq.h`       | HW driver functions for the **XIRQ**
| `syscalls.c`        | -                      | newlib system calls
| `syscalls.c`        | -                      | newlib system calls
|=======================
|=======================
[TIP]
[TIP]
A CMSIS-SVD-compatible **System View Description (SVD)** file including all peripherals is available in `sw/svd`.
A CMSIS-SVD-compatible **System View Description (SVD)** file including all peripherals is available in `sw/svd`.
`sw/lib/include`. Currently, the following library files are available:
`sw/lib/include`. Currently, the following library files are available:
<<<
<<<
// ####################################################################################################################
// ####################################################################################################################
:sectnums:
:sectnums:
=== Application Makefile
=== Application Makefile
Application compilation is based on a single, centralized **GNU makefiles** `sw/common/common.mk`. Each project in the
Application compilation is based on a single, centralized **GNU makefiles** `sw/common/common.mk`. Each project in the
`sw/example` folder features a makefile that just includes this central makefile. When creating a new project copy an
`sw/example` folder features a makefile that just includes this central makefile. When creating a new project copy an
existing project folder or at least the makefile to the new project folder. It is suggested to create new projects also
existing project folder or at least the makefile to the new project folder. It is suggested to create new projects also
in `sw/example` to keep the file dependencies. However, these dependencies can be manually configured via makefiles
in `sw/example` to keep the file dependencies. However, these dependencies can be manually configured via makefiles
variables when the new project is located somewhere else.
variables when the new project is located somewhere else.
[NOTE]
[NOTE]
Before the makefile can be used to compile applications, the RISC-V GCC toolchain needs to be installed. Furthermore,
Before the makefile can be used to compile applications, the RISC-V GCC toolchain needs to be installed. Furthermore,
the `bin` folder of the compiler needs to be added to the system's `PATH` variable. More information can be found in
the `bin` folder of the compiler needs to be added to the system's `PATH` variable. More information can be found in
https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[User Guide: Software Toolchain Setup].
https://stnolting.github.io/neorv32/ug/#_software_toolchain_setup[User Guide: Software Toolchain Setup].
The makefile is invoked by simply executing `make` in the console. For example:
The makefile is invoked by simply executing `make` in the console. For example:
[source,bash]
[source,bash]
----
----
neorv32/sw/example/blink_led$ make
neorv32/sw/example/blink_led$ make
----
----
:sectnums:
:sectnums:
==== Targets
==== Targets
Just executing `make` (or executing `make help`) will show the help menu listing all available targets.
Just executing `make` (or executing `make help`) will show the help menu listing all available targets.
[source,makefile]
[source,makefile]
----
----
$ make
$ make
<<< NEORV32 SW Application Makefile >>>
<<< NEORV32 SW Application Makefile >>>
Make sure to add the bin folder of RISC-V GCC to your PATH variable.
Make sure to add the bin folder of RISC-V GCC to your PATH variable.
== Targets ==
== Targets ==
 help         - show this text
 help         - show this text
 check        - check toolchain
 check        - check toolchain
 info         - show makefile/toolchain configuration
 info         - show makefile/toolchain configuration
 exe          - compile and generate  executable for upload via bootloader
 exe          - compile and generate  executable for upload via bootloader
 hex          - compile and generate  executable raw file
 hex          - compile and generate  executable raw file
 image        - compile and generate VHDL IMEM boot image (for application) in local folder
 image        - compile and generate VHDL IMEM boot image (for application) in local folder
 install      - compile, generate and install VHDL IMEM boot image (for application)
 install      - compile, generate and install VHDL IMEM boot image (for application)
 sim          - in-console simulation using default/simple testbench and GHDL
 sim          - in-console simulation using default/simple testbench and GHDL
 all          - exe + hex + install
 all          - exe + hex + install
 elf_info     - show ELF layout info
 elf_info     - show ELF layout info
 clean        - clean up project
 clean        - clean up project
 clean_all    - clean up project, core libraries and image generator
 clean_all    - clean up project, core libraries and image generator
 bl_image     - compile and generate VHDL BOOTROM boot image (for bootloader only!) in local folder
 bl_image     - compile and generate VHDL BOOTROM boot image (for bootloader only!) in local folder
 bootloader   - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)
 bootloader   - compile, generate and install VHDL BOOTROM boot image (for bootloader only!)
== Variables ==
== Variables ==
 USER_FLAGS   - Custom toolchain flags [append only], default ""
 USER_FLAGS   - Custom toolchain flags [append only], default ""
 EFFORT       - Optimization level, default "-Os"
 EFFORT       - Optimization level, default "-Os"
 MARCH        - Machine architecture, default "rv32i"
 MARCH        - Machine architecture, default "rv32i"
 MABI         - Machine binary interface, default "ilp32"
 MABI         - Machine binary interface, default "ilp32"
 APP_INC      - C include folder(s) [append only], default "-I ."
 APP_INC      - C include folder(s) [append only], default "-I ."
 ASM_INC      - ASM include folder(s) [append only], default "-I ."
 ASM_INC      - ASM include folder(s) [append only], default "-I ."
 RISCV_PREFIX - Toolchain prefix, default "riscv32-unknown-elf-"
 RISCV_PREFIX - Toolchain prefix, default "riscv32-unknown-elf-"
 NEORV32_HOME - NEORV32 home folder, default "../../.."
 NEORV32_HOME - NEORV32 home folder, default "../../.."
----
----
:sectnums:
:sectnums:
==== Configuration
==== Configuration
The compilation flow is configured via variables right at the beginning of the central
The compilation flow is configured via variables right at the beginning of the central
makefile (`sw/common/common.mk`):
makefile (`sw/common/common.mk`):
[TIP]
[TIP]
The makefile configuration variables can be overridden or extended directly when invoking the makefile. For
The makefile configuration variables can be overridden or extended directly when invoking the makefile. For
example `$ make MARCH=rv32ic clean_all exe` overrides the default `MARCH` variable definitions.
example `$ make MARCH=rv32ic clean_all exe` overrides the default `MARCH` variable definitions.
Permanent modifications/definitions can be made in the project-local makefile
Permanent modifications/definitions can be made in the project-local makefile
(e.g., `sw/example/blink_led/makefile`).
(e.g., `sw/example/blink_led/makefile`).
.Default Makefile Configuration
.Default Makefile Configuration
[source,makefile]
[source,makefile]
----
----
# *****************************************************************************
# *****************************************************************************
# USER CONFIGURATION
# USER CONFIGURATION
# *****************************************************************************
# *****************************************************************************
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here
# User's application sources (*.c, *.cpp, *.s, *.S); add additional files here
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S)
APP_SRC ?= $(wildcard ./*.c) $(wildcard ./*.s) $(wildcard ./*.cpp) $(wildcard ./*.S)
# User's application include folders (don't forget the '-I' before each entry)
# User's application include folders (don't forget the '-I' before each entry)
APP_INC ?= -I .
APP_INC ?= -I .
# User's application include folders - for assembly files only (don't forget the '-I' before each
# User's application include folders - for assembly files only (don't forget the '-I' before each
entry)
entry)
ASM_INC ?= -I .
ASM_INC ?= -I .
# Optimization
# Optimization
EFFORT ?= -Os
EFFORT ?= -Os
# Compiler toolchain
# Compiler toolchain
RISCV_PREFIX ?= riscv32-unknown-elf-
RISCV_PREFIX ?= riscv32-unknown-elf-
# CPU architecture and ABI
# CPU architecture and ABI
MARCH ?= rv32i
MARCH ?= rv32i
MABI  ?= ilp32
MABI  ?= ilp32
# User flags for additional configuration (will be added to compiler flags)
# User flags for additional configuration (will be added to compiler flags)
USER_FLAGS ?=
USER_FLAGS ?=
# Relative or absolute path to the NEORV32 home folder
# Relative or absolute path to the NEORV32 home folder
NEORV32_HOME ?= ../../..
NEORV32_HOME ?= ../../..
# *****************************************************************************
# *****************************************************************************
----
----
.Variables Description
.Variables Description
[cols="<3,<10"]
[cols="<3,<10"]
[grid="none"]
[grid="none"]
|=======================
|=======================
| `APP_SRC`      | The source files of the application (`*.c`, `*.cpp`, `*.S` and `*.s` files are allowed;
| `APP_SRC`      | The source files of the application (`*.c`, `*.cpp`, `*.S` and `*.s` files are allowed;
files of these types in the project folder are automatically added via wild cards). Additional files can be added separated by white spaces
files of these types in the project folder are automatically added via wild cards). Additional files can be added separated by white spaces
| `APP_INC`      | Include file folders; separated by white spaces; must be defined with `-I` prefix
| `APP_INC`      | Include file folders; separated by white spaces; must be defined with `-I` prefix
| `ASM_INC`      | Include file folders that are used only for the assembly source files (`*.S`/`*.s`).
| `ASM_INC`      | Include file folders that are used only for the assembly source files (`*.S`/`*.s`).
| `EFFORT`       | Optimization level, optimize for size (`-Os`) is default; legal values: `-O0`, `-O1`, `-O2`, `-O3`, `-Os`, `-Ofast`, ...
| `EFFORT`       | Optimization level, optimize for size (`-Os`) is default; legal values: `-O0`, `-O1`, `-O2`, `-O3`, `-Os`, `-Ofast`, ...
| `RISCV_PREFIX` | The toolchain prefix to be used; follows the triplet naming convention `[architecture]-[host_system]-[output]-...`
| `RISCV_PREFIX` | The toolchain prefix to be used; follows the triplet naming convention `[architecture]-[host_system]-[output]-...`
| `MARCH`        | The targeted RISC-V architecture/ISA; enable compiler support of optional CPU extension by adding the according extension
| `MARCH`        | The targeted RISC-V architecture/ISA; enable compiler support of optional CPU extension by adding the according extension
name (e.g. `rv32im` for `M` CPU extension; see https://stnolting.github.io/neorv32/ug/#_enabling_risc_v_cpu_extensions[User Guide: Enabling RISC-V CPU Extensions]
name (e.g. `rv32im` for `M` CPU extension; see https://stnolting.github.io/neorv32/ug/#_enabling_risc_v_cpu_extensions[User Guide: Enabling RISC-V CPU Extensions]
for more information
for more information
| `MABI`         | Application binary interface (default: 32-bit integer ABI `ilp32`)
| `MABI`         | Application binary interface (default: 32-bit integer ABI `ilp32`)
| `USER_FLAGS`   | Additional flags that will be forwarded to the compiler tools
| `USER_FLAGS`   | Additional flags that will be forwarded to the compiler tools
| `NEORV32_HOME` | Relative or absolute path to the NEORV32 project home folder; adapt this if the makefile/project is not in the project's
| `NEORV32_HOME` | Relative or absolute path to the NEORV32 project home folder; adapt this if the makefile/project is not in the project's
default `sw/example` folder
default `sw/example` folder
|=======================
|=======================
:sectnums:
:sectnums:
==== Default Compiler Flags
==== Default Compiler Flags
The following default compiler flags are used for compiling an application. These flags are defined via the
The following default compiler flags are used for compiling an application. These flags are defined via the
`CC_OPTS` variable. Custom flags can be _appended_ to it using the `USER_FLAGS` variable.
`CC_OPTS` variable. Custom flags can be _appended_ to it using the `USER_FLAGS` variable.
[cols="<3,<9"]
[cols="<3,<9"]
[grid="none"]
[grid="none"]
|=======================
|=======================
| `-Wall`                  | Enable all compiler warnings.
| `-Wall`                  | Enable all compiler warnings.
| `-ffunction-sections`    | Put functions and data segment in independent sections. This allows a code optimization as dead code and unused data can be easily removed.
| `-ffunction-sections`    | Put functions and data segment in independent sections. This allows a code optimization as dead code and unused data can be easily removed.
| `-nostartfiles`          | Do not use the default start code. Instead, use the NEORV32-specific start-up code (`sw/common/crt0.S`).
| `-nostartfiles`          | Do not use the default start code. Instead, use the NEORV32-specific start-up code (`sw/common/crt0.S`).
| `-Wl,--gc-sections`      | Make the linker perform dead code elimination.
| `-Wl,--gc-sections`      | Make the linker perform dead code elimination.
| `-lm`                    | Include/link with `math.h`.
| `-lm`                    | Include/link with `math.h`.
| `-lc`                    | Search for the standard C library when linking.
| `-lc`                    | Search for the standard C library when linking.
| `-lgcc`                  | Make sure we have no unresolved references to internal GCC library subroutines.
| `-lgcc`                  | Make sure we have no unresolved references to internal GCC library subroutines.
| `-mno-fdiv`              | Use built-in software functions for floating-point divisions and square roots (since the according instructions are not supported yet).
| `-mno-fdiv`              | Use built-in software functions for floating-point divisions and square roots (since the according instructions are not supported yet).
| `-falign-functions=4` .4+| Force a 32-bit alignment of functions and labels (branch/jump/call targets). This increases performance as it simplifies instruction fetch when using the C extension. As a drawback this will also slightly increase the program code.
| `-falign-functions=4` .4+| Force a 32-bit alignment of functions and labels (branch/jump/call targets). This increases performance as it simplifies instruction fetch when using the C extension. As a drawback this will also slightly increase the program code.
| `-falign-labels=4`
| `-falign-labels=4`
| `-falign-loops=4`
| `-falign-loops=4`
| `-falign-jumps=4`
| `-falign-jumps=4`
|=======================
|=======================
<<<
<<<
// ####################################################################################################################
// ####################################################################################################################
:sectnums:
:sectnums:
=== Executable Image Format
=== Executable Image Format
In order to generate a file, which can be executed by the processor, all source files have to be compiler, linked
In order to generate a file, which can be executed by the processor, all source files have to be compiler, linked
and packed into a final _executable_.
and packed into a final _executable_.
:sectnums:
:sectnums:
==== Linker Script
==== Linker Script
When all the application sources have been compiled, they need to be _linked_ in order to generate a unified
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
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.
linking all object files that were generated during compilation.
The linker script defines three memory _sections_: `rom`, `ram` and `iodev`. Each section provides specific
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`).
access _attributes_: read access (`r`), write access (`w`) and executable (`x`).
.Linker memory sections - general
.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
| `ram`           | `rwx`      | Data memory address space (processor-internal/external DMEM)
| `ram`           | `rwx`      | Data memory address space (processor-internal/external DMEM)
| `rom`           | `rx`       | Instruction memory address space (processor-internal/external IMEM) _or_ internal bootloader ROM
| `rom`           | `rx`       | Instruction memory address space (processor-internal/external IMEM) _or_ internal bootloader ROM
| `iodev`         | `rw`       | Processor-internal memory-mapped IO/peripheral devices address space
| `iodev`         | `rw`       | Processor-internal memory-mapped IO/peripheral devices address space
|=======================
|=======================
These sections are defined right at the beginning of the linker script:
These sections are defined right at the beginning of the linker script:
.Linker memory sections - cut-out from linker script `neorv32.ld`
.Linker memory sections - cut-out from linker script `neorv32.ld`
[source,c]
[source,c]
----
----
MEMORY
MEMORY
{
{
  ram  (rwx) : ORIGIN = 0x80000000, LENGTH = DEFINED(make_bootloader) ? 512 : 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
  rom   (rx) : ORIGIN = DEFINED(make_bootloader) ? 0xFFFF0000 : 0x00000000, LENGTH = DEFINED(make_bootloader) ? 32K : 2048M
  iodev (rw) : ORIGIN = 0xFFFFFE00, LENGTH = 512
  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
Each memory section provides a _base address_ `ORIGIN` and a _size_ `LENGTH`. The base address and size of the `iodev` section is
fixed and should not be altered. The base addresses and sizes of the `ram` and `rom` regions correspond to the total available instruction
fixed and should 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>>) as defined in `rtl/core/neorv32_package.vhd`.
and data memory address space (see section <<_address_space_layout>>) as defined in `rtl/core/neorv32_package.vhd`.
[IMPORTANT]
[IMPORTANT]
`ORIGIN` of the `ram` section has to be always identical to the processor's `dspace_base_c` hardware configuration. +
`ORIGIN` of the `ram` section has to be always identical to the processor's `dspace_base_c` hardware configuration. +
 +
 +
`ORIGIN` of the `rom` section has to be always identical to the processor's `ispace_base_c` hardware configuration.
`ORIGIN` of the `rom` section has to be always identical to the processor's `ispace_base_c` hardware configuration.
The sizes of `rom` section is a little bit more complicated. The default linker script configuration assumes a _maximum_ of 2GB _logical_
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
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
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.
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
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).
is sufficient (e.g., via the <<_mem_int_imem_size>> generic).
[IMPORTANT]
[IMPORTANT]
The `rom` region uses a conditional assignment (via the `make_bootloader` symbol) for `ORIGIN` and `LENGTH` that is used to place
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
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
(`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.
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 five final sections: `.text`, `.rodata`, `.data`, `.bss` and `.heap`.
The linker maps all the regions from the compiled object files into five final sections: `.text`, `.rodata`, `.data`, `.bss` and `.heap`.
These regions contain everything required for the application to run:
These regions contain everything required for the application to run:
.Linker memory 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.
| `.rodata` | Constants (like strings) from the application; also the initial data for initialized variables.
| `.rodata` | Constants (like strings) from the application; also the initial data for initialized variables.
| `.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.
| `.heap`   | This section is required for the address generation of dynamic memory constructs only.
| `.heap`   | 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`,
The `.text` and `.rodata` sections are mapped to processor's instruction memory space and the `.data`,
`.bss` and `heap` sections are mapped to the processor's data memory space. Finally, the `.text`, `.rodata` and `.data`
`.bss` and `heap` 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 `main.bin`.
sections are extracted and concatenated into a single file `main.bin`.
:sectnums:
:sectnums:
==== RAM Layout
==== RAM Layout
The default NEORV32 linker script uses all of the defined RAM (linker script memory section `ram`) to create four areas.
The default NEORV32 linker script uses all of the defined RAM (linker script memory section `ram`) to create four areas.
Note that depending on the application some areas might not be existent at all.
Note that depending on the application some areas might not be existent at all.
.Default RAM Layout
.Default RAM Layout
image::ram_layout.png[400]
image::ram_layout.png[400]
[start=1]
[start=1]
. **Constant data (`.data`)**: The constant data section is placed right at the beginning of the RAM. For example, this section
. **Constant data (`.data`)**: The constant data section is placed right at the beginning of the RAM. For example, this section
contains _explicitly initialized_ global variables. This section is initialized by the executable.
contains _explicitly initialized_ global variables. This section is initialized by the executable.
. **Dynamic data (`.bss`)**: The constant data section is followed by the dynamic data section, which contains _uninitialized_ data
. **Dynamic data (`.bss`)**: The constant data section is followed by the dynamic data section, which contains _uninitialized_ data
like global variables without explicit initialization. This section is cleared by the start-up code `crt0.S`.
like global variables without explicit initialization. This section is cleared by the start-up code `crt0.S`.
. **Heap (`.heap`)**: The heap is used for dynamic memory that is managed by functions like `malloc()` and `free()`. The heap
. **Heap (`.heap`)**: The heap is used for dynamic memory that is managed by functions like `malloc()` and `free()`. The heap
grows upwards. This section is not initialized at all.
grows upwards. This section is not initialized at all.
. **Stack**: The stack starts at the very end of the RAM at address `ORIGIN(ram) + LENGTH(ram) - 4`. The stack grows downwards.
. **Stack**: The stack starts at the very end of the RAM at address `ORIGIN(ram) + LENGTH(ram) - 4`. The stack grows downwards.
There is _no explicit limit_ for the maximum stack size as this is hard to check. However, a physical memory protection rule could
There is _no explicit limit_ for the maximum stack size as this is hard to check. However, a physical memory protection rule could
be used to configure a maximum size by adding a "protection area" between stack and heap (a PMP region without any access rights).
be used to configure a maximum size by adding a "protection area" between stack and heap (a PMP region without any access rights).
The maximum size of the heap is defined by the linker script's `__heap_size` symbol. This symbol can be overridden at any time.
The maximum size of the heap is defined by the linker script's `__heap_size` symbol. This symbol can be overridden at any time.
By default, the maximum heap size is 1/4 of the total RAM size.
By default, the maximum heap size is 1/4 of the total RAM size.
.Heap-Stack Collisions
.Heap-Stack Collisions
[WARNING]
[WARNING]
Take care when using dynamic memory to avoid collision of the heap and stack memory areas. There is no compile-time protection
Take care when using dynamic memory to avoid collision of the heap and stack memory areas. There is no compile-time protection
mechanism available as the actual heap and stack size are defined by _runtime_ data. Also beware of fragmentation when
mechanism available as the actual heap and stack size are defined by _runtime_ data. Also beware of fragmentation when
using dynamic memory allocation.
using dynamic memory allocation.
:sectnums:
:sectnums:
==== C Standard Library
==== C Standard Library
.Constructors and Deconstructors
.Constructors and Deconstructors
[IMPORTANT]
[IMPORTANT]
The NEORV32 processor is an embedded system intended for running bare-metal or RTOS applications. To simplify this setup
The NEORV32 processor is an embedded system intended for running bare-metal or RTOS applications. To simplify this setup
explicit constructors and deconstructors are not supported by default. However, a minimal "deconstructor-alike" support is
explicit constructors and deconstructors are not supported by default. However, a minimal "deconstructor-alike" support is
provided by the <<_after_main_handler>>.
provided by the <<_after_main_handler>>.
The NEORV32 is a processor for _embedded_ applications. Hence, it is not capable of running desktop OSs like Linux
The NEORV32 is a processor for _embedded_ applications. Hence, it is not capable of running desktop OSs like Linux
(at least not without emulation). Hence, the software framework relies on a "bare-metal" setup that uses **newlib**
(at least not without emulation). Hence, the software framework relies on a "bare-metal" setup that uses **newlib**
as default C standard library.
as default C standard library.
.RTOS Support
.RTOS Support
[NOTE]
[NOTE]
The NEORV32 CPU and processor **do support** embedded RTOS like FreeRTOS and Zephyr. See the User guide section
The NEORV32 CPU and processor **do support** embedded RTOS like FreeRTOS and Zephyr. See the User guide section
https://stnolting.github.io/neorv32/ug/#_zephyr_rtos_support[Zephyr RTOS Support] and
https://stnolting.github.io/neorv32/ug/#_zephyr_rtos_support[Zephyr RTOS Support] and
https://stnolting.github.io/neorv32/ug/#_freertos_support[FreeRTOS Support]
https://stnolting.github.io/neorv32/ug/#_freertos_support[FreeRTOS Support]
for more information.
for more information.
Newlib provides stubs for common "system calls" (like file handling and standard input/output) that are used by other
Newlib provides stubs for common "system calls" (like file handling and standard input/output) that are used by other
C libraries like `stdio`. These stubs are available in `sw/source/syscalls.c` and were adapted for the NEORV32 processor.
C libraries like `stdio`. These stubs are available in `sw/source/syscalls.c` and were adapted for the NEORV32 processor.
.Standard Console(s)
.Standard Console(s)
[NOTE]
[NOTE]
<<_primary_universal_asynchronous_receiver_and_transmitter_uart0, UART0>>
<<_primary_universal_asynchronous_receiver_and_transmitter_uart0, UART0>>
is used to implement all the standard input, output and error consoles (`STDIN`, `STDOUT` and `STDERR`).
is used to implement all the standard input, output and error consoles (`STDIN`, `STDOUT` and `STDERR`).
.Newlib Test/Demo Program
.Newlib Test/Demo Program
[TIP]
[TIP]
A simple test and demo program, which uses some of newlib's core functions (like `malloc`/`free` and `read`/`write`)
A simple test and demo program, which uses some of newlib's core functions (like `malloc`/`free` and `read`/`write`)
is available in `sw/example_newlib_demo`
is available in `sw/example/demo_newlib`
 
 
:sectnums:
:sectnums:
==== Executable Image Generator
==== Executable Image Generator
The `main.bin` file is packed by the NEORV32 image generator (`sw/image_gen`) to generate the final executable file.
The `main.bin` file is packed by the NEORV32 image generator (`sw/image_gen`) to generate the final executable file.
[NOTE]
[NOTE]
The sources of the image generator are automatically compiled when invoking the makefile.
The sources of the image generator are automatically compiled when invoking the makefile.
The image generator can generate three types of executables, selected by a flag when calling the generator:
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_hex` | Generates a plain ASCII hex-char file `neorv32_exe.hex` that can be used to initialize custom (instruction-) memories (in synthesis/simulation).
| `-app_hex` | Generates a plain ASCII hex-char file `neorv32_exe.hex` that can be used to initialize custom (instruction-) memories (in synthesis/simulation).
| `-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. The _normal application_ compilation flow will generate the `neorv32_exe.bin`
All these options are managed by the makefile. The _normal application_ compilation flow will generate the `neorv32_exe.bin`
executable to be upload via UART to the NEORV32 bootloader.
executable to be 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 image generator add a small header to the `neorv32_exe.bin` executable, which consists 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. The first word of the executable is the signature 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
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.
:sectnums:
:sectnums:
==== Start-Up Code (crt0)
==== 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)
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.
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
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.
and placed right before the actual application code so it gets executed right after reset.
The `crt0.S` start-up performs the following operations:
The `crt0.S` start-up performs the following operations:
[start=1]
[start=1]
 
. Disable interrupts globally by clearing <<_mstatus>>`.mie`.
. Initialize all integer registers `x1 - x31` (or just `x1 - x15` when using the `E` CPU extension) to a defined value.
. Initialize all integer registers `x1 - x31` (or just `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 <<_ram_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
. Initialize all CPU core CSRs and also install a default "dummy" trap handler for _all_ traps. This handler catches all traps
 
** All interrupt sources are disabled and all pending interrupts are cleared.
 
. Initialize the global pointer `gp` and the stack pointer `sp` according to the <<_ram_layout>> provided by the linker script.
during the early boot phase.
during the early boot phase.
. All interrupt sources are disabled and all pending interrupts are cleared.
 
. Clear all counter CSRs and stop auto-increment.
. Clear all counter CSRs and stop auto-increment.
. Clear IO area: Write zero to all memory-mapped registers within the IO region (`iodev` section). If certain devices have not
. 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.
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.
. 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.
. 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).
. Call the application's `main` function (with _no_ arguments: `argc` = `argv` = 0).
. If the main function returns...
. If the main function returns...
** the return value is copied to the <<_mscratch>> CSR to allow inspection by the on-chip debugger.
** the return value is copied to the <<_mscratch>> CSR to allow inspection by the on-chip debugger.
** an optional <<_after_main_handler>> is called (if defined at all).
** an optional <<_after_main_handler>> is called (if defined at all).
** the last step the CPU does is entering endless sleep mode (using the `wfi` instruction).
** the last step the CPU does is entering endless sleep mode (using the `wfi` instruction).
:sectnums:
:sectnums:
===== After-Main Handler
===== After-Main Handler
If the application's `main()` function actually returns, an _after main handler_ can be executed. This handler is a "normal" function
If the application's `main()` function actually returns, an _after main handler_ can be executed. This handler is a "normal" function
as the C runtime is still available when executed. If this handler uses any kind of peripheral/IO modules make sure these are
as the C runtime is still available when executed. If this handler uses any kind of peripheral/IO modules make sure these are
already initialized within the application. Otherwise you have to initialize them _inside_ the handler.
already initialized within the application. Otherwise you have to initialize them _inside_ the handler.
.After-main handler - function prototype
.After-main handler - function prototype
[source,c]
[source,c]
----
----
void __neorv32_crt0_after_main(int32_t return_code);
void __neorv32_crt0_after_main(int32_t return_code);
----
----
The function has exactly one argument (`return_code`) that provides the _return value_ of the application's main function.
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 after-main handler itself does
For instance, this variable contains `-1` if the main function returned with `return -1;`. The after-main handler itself does
not provide a return value.
not provide a return value.
A simple UART output can be used to inform the user when the application's main function returns
A simple UART output can be used to inform the user when the application's main function returns
(this example assumes that UART0 has been already properly configured in the actual application):
(this example assumes that UART0 has been already properly configured in the actual application):
.After-main handler - simple example
.After-main handler - simple example
[source,c]
[source,c]
----
----
void __neorv32_crt0_after_main(int32_t return_code) {
void __neorv32_crt0_after_main(int32_t return_code) {
  neorv32_uart0_printf("\n main function returned with exit code %i. \n", return_code); <1>
  neorv32_uart0_printf("\n main function returned with exit code %i. \n", return_code); <1>
}
}
----
----
<1> Use `` here to make clear this is a message comes from the runtime environment.
<1> Use `` here to make clear this is a message comes from the runtime environment.
<<<
<<<
// ####################################################################################################################
// ####################################################################################################################
include::software_bootloader.adoc[]
include::software_bootloader.adoc[]
<<<
<<<
// ####################################################################################################################
// ####################################################################################################################
include::software_rte.adoc[]
include::software_rte.adoc[]
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.